argh, reading regfile over DMI was overlapped and corrupting reg 0
[soc.git] / src / soc / litex / florent / sim.py
index 042c31be10eb83cdd11f3f1431683378c184986d..688fde4b67dfdf1d46eb579ff99eb22b58baf198 100755 (executable)
@@ -14,6 +14,7 @@ from litex.soc.integration.soc import SoCRegion
 from litex.soc.integration.soc_core import SoCCore
 from litex.soc.integration.soc_sdram import SoCSDRAM
 from litex.soc.integration.builder import Builder
+from litex.soc.integration.common import get_mem_data
 
 from litedram import modules as litedram_modules
 from litedram.phy.model import SDRAMPHYModel
@@ -28,35 +29,68 @@ from microwatt import Microwatt
 
 class LibreSoCSim(SoCSDRAM):
     def __init__(self, cpu="libresoc", debug=False, with_sdram=True,
-            #sdram_module          = "AS4C16M16",
+            sdram_module          = "AS4C16M16",
             #sdram_data_width      = 16,
-            sdram_module          = "MT48LC16M16",
-            sdram_data_width      = 32,
+            #sdram_module          = "MT48LC16M16",
+            sdram_data_width      = 16,
             ):
         assert cpu in ["libresoc", "microwatt"]
         platform     = Platform()
         sys_clk_freq = int(100e6)
 
+        #cpu_data_width = 32
+        cpu_data_width = 64
+
+        if cpu_data_width == 32:
+            variant = "standard32"
+        else:
+            variant = "standard"
+
+        #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
+        #            "hello_world/hello_world.bin"
+        ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
+                    "tests/1.bin"
+        #ram_fname = None
+
+        ram_init = []
+        if ram_fname:
+            #ram_init = get_mem_data({
+            #    ram_fname:       "0x00000000",
+            #    }, "little")
+            ram_init = get_mem_data(ram_fname, "little")
+
+            # remap the main RAM to reset-start-address
+            self.mem_map["main_ram"] = 0x00000000
+
+            # without sram nothing works, therefore move it to higher up
+            self.mem_map["sram"] = 0x90000000
+
+
         # SoCCore -------------------------------------------------------------
         SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
             cpu_type                 = "microwatt",
             cpu_cls                  = LibreSoC   if cpu == "libresoc" \
                                        else Microwatt,
             #bus_data_width           = 64,
+            cpu_variant              = variant,
+            csr_data_width            = 32,
+            l2_size             = 0,
             uart_name                = "sim",
             with_sdram               = with_sdram,
             sdram_module          = sdram_module,
             sdram_data_width      = sdram_data_width,
-            integrated_rom_size      = 0x10000,
+            integrated_rom_size      = 0 if ram_fname else 0x10000,
+            integrated_sram_size     = 0x40000,
+            #integrated_main_ram_init  = ram_init,
             integrated_main_ram_size = 0x00000000 if with_sdram \
                                         else 0x10000000 , # 256MB
-            ) 
+            )
         self.platform.name = "sim"
 
         # CRG -----------------------------------------------------------------
         self.submodules.crg = CRG(platform.request("sys_clk"))
 
-        ram_init = []
+        #ram_init = []
 
         # SDRAM ----------------------------------------------------
         if with_sdram:
@@ -78,9 +112,12 @@ class LibreSoCSim(SoCSDRAM):
                             sdram_module.geom_settings,
                             sdram_module.timing_settings)
             # FIXME: skip memtest to avoid corrupting memory
-            self.add_constant("MEMTEST_BUS_SIZE",  64//16)
-            self.add_constant("MEMTEST_DATA_SIZE", 64//16)
-            self.add_constant("MEMTEST_ADDR_SIZE", 64//16)
+            self.add_constant("MEMTEST_BUS_SIZE",  128//16)
+            self.add_constant("MEMTEST_DATA_SIZE", 128//16)
+            self.add_constant("MEMTEST_ADDR_SIZE", 128//16)
+            self.add_constant("MEMTEST_BUS_DEBUG", 1)
+            self.add_constant("MEMTEST_ADDR_DEBUG", 1)
+            self.add_constant("MEMTEST_DATA_DEBUG", 1)
 
 
         # Debug ---------------------------------------------------------------
@@ -99,12 +136,19 @@ class LibreSoCSim(SoCSDRAM):
         dbg_dout = Signal(64)
         dbg_msg = Signal(1)
 
-        uptime = Signal(64)
+        # capture pc from dmi
+        pc = Signal(64)
+        active_dbg = Signal()
+
         # increment counter, Stop after 100000 cycles
         uptime = Signal(64)
         self.sync += uptime.eq(uptime + 1)
-        self.sync += If(uptime == 100000, Finish())
+        #self.sync += If(uptime == 1000000000000, Finish())
 
+        # DMI FSM counter and FSM itself
+        dmicount = Signal(10)
+        dmirunning = Signal(1)
+        dmi_monitor = Signal(1)
         dmifsm = FSM()
         self.submodules += dmifsm
 
@@ -126,36 +170,63 @@ class LibreSoCSim(SoCSDRAM):
                  self.cpu.dmi_req.eq(1),    # DMI request
                  self.cpu.dmi_wr.eq(0),    # DMI read
                  If(self.cpu.dmi_ack,
+                    # acknowledge received: capture data.
                     (NextState("IDLE"),
                      NextValue(dbg_addr, dmi_addr),
                      NextValue(dbg_dout, self.cpu.dmi_dout),
                      NextValue(dbg_msg, 1),
-                    )
+                    ),
                  ),
                 ),
             )
         )
 
+        # DMI response received: reset the dmi request and check if
+        # in "monitor" mode
         dmifsm.act("IDLE",
-            (NextValue(dmi_req, 0),
-             NextValue(dmi_addr, 0),
+            If(dmi_monitor,
+                 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
+            ).Else(
+                 NextState("START"), # back to start on next cycle
+            ),
+            NextValue(dmi_req, 0),
+            NextValue(dmi_addr, 0),
+            NextValue(dmi_din, 0),
+            NextValue(dmi_wen, 0),
+        )
+
+        # "monitor" mode fires off a STAT request
+        dmifsm.act("FIRE_MONITOR",
+            (NextValue(dmi_req, 1),
+             NextValue(dmi_addr, 1), # DMI STAT address
              NextValue(dmi_din, 0),
-             NextValue(dmi_wen, 0),
+             NextValue(dmi_wen, 0), # read STAT
              NextState("START"), # back to start on next cycle
             )
         )
 
         # debug messages out
         self.sync += If(dbg_msg,
-            (If(dbg_addr == 0b10, # PC
+            (If(active_dbg & (dbg_addr == 0b10), # PC
                 Display("pc : %016x", dbg_dout),
              ),
-             If(dbg_addr == 0b11, # PC
-                Display("    msr: %016x", dbg_dout),
+             If(dbg_addr == 0b10, # PC
+                 pc.eq(dbg_dout),     # capture PC
              ),
+             #If(dbg_addr == 0b11, # MSR
+             #   Display("    msr: %016x", dbg_dout),
+             #),
              If(dbg_addr == 0b101, # GPR
                 Display("    gpr: %016x", dbg_dout),
              ),
+            # also check if this is a "stat"
+            If(dbg_addr == 1, # requested a STAT
+                #Display("    stat: %x", dbg_dout),
+                If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
+                     dmirunning.eq(1), # continue running
+                     dmi_monitor.eq(0), # and stop monitor mode
+                ),
+            ),
              dbg_msg.eq(0)
             )
         )
@@ -169,11 +240,19 @@ class LibreSoCSim(SoCSDRAM):
             )
         )
 
+        self.sync += If(uptime == 4,
+             dmirunning.eq(1),
+        )
+
+        self.sync += If(dmirunning,
+             dmicount.eq(dmicount + 1),
+        )
+
         # loop every 1<<N cycles
         cyclewid = 9
 
         # get the PC
-        self.sync += If(uptime[0:cyclewid] == 4,
+        self.sync += If(dmicount == 4,
             (dmi_addr.eq(0b10), # NIA
              dmi_req.eq(1),
              dmi_wen.eq(0),
@@ -181,16 +260,23 @@ class LibreSoCSim(SoCSDRAM):
         )
 
         # kick off a "step"
-        self.sync += If(uptime[0:cyclewid] == 8,
+        self.sync += If(dmicount == 8,
             (dmi_addr.eq(0), # CTRL
              dmi_din.eq(1<<3), # STEP
              dmi_req.eq(1),
              dmi_wen.eq(1),
+             dmirunning.eq(0), # stop counter, need to fire "monitor"
+             dmi_monitor.eq(1), # start "monitor" instead
             )
         )
 
+        # limit range of pc for debug reporting
+        #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
+        #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
+        self.comb += active_dbg.eq(1)
+
         # get the MSR
-        self.sync += If(uptime[0:cyclewid] == 28,
+        self.sync += If(active_dbg & (dmicount == 12),
             (dmi_addr.eq(0b11), # MSR
              dmi_req.eq(1),
              dmi_wen.eq(0),
@@ -199,7 +285,7 @@ class LibreSoCSim(SoCSDRAM):
 
         # read all 32 GPRs
         for i in range(32):
-            self.sync += If(uptime[0:cyclewid] == 30+(i*8),
+            self.sync += If(active_dbg & (dmicount == 16+(i*8)),
                 (dmi_addr.eq(0b100), # GSPR addr
                  dmi_din.eq(i), # r1
                  dmi_req.eq(1),
@@ -207,46 +293,51 @@ class LibreSoCSim(SoCSDRAM):
                 )
             )
 
-            self.sync += If(uptime[0:cyclewid] == 34+(i*8),
+            self.sync += If(active_dbg & (dmicount == 20+(i*8)),
                 (dmi_addr.eq(0b101), # GSPR data
                  dmi_req.eq(1),
                  dmi_wen.eq(0),
                 )
             )
 
+        # monitor bbus read/write
+        self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
+            Display("    [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
+                #uptime,
+                0,
+                self.cpu.dbus.adr,
+                self.cpu.dbus.we,
+                self.cpu.dbus.sel,
+                self.cpu.dbus.dat_w,
+                self.cpu.dbus.dat_r
+            )
+        )
+
+        return
+
         # monitor ibus write
-        self.sync += If(self.cpu.ibus.stb & self.cpu.ibus.ack &
+        self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
                         self.cpu.ibus.we,
             Display("    [%06x] iadr: %8x, s %01x w %016x",
-                uptime,
+                #uptime,
+                0,
                 self.cpu.ibus.adr,
                 self.cpu.ibus.sel,
                 self.cpu.ibus.dat_w,
             )
         )
         # monitor ibus read
-        self.sync += If(self.cpu.ibus.stb & self.cpu.ibus.ack &
+        self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
                         ~self.cpu.ibus.we,
             Display("    [%06x] iadr: %8x, s %01x r %016x",
-                uptime,
+                #uptime,
+                0,
                 self.cpu.ibus.adr,
                 self.cpu.ibus.sel,
                 self.cpu.ibus.dat_r
             )
         )
 
-        # monitor bbus read/write
-        self.sync += If(self.cpu.dbus.stb & self.cpu.dbus.ack,
-            Display("    [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
-                uptime,
-                self.cpu.dbus.adr,
-                self.cpu.dbus.we,
-                self.cpu.dbus.sel,
-                self.cpu.dbus.dat_w,
-                self.cpu.dbus.dat_r
-            )
-        )
-
 # Build -----------------------------------------------------------------------
 
 def main():