integration/soc: Add initial AXI-full support.

Main bus can now be switched to AXI-full with --bus-standard=axi.
The interconnect will be AXI-Full (Using Alex Forenchich's verilog_axi
Interconnect and Crossbar) but ROM/SRAM will still be in AXI-Lite (Will
be switched to AXI-full in the future).

This gives a first working version that can be used for further improvements.

Note that the interconnect can also be selected by --bus-interconnect=shared or
crossbar.
This commit is contained in:
Florent Kermarrec 2022-06-17 16:21:31 +02:00
parent 8394e93742
commit 0941459061

View file

@ -113,7 +113,7 @@ class SoCCSRRegion:
# SoCBusHandler ------------------------------------------------------------------------------------ # SoCBusHandler ------------------------------------------------------------------------------------
class SoCBusHandler(Module): class SoCBusHandler(Module):
supported_standard = ["wishbone", "axi-lite"] supported_standard = ["wishbone", "axi-lite", "axi"]
supported_data_width = [32, 64] supported_data_width = [32, 64]
supported_address_width = [32] supported_address_width = [32]
@ -346,6 +346,7 @@ class SoCBusHandler(Module):
main_bus_cls = { main_bus_cls = {
"wishbone": wishbone.Interface, "wishbone": wishbone.Interface,
"axi-lite": axi.AXILiteInterface, "axi-lite": axi.AXILiteInterface,
"axi" : axi.AXIInterface,
}[self.standard] }[self.standard]
# Same Bus-Standard: Return un-modified interface. # Same Bus-Standard: Return un-modified interface.
if isinstance(interface, main_bus_cls): if isinstance(interface, main_bus_cls):
@ -874,10 +875,12 @@ class SoC(Module):
ram_cls = { ram_cls = {
"wishbone": wishbone.SRAM, "wishbone": wishbone.SRAM,
"axi-lite": axi.AXILiteSRAM, "axi-lite": axi.AXILiteSRAM,
"axi" : axi.AXILiteSRAM, # FIXME: Use AXI-Lite for now, create AXISRAM.
}[self.bus.standard] }[self.bus.standard]
interface_cls = { interface_cls = {
"wishbone": wishbone.Interface, "wishbone": wishbone.Interface,
"axi-lite": axi.AXILiteInterface, "axi-lite": axi.AXILiteInterface,
"axi" : axi.AXILiteInterface, # FIXME: Use AXI-Lite for now, create AXISRAM.
}[self.bus.standard] }[self.bus.standard]
ram_bus = interface_cls(data_width=self.bus.data_width, bursting=self.bus.bursting) ram_bus = interface_cls(data_width=self.bus.data_width, bursting=self.bus.bursting)
ram = ram_cls(size, bus=ram_bus, init=contents, read_only=(mode == "r"), name=name) ram = ram_cls(size, bus=ram_bus, init=contents, read_only=(mode == "r"), name=name)
@ -910,9 +913,10 @@ class SoC(Module):
csr_bridge_cls = { csr_bridge_cls = {
"wishbone": wishbone.Wishbone2CSR, "wishbone": wishbone.Wishbone2CSR,
"axi-lite": axi.AXILite2CSR, "axi-lite": axi.AXILite2CSR,
"axi" : axi.AXILite2CSR, # Note: CSR is a slow bus so using AXI-Lite is fine.
}[self.bus.standard] }[self.bus.standard]
csr_bridge_name = name + "_bridge" csr_bridge_name = name + "_bridge"
self.check_if_exists(csr_bridge_name ) self.check_if_exists(csr_bridge_name)
csr_bridge = csr_bridge_cls( csr_bridge = csr_bridge_cls(
bus_csr = csr_bus.Interface( bus_csr = csr_bus.Interface(
address_width = self.csr.address_width, address_width = self.csr.address_width,
@ -924,9 +928,14 @@ class SoC(Module):
setattr(self.submodules, csr_bridge_name, csr_bridge) setattr(self.submodules, csr_bridge_name, csr_bridge)
csr_size = 2**(self.csr.address_width + 2) csr_size = 2**(self.csr.address_width + 2)
csr_region = SoCRegion(origin=origin, size=csr_size, cached=False, decode=self.cpu.csr_decode) csr_region = SoCRegion(origin=origin, size=csr_size, cached=False, decode=self.cpu.csr_decode)
bus = getattr(self.csr_bridge, self.bus.standard.replace('-', '_')) bus_standard = {
"wishbone": "wishbone",
"axi-lite": "axi-lite",
"axi" : "axi-lite",
}[self.bus.standard]
bus = getattr(csr_bridge, bus_standard.replace("-", "_"))
self.bus.add_slave(name=name, slave=bus, region=csr_region) self.bus.add_slave(name=name, slave=bus, region=csr_region)
self.csr.add_master(name=name, master=self.csr_bridge.csr) self.csr.add_master(name=name, master=csr_bridge.csr)
self.add_config("CSR_DATA_WIDTH", self.csr.data_width) self.add_config("CSR_DATA_WIDTH", self.csr.data_width)
self.add_config("CSR_ALIGNMENT", self.csr.alignment) self.add_config("CSR_ALIGNMENT", self.csr.alignment)
@ -1071,19 +1080,6 @@ class SoC(Module):
if self.finalized: if self.finalized:
return return
interconnect_p2p_cls = {
"wishbone": wishbone.InterconnectPointToPoint,
"axi-lite": axi.AXILiteInterconnectPointToPoint,
}[self.bus.standard]
interconnect_shared_cls = {
"wishbone": wishbone.InterconnectShared,
"axi-lite": axi.AXILiteInterconnectShared,
}[self.bus.standard]
interconnect_crossbar_cls = {
"wishbone": wishbone.Crossbar,
"axi-lite": axi.AXILiteCrossbar,
}[self.bus.standard]
# SoC Reset -------------------------------------------------------------------------------- # SoC Reset --------------------------------------------------------------------------------
# Connect soc_rst to CRG's rst if present. # Connect soc_rst to CRG's rst if present.
if hasattr(self, "ctrl") and hasattr(self, "crg"): if hasattr(self, "ctrl") and hasattr(self, "crg"):
@ -1092,14 +1088,29 @@ class SoC(Module):
self.comb += If(getattr(self.ctrl, "soc_rst", 0), crg_rst.eq(1)) self.comb += If(getattr(self.ctrl, "soc_rst", 0), crg_rst.eq(1))
# SoC CSR bridge --------------------------------------------------------------------------- # SoC CSR bridge ---------------------------------------------------------------------------
# FIXME: for now, use registered CSR bridge when SDRAM is present; find the best compromise.
self.add_csr_bridge( self.add_csr_bridge(
name = "csr", name = "csr",
origin = self.mem_map["csr"], origin = self.mem_map["csr"],
register = hasattr(self, "sdram") register = hasattr(self, "sdram"),
) )
# SoC Bus Interconnect --------------------------------------------------------------------- # SoC Bus Interconnect ---------------------------------------------------------------------
interconnect_p2p_cls = {
"wishbone": wishbone.InterconnectPointToPoint,
"axi-lite": axi.AXILiteInterconnectPointToPoint,
"axi" : axi.AXIInterconnectPointToPoint,
}[self.bus.standard]
interconnect_shared_cls = {
"wishbone": wishbone.InterconnectShared,
"axi-lite": axi.AXILiteInterconnectShared,
"axi" : axi.AXIInterconnectShared,
}[self.bus.standard]
interconnect_crossbar_cls = {
"wishbone": wishbone.Crossbar,
"axi-lite": axi.AXILiteCrossbar,
"axi" : axi.AXICrossbar,
}[self.bus.standard]
if len(self.bus.masters) and len(self.bus.slaves): if len(self.bus.masters) and len(self.bus.slaves):
# If 1 bus_master, 1 bus_slave and no address translation, use InterconnectPointToPoint. # If 1 bus_master, 1 bus_slave and no address translation, use InterconnectPointToPoint.
if ((len(self.bus.masters) == 1) and if ((len(self.bus.masters) == 1) and
@ -1114,6 +1125,14 @@ class SoC(Module):
"shared" : interconnect_shared_cls, "shared" : interconnect_shared_cls,
"crossbar": interconnect_crossbar_cls, "crossbar": interconnect_crossbar_cls,
}[self.bus.interconnect] }[self.bus.interconnect]
if interconnect_cls in [axi.AXIInterconnectShared, axi.AXICrossbar]:
# FIXME: WIP, try to have compatibility with other interconnects.
self.submodules.bus_interconnect = interconnect_cls(
platform = self.platform,
masters = list(self.bus.masters.values()),
slaves = [(s, self.bus.regions[n].origin, self.bus.regions[n].size) for n, s in self.bus.slaves.items()]
)
else:
self.submodules.bus_interconnect = interconnect_cls( self.submodules.bus_interconnect = interconnect_cls(
masters = list(self.bus.masters.values()), masters = list(self.bus.masters.values()),
slaves = [(self.bus.regions[n].decoder(self.bus), s) for n, s in self.bus.slaves.items()], slaves = [(self.bus.regions[n].decoder(self.bus), s) for n, s in self.bus.slaves.items()],