Merge remote-tracking branch 'upstream/master' into pr
[soc.git] / src / soc / simple / test / test_runner.py
index a25b442636b87ca55550951452a6726a3b26b158..a8898bf5caaefdae9b03fbd891e6c8b4de6c4519 100644 (file)
@@ -35,7 +35,7 @@ from soc.fu.compunits.test.test_compunit import (setup_tst_memory,
 from soc.debug.dmi import DBGCore, DBGCtrl, DBGStat
 from nmutil.util import wrap
 from soc.experiment.test.test_mmu_dcache import wb_get
-from openpower.test.state import TestState
+from openpower.test.state import TestState, StateRunner
 
 
 def setup_i_memory(imem, startaddr, instructions):
@@ -211,7 +211,7 @@ def run_hdl_state(dut, test, issuer, pc_i, svstate_i, instructions):
     return hdl_states
 
 
-def run_sim_state(dut, test, simdec2, instructions):
+def run_sim_state(dut, test, simdec2, instructions, gen, insncode):
     """run_sim_state - runs an ISACaller simulation
     """
 
@@ -253,21 +253,41 @@ def run_sim_state(dut, test, simdec2, instructions):
     return sim_states
 
 
+class SimRunner(StateRunner):
+    def __init__(self, dut, m, pspec):
+        self.dut = dut
+
+        regreduce_en = pspec.regreduce_en == True
+        self.simdec2 = simdec2 = PowerDecode2(None, regreduce_en=regreduce_en)
+        m.submodules.simdec2 = simdec2  # pain in the neck
+
+
+class HDLRunner(StateRunner):
+    def __init__(self, dut, m, pspec):
+        self.dut = dut
+        #hard_reset = Signal(reset_less=True)
+        self.issuer = TestIssuerInternal(pspec)
+        # use DMI RESET command instead, this does actually work though
+        #issuer = ResetInserter({'coresync': hard_reset,
+        #                        'sync': hard_reset})(issuer)
+        m.submodules.issuer = self.issuer
+        self.dmi = self.issuer.dbg.dmi
+
+
 class TestRunner(FHDLTestCase):
     def __init__(self, tst_data, microwatt_mmu=False, rom=None,
-                        svp64=True):
+                        svp64=True, run_hdl=True, run_sim=True):
         super().__init__("run_all")
         self.test_data = tst_data
         self.microwatt_mmu = microwatt_mmu
         self.rom = rom
         self.svp64 = svp64
+        self.run_hdl = run_hdl
+        self.run_sim = run_sim
 
     def run_all(self):
         m = Module()
         comb = m.d.comb
-        pc_i = Signal(32)
-        svstate_i = Signal(64)
-
         if self.microwatt_mmu:
             ldst_ifacetype = 'test_mmu_cache_wb'
         else:
@@ -288,51 +308,64 @@ class TestRunner(FHDLTestCase):
                              svp64=self.svp64,
                              mmu=self.microwatt_mmu,
                              reg_wid=64)
-        #hard_reset = Signal(reset_less=True)
-        issuer = TestIssuerInternal(pspec)
-        # use DMI RESET command instead, this does actually work though
-        #issuer = ResetInserter({'coresync': hard_reset,
-        #                        'sync': hard_reset})(issuer)
-        m.submodules.issuer = issuer
-        dmi = issuer.dbg.dmi
 
-        regreduce_en = pspec.regreduce_en == True
-        simdec2 = PowerDecode2(None, regreduce_en=regreduce_en)
-        m.submodules.simdec2 = simdec2  # pain in the neck
+        ###### SETUP PHASE #######
+        # StateRunner.setup_for_test()
+
+        if self.run_hdl:
+            hdlrun = HDLRunner(self, m, pspec)
+
+        if self.run_sim:
+            simrun = SimRunner(self, m, pspec)
 
         # run core clock at same rate as test clock
         intclk = ClockSignal("coresync")
         comb += intclk.eq(ClockSignal())
 
-        comb += issuer.pc_i.data.eq(pc_i)
-        comb += issuer.svstate_i.data.eq(svstate_i)
+        if self.run_hdl:
+
+            pc_i = Signal(32)
+            svstate_i = Signal(64)
 
-        # nmigen Simulation
+            comb += hdlrun.issuer.pc_i.data.eq(pc_i)
+            comb += hdlrun.issuer.svstate_i.data.eq(svstate_i)
+
+        # nmigen Simulation - everything runs around this, so it
+        # still has to be created.
         sim = Simulator(m)
         sim.add_clock(1e-6)
 
         def process():
 
-            # start in stopped
-            yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
-            yield
+            ###### PREPARATION PHASE AT START OF RUNNING #######
+            # StateRunner.setup_during_test()
+
+            if self.run_hdl:
+                # start in stopped
+                yield from set_dmi(hdlrun.dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
+                yield
 
             # get each test, completely reset the core, and run it
 
             for test in self.test_data:
 
-                # set up bigendian (TODO: don't do this, use MSR)
-                yield issuer.core_bigendian_i.eq(bigendian)
-                yield Settle()
+                with self.subTest(test.name):
 
-                yield
-                yield
-                yield
-                yield
+                    ###### PREPARATION PHASE AT START OF TEST #######
+                    # StateRunner.prepare_for_test()
 
-                print(test.name)
-                program = test.program
-                with self.subTest(test.name):
+                    if self.run_hdl:
+                        # set up bigendian (TODO: don't do this, use MSR)
+                        yield hdlrun.issuer.core_bigendian_i.eq(bigendian)
+                        yield Settle()
+
+                        yield
+                        yield
+                        yield
+                        yield
+
+                    print(test.name)
+                    program = test.program
                     print("regs", test.regs)
                     print("sprs", test.sprs)
                     print("cr", test.cr)
@@ -343,6 +376,9 @@ class TestRunner(FHDLTestCase):
                     insncode = program.assembly.splitlines()
                     instructions = list(zip(gen, insncode))
 
+                    ###### RUNNING OF EACH TEST #######
+                    # StateRunner.step_test()
+
                     # Run two tests (TODO, move these to functions)
                     # * first the Simulator, collate a batch of results
                     # * then the HDL, likewise
@@ -353,66 +389,101 @@ class TestRunner(FHDLTestCase):
                     ##########
                     # 1. HDL
                     ##########
-                    hdl_states = yield from run_hdl_state(self, test, issuer,
-                                                          pc_i, svstate_i,
-                                                          instructions)
+                    if self.run_hdl:
+                        hdl_states = yield from run_hdl_state(self, test,
+                                                              hdlrun.issuer,
+                                                              pc_i, svstate_i,
+                                                              instructions)
 
                     ##########
                     # 2. Simulator
                     ##########
 
-                    sim_states = yield from run_sim_state(self, test, simdec2,
-                                                          instructions)
+                    if self.run_sim:
+                        sim_states = yield from run_sim_state(self, test,
+                                                          simrun.simdec2,
+                                                          instructions, gen,
+                                                          insncode)
+
+                    ###### COMPARING THE TESTS #######
 
                     ###############
                     # 3. Compare
                     ###############
 
-                    for simstate, hdlstate in zip(sim_states, hdl_states):
-                        simstate.compare(hdlstate)     # register check
-                        simstate.compare_mem(hdlstate) # memory check
-
-                    print ("hdl_states")
-                    for state in hdl_states:
-                        print (state)
+                    if self.run_sim:
+                        last_sim = copy(sim_states[-1])
+                    elif self.run_hdl:
+                        last_sim = copy(hdl_states[-1])
+                    else:
+                        last_sim = None # err what are you doing??
+
+                    if self.run_hdl and self.run_sim:
+                        for simstate, hdlstate in zip(sim_states, hdl_states):
+                            simstate.compare(hdlstate)     # register check
+                            simstate.compare_mem(hdlstate) # memory check
+
+                    if self.run_hdl:
+                        print ("hdl_states")
+                        for state in hdl_states:
+                            print (state)
+
+                    if self.run_sim:
+                        print ("sim_states")
+                        for state in sim_states:
+                            print (state)
+
+                    # compare against expected results
+                    if test.expected is not None:
+                        # have to put these in manually
+                        test.expected.to_test = test.expected
+                        test.expected.dut = self
+                        test.expected.state_type = "expected"
+                        test.expected.code = 0
+                        # do actual comparison, against last item
+                        last_sim.compare(test.expected)
+
+                    if self.run_hdl and self.run_sim:
+                        self.assertTrue(len(hdl_states) == len(sim_states),
+                                    "number of instructions run not the same")
 
-                    print ("sim_states")
-                    for state in sim_states:
-                        print (state)
+                ###### END OF A TEST #######
+                # StateRunner.end_test()
 
-                    self.assertTrue(len(hdl_states) == len(sim_states),
-                                    "number of instructions run not the same")
+                if self.run_hdl:
+                    # stop at end
+                    yield from set_dmi(hdlrun.dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
+                    yield
+                    yield
 
-                # stop at end
-                yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
-                yield
-                yield
+                    # TODO, here is where the static (expected) results
+                    # can be checked: register check (TODO, memory check)
+                    # see https://bugs.libre-soc.org/show_bug.cgi?id=686#c51
+                    # yield from check_regs(self, sim, core, test, code,
+                    #                       >>>expected_data<<<)
 
-                # TODO, here is where the static (expected) results
-                # can be checked: register check (TODO, memory check)
-                # see https://bugs.libre-soc.org/show_bug.cgi?id=686#c51
-                # yield from check_regs(self, sim, core, test, code,
-                #                       >>>expected_data<<<)
+                    # get CR
+                    cr = yield from get_dmi(hdlrun.dmi, DBGCore.CR)
+                    print("after test %s cr value %x" % (test.name, cr))
 
-                # get CR
-                cr = yield from get_dmi(dmi, DBGCore.CR)
-                print("after test %s cr value %x" % (test.name, cr))
+                    # get XER
+                    xer = yield from get_dmi(hdlrun.dmi, DBGCore.XER)
+                    print("after test %s XER value %x" % (test.name, xer))
 
-                # get XER
-                xer = yield from get_dmi(dmi, DBGCore.XER)
-                print("after test %s XER value %x" % (test.name, xer))
+                    # test of dmi reg get
+                    for int_reg in range(32):
+                        yield from set_dmi(hdlrun.dmi, DBGCore.GSPR_IDX, int_reg)
+                        value = yield from get_dmi(hdlrun.dmi, DBGCore.GSPR_DATA)
 
-                # test of dmi reg get
-                for int_reg in range(32):
-                    yield from set_dmi(dmi, DBGCore.GSPR_IDX, int_reg)
-                    value = yield from get_dmi(dmi, DBGCore.GSPR_DATA)
+                        print("after test %s reg %2d value %x" %
+                              (test.name, int_reg, value))
 
-                    print("after test %s reg %2d value %x" %
-                          (test.name, int_reg, value))
+                    # pull a reset
+                    yield from set_dmi(hdlrun.dmi, DBGCore.CTRL, 1<<DBGCtrl.RESET)
+                    yield
 
-                # pull a reset
-                yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.RESET)
-                yield
+        ###### END OF EVERYTHING (but none needs doing, still call fn) #######
+        # StateRunner.cleanup()
 
         styles = {
             'dec': {'base': 'dec'},