working on svp64 utf-8 validation -- still broken
[openpower-isa.git] / src / openpower / test / runner.py
index dd59e9faf5774a5218c2d068ab3d7406b04f26b5..b03509b1f10bf59986683f0a7ab7cef5c3628536 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: LGPL-2-or-later
 """TestRunner class, part of the Test API
 
 SPDX-License: LGPLv2+
@@ -15,7 +16,8 @@ related bugs:
 """
 
 from nmigen import Module, ClockSignal
-from copy import copy
+from copy import copy, deepcopy
+from pprint import pprint
 
 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
 # Also, check out the cxxsim nmigen branch, and latest yosys from git
@@ -30,7 +32,8 @@ from openpower.decoder.power_decoder2 import PowerDecode2
 
 from soc.config.test.test_loadstore import TestMemPspec
 from nmutil.util import wrap
-from soc.experiment.test.test_mmu_dcache import wb_get
+from openpower.test.wb_get import wb_get
+import openpower.test.wb_get as wbget
 from openpower.test.state import TestState, StateRunner, ExpectedState
 
 
@@ -42,6 +45,7 @@ class SimRunner(StateRunner):
         super().__init__("sim", SimRunner)
         self.dut = dut
 
+        self.mmu = pspec.mmu == True
         regreduce_en = pspec.regreduce_en == True
         self.simdec2 = simdec2 = PowerDecode2(None, regreduce_en=regreduce_en)
         m.submodules.simdec2 = simdec2  # pain in the neck
@@ -64,7 +68,8 @@ class SimRunner(StateRunner):
                   initial_insns=gen, respect_pc=True,
                   disassembly=insncode,
                   bigendian=bigendian,
-                  initial_svstate=test.svstate)
+                  initial_svstate=test.svstate,
+                  mmu=self.mmu)
 
         # run the loop of the instructions on the current test
         index = sim.pc.CIA.value//4
@@ -91,6 +96,11 @@ class SimRunner(StateRunner):
             state = yield from TestState("sim", sim, dut, code)
             sim_states.append(state)
 
+        if self.dut.allow_overlap:
+            # get last state, at end of run
+            state = yield from TestState("sim", sim, dut, code)
+            sim_states.append(state)
+
         return sim_states
 
 
@@ -105,12 +115,15 @@ class TestRunnerBase(FHDLTestCase):
     is passed in with tst_data.
     """
     def __init__(self, tst_data, microwatt_mmu=False, rom=None,
-                        svp64=True, run_hdl=None, run_sim=True):
+                        svp64=True, run_hdl=None, run_sim=True,
+                        allow_overlap=False, inorder=False):
         super().__init__("run_all")
         self.test_data = tst_data
         self.microwatt_mmu = microwatt_mmu
         self.rom = rom
         self.svp64 = svp64
+        self.allow_overlap = allow_overlap
+        self.inorder = inorder
         self.run_hdl = run_hdl
         self.run_sim = run_sim
 
@@ -118,23 +131,33 @@ class TestRunnerBase(FHDLTestCase):
         m = Module()
         comb = m.d.comb
         if self.microwatt_mmu:
-            ldst_ifacetype = 'test_mmu_cache_wb'
+            # do not wire these up to anything if wb_get is to be used
+            if self.rom is not None:
+                ldst_ifacetype = 'mmu_cache_wb'
+                imem_ifacetype = 'mmu_cache_wb'
+            else:
+                ldst_ifacetype = 'test_mmu_cache_wb'
+                imem_ifacetype = 'test_bare_wb'
         else:
             ldst_ifacetype = 'test_bare_wb'
-        imem_ifacetype = 'test_bare_wb'
+            imem_ifacetype = 'test_bare_wb'
 
         pspec = TestMemPspec(ldst_ifacetype=ldst_ifacetype,
                              imem_ifacetype=imem_ifacetype,
-                             addr_wid=48,
+                             addr_wid=64,
                              mask_wid=8,
+                             XLEN=64,
                              imem_reg_wid=64,
                              # wb_data_width=32,
                              use_pll=False,
                              nocore=False,
                              xics=False,
                              gpio=False,
-                             regreduce=True,
+                             regreduce=not self.allow_overlap,
+                             core_domain="sync", # no alternative domain
                              svp64=self.svp64,
+                             allow_overlap=self.allow_overlap,
+                             inorder=self.inorder,
                              mmu=self.microwatt_mmu,
                              reg_wid=64)
 
@@ -144,6 +167,10 @@ class TestRunnerBase(FHDLTestCase):
         # The methods contained in the respective Runner classes are
         # called using this list when possible
 
+        # allow wb_get to run
+        if self.rom is not None:
+            wbget.stop = False
+
         state_list = []
 
         if self.run_hdl:
@@ -159,6 +186,8 @@ class TestRunnerBase(FHDLTestCase):
         # but Simulation-only fails without it
         intclk = ClockSignal("coresync")
         comb += intclk.eq(ClockSignal())
+        dbgclk = ClockSignal("dbgsync")
+        comb += dbgclk.eq(ClockSignal())
 
         # nmigen Simulation - everything runs around this, so it
         # still has to be created.
@@ -175,11 +204,20 @@ class TestRunnerBase(FHDLTestCase):
             # get each test, completely reset the core, and run it
 
             for test in self.test_data:
-
-                with self.subTest(test.name):
+                with self.subTest(test.name, **test.subtest_args):
 
                     ###### PREPARATION PHASE AT START OF TEST #######
 
+                    # HACK: if there is test memory and wb_get is in use,
+                    # overwrite (reset) the wb_get memory dictionary with
+                    # the test's memory contents (oh, and put the wb_get
+                    # memory back in as well)
+                    self.default_mem.clear()
+                    if self.rom is not None:
+                        self.default_mem.update(deepcopy(self.rom))
+                    if test.mem is not None:
+                        self.default_mem.update(deepcopy(test.mem))
+
                     for runner in state_list:
                         yield from runner.prepare_for_test(test)
 
@@ -251,6 +289,17 @@ class TestRunnerBase(FHDLTestCase):
 
                     # compare the states
                     if self.run_hdl and self.run_sim:
+                        # if allow_overlap is enabled, because allow_overlap
+                        # can commit out-of-order, only compare the last ones
+                        if self.allow_overlap:
+                            print ("allow_overlap: truncating %d %d "
+                                    "states to last" % (len(sim_states),
+                                                        len(hdl_states)))
+                            sim_states = sim_states[-1:]
+                            hdl_states = hdl_states[-1:]
+                            sim_states[-1].dump_state_tofile()
+                            print ("allow_overlap: last hdl_state")
+                            hdl_states[-1].dump_state_tofile()
                         for simstate, hdlstate in zip(sim_states, hdl_states):
                             simstate.compare(hdlstate)     # register check
                             simstate.compare_mem(hdlstate) # memory check
@@ -258,9 +307,7 @@ class TestRunnerBase(FHDLTestCase):
                     # if no expected, create /tmp/case_name.py with code
                     # setting expected state to last_sim
                     if test.expected is None:
-                        e = ExpectedState()
-                        e.dump_state_tofile(last_sim, test.name,
-                                            test.test_file)
+                        last_sim.dump_state_tofile(test.name, test.test_file)
 
                     # compare against expected results
                     if test.expected is not None:
@@ -272,9 +319,13 @@ class TestRunnerBase(FHDLTestCase):
                         # do actual comparison, against last item
                         last_sim.compare(test.expected)
 
+                    # check number of instructions run (sanity)
                     if self.run_hdl and self.run_sim:
-                        self.assertTrue(len(hdl_states) == len(sim_states),
-                                    "number of instructions run not the same")
+                        n_hdl = len(hdl_states)
+                        n_sim = len(sim_states)
+                        self.assertTrue(n_hdl == n_sim,
+                                    "number of instructions %d %d "
+                                    "run not the same" % (n_hdl, n_sim))
 
                 ###### END OF A TEST #######
                 # StateRunner.end_test()
@@ -288,6 +339,10 @@ class TestRunnerBase(FHDLTestCase):
             for runner in state_list:
                 yield from runner.cleanup() # TODO, some arguments?
 
+            # finally stop wb_get from going
+            if self.rom is not None:
+                wbget.stop = True
+
         styles = {
             'dec': {'base': 'dec'},
             'bin': {'base': 'bin'},
@@ -370,7 +425,14 @@ class TestRunnerBase(FHDLTestCase):
             'core.int.rp_src1.memory(7)[63:0]',
             'core.int.rp_src1.memory(9)[63:0]',
             'core.int.rp_src1.memory(10)[63:0]',
-            'core.int.rp_src1.memory(13)[63:0]'
+            'core.int.rp_src1.memory(13)[63:0]',
+            # Exceptions: see list archive for description of the chain
+            # http://lists.libre-soc.org/pipermail/libre-soc-dev/2021-December/004220.html
+            ('exceptions', 'closed', [
+                'exc_happened',
+                'pdecode2.exc_happened',
+                'core.exc_happened',
+                'core.fus.ldst0.exc_o_happened']),
         ]
 
         # PortInterface module path varies depending on MMU option
@@ -381,6 +443,7 @@ class TestRunnerBase(FHDLTestCase):
 
         traces += [('ld/st port interface', {'submodule': pi_module}, [
             'oper_r__insn_type',
+            'oper_r__msr[63:0]',
             'ldst_port0_is_ld_i',
             'ldst_port0_is_st_i',
             'ldst_port0_busy_o',
@@ -392,6 +455,7 @@ class TestRunnerBase(FHDLTestCase):
             'ldst_port0_st_data_i_ok',
             'ldst_port0_ld_data_o[63:0]',
             'ldst_port0_ld_data_o_ok',
+            'ldst_port0_msr_pr',
             'exc_o_happened',
             'cancel'
         ])]
@@ -405,15 +469,25 @@ class TestRunnerBase(FHDLTestCase):
                 'core.fus.mmu0.alu_mmu0.mmu.pid[31:0]',
                 'core.fus.mmu0.alu_mmu0.mmu.prtbl[63:0]',
                 {'comment': 'wishbone_memory'},
-                'core.fus.mmu0.alu_mmu0.dcache.stb',
-                'core.fus.mmu0.alu_mmu0.dcache.cyc',
-                'core.fus.mmu0.alu_mmu0.dcache.we',
-                'core.fus.mmu0.alu_mmu0.dcache.ack',
-                'core.fus.mmu0.alu_mmu0.dcache.stall,'
+                'core.l0.pimem.bus__ack',
+                'core.l0.pimem.bus__adr[4:0]',
+                'core.l0.pimem.bus__bte',
+                'core.l0.pimem.bus__cti',
+                'core.l0.pimem.bus__cyc',
+                'core.l0.pimem.bus__dat_r[63:0]',
+                'core.l0.pimem.bus__dat_w[63:0]',
+                'core.l0.pimem.bus__dat_err',
+                'core.l0.pimem.bus__dat_sel[7:0]',
+                'core.l0.pimem.bus__dat_stb',
+                'core.l0.pimem.bus__dat_we',
             ]
 
-        write_gtkw("issuer_simulator.gtkw",
-                   "issuer_simulator.vcd",
+        gtkname = "issuer_simulator"
+        if self.rom:
+            gtkname += "_mmu"
+
+        write_gtkw("%s.gtkw" % gtkname,
+                   "%s.vcd" % gtkname,
                    traces, styles, module='top.issuer')
 
         # add run of instructions
@@ -425,10 +499,17 @@ class TestRunnerBase(FHDLTestCase):
 
         # optionally, if a wishbone-based ROM is passed in, run that as an
         # extra emulated process
+        self.default_mem = {}
         if self.rom is not None:
+            print ("TestRunner with MMU ROM")
+            pprint (self.rom)
             dcache = hdlrun.issuer.core.fus.fus["mmu0"].alu.dcache
-            default_mem = self.rom
-            sim.add_sync_process(wrap(wb_get(dcache, default_mem, "DCACHE")))
-
-        with sim.write_vcd("issuer_simulator.vcd"):
+            icache = hdlrun.issuer.core.fus.fus["mmu0"].alu.icache
+            self.default_mem = deepcopy(self.rom)
+            sim.add_sync_process(wrap(wb_get(dcache.bus,
+                                             self.default_mem, "DCACHE")))
+            sim.add_sync_process(wrap(wb_get(icache.ibus,
+                                             self.default_mem, "ICACHE")))
+
+        with sim.write_vcd("%s.vcd" % gtkname):
             sim.run()