X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fopenpower%2Fdecoder%2Fisa%2Ftest_caller_bcd.py;h=f9efcf43fd98aa908b7a7f5632a5592e50b36fc1;hb=5876b417baf71d23fae41ca2626fc4737647696a;hp=5c6deca6a5f995957292b86c7dfccb7d5a0b4973;hpb=0d88ddfc94c7401e6327c2285ab0b0737ab8f273;p=openpower-isa.git diff --git a/src/openpower/decoder/isa/test_caller_bcd.py b/src/openpower/decoder/isa/test_caller_bcd.py index 5c6deca6..f9efcf43 100644 --- a/src/openpower/decoder/isa/test_caller_bcd.py +++ b/src/openpower/decoder/isa/test_caller_bcd.py @@ -1,21 +1,14 @@ -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) from openpower.simulator.program import Program -from openpower.decoder.isa.caller import ISACaller, inject from openpower.decoder.selectable_int import SelectableInt -from openpower.decoder.orderedset import OrderedSet -from openpower.decoder.isa.all import ISA - -# addg6s product limitations -ADDG6S_PRODUCT_LIMIT = 16 +from openpower.decoder.isa.test_runner import run_tst # PowerISA Version 3.0C Book 1 App. B, Table 129 @@ -201,72 +194,7 @@ BCD_TO_DPD_PATTERN = (r"^(\d{2})_\s" + BCD_TO_DPD_REGEX = re.compile(BCD_TO_DPD_PATTERN, re.M) -def run_tst(generator, initial_regs, initial_sprs=None, svstate=0, mmu=False, - initial_cr=0, mem=None, - initial_fprs=None, - pdecode2=None): - if initial_sprs is None: - initial_sprs = {} - m = Module() - comb = m.d.comb - instruction = Signal(32) - - if pdecode2 is None: - pdecode = create_pdecode(include_fp=initial_fprs is not None) - pdecode2 = PowerDecode2(pdecode) - - gen = list(generator.generate_instructions()) - insncode = generator.assembly.splitlines() - instructions = list(zip(gen, insncode)) - - m.submodules.pdecode2 = pdecode2 - simulator = ISA(pdecode2, initial_regs, initial_sprs, initial_cr, - initial_insns=gen, respect_pc=True, - initial_svstate=svstate, - initial_mem=mem, - fpregfile=initial_fprs, - disassembly=insncode, - bigendian=0, - mmu=mmu) - comb += pdecode2.dec.raw_opcode_in.eq(instruction) - sim = Simulator(m) - - def process(): - - print ("GPRs") - simulator.gpr.dump() - print ("FPRs") - simulator.fpr.dump() - - yield pdecode2.dec.bigendian.eq(0) # little / big? - pc = simulator.pc.CIA.value - index = pc//4 - while index < len(instructions): - print("instr pc", pc) - try: - yield from simulator.setup_one() - except KeyError: # indicates instruction not in imem: stop - break - yield Settle() - - ins, code = instructions[index] - print(" 0x{:X}".format(ins & 0xffffffff)) - opname = code.split(' ')[0] - print(code, opname) - - # ask the decoder to decode this binary data (endian'd) - yield from simulator.execute_one() - pc = simulator.pc.CIA.value - index = pc//4 - - sim.add_process(process) - with sim.write_vcd("simulator.vcd", "simulator.gtkw", - traces=[]): - sim.run() - return simulator - - -def testgen(mapping): +def tstgen(mapping): zeros = [0] * 32 length = len(mapping) iregs_whole = list(mapping.keys()) @@ -285,11 +213,10 @@ class BCDTestCase(FHDLTestCase): def run_tst(self, instr, mapping): lst = [f"{instr} {reg}, {reg}" for reg in range(32)] - for (iregs, oregs) in testgen(mapping): + for (iregs, oregs) in tstgen(mapping): with self.subTest(): with Program(lst, bigendian=False) as program: sim = self.run_tst_program(program, iregs) - gprs = [sim.gpr(gpr) for gpr in range(32)] for gpr in range(32): self.assertEqual(sim.gpr(gpr), SelectableInt(oregs[gpr], 64)) @@ -300,8 +227,8 @@ class BCDTestCase(FHDLTestCase): for digit in range(0x10): dpd = int((match[0] + f"{digit:X}"), 16) bcd = ((int(match[1 + digit][0]) << 8) | - (int(match[1 + digit][1]) << 4) | - (int(match[1 + digit][2]) << 0)) + (int(match[1 + digit][1]) << 4) | + (int(match[1 + digit][2]) << 0)) mapping[dpd] = bcd self.run_tst("cdtbcd", mapping) @@ -310,76 +237,50 @@ class BCDTestCase(FHDLTestCase): for match in BCD_TO_DPD_REGEX.findall(BCD_TO_DPD_TABLE): for digit in range(10): bcd = ((int(match[0][0]) << 8) | - (int(match[0][1]) << 4) | - (int(digit) << 0)) + (int(match[0][1]) << 4) | + (int(digit) << 0)) dpd = int(match[1 + digit], 16) 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]]) - + # Reference implementation for addg6s, adopted to Python. + # https://github.com/antonblanchard/microwatt/blob/master/execute1.vhdl 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) + 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)): - 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 + if (a_in[hi] ^ b_in[hi] ^ (sum_with_carry[hi] == 0)): + addg6s[lo:lo + 3 + 1] = [0, 1, 1, 0] + if sum_with_carry[64] == 0: + addg6s[60:63] = [0, 1, 1, 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)] + def rng10(): return random.randrange(0, 10) + def bcdrng(): return int("".join((bcd[rng10()] for _ in range(16))), 2) + + lst = [f"addg6s {gpr}, {gpr + 0}, {gpr + 1}" for gpr in range(31)] + oregs = [0] * 32 + for _ in range(16): + iregs = [bcdrng() for _ in range(32)] + for gpr in range(31): + oregs[gpr] = addg6s(iregs[gpr + 0], iregs[gpr + 1]) + with self.subTest(): + 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)