From: Dmitry Selyutin Date: Wed, 18 Aug 2021 19:57:47 +0000 (+0000) Subject: test_caller_bcd: addg6s sketch X-Git-Tag: xlen-bcd~118 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0d88ddfc94c7401e6327c2285ab0b0737ab8f273;p=openpower-isa.git test_caller_bcd: addg6s sketch --- diff --git a/src/openpower/decoder/isa/test_caller_bcd.py b/src/openpower/decoder/isa/test_caller_bcd.py index c22aee8f..5c6deca6 100644 --- a/src/openpower/decoder/isa/test_caller_bcd.py +++ b/src/openpower/decoder/isa/test_caller_bcd.py @@ -1,3 +1,4 @@ +import itertools import re from nmigen import Module, Signal from nmigen.back.pysim import Simulator, Settle @@ -13,6 +14,10 @@ from openpower.decoder.orderedset import OrderedSet from openpower.decoder.isa.all import ISA +# addg6s product limitations +ADDG6S_PRODUCT_LIMIT = 16 + + # PowerISA Version 3.0C Book 1 App. B, Table 129 DPD_TO_BCD_TABLE = """ 0 1 2 3 4 5 6 7 8 9 A B C D E F @@ -311,6 +316,71 @@ class BCDTestCase(FHDLTestCase): mapping[bcd] = dpd self.run_tst("cbcdtd", mapping) + def test_addg6s(self): + def half_adder(a, b): + (a, b) = map(bool, [a, b]) + carry = a & b + sum = a ^ b + return (int(sum), int(carry)) + + def full_adder(a, b, c): + (a, b, c) = map(bool, [a, b, c]) + (sum0, carry0) = half_adder(a, b) + (sum, carry1) = half_adder(sum0, c) + carry = (carry0 | carry1) + return (int(sum), int(carry)) + + def full_adder64(a, b): + sum = [0] * 64 + carry = [0] * 64 + (sum[0], carry[0]) = half_adder(a[0], b[0]) + for bit in range(1, 64, 1): + (sum[bit], carry[bit]) = full_adder(a[bit], b[bit], carry[bit - 1]) + return (sum + [carry[63]]) + + def addg6s(a, b): + BIT = lambda value, bit: int(bool((value >> bit) & 1)) + a = list(reversed(list(map(lambda bit: BIT(a, bit), range(63, -1, -1))))) + b = list(reversed(list(map(lambda bit: BIT(b, bit), range(63, -1, -1))))) + sum = full_adder64(a, b) + + a_in = lambda bit: a[bit] + b_in = lambda bit: b[bit] + sum_with_carry = lambda bit: sum[bit] + + addg6s = [0] * 64 + for i in range(15): + lo = i * 4 + hi = (i + 1) * 4 + if (a_in(hi) ^ b_in(hi) ^ (sum_with_carry(hi) == 0)): + addg6s[lo + 3] = 0 + addg6s[lo + 2] = 1 + addg6s[lo + 1] = 1 + addg6s[lo + 0] = 0 + if sum_with_carry(64) == 0: + addg6s[63] = 0 + addg6s[62] = 1 + addg6s[61] = 1 + addg6s[60] = 0 + return int("".join(map(str, reversed(addg6s))), 2) + + cond = lambda item: item[0] < ADDG6S_PRODUCT_LIMIT + bcd = map(lambda digit: f"{digit:04b}", range(10)) + product = enumerate(itertools.product(bcd, repeat=16)) + sequences = (seq for (_, seq) in itertools.takewhile(cond, product)) + numbers = [int("".join(seq), 2) for seq in sequences] + iregs = [0] * 32 + for a in numbers: + for b in numbers: + rv = addg6s(a, b) + with self.subTest(): + iregs[2] = b + iregs[1] = a + lst = ["addg6s 0, 1, 2"] + with Program(lst, bigendian=False) as program: + sim = self.run_tst_program(program, iregs) + self.assertEqual(sim.gpr(0), SelectableInt(rv, 64)) + def run_tst_program(self, prog, initial_regs=[0] * 32): simulator = run_tst(prog, initial_regs, pdecode2=self.pdecode2) simulator.gpr.dump()