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 <gsomlo@gmail.com>
This commit is contained in:
Gabriel Somlo 2019-10-30 10:37:17 -04:00
parent 9c3c43c94a
commit ec831f5b63
2 changed files with 37 additions and 19 deletions

View 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.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.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.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 # 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! # NOTE: AXI2Wishbone FSMs must be reset with the CPU!
self.comb += [ mmio_a2w = ResetInserter()(axi.AXI2Wishbone(mmio_axi, mmio_wb,
mem_a2w.reset.eq( ResetSignal() | self.reset), base_address=0))
mmio_a2w.reset.eq(ResetSignal() | self.reset), self.comb += mmio_a2w.reset.eq(ResetSignal() | self.reset)
] self.submodules += mmio_a2w
self.submodules += mem_a2w, mmio_a2w
# add verilog sources # add verilog sources
self.add_sources(platform, variant) self.add_sources(platform, variant)

View File

@ -11,6 +11,7 @@ from litex.soc.interconnect import wishbone
from litex.soc.integration.soc_core import * from litex.soc.integration.soc_core import *
from litedram.frontend.wishbone import * from litedram.frontend.wishbone import *
from litedram.frontend.axi import *
from litedram.core import LiteDRAMCore from litedram.core import LiteDRAMCore
__all__ = ["SoCSDRAM", "soc_sdram_args", "soc_sdram_argdict"] __all__ = ["SoCSDRAM", "soc_sdram_args", "soc_sdram_argdict"]
@ -52,18 +53,39 @@ class SoCSDRAM(SoCCore):
clk_freq = self.clk_freq, clk_freq = self.clk_freq,
**kwargs) **kwargs)
# SoC <--> L2 Cache <--> LiteDRAM ----------------------------------------------------------
if self.with_wishbone:
# LiteDRAM port ------------------------------------------------------------------------ # LiteDRAM port ------------------------------------------------------------------------
port = self.sdram.crossbar.get_port() port = self.sdram.crossbar.get_port()
port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2 port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2
# Parameters --------------------------------------------------------------------------- # Main RAM size ------------------------------------------------------------------------
main_ram_size = 2**(geom_settings.bankbits + main_ram_size = 2**(geom_settings.bankbits +
geom_settings.rowbits + geom_settings.rowbits +
geom_settings.colbits)*phy.settings.databits//8 geom_settings.colbits)*phy.settings.databits//8
main_ram_size = min(main_ram_size, 0x20000000) # FIXME: limit to 512MB for now 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 = 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 l2_size = 2**int(log2(l2_size)) # Round to nearest power of 2