soc/cpu: add memory_buses to cpus and use them in add_sdram.

This allows the CPU to have direct buses to the memory and replace the Rocket specific code.
This commit is contained in:
Florent Kermarrec 2020-04-27 23:51:17 +02:00
parent 467fee3e23
commit 5ef869b9eb
11 changed files with 81 additions and 43 deletions

View file

@ -26,6 +26,8 @@ class CPUNone(CPU):
data_width = 32
reset_address = 0x00000000
io_regions = {0x00000000: 0x100000000} # origin, length
periph_buses = []
memory_buses = []
# CPUS ---------------------------------------------------------------------------------------------

View file

@ -79,6 +79,7 @@ class BlackParrotRV64(CPU):
self.interrupt = Signal(4)
self.idbus = idbus = wishbone.Interface(data_width=64, adr_width=37)
self.periph_buses = [idbus]
self.memory_buses = []
# # #

View file

@ -41,6 +41,7 @@ class LM32(CPU):
self.dbus = d = wishbone.Interface()
self.interrupt = Signal(32)
self.periph_buses = [i, d]
self.memory_buses = []
# # #

View file

@ -47,6 +47,7 @@ class Microwatt(CPU):
self.wb_insn = wb_insn = wishbone.Interface(data_width=64, adr_width=28)
self.wb_data = wb_data = wishbone.Interface(data_width=64, adr_width=28)
self.periph_buses = [wb_insn, wb_data]
self.memory_buses = []
# # #

View file

@ -34,10 +34,11 @@ class Minerva(CPU):
self.platform = platform
self.variant = variant
self.reset = Signal()
self.interrupt = Signal(32)
self.ibus = wishbone.Interface()
self.dbus = wishbone.Interface()
self.periph_buses = [self.ibus, self.dbus]
self.interrupt = Signal(32)
self.memory_buses = []
# TODO: create variants
self.with_icache = False

View file

@ -66,10 +66,12 @@ class MOR1KX(CPU):
self.platform = platform
self.variant = variant
self.reset = Signal()
self.interrupt = Signal(32)
self.ibus = i = wishbone.Interface()
self.dbus = d = wishbone.Interface()
self.periph_buses = [i, d]
self.interrupt = Signal(32)
self.memory_buses = []
if variant == "linux":
self.mem_map = self.mem_map_linux

View file

@ -58,11 +58,12 @@ class PicoRV32(CPU):
assert variant in CPU_VARIANTS, "Unsupported variant %s" % variant
self.platform = platform
self.variant = variant
self.trap = Signal()
self.reset = Signal()
self.interrupt = Signal(32)
self.idbus = idbus = wishbone.Interface()
self.periph_buses = [idbus]
self.interrupt = Signal(32)
self.trap = Signal()
self.memory_buses = []
# # #

View file

@ -107,6 +107,7 @@ class RocketRV64(CPU):
self.mmio_wb = mmio_wb = wishbone.Interface(data_width=mmio_dw, adr_width=32-log2_int(mmio_dw//8))
self.periph_buses = [mmio_wb]
self.memory_buses = [mem_axi]
# # #

View file

@ -37,6 +37,7 @@ class SERV(CPU):
self.ibus = ibus = wishbone.Interface()
self.dbus = dbus = wishbone.Interface()
self.periph_buses = [ibus, dbus]
self.memory_buses = []
# # #

View file

@ -103,10 +103,13 @@ class VexRiscv(CPU, AutoCSR):
self.variant = variant
self.external_variant = None
self.reset = Signal()
self.interrupt = Signal(32)
self.ibus = ibus = wishbone.Interface()
self.dbus = dbus = wishbone.Interface()
self.periph_buses = [ibus, dbus]
self.interrupt = Signal(32)
self.memory_buses = []
# # #
self.cpu_params = dict(
i_clk = ClockSignal(),

View file

@ -991,6 +991,7 @@ class LiteXSoC(SoC):
**kwargs):
# Imports
from litedram.common import LiteDRAMNativePort
from litedram.core import LiteDRAMCore
from litedram.frontend.wishbone import LiteDRAMWishbone2Native
from litedram.frontend.axi import LiteDRAMAXI2Native
@ -1004,27 +1005,34 @@ class LiteXSoC(SoC):
**kwargs)
self.csr.add("sdram")
# LiteDRAM port
port = self.sdram.crossbar.get_port()
port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2
# SDRAM size
# Compute/Check SDRAM size
sdram_size = 2**(module.geom_settings.bankbits +
module.geom_settings.rowbits +
module.geom_settings.colbits)*phy.settings.databits//8
if size is not None:
sdram_size = min(sdram_size, size)
# Add SDRAM region
self.bus.add_region("main_ram", SoCRegion(origin=origin, size=sdram_size))
# SoC [<--> L2 Cache] <--> LiteDRAM --------------------------------------------------------
if self.cpu.name == "rocket":
# Rocket has its own I/D L1 cache: connect directly to LiteDRAM when possible.
if port.data_width == self.cpu.mem_axi.data_width:
if len(self.cpu.memory_buses):
# When CPU has at least a direct memory bus, connect them directly to LiteDRAM.
for mem_bus in self.cpu.memory_buses:
# Request a LiteDRAM native port.
port = self.sdram.crossbar.get_port()
port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2.
# Check if bus is an AXI bus and connect it.
if isinstance(mem_bus, axi.AXIInterface):
# If same data_width, connect it directly.
if port.data_width == mem_bus.data_width:
self.logger.info("Matching AXI MEM data width ({})\n".format(port.data_width))
self.submodules += LiteDRAMAXI2Native(
axi = self.cpu.mem_axi,
port = port,
base_address = self.bus.regions["main_ram"].origin)
# If different data_width, do the adaptation and connect it via Wishbone.
else:
self.logger.info("Converting MEM data width: {} to {} via Wishbone".format(
port.data_width,
@ -1046,8 +1054,24 @@ class LiteXSoC(SoC):
port = port,
base_address = origin)
self.submodules += wishbone.Converter(mem_wb, litedram_wb)
elif self.with_wishbone:
# Wishbone Slave SDRAM interface
# Check if bus is a Native bus and connect it.
if isinstance(mem_bus, LiteDRAMNativePort):
# If same data_width, connect it directly.
if port.data_width == mem_bus.data_width:
self.comb += mem_bus.cmd.connect(port.cmd)
self.comb += mem_bus.wdata.connect(port.wdata)
self.comb += port.rdata.connect(mem_bus.rdata)
# Else raise Error.
else:
raise NotImplementedError
else:
# When CPU has no direct memory interface, create a Wishbone Slave interface to LiteDRAM.
# Request a LiteDRAM native port.
port = self.sdram.crossbar.get_port()
port.data_width = 2**int(log2(port.data_width)) # Round to nearest power of 2.
# Create Wishbone Slave.
wb_sdram = wishbone.Interface()
self.bus.add_slave("main_ram", wb_sdram)