From f2ed9ea6869bbfb72c3d590f02b3792e81bbfc08 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Thu, 19 Aug 2021 15:40:32 +0000 Subject: [PATCH] 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. --- src/openpower/decoder/isa/test_caller_bcd.py | 81 ++++++++------------ 1 file changed, 31 insertions(+), 50 deletions(-) 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) -- 2.30.2