From ec831f5b631771c660109d2ae8ed9f1b67fc094f Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Wed, 30 Oct 2019 10:37:17 -0400 Subject: [PATCH 1/3] cpu/rocket, soc_sdram: Connect mem_axi to LiteDRAM, bypass WB bus 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 --- litex/soc/cores/cpu/rocket/core.py | 14 ++++------ litex/soc/integration/soc_sdram.py | 42 +++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/litex/soc/cores/cpu/rocket/core.py b/litex/soc/cores/cpu/rocket/core.py index 2fa220a98..a7fe578a0 100644 --- a/litex/soc/cores/cpu/rocket/core.py +++ b/litex/soc/cores/cpu/rocket/core.py @@ -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) diff --git a/litex/soc/integration/soc_sdram.py b/litex/soc/integration/soc_sdram.py index b373c8342..f16e596ad 100644 --- a/litex/soc/integration/soc_sdram.py +++ b/litex/soc/integration/soc_sdram.py @@ -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 + # 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 + # 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 From 014db664440525abcf6442ce2493ddcf257025dd Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Thu, 31 Oct 2019 16:23:36 -0400 Subject: [PATCH 2/3] soc_sdram: remove upper limit on usable main RAM Revert commit #68a503174. --- litex/soc/integration/soc_sdram.py | 1 - 1 file changed, 1 deletion(-) diff --git a/litex/soc/integration/soc_sdram.py b/litex/soc/integration/soc_sdram.py index f16e596ad..71f54b177 100644 --- a/litex/soc/integration/soc_sdram.py +++ b/litex/soc/integration/soc_sdram.py @@ -61,7 +61,6 @@ class SoCSDRAM(SoCCore): 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": From 28708f420848294dc17417cb7f24aa9d01447612 Mon Sep 17 00:00:00 2001 From: Gabriel Somlo Date: Fri, 1 Nov 2019 08:45:23 -0400 Subject: [PATCH 3/3] cpu/rocket: parameterize axi interface data width Rocket variants can be configured with axi port data widths that are multiples of the native word size (64 bits in our case). In the future, we will add variants with mem_axi data width > 64 bit, to match the native data width of the LiteDRAM controller on various development boards (e.g., 128 bits on the ecp5versa, and 256 bits on the trellisboard). Signed-off-by: Gabriel Somlo --- litex/soc/cores/cpu/rocket/core.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/litex/soc/cores/cpu/rocket/core.py b/litex/soc/cores/cpu/rocket/core.py index a7fe578a0..1c3899eba 100644 --- a/litex/soc/cores/cpu/rocket/core.py +++ b/litex/soc/cores/cpu/rocket/core.py @@ -50,6 +50,13 @@ GCC_FLAGS = { "full": "-march=rv64imafdc -mabi=lp64 ", } +AXI_DATA_WIDTHS = { + # variant : (mem, mmio) + "standard": ( 64, 64), + "linux": ( 64, 64), + "full": ( 64, 64), +} + class RocketRV64(CPU): name = "rocket" data_width = 64 @@ -85,10 +92,12 @@ class RocketRV64(CPU): self.reset = Signal() self.interrupt = Signal(4) - 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) + mem_dw, mmio_dw = AXI_DATA_WIDTHS[self.variant] - self.mmio_wb = mmio_wb = wishbone.Interface(data_width=64, adr_width=29) + self.mem_axi = mem_axi = axi.AXIInterface(data_width= mem_dw, address_width=32, id_width=4) + self.mmio_axi = mmio_axi = axi.AXIInterface(data_width=mmio_dw, address_width=32, id_width=4) + + self.mmio_wb = mmio_wb = wishbone.Interface(data_width=mmio_dw, adr_width=32-log2_int(mmio_dw//8)) self.buses = [mmio_wb]