Re-enable core stopped signal when stopped.
[soc.git] / src / soc / simple / issuer.py
index 156fce3cdf79ddc786804e6342a49533b12f3397..6da1610ce25a487d4014287d8dfb76ae12b51122 100644 (file)
@@ -713,13 +713,15 @@ class FetchFSM(ControlBase):
         # set priv / virt mode on I-Cache, sigh
         if isinstance(self.imem, ICache):
             comb += self.imem.i_in.priv_mode.eq(~msr[MSR.PR])
-            comb += self.imem.i_in.virt_mode.eq(msr[MSR.DR])
+            comb += self.imem.i_in.virt_mode.eq(msr[MSR.IR]) # Instr. Redir (VM)
 
         with m.FSM(name='fetch_fsm'):
 
             # waiting (zzz)
             with m.State("IDLE"):
-                with m.If(~dbg.stopping_o & ~fetch_failed & ~dbg.core_stop_o):
+                # fetch allowed if not failed and stopped but not stepping
+                # (see dmi.py for how core_stop_o is generated)
+                with m.If(~fetch_failed & ~dbg.core_stop_o):
                     comb += fetch_pc_o_ready.eq(1)
                 with m.If(fetch_pc_i_valid & ~pdecode2.instr_fault
                           & ~dbg.core_stop_o):
@@ -739,10 +741,11 @@ class FetchFSM(ControlBase):
 
             # dummy pause to find out why simulation is not keeping up
             with m.State("INSN_READ"):
-                if self.allow_overlap:
-                    stopping = dbg.stopping_o
-                else:
-                    stopping = Const(0)
+                # when using "single-step" mode, checking dbg.stopping_o
+                # prevents progress.  allow fetch to proceed once started
+                stopping = Const(0)
+                #if self.allow_overlap:
+                #    stopping = dbg.stopping_o
                 with m.If(stopping):
                     # stopping: jump back to idle
                     m.next = "IDLE"
@@ -750,6 +753,7 @@ class FetchFSM(ControlBase):
                     with m.If(self.imem.f_busy_o &
                               ~pdecode2.instr_fault):  # zzz...
                         # busy but not fetch failed: stay in wait-read
+                        comb += self.imem.a_pc_i.eq(pc)
                         comb += self.imem.a_i_valid.eq(1)
                         comb += self.imem.f_i_valid.eq(1)
                     with m.Else():
@@ -800,7 +804,11 @@ class FetchFSM(ControlBase):
                     comb += self.imem.f_i_valid.eq(1)
                 with m.Else():
                     # not busy: instruction fetched
-                    insn = get_insn(self.imem.f_instr_o, cur_state.pc+4)
+                    if hasattr(core, "icache"):
+                        # blech, icache returns actual instruction
+                        insn = self.imem.f_instr_o
+                    else:
+                        insn = get_insn(self.imem.f_instr_o, cur_state.pc+4)
                     sync += dec_opcode_o.eq(insn)
                     m.next = "INSN_READY"
                     # TODO: probably can start looking at pdecode2.rm_dec
@@ -1089,10 +1097,11 @@ class TestIssuerInternal(TestIssuerBase):
 
             # wait for an instruction to arrive from Fetch
             with m.State("INSN_WAIT"):
-                if self.allow_overlap:
-                    stopping = dbg.stopping_o
-                else:
-                    stopping = Const(0)
+                # when using "single-step" mode, checking dbg.stopping_o
+                # prevents progress.  allow issue to proceed once started
+                stopping = Const(0)
+                #if self.allow_overlap:
+                #    stopping = dbg.stopping_o
                 with m.If(stopping):
                     # stopping: jump back to idle
                     m.next = "ISSUE_START"
@@ -1227,9 +1236,23 @@ 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"
+                # when using "single-step" mode, checking dbg.stopping_o
+                # prevents progress.  allow execute to proceed once started
+                stopping = Const(0)
+                #if self.allow_overlap:
+                #    stopping = dbg.stopping_o
+                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 +1347,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 +1368,7 @@ class TestIssuerInternal(TestIssuerBase):
 
         comb = m.d.comb
         sync = m.d.sync
+        dbg = self.dbg
         pdecode2 = self.pdecode2
 
         # temporaries
@@ -1394,6 +1421,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)