add hard stop address in ifetch unit test, bit of a mess:
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 19 Dec 2021 21:26:25 +0000 (21:26 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 19 Dec 2021 21:26:25 +0000 (21:26 +0000)
TestIssuerFSM is just being caught on the edge of attempting to execute
another instruction at a TRAP point

src/soc/simple/issuer.py
src/soc/simple/test/test_issuer_mmu_ifetch.py
src/soc/simple/test/test_runner.py

index 156fce3cdf79ddc786804e6342a49533b12f3397..4629c4ed5f0bb896977c22e08e4c1ee28509b6b9 100644 (file)
@@ -1227,9 +1227,22 @@ class TestIssuerInternal(TestIssuerBase):
 
             # handshake with execution FSM, move to "wait" once acknowledged
             with m.State("INSN_EXECUTE"):
-                comb += exec_insn_i_valid.eq(1)  # trigger execute
-                with m.If(exec_insn_o_ready):   # execute acknowledged us
-                    m.next = "EXECUTE_WAIT"
+                if self.allow_overlap:
+                    stopping = dbg.stopping_o
+                else:
+                    stopping = Const(0)
+                with m.If(stopping):
+                    # stopping: jump back to idle
+                    m.next = "ISSUE_START"
+                    if flush_needed:
+                        # request the icache to stop asserting "failed"
+                        comb += core.icache.flush_in.eq(1)
+                    # stop instruction fault
+                    sync += pdecode2.instr_fault.eq(0)
+                with m.Else():
+                    comb += exec_insn_i_valid.eq(1)  # trigger execute
+                    with m.If(exec_insn_o_ready):   # execute acknowledged us
+                        m.next = "EXECUTE_WAIT"
 
             with m.State("EXECUTE_WAIT"):
                 # wait on "core stop" release, at instruction end
@@ -1324,6 +1337,9 @@ class TestIssuerInternal(TestIssuerBase):
                         comb += core.icache.flush_in.eq(1)
                     # stop instruction fault
                     sync += pdecode2.instr_fault.eq(0)
+                    # if terminated return to idle
+                    with m.If(dbg.terminate_i):
+                        m.next = "ISSUE_START"
 
         # check if svstate needs updating: if so, write it to State Regfile
         with m.If(self.update_svstate):
@@ -1342,6 +1358,7 @@ class TestIssuerInternal(TestIssuerBase):
 
         comb = m.d.comb
         sync = m.d.sync
+        dbg = self.dbg
         pdecode2 = self.pdecode2
 
         # temporaries
@@ -1394,6 +1411,10 @@ class TestIssuerInternal(TestIssuerBase):
                                    ~pdecode2.instr_fault):
                             comb += self.insn_done.eq(1)
                         m.next = "INSN_START"  # back to fetch
+                # terminate returns directly to INSN_START
+                with m.If(dbg.terminate_i):
+                    # comb += self.insn_done.eq(1) - no because it's not
+                    m.next = "INSN_START"  # back to fetch
 
     def elaborate(self, platform):
         m = super().elaborate(platform)
index 5175b7cde40260edec619c5a3e482b22437acf37..4d434c7f67db7ddeae11db7a2e1de1d3da52fa4e 100644 (file)
@@ -39,34 +39,57 @@ from soc.experiment.test import pagetables
 
 class MMUTestCase(TestAccumulatorBase):
 
-    # MMUTEST: initial_msr= 16384
-    # msr 16384
-    # ISACaller initial_msr 16384
-    # FIXME msr does not get passed to LoadStore1
-    def case_5_ldst_exception(self):
-        lst = [#"mtspr 720,1", # mtspr PRTBL,r1
-               "stb 10,0(2)",
+    def cse_virtual_ld_st(self):
+        lst = ["stb 10,0(2)",
                "addi 10,0, -4",
                "stb 10,0(5)",
                "lhz 6,0(2)",
               ]
+
+        # set up regs
         initial_regs = [0] * 32
-        initial_regs[1] = 0x1000000
+        initial_regs[1] = 0x1000000 # hm, was going to do mtspr 720,1 with this
         initial_regs[2] = 0x3456
         initial_regs[3] = 0x4321
         initial_regs[4] = 0x6543
         initial_regs[5] = 0x3457
         initial_regs[10] = 0xfe
+
+        # no pre-loaded memory here
         initial_mem = {}
+
+        # set virtual and non-privileged
         initial_msr = 1 << MSR.PR # must set "problem" state
         initial_msr |= 1 << MSR.DR # set "virtual" state
+
+        # set PRTBL to 0x1000000
         initial_sprs = {720: 0x1000000} # PRTBL
+
         print("MMUTEST: initial_msr=",initial_msr)
         self.add_case(Program(lst, bigendian), initial_regs,
                              initial_mem=initial_mem,
                              initial_sprs=initial_sprs,
                              initial_msr=initial_msr)
 
+    def case_virtual_invalid_no_prtbl(self):
+        """virtual memory test but with no PRTBL set it is expected
+        to throw an "invalid" exception
+        """
+        lst = ["stb 10,0(2)",
+              ]
+
+        # set up regs
+        initial_regs = [0] * 32
+
+        # set virtual and non-privileged
+        initial_msr = 1 << MSR.PR # must set "problem" state
+        initial_msr |= 1 << MSR.DR # set "virtual" state
+
+        print("MMUTEST: initial_msr=",initial_msr)
+        self.add_case(Program(lst, bigendian), initial_regs,
+                             initial_msr=initial_msr,
+                             stop_at_pc=0x400) # stop at this exception addr
+
 if __name__ == "__main__":
     svp64 = True
     if len(sys.argv) == 2:
index e83a39b729ad3be5db70b2f8e5e0abc234a70de9..afc245137b3ccf1bcfbe009c29f61a295cb0b1de 100644 (file)
@@ -269,7 +269,10 @@ class HDLRunner(StateRunner):
         # just after the last instruction. if a load of an instruction is
         # requested at this address, the core is immediately put into "halt"
         # XXX: keep an eye out for in-order problems
-        yield from set_dmi(dmi, DBGCore.STOPADDR, len(instructions)*4)
+        hard_stop_addr = self.test.stop_at_pc
+        if hard_stop_addr is None:
+            hard_stop_addr = len(instructions)*4
+        yield from set_dmi(dmi, DBGCore.STOPADDR, hard_stop_addr)
 
         # run the loop of the instructions on the current test
         index = (yield self.issuer.cur_state.pc) // 4
@@ -292,7 +295,8 @@ class HDLRunner(StateRunner):
             counter = counter + 1
 
             # wait until executed
-            while not (yield self.issuer.insn_done):
+            while not ((yield self.issuer.insn_done) or
+                       (yield self.issuer.dbg.terminated_o)):
                 yield
 
             # okaaay long story: in overlap mode, PC is updated one cycle