From: Dmitry Selyutin Date: Thu, 19 Aug 2021 15:40:32 +0000 (+0000) Subject: test_caller_bcd: refactor addg6s test X-Git-Tag: xlen-bcd~115 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f2ed9ea6869bbfb72c3d590f02b3792e81bbfc08;p=openpower-isa.git test_caller_bcd: refactor addg6s test This patch should vastly simplify and speed up the addg6s test. Most importantly, we drop half adders and full adders, making use of the fact that Python uses big integers directly. Also, we don't bother generating all posible products of BCD numbers; instead, we simply resort to random number generator. Note, however, that we only check the numbers that are correct from BCD point of view. --- diff --git a/src/openpower/decoder/isa/test_caller_bcd.py b/src/openpower/decoder/isa/test_caller_bcd.py index d831e11a..12b00b55 100644 --- a/src/openpower/decoder/isa/test_caller_bcd.py +++ b/src/openpower/decoder/isa/test_caller_bcd.py @@ -1,9 +1,11 @@ import itertools +import random import re from nmigen import Module, Signal from nmigen.back.pysim import Simulator, Settle from nmutil.formaltest import FHDLTestCase import unittest + from openpower.decoder.isa.caller import ISACaller from openpower.decoder.power_decoder import create_pdecode from openpower.decoder.power_decoder2 import (PowerDecode2) @@ -316,73 +318,52 @@ class BCDTestCase(FHDLTestCase): mapping[bcd] = dpd self.run_tst("cbcdtd", mapping) - @unittest.skip("slowpoke") 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)) - r64 = range(63, -1, -1) - a = list(reversed(list(map(lambda bit: BIT(a, bit), r64)))) - b = list(reversed(list(map(lambda bit: BIT(b, bit), r64)))) - sum = full_adder64(a, b) + def bits(value, bits): + lsb = [((value >> bit) & 1) for bit in range(bits, -1, -1)] + return list(reversed(lsb)) - a_in = lambda bit: a[bit] - b_in = lambda bit: b[bit] - sum_with_carry = lambda bit: sum[bit] + a_in = bits(a, 64) + b_in = bits(b, 64) + sum_with_carry = bits((a + b), 65) addg6s = [0] * 64 - for i in range(15): + for i in range(16): lo = i * 4 hi = (i + 1) * 4 - if (a_in(hi) ^ b_in(hi) ^ (sum_with_carry(hi) == 0)): + 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: + 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)) + bcd = [f"{digit:04b}" for digit in range(10)] + rng10 = lambda: random.randrange(0, 10) + bcdrng = lambda: int("".join((bcd[rng10()] for _ in range(16))), 2) + + lst = [] + oregs = [0] * 32 + iregs = [bcdrng() for _ in range(32)] + for gpr in range(31): + lst += [f"addg6s {gpr}, {gpr + 0}, {gpr + 1}"] + oregs[gpr] = addg6s(iregs[gpr + 0], iregs[gpr + 1]) + + for _ in range(16): + with self.subTest(): + for line in lst: + print(line) + with Program(lst, bigendian=False) as program: + sim = self.run_tst_program(program, iregs) + for gpr in range(31): + self.assertEqual(sim.gpr(gpr), + SelectableInt(oregs[gpr], 64)) def run_tst_program(self, prog, initial_regs=[0] * 32): simulator = run_tst(prog, initial_regs, pdecode2=self.pdecode2)