add openocd.cfg experiment
[soc.git] / src / soc / debug / dmi.py
index 102afab23d12ad28a4552802d1b03c594e8fd204..39ea799b4da63acddc2081818c2eb0e853327968 100644 (file)
@@ -10,18 +10,21 @@ from nmigen import Elaboratable, Module, Signal, Cat, Const, Record, Array, Mux
 from nmutil.iocontrol import RecordObject
 from nmigen.utils import log2_int
 from nmigen.cli import rtlil
+from soc.config.state import CoreState
 
 
 # DMI register addresses
 class DBGCore:
-    CTRL           = 0b0000
-    STAT           = 0b0001
-    NIA            = 0b0010 # NIA register (read only for now)
-    MSR            = 0b0011 # MSR (read only)
-    GSPR_INDEX     = 0b0100 # GSPR register index
-    GSPR_DATA      = 0b0101 # GSPR register data
-    LOG_ADDR       = 0b0110 # Log buffer address register
-    LOG_DATA       = 0b0111 # Log buffer data register
+    CTRL         = 0b0000
+    STAT         = 0b0001
+    NIA          = 0b0010 # NIA register (read only for now)
+    MSR          = 0b0011 # MSR (read only)
+    GSPR_IDX     = 0b0100 # GSPR register index
+    GSPR_DATA    = 0b0101 # GSPR register data
+    LOG_ADDR     = 0b0110 # Log buffer address register
+    LOG_DATA     = 0b0111 # Log buffer data register
+    CR           = 0b1000 # CR (read only)
+    XER          = 0b1001 # XER (read only) - note this is a TEMPORARY hack
 
 
 # CTRL register (direct actions, write 1 to act, read back 0)
@@ -49,15 +52,40 @@ class DBGStat:
 
 
 class DMIInterface(RecordObject):
-    def __init__(self, name):
+    def __init__(self, name=None):
         super().__init__(name=name)
         self.addr_i = Signal(4)   # DMI register address
-        self.din    = Signal(64)  # DMI data in (if we=1)
-        self.dout   = Signal(64)  # DMI data out (if we=0)
+        self.din    = Signal(64)  # DMI data write in (if we=1)
+        self.dout   = Signal(64)  # DMI data read out (if we=0)
         self.req_i  = Signal()    # DMI request valid (stb)
         self.we_i   = Signal()    # DMI write-enable
         self.ack_o  = Signal()    # DMI ack request
 
+    def connect_to(self, other):
+        return [self.addr_i.eq(other.addr_i),
+                self.req_i.eq(other.req_i),
+                self.we_i.eq(other.we_i),
+                self.din.eq(other.din),
+                other.ack_o.eq(self.ack_o),
+                other.dout.eq(self.dout),
+                ]
+
+class DbgReg(RecordObject):
+    def __init__(self, name):
+        super().__init__(name=name)
+        self.req     = Signal()
+        self.ack     = Signal()
+        self.addr    = Signal(7) #  includes fast SPRs, others?
+        self.data    = Signal(64)
+
+
+class DbgCRReg(RecordObject):
+    def __init__(self, name):
+        super().__init__(name=name)
+        self.req     = Signal()
+        self.ack     = Signal()
+        self.data    = Signal(32)
+
 
 class CoreDebug(Elaboratable):
     def __init__(self, LOG_LENGTH=0): # TODO - debug log 512):
@@ -73,14 +101,16 @@ class CoreDebug(Elaboratable):
         # Core status inputs
         self.terminate_i    = Signal()
         self.core_stopped_i = Signal()
-        self.nia            = Signal(64)
-        self.msr            = Signal(64)
+        self.state = CoreState("core_dbg")
 
         # GSPR register read port
-        self.dbg_gpr_req_o     = Signal()
-        self.dbg_gpr_ack_i     = Signal()
-        self.dbg_gpr_addr_o    = Signal(7) #  includes fast SPRs, others?
-        self.dbg_gpr_data_i    = Signal(64)
+        self.d_gpr = DbgReg("d_gpr")
+
+        # CR register read port
+        self.d_cr = DbgReg("d_cr")
+
+        # XER register read port
+        self.d_xer = DbgReg("d_xer")
 
         # Core logging data
         self.log_data_i        = Signal(256)
@@ -95,6 +125,7 @@ class CoreDebug(Elaboratable):
 
         m = Module()
         comb, sync = m.d.comb, m.d.sync
+        dmi, d_gpr, d_cr, d_xer, = self.dmi, self.d_gpr, self.d_cr, self.d_xer
 
         # DMI needs fixing... make a one clock pulse
         dmi_req_i_1 = Signal()
@@ -109,7 +140,7 @@ class CoreDebug(Elaboratable):
         do_icreset   = Signal()
         terminated   = Signal()
         do_gspr_rd   = Signal()
-        gspr_index   = Signal.like(self.dbg_gpr_addr_o)
+        gspr_index   = Signal.like(d_gpr.addr)
 
         log_dmi_addr = Signal(32)
         log_dmi_data = Signal(64)
@@ -120,10 +151,18 @@ class CoreDebug(Elaboratable):
         LOG_INDEX_BITS = log2_int(self.LOG_LENGTH)
 
         # Single cycle register accesses on DMI except for GSPR data
-        comb += self.dmi.ack_o.eq(Mux(self.dmi.addr_i == DBGCore.GSPR_DATA,
-                                      self.dbg_gpr_ack_i, self.dmi.req_i))
-        comb += self.dbg_gpr_req_o.eq(Mux(self.dmi.addr_i == DBGCore.GSPR_DATA,
-                                      self.dmi.req_i, 0))
+        with m.Switch(dmi.addr_i):
+            with m.Case(DBGCore.GSPR_DATA):
+                comb += dmi.ack_o.eq(d_gpr.ack)
+                comb += d_gpr.req.eq(dmi.req_i)
+            with m.Case(DBGCore.CR):
+                comb += dmi.ack_o.eq(d_cr.ack)
+                comb += d_cr.req.eq(dmi.req_i)
+            with m.Case(DBGCore.XER):
+                comb += dmi.ack_o.eq(d_xer.ack)
+                comb += d_xer.req.eq(dmi.req_i)
+            with m.Default():
+                comb += dmi.ack_o.eq(dmi.req_i)
 
         # Status register read composition (DBUG_CORE_STAT_xxx)
         comb += stat_reg.eq(Cat(stopping,            # bit 0
@@ -131,20 +170,23 @@ class CoreDebug(Elaboratable):
                                 terminated))         # bit 2
 
         # DMI read data mux
-        with m.Switch(self.dmi.addr_i):
+        with m.Switch(dmi.addr_i):
             with m.Case( DBGCore.STAT):
-                comb += self.dmi.dout.eq(stat_reg)
+                comb += dmi.dout.eq(stat_reg)
             with m.Case( DBGCore.NIA):
-                comb += self.dmi.dout.eq(self.nia)
+                comb += dmi.dout.eq(self.state.pc)
             with m.Case( DBGCore.MSR):
-                comb += self.dmi.dout.eq(self.msr)
+                comb += dmi.dout.eq(self.state.msr)
             with m.Case( DBGCore.GSPR_DATA):
-                comb += self.dmi.dout.eq(self.dbg_gpr_data_i)
+                comb += dmi.dout.eq(d_gpr.data)
             with m.Case( DBGCore.LOG_ADDR):
-                comb += self.dmi.dout.eq(Cat(log_dmi_addr,
-                                             self.log_write_addr_o))
+                comb += dmi.dout.eq(Cat(log_dmi_addr, self.log_write_addr_o))
             with m.Case( DBGCore.LOG_DATA):
-                comb += self.dmi.dout.eq(log_dmi_data)
+                comb += dmi.dout.eq(log_dmi_data)
+            with m.Case(DBGCore.CR):
+                comb += dmi.dout.eq(d_cr.data)
+            with m.Case(DBGCore.XER):
+                comb += dmi.dout.eq(d_xer.data)
 
         # DMI writes
         # Reset the 1-cycle "do" signals
@@ -154,36 +196,36 @@ class CoreDebug(Elaboratable):
         sync += do_dmi_log_rd.eq(0)
 
         # Edge detect on dmi_req_i for 1-shot pulses
-        sync += dmi_req_i_1.eq(self.dmi.req_i)
-        with m.If(self.dmi.req_i & ~dmi_req_i_1):
-            with m.If(self.dmi.we_i):
+        sync += dmi_req_i_1.eq(dmi.req_i)
+        with m.If(dmi.req_i & ~dmi_req_i_1):
+            with m.If(dmi.we_i):
                 #sync += Display("DMI write to " & to_hstring(dmi_addr))
 
                 # Control register actions
 
                 # Core control
-                with m.If(self.dmi.addr_i == DBGCore.CTRL):
-                    with m.If(self.dmi.din[DBGCtrl.RESET]):
+                with m.If(dmi.addr_i == DBGCore.CTRL):
+                    with m.If(dmi.din[DBGCtrl.RESET]):
                         sync += do_reset.eq(1)
                         sync += terminated.eq(0)
-                    with m.If(self.dmi.din[DBGCtrl.STOP]):
+                    with m.If(dmi.din[DBGCtrl.STOP]):
                         sync += stopping.eq(1)
-                    with m.If(self.dmi.din[DBGCtrl.STEP]):
+                    with m.If(dmi.din[DBGCtrl.STEP]):
                         sync += do_step.eq(1)
                         sync += terminated.eq(0)
-                    with m.If(self.dmi.din[DBGCtrl.ICRESET]):
+                    with m.If(dmi.din[DBGCtrl.ICRESET]):
                         sync += do_icreset.eq(1)
-                    with m.If(self.dmi.din[DBGCtrl.START]):
+                    with m.If(dmi.din[DBGCtrl.START]):
                         sync += stopping.eq(0)
                         sync += terminated.eq(0)
 
                 # GSPR address
-                with m.Elif(self.dmi.addr_i == DBGCore.GSPR_INDEX):
-                    sync += gspr_index.eq(self.dmi.din)
+                with m.Elif(dmi.addr_i == DBGCore.GSPR_IDX):
+                    sync += gspr_index.eq(dmi.din)
 
                 # Log address
-                with m.Elif(self.dmi.addr_i == DBGCore.LOG_ADDR):
-                    sync += log_dmi_addr.eq(self.dmi.din)
+                with m.Elif(dmi.addr_i == DBGCore.LOG_ADDR):
+                    sync += log_dmi_addr.eq(dmi.din)
                     sync += do_dmi_log_rd.eq(1)
             with m.Else():
                 # sync += Display("DMI read from " & to_string(dmi_addr))
@@ -196,8 +238,8 @@ class CoreDebug(Elaboratable):
             sync += do_dmi_log_rd.eq(1)
 
         sync += dmi_read_log_data_1.eq(dmi_read_log_data)
-        sync += dmi_read_log_data.eq(self.dmi.req_i &
-                                     (self.dmi.addr_i == DBGCore.LOG_DATA))
+        sync += dmi_read_log_data.eq(dmi.req_i &
+                                     (dmi.addr_i == DBGCore.LOG_DATA))
 
         # Set core stop on terminate. We'll be stopping some time *after*
         # the offending instruction, at least until we can do back flushes
@@ -206,7 +248,7 @@ class CoreDebug(Elaboratable):
             sync += stopping.eq(1)
             sync += terminated.eq(1)
 
-        comb += self.dbg_gpr_addr_o.eq(gspr_index)
+        comb += d_gpr.addr.eq(gspr_index)
 
         # Core control signals generated by the debug module
         comb += self.core_stop_o.eq(stopping & ~do_step)
@@ -307,12 +349,10 @@ class CoreDebug(Elaboratable):
         yield self.icache_rst_o
         yield self.terminate_i
         yield self.core_stopped_i
-        yield self.nia
-        yield self.msr
-        yield self.dbg_gpr_req_o
-        yield self.dbg_gpr_ack_i
-        yield self.dbg_gpr_addr_o
-        yield self.dbg_gpr_data_i
+        yield from self.state
+        yield from self.d_gpr
+        yield from self.d_cr
+        yield from self.d_xer
         yield self.log_data_i
         yield self.log_read_addr_i
         yield self.log_read_data_o