set defaults in pspec
[soc.git] / src / soc / simple / test / test_core.py
index 96abda8d836f7da9e8d38e4904207f2a232a4f39..9d751cf016eccb5fdf104cea802edb4832dbe59e 100644 (file)
@@ -1,3 +1,9 @@
+"""simple core test
+
+related bugs:
+
+ * https://bugs.libre-soc.org/show_bug.cgi?id=363
+"""
 from nmigen import Module, Signal, Cat
 from nmigen.back.pysim import Simulator, Delay, Settle
 from nmutil.formaltest import FHDLTestCase
 from nmigen import Module, Signal, Cat
 from nmigen.back.pysim import Simulator, Delay, Settle
 from nmutil.formaltest import FHDLTestCase
@@ -6,12 +12,17 @@ import unittest
 from soc.decoder.isa.caller import special_sprs
 from soc.decoder.power_decoder import create_pdecode
 from soc.decoder.power_decoder2 import PowerDecode2
 from soc.decoder.isa.caller import special_sprs
 from soc.decoder.power_decoder import create_pdecode
 from soc.decoder.power_decoder2 import PowerDecode2
+from soc.decoder.selectable_int import SelectableInt
 from soc.decoder.isa.all import ISA
 from soc.decoder.isa.all import ISA
-from soc.decoder.power_enums import Function, XER_bits
-
+from soc.decoder.power_enums import SPR, spr_dict, Function, XER_bits
+from soc.config.test.test_loadstore import TestMemPspec
+from soc.config.endian import bigendian
 
 from soc.simple.core import NonProductionCore
 
 from soc.simple.core import NonProductionCore
-from soc.experiment.compalu_multi import find_ok # hack
+from soc.experiment.compalu_multi import find_ok  # hack
+
+from soc.fu.compunits.test.test_compunit import (setup_test_memory,
+                                                 check_sim_memory)
 
 # test with ALU data and Logical data
 from soc.fu.alu.test.test_pipe_caller import ALUTestCase
 
 # test with ALU data and Logical data
 from soc.fu.alu.test.test_pipe_caller import ALUTestCase
@@ -19,24 +30,173 @@ from soc.fu.logical.test.test_pipe_caller import LogicalTestCase
 from soc.fu.shift_rot.test.test_pipe_caller import ShiftRotTestCase
 from soc.fu.cr.test.test_pipe_caller import CRTestCase
 from soc.fu.branch.test.test_pipe_caller import BranchTestCase
 from soc.fu.shift_rot.test.test_pipe_caller import ShiftRotTestCase
 from soc.fu.cr.test.test_pipe_caller import CRTestCase
 from soc.fu.branch.test.test_pipe_caller import BranchTestCase
+from soc.fu.ldst.test.test_pipe_caller import LDSTTestCase
+from soc.regfile.util import spr_to_fast_reg
 
 
 
 
-def set_issue(core, dec2, sim):
-    yield core.issue_i.eq(1)
-    yield
-    yield core.issue_i.eq(0)
+def setup_regs(pdecode2, core, test):
+
+    # set up INT regfile, "direct" write (bypass rd/write ports)
+    intregs = core.regs.int
+    for i in range(32):
+        if intregs.unary:
+            yield intregs.regs[i].reg.eq(test.regs[i])
+        else:
+            yield intregs.memory._array[i].eq(test.regs[i])
+    yield Settle()
+
+    # set up CR regfile, "direct" write across all CRs
+    cr = test.cr
+    crregs = core.regs.cr
+    #cr = int('{:32b}'.format(cr)[::-1], 2)
+    print("setup cr reg", hex(cr))
+    for i in range(8):
+        #j = 7-i
+        cri = (cr >> (i*4)) & 0xf
+        #cri = int('{:04b}'.format(cri)[::-1], 2)
+        print("setup cr reg", hex(cri), i,
+              crregs.regs[i].reg.shape())
+        yield crregs.regs[i].reg.eq(cri)
+
+    # set up XER.  "direct" write (bypass rd/write ports)
+    xregs = core.regs.xer
+    print("setup sprs", test.sprs)
+    xer = None
+    if 'XER' in test.sprs:
+        xer = test.sprs['XER']
+    if 1 in test.sprs:
+        xer = test.sprs[1]
+    if xer is not None:
+        if isinstance(xer, int):
+            xer = SelectableInt(xer, 64)
+        sobit = xer[XER_bits['SO']].value
+        yield xregs.regs[xregs.SO].reg.eq(sobit)
+        cabit = xer[XER_bits['CA']].value
+        ca32bit = xer[XER_bits['CA32']].value
+        yield xregs.regs[xregs.CA].reg.eq(Cat(cabit, ca32bit))
+        ovbit = xer[XER_bits['OV']].value
+        ov32bit = xer[XER_bits['OV32']].value
+        yield xregs.regs[xregs.OV].reg.eq(Cat(ovbit, ov32bit))
+        print("setting XER so %d ca %d ca32 %d ov %d ov32 %d" %
+              (sobit, cabit, ca32bit, ovbit, ov32bit))
+    else:
+        yield xregs.regs[xregs.SO].reg.eq(0)
+        yield xregs.regs[xregs.OV].reg.eq(0)
+        yield xregs.regs[xregs.CA].reg.eq(0)
+
+    # setting both fast and slow SPRs from test data
+
+    fregs = core.regs.fast
+    sregs = core.regs.spr
+    for sprname, val in test.sprs.items():
+        if isinstance(val, SelectableInt):
+            val = val.value
+        if isinstance(sprname, int):
+            sprname = spr_dict[sprname].SPR
+        if sprname == 'XER':
+            continue
+        fast = spr_to_fast_reg(sprname)
+        if fast is None:
+            # match behaviour of SPRMap in power_decoder2.py
+            for i, x in enumerate(SPR):
+                if sprname == x.name:
+                    yield sregs[i].reg.eq(val)
+                    print("setting slow SPR %d (%s) to %x" %
+                          (i, sprname, val))
+        else:
+            yield fregs.regs[fast].reg.eq(val)
+            print("setting fast reg %d (%s) to %x" %
+                  (fast, sprname, val))
+
+    # allow changes to settle before reporting on XER
+    yield Settle()
+
+    # XER
+    so = yield xregs.regs[xregs.SO].reg
+    ov = yield xregs.regs[xregs.OV].reg
+    ca = yield xregs.regs[xregs.CA].reg
+    oe = yield pdecode2.e.do.oe.oe
+    oe_ok = yield pdecode2.e.do.oe.oe_ok
+
+    print("before: so/ov-32/ca-32", so, bin(ov), bin(ca))
+    print("oe:", oe, oe_ok)
+
+
+def check_regs(dut, sim, core, test, code):
+    # int regs
+    intregs = []
+    for i in range(32):
+        if core.regs.int.unary:
+            rval = yield core.regs.int.regs[i].reg
+        else:
+            rval = yield core.regs.int.memory._array[i]
+        intregs.append(rval)
+    print("int regs", list(map(hex, intregs)))
+    for i in range(32):
+        simregval = sim.gpr[i].asint()
+        dut.assertEqual(simregval, intregs[i],
+                        "int reg %d not equal %s" % (i, repr(code)))
+
+    # CRs
+    crregs = []
+    for i in range(8):
+        rval = yield core.regs.cr.regs[i].reg
+        crregs.append(rval)
+    print("cr regs", list(map(hex, crregs)))
+    for i in range(8):
+        rval = crregs[i]
+        cri = sim.crl[7-i].get_range().value
+        print("cr reg", i, hex(cri), i, hex(rval))
+        # XXX https://bugs.libre-soc.org/show_bug.cgi?id=363
+        dut.assertEqual(cri, rval,
+                        "cr reg %d not equal %s" % (i, repr(code)))
+
+    # XER
+    xregs = core.regs.xer
+    so = yield xregs.regs[xregs.SO].reg
+    ov = yield xregs.regs[xregs.OV].reg
+    ca = yield xregs.regs[xregs.CA].reg
+
+    print("sim SO", sim.spr['XER'][XER_bits['SO']])
+    e_so = sim.spr['XER'][XER_bits['SO']].value
+    e_ov = sim.spr['XER'][XER_bits['OV']].value
+    e_ov32 = sim.spr['XER'][XER_bits['OV32']].value
+    e_ca = sim.spr['XER'][XER_bits['CA']].value
+    e_ca32 = sim.spr['XER'][XER_bits['CA32']].value
+
+    e_ov = e_ov | (e_ov32 << 1)
+    e_ca = e_ca | (e_ca32 << 1)
+
+    print("after: so/ov-32/ca-32", so, bin(ov), bin(ca))
+    dut.assertEqual(e_so, so, "so mismatch %s" % (repr(code)))
+    dut.assertEqual(e_ov, ov, "ov mismatch %s" % (repr(code)))
+    dut.assertEqual(e_ca, ca, "ca mismatch %s" % (repr(code)))
+
+
+def wait_for_busy_hi(cu):
     while True:
     while True:
-        busy_o = yield core.busy_o
+        busy_o = yield cu.busy_o
+        terminate_o = yield cu.core_terminate_o
         if busy_o:
         if busy_o:
+            print("busy/terminate:", busy_o, terminate_o)
             break
             break
-        print("!busy",)
+        print("!busy", busy_o, terminate_o)
         yield
 
 
         yield
 
 
+def set_issue(core, dec2, sim):
+    yield core.issue_i.eq(1)
+    yield
+    yield core.issue_i.eq(0)
+    yield from wait_for_busy_hi(core)
+
+
 def wait_for_busy_clear(cu):
     while True:
         busy_o = yield cu.busy_o
 def wait_for_busy_clear(cu):
     while True:
         busy_o = yield cu.busy_o
+        terminate_o = yield cu.core_terminate_o
         if not busy_o:
         if not busy_o:
+            print("busy/terminate:", busy_o, terminate_o)
             break
         print("busy",)
         yield
             break
         print("busy",)
         yield
@@ -53,14 +213,26 @@ class TestRunner(FHDLTestCase):
         instruction = Signal(32)
         ivalid_i = Signal()
 
         instruction = Signal(32)
         ivalid_i = Signal()
 
-        m.submodules.core = core = NonProductionCore()
-        pdecode = core.pdecode
+        pspec = TestMemPspec(ldst_ifacetype='testpi',
+                             imem_ifacetype='',
+                             addr_wid=48,
+                             mask_wid=8,
+                             reg_wid=64)
+
+        m.submodules.core = core = NonProductionCore(pspec)
         pdecode2 = core.pdecode2
         pdecode2 = core.pdecode2
+        l0 = core.l0
 
 
-        comb += pdecode2.dec.raw_opcode_in.eq(instruction)
+        comb += core.raw_opcode_i.eq(instruction)
         comb += core.ivalid_i.eq(ivalid_i)
         comb += core.ivalid_i.eq(ivalid_i)
-        sim = Simulator(m)
 
 
+        # temporary hack: says "go" immediately for both address gen and ST
+        ldst = core.fus.fus['ldst0']
+        m.d.comb += ldst.ad.go.eq(ldst.ad.rel)  # link addr-go direct to rel
+        m.d.comb += ldst.st.go.eq(ldst.st.rel)  # link store-go direct to rel
+
+        # nmigen Simulation
+        sim = Simulator(m)
         sim.add_clock(1e-6)
 
         def process():
         sim.add_clock(1e-6)
 
         def process():
@@ -71,54 +243,28 @@ class TestRunner(FHDLTestCase):
                 print(test.name)
                 program = test.program
                 self.subTest(test.name)
                 print(test.name)
                 program = test.program
                 self.subTest(test.name)
-                sim = ISA(pdecode2, test.regs, test.sprs, test.cr)
+                sim = ISA(pdecode2, test.regs, test.sprs, test.cr, test.mem,
+                          test.msr,
+                          bigendian=bigendian)
                 gen = program.generate_instructions()
                 instructions = list(zip(gen, program.assembly.splitlines()))
 
                 gen = program.generate_instructions()
                 instructions = list(zip(gen, program.assembly.splitlines()))
 
-                # set up INT regfile, "direct" write (bypass rd/write ports)
-                for i in range(32):
-                    yield core.regs.int.regs[i].reg.eq(test.regs[i])
-
-                # set up CR regfile, "direct" write across all CRs
-                cr = test.cr
-                print ("cr reg", hex(cr))
-                for i in range(8):
-                    cri = (cr>>(i*4)) & 0xf
-                    print ("cr reg", hex(cri), i,
-                            core.regs.cr.regs[i].reg.shape())
-                    yield core.regs.cr.regs[i].reg.eq(cri)
-
-                # set up XER.  "direct" write (bypass rd/write ports)
-                xregs = core.regs.xer
-                print ("sprs", test.sprs)
-                if special_sprs['XER'] in test.sprs:
-                    xer = test.sprs[special_sprs['XER']]
-                    sobit = xer[XER_bits['SO']].asint()
-                    yield xregs.regs[xregs.SO].reg.eq(sobit)
-                    cabit = xer[XER_bits['CA']].asint()
-                    ca32bit = xer[XER_bits['CA32']].asint()
-                    yield xregs.regs[xregs.CA].reg.eq(Cat(cabit, ca32bit))
-                    ovbit = xer[XER_bits['OV']].asint()
-                    ov32bit = xer[XER_bits['OV32']].asint()
-                    yield xregs.regs[xregs.OV].reg.eq(Cat(ovbit, ov32bit))
-                else:
-                    yield xregs.regs[xregs.SO].reg.eq(0)
-                    yield xregs.regs[xregs.OV].reg.eq(0)
-                    yield xregs.regs[xregs.CA].reg.eq(0)
+                yield from setup_test_memory(l0, sim)
+                yield from setup_regs(core, test)
 
                 index = sim.pc.CIA.value//4
                 while index < len(instructions):
                     ins, code = instructions[index]
 
 
                 index = sim.pc.CIA.value//4
                 while index < len(instructions):
                     ins, code = instructions[index]
 
-                    print("0x{:X}".format(ins & 0xffffffff))
+                    print("instruction: 0x{:X}".format(ins & 0xffffffff))
                     print(code)
 
                     # ask the decoder to decode this binary data (endian'd)
                     print(code)
 
                     # ask the decoder to decode this binary data (endian'd)
-                    yield pdecode2.dec.bigendian.eq(0)  # little / big?
+                    yield core.bigendian_i.eq(bigendian)  # little / big?
                     yield instruction.eq(ins)          # raw binary instr.
                     yield ivalid_i.eq(1)
                     yield Settle()
                     yield instruction.eq(ins)          # raw binary instr.
                     yield ivalid_i.eq(1)
                     yield Settle()
-                    #fn_unit = yield pdecode2.e.fn_unit
+                    # fn_unit = yield pdecode2.e.fn_unit
                     #fuval = self.funit.value
                     #self.assertEqual(fn_unit & fuval, fuval)
 
                     #fuval = self.funit.value
                     #self.assertEqual(fn_unit & fuval, fuval)
 
@@ -130,32 +276,28 @@ class TestRunner(FHDLTestCase):
                     yield ivalid_i.eq(0)
                     yield
 
                     yield ivalid_i.eq(0)
                     yield
 
-                    print ("sim", code)
+                    print("sim", code)
                     # call simulated operation
                     opname = code.split(' ')[0]
                     yield from sim.call(opname)
                     index = sim.pc.CIA.value//4
 
                     # call simulated operation
                     opname = code.split(' ')[0]
                     yield from sim.call(opname)
                     index = sim.pc.CIA.value//4
 
-                    # int regs
-                    intregs = []
-                    for i in range(32):
-                        rval = yield core.regs.int.regs[i].reg
-                        intregs.append(rval)
-                    print ("int regs", list(map(hex, intregs)))
-                    for i in range(32):
-                        simregval = sim.gpr[i].asint()
-                        self.assertEqual(simregval, intregs[i],
-                            "int reg %d not equal %s" % (i, repr(code)))
+                    # register check
+                    yield from check_regs(self, sim, core, test, code)
+
+                    # Memory check
+                    yield from check_sim_memory(self, l0, sim, code)
 
         sim.add_sync_process(process)
         with sim.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
 
         sim.add_sync_process(process)
         with sim.write_vcd("core_simulator.vcd", "core_simulator.gtkw",
-                            traces=[]):
+                           traces=[]):
             sim.run()
 
 
 if __name__ == "__main__":
     unittest.main(exit=False)
     suite = unittest.TestSuite()
             sim.run()
 
 
 if __name__ == "__main__":
     unittest.main(exit=False)
     suite = unittest.TestSuite()
+    suite.addTest(TestRunner(LDSTTestCase.test_data))
     suite.addTest(TestRunner(CRTestCase.test_data))
     suite.addTest(TestRunner(ShiftRotTestCase.test_data))
     suite.addTest(TestRunner(LogicalTestCase.test_data))
     suite.addTest(TestRunner(CRTestCase.test_data))
     suite.addTest(TestRunner(ShiftRotTestCase.test_data))
     suite.addTest(TestRunner(LogicalTestCase.test_data))
@@ -164,4 +306,3 @@ if __name__ == "__main__":
 
     runner = unittest.TextTestRunner()
     runner.run(suite)
 
     runner = unittest.TextTestRunner()
     runner.run(suite)
-