add DMI STOPADDR register and use it in HDLRunner to halt simulations
[soc.git] / src / soc / debug / dmi.py
index 8a6686df5c26af6d26052598552d0e7ad3fb4921..8a3aaea504d7aa8290a2da6a54e619190f6f026e 100644 (file)
@@ -26,6 +26,7 @@ class DBGCore:
     CR           = 0b1000 # CR (read only)
     XER          = 0b1001 # XER (read only) - note this is a TEMPORARY hack
     SVSTATE      = 0b1010 # SVSTATE register (read only for now)
+    STOPADDR     = 0b1011 # Address at which the core automatically stops
 
 
 # CTRL register (direct actions, write 1 to act, read back 0)
@@ -120,6 +121,10 @@ class CoreDebug(Elaboratable):
         self.log_read_data_o   = Signal(64)
         self.log_write_addr_o  = Signal(32)
 
+        # address at which the processor stops automatically
+        # set to 0xffffffffffffffff by default (impossible to reach)
+        self.stop_addr_o = Signal(64, reset=-1)
+
         # Misc
         self.terminated_o  = Signal()
 
@@ -191,6 +196,8 @@ class CoreDebug(Elaboratable):
                 comb += dmi.dout.eq(d_cr.data)
             with m.Case(DBGCore.XER):
                 comb += dmi.dout.eq(d_xer.data)
+            with m.Case(DBGCore.STOPADDR):            # Halt PC
+                comb += dmi.dout.eq(self.stop_addr_o)
 
         # DMI writes
         # Reset the 1-cycle "do" signals
@@ -231,6 +238,11 @@ class CoreDebug(Elaboratable):
                 with m.Elif(dmi.addr_i == DBGCore.LOG_ADDR):
                     sync += log_dmi_addr.eq(dmi.din)
                     sync += do_dmi_log_rd.eq(1)
+
+                # set PC Halt address
+                with m.Elif(dmi.addr_i == DBGCore.STOPADDR):
+                    sync += self.stop_addr_o.eq(dmi.din)
+
             with m.Else():
                 # sync += Display("DMI read from " & to_string(dmi_addr))
                 pass
@@ -255,10 +267,10 @@ class CoreDebug(Elaboratable):
         comb += d_gpr.addr.eq(gspr_index)
 
         # Core control signals generated by the debug module
-        comb += self.core_stop_o.eq(stopping & ~do_step)
+        comb += self.core_stop_o.eq((stopping & ~do_step) | self.terminate_i)
         comb += self.core_rst_o.eq(do_reset)
         comb += self.icache_rst_o.eq(do_icreset)
-        comb += self.terminated_o.eq(terminated)
+        comb += self.terminated_o.eq(terminated | self.terminate_i)
 
         # Logging RAM (none)