sorting out bigendian/littleendian including in qemu
[soc.git] / src / soc / fu / compunits / test / test_compunit.py
index 293a5ef789db5106b65a67d0b71be20c7538c92d..7a73cb83f5f61d29d612b18a0b522e68ff2738ef 100644 (file)
@@ -1,19 +1,15 @@
-from nmigen import Module, Signal
+from nmigen import Module, Signal, ResetSignal
 from nmigen.back.pysim import Simulator, Delay, Settle
 from nmutil.formaltest import FHDLTestCase
 from nmigen.cli import rtlil
 import unittest
-from soc.decoder.isa.caller import ISACaller, special_sprs
 from soc.decoder.power_decoder import (create_pdecode)
 from soc.decoder.power_decoder2 import (PowerDecode2)
-from soc.decoder.power_enums import (XER_bits, Function, InternalOp)
-from soc.decoder.selectable_int import SelectableInt
-from soc.simulator.program import Program
+from soc.decoder.power_enums import Function
 from soc.decoder.isa.all import ISA
 
-from soc.fu.alu.test.test_pipe_caller import TestCase, ALUTestCase, test_data
 from soc.experiment.compalu_multi import find_ok # hack
-import random
+from soc.config.test.test_loadstore import TestMemPspec
 
 
 def set_cu_input(cu, idx, data):
@@ -61,10 +57,12 @@ def get_cu_output(cu, idx, code):
     yield
     yield cu.wr.go[idx].eq(0)
     print ("result", repr(code), idx, wrop, wrok, hex(result))
+
     return result
 
 
 def set_cu_inputs(cu, inp):
+    print ("set_cu_inputs", inp)
     for idx, data in inp.items():
         yield from set_cu_input(cu, idx, data)
 
@@ -79,6 +77,16 @@ def set_operand(cu, dec2, sim):
 
 def get_cu_outputs(cu, code):
     res = {}
+    wrmask = yield cu.wrmask
+    print ("get_cu_outputs", cu.n_dst, wrmask)
+    if not wrmask: # no point waiting (however really should doublecheck wr.rel)
+        return {}
+    # wait for at least one result
+    while True:
+        wr_rel_o = yield cu.wr.rel
+        if wr_rel_o:
+            break
+        yield
     for i in range(cu.n_dst):
         wr_rel_o = yield cu.wr.rel[i]
         if wr_rel_o:
@@ -97,14 +105,56 @@ def get_inp_indexed(cu, inp):
             res[i] = inp[wrop]
     return res
 
+def get_l0_mem(l0): # BLECH!
+    if hasattr(l0.pimem, 'lsui'):
+        return l0.pimem.lsui.mem
+    return l0.pimem.mem.mem
+
+def setup_test_memory(l0, sim):
+    mem = get_l0_mem(l0)
+    print ("before, init mem", mem.depth, mem.width, mem)
+    for i in range(mem.depth):
+        data = sim.mem.ld(i*8, 8, False)
+        print ("init ", i, hex(data))
+        yield mem._array[i].eq(data)
+    yield Settle()
+    for k, v in sim.mem.mem.items():
+        print ("    %6x %016x" % (k, v))
+    print ("before, nmigen mem dump")
+    for i in range(mem.depth):
+        actual_mem = yield mem._array[i]
+        print ("    %6i %016x" % (i, actual_mem))
+
+
+def dump_sim_memory(dut, l0, sim, code):
+    mem = get_l0_mem(l0)
+    print ("sim mem dump")
+    for k, v in sim.mem.mem.items():
+        print ("    %6x %016x" % (k, v))
+    print ("nmigen mem dump")
+    for i in range(mem.depth):
+        actual_mem = yield mem._array[i]
+        print ("    %6i %016x" % (i, actual_mem))
+
+
+def check_sim_memory(dut, l0, sim, code):
+    mem = get_l0_mem(l0)
+
+    for i in range(mem.depth):
+        expected_mem = sim.mem.ld(i*8, 8, False)
+        actual_mem = yield mem._array[i]
+        dut.assertEqual(expected_mem, actual_mem,
+                "%s %d %x %x" % (code, i,
+                                 expected_mem, actual_mem))
 
 class TestRunner(FHDLTestCase):
-    def __init__(self, test_data, fukls, iodef, funit):
+    def __init__(self, test_data, fukls, iodef, funit, bigendian):
         super().__init__("run_all")
         self.test_data = test_data
         self.fukls = fukls
         self.iodef = iodef
         self.funit = funit
+        self.bigendian = bigendian
 
     def run_all(self):
         m = Module()
@@ -112,9 +162,26 @@ class TestRunner(FHDLTestCase):
         instruction = Signal(32)
 
         pdecode = create_pdecode()
-
         m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
-        m.submodules.cu = cu = self.fukls()
+
+        # copy of the decoder for simulator
+        simdec = create_pdecode()
+        simdec2 = PowerDecode2(simdec)
+        m.submodules.simdec2 = simdec2 # pain in the neck
+
+        if self.funit == Function.LDST:
+            from soc.experiment.l0_cache import TstL0CacheBuffer
+            pspec = TestMemPspec(ldst_ifacetype='test_bare_wb',
+                                 addr_wid=48,
+                                 mask_wid=8,
+                                 reg_wid=64)
+            m.submodules.l0 = l0 = TstL0CacheBuffer(pspec, n_units=1)
+            pi = l0.l0.dports[0]
+            m.submodules.cu = cu = self.fukls(pi, idx=0, awid=3)
+            m.d.comb += cu.ad.go.eq(cu.ad.rel) # link addr-go direct to rel
+            m.d.comb += cu.st.go.eq(cu.st.rel) # link store-go direct to rel
+        else:
+            m.submodules.cu = cu = self.fukls(0)
 
         comb += pdecode2.dec.raw_opcode_in.eq(instruction)
         sim = Simulator(m)
@@ -129,27 +196,41 @@ class TestRunner(FHDLTestCase):
                 print(test.name)
                 program = test.program
                 self.subTest(test.name)
-                sim = ISA(pdecode2, test.regs, test.sprs, 0)
-                gen = program.generate_instructions()
-                instructions = list(zip(gen, program.assembly.splitlines()))
+                print ("test", test.name, test.mem)
+                gen = list(program.generate_instructions())
+                insncode = program.assembly.splitlines()
+                instructions = list(zip(gen, insncode))
+                sim = ISA(simdec2, test.regs, test.sprs, test.cr, test.mem,
+                          test.msr,
+                          initial_insns=gen, respect_pc=False,
+                          disassembly=insncode,
+                          bigendian=self.bigendian)
+
+                # initialise memory
+                if self.funit == Function.LDST:
+                    yield from setup_test_memory(l0, sim)
 
                 index = sim.pc.CIA.value//4
-                while index < len(instructions):
+                while True:
+                    try:
+                        yield from sim.setup_one()
+                    except KeyError: # indicates instruction not in imem: stop
+                        break
+                    yield Settle()
                     ins, code = instructions[index]
-
-                    print("0x{:X}".format(ins & 0xffffffff))
-                    print(code)
+                    print(index, code)
 
                     # ask the decoder to decode this binary data (endian'd)
-                    yield pdecode2.dec.bigendian.eq(0)  # little / big?
+                    yield pdecode2.dec.bigendian.eq(self.bigendian)  # le / be?
                     yield instruction.eq(ins)          # raw binary instr.
                     yield Settle()
-                    fn_unit = yield pdecode2.e.fn_unit
+                    fn_unit = yield pdecode2.e.do.fn_unit
                     fuval = self.funit.value
                     self.assertEqual(fn_unit & fuval, fuval)
 
                     # set operand and get inputs
                     yield from set_operand(cu, pdecode2, sim)
+                    yield Settle()
                     iname = yield from self.iodef.get_cu_inputs(pdecode2, sim)
                     inp = get_inp_indexed(cu, iname)
 
@@ -177,7 +258,6 @@ class TestRunner(FHDLTestCase):
                                 "respec %s" % \
                                 (bin(wr_rel_o), cu.rwid[1])
                     yield from set_cu_inputs(cu, inp)
-                    yield
                     rd_rel_o = yield cu.rd.rel
                     wr_rel_o = yield cu.wr.rel
                     wrmask = yield cu.wrmask
@@ -185,19 +265,47 @@ class TestRunner(FHDLTestCase):
                             bin(rd_rel_o), bin(wr_rel_o), bin(wrmask))
 
                     # call simulated operation
-                    opname = code.split(' ')[0]
-                    yield from sim.call(opname)
+                    yield from sim.execute_one()
+                    yield Settle()
                     index = sim.pc.CIA.value//4
 
-                    yield Settle()
                     # get all outputs (one by one, just "because")
                     res = yield from get_cu_outputs(cu, code)
+                    wrmask = yield cu.wrmask
+                    rd_rel_o = yield cu.rd.rel
+                    wr_rel_o = yield cu.wr.rel
+                    print ("after got outputs, rd_rel, wr_rel, wrmask: ",
+                            bin(rd_rel_o), bin(wr_rel_o), bin(wrmask))
+
+                    # wait for busy to go low
+                    while True:
+                        busy_o = yield cu.busy_o
+                        print ("busy", busy_o)
+                        if not busy_o:
+                            break
+                        yield
+
+                    if self.funit == Function.LDST:
+                        yield from dump_sim_memory(self, l0, sim, code)
+
+
+                    # sigh.  hard-coded.  test memory
+                    if self.funit == Function.LDST:
+                        yield from check_sim_memory(self, l0, sim, code)
+                        yield from self.iodef.check_cu_outputs(res, pdecode2,
+                                                                sim, cu,
+                                                                code)
+                    else:
+                        yield from self.iodef.check_cu_outputs(res, pdecode2,
+                                                                sim, cu.alu,
+                                                                code)
 
-                    yield from self.iodef.check_cu_outputs(res, pdecode2,
-                                                            sim, code)
 
         sim.add_sync_process(process)
-        with sim.write_vcd("simulator.vcd", "simulator.gtkw",
+
+        name = self.funit.name.lower()
+        with sim.write_vcd("%s_simulator.vcd" % name,
+                           "%s_simulator.gtkw" % name,
                             traces=[]):
             sim.run()