cpu/rocket, soc_sdram: Connect mem_axi to LiteDRAM, bypass WB bus
authorGabriel Somlo <gsomlo@gmail.com>
Wed, 30 Oct 2019 14:37:17 +0000 (10:37 -0400)
committerGabriel Somlo <gsomlo@gmail.com>
Fri, 1 Nov 2019 12:52:39 +0000 (08:52 -0400)
Connect Rocket's dedicated port for cached RAM accesses (mem_axi)
directly to the LiteDRAM data port, bypassing the shared LiteX
(Wishbone) bus.

When both Rocket's mem_axi and LiteDRAM's port have the same data
width, use a native point-to-point AXI connection.

Otherwise, convert both ends to Wishbone, and use the Wishbone
data width converter to bridge the gap.
FIXME: In the future, this part should be replaced with a native
AXI data width converter!

Signed-off-by: Gabriel Somlo <gsomlo@gmail.com>
litex/soc/cores/cpu/rocket/core.py
litex/soc/integration/soc_sdram.py

index 2fa220a9811f20b886afbc59fdeb8ce644081c41..a7fe578a0c60d56abf864b488f086340b785726b 100644 (file)
@@ -88,10 +88,9 @@ class RocketRV64(CPU):
         self.mem_axi   =  mem_axi = axi.AXIInterface(data_width=64, address_width=32, id_width=4)
         self.mmio_axi  = mmio_axi = axi.AXIInterface(data_width=64, address_width=32, id_width=4)
 
-        self.mem_wb    =  mem_wb = wishbone.Interface(data_width=64, adr_width=29)
         self.mmio_wb   = mmio_wb = wishbone.Interface(data_width=64, adr_width=29)
 
-        self.buses     = [mem_wb, mmio_wb]
+        self.buses     = [mmio_wb]
 
         # # #
 
@@ -207,14 +206,11 @@ class RocketRV64(CPU):
         )
 
         # adapt axi interfaces to wishbone
-        mem_a2w  = ResetInserter()(axi.AXI2Wishbone(mem_axi, mem_wb, base_address=0))
-        mmio_a2w = ResetInserter()(axi.AXI2Wishbone(mmio_axi, mmio_wb, base_address=0))
         # NOTE: AXI2Wishbone FSMs must be reset with the CPU!
-        self.comb += [
-            mem_a2w.reset.eq( ResetSignal() | self.reset),
-            mmio_a2w.reset.eq(ResetSignal() | self.reset),
-        ]
-        self.submodules += mem_a2w, mmio_a2w
+        mmio_a2w = ResetInserter()(axi.AXI2Wishbone(mmio_axi, mmio_wb,
+                                                    base_address=0))
+        self.comb += mmio_a2w.reset.eq(ResetSignal() | self.reset)
+        self.submodules += mmio_a2w
 
         # add verilog sources
         self.add_sources(platform, variant)
index b373c8342be26a662fcea6cd883683abe519d567..f16e596ad0e736c07ff4625990f4b8e9fe5fac54 100644 (file)
@@ -11,6 +11,7 @@ from litex.soc.interconnect import wishbone
 from litex.soc.integration.soc_core import *
 
 from litedram.frontend.wishbone import *
+from litedram.frontend.axi import *
 from litedram.core import LiteDRAMCore
 
 __all__ = ["SoCSDRAM", "soc_sdram_args", "soc_sdram_argdict"]
@@ -52,18 +53,39 @@ class SoCSDRAM(SoCCore):
             clk_freq        = self.clk_freq,
             **kwargs)
 
-        # SoC <--> L2 Cache <--> LiteDRAM ----------------------------------------------------------
-        if self.with_wishbone:
-            # LiteDRAM port ------------------------------------------------------------------------
-            port = self.sdram.crossbar.get_port()
-            port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2
-
-            # Parameters ---------------------------------------------------------------------------
-            main_ram_size = 2**(geom_settings.bankbits +
-                                geom_settings.rowbits +
-                                geom_settings.colbits)*phy.settings.databits//8
-            main_ram_size = min(main_ram_size, 0x20000000) # FIXME: limit to 512MB for now
-
+        # LiteDRAM port ------------------------------------------------------------------------
+        port = self.sdram.crossbar.get_port()
+        port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2
+
+        # Main RAM size ------------------------------------------------------------------------
+        main_ram_size = 2**(geom_settings.bankbits +
+                            geom_settings.rowbits +
+                            geom_settings.colbits)*phy.settings.databits//8
+        main_ram_size = min(main_ram_size, 0x20000000) # FIXME: limit to 512MB for now
+
+        # SoC [<--> L2 Cache] <--> LiteDRAM ----------------------------------------------------
+        if self.cpu.name == "rocket":
+            # Rocket has its own I/D L1 cache: connect directly to LiteDRAM, also bypassing MMIO/CSR wb bus:
+            if port.data_width == self.cpu.mem_axi.data_width:
+                # straightforward AXI link, no data_width conversion needed:
+                self.submodules += LiteDRAMAXI2Native(self.cpu.mem_axi, port,
+                                                      base_address=self.mem_map["main_ram"])
+            else:
+                # FIXME: replace WB data-width converter with native AXI converter!!!
+                mem_wb  = wishbone.Interface(data_width=self.cpu.mem_axi.data_width,
+                                             adr_width=32-log2_int(self.cpu.mem_axi.data_width//8))
+                # NOTE: AXI2Wishbone FSMs must be reset with the CPU!
+                mem_a2w = ResetInserter()(AXI2Wishbone(self.cpu.mem_axi, mem_wb, base_address=0))
+                self.comb += mem_a2w.reset.eq(ResetSignal() | self.cpu.reset)
+                self.submodules += mem_a2w
+                litedram_wb = wishbone.Interface(port.data_width)
+                self.submodules += LiteDRAMWishbone2Native(litedram_wb, port,
+                                                           base_address=self.mem_map["main_ram"])
+                self.submodules += wishbone.Converter(mem_wb, litedram_wb)
+            # Register main_ram region (so it will be added to generated/mem.h):
+            self.add_memory_region("main_ram", self.mem_map["main_ram"], main_ram_size)
+        elif self.with_wishbone:
+            # Insert L2 cache inbetween Wishbone bus and LiteDRAM
             l2_size = max(self.l2_size, int(2*port.data_width/8)) # L2 has a minimal size, use it if lower
             l2_size = 2**int(log2(l2_size))                       # Round to nearest power of 2