soc/add_master: Add region support to allow remapping.

Allow connecting a master to a specific region of the SoC and limiting access to it.
This commit is contained in:
Florent Kermarrec 2024-02-13 15:59:42 +01:00
parent 36767c66b4
commit bd7921cda8
4 changed files with 78 additions and 2 deletions

View File

@ -447,7 +447,34 @@ class SoCBusHandler(LiteXModule):
return adapted_interface return adapted_interface
def add_master(self, name=None, master=None): # Add Remapper ---------------------------------------------------------------------------------
def add_remapper(self, name, interface, origin, size):
interface_cls = type(interface)
remapper_cls = {
wishbone.Interface : wishbone.Remapper,
axi.AXILiteInterface : axi.AXILiteRemapper,
axi.AXIInterface : axi.AXIRemapper,
}[interface_cls]
adapted_interface = interface_cls(
data_width = interface.data_width,
address_width = interface.address_width,
addressing = interface.addressing,
)
self.submodules += remapper_cls(interface, adapted_interface, origin, size)
fmt = "{name} Bus {remapped} to {origin} (Size: {size})."
self.logger.info(fmt.format(
name = colorer(name),
remapped = colorer("remapped", color="cyan"),
origin = colorer(f"0x{origin:08x}"),
size = colorer(f"0x{size:08x}"),
))
return adapted_interface
def add_master(self, name=None, master=None, region=None):
if name is None: if name is None:
name = "master{:d}".format(len(self.masters)) name = "master{:d}".format(len(self.masters))
if name in self.masters.keys(): if name in self.masters.keys():
@ -456,6 +483,8 @@ class SoCBusHandler(LiteXModule):
colorer("already declared", color="red"))) colorer("already declared", color="red")))
self.logger.error(self) self.logger.error(self)
raise SoCError() raise SoCError()
if region:
master = self.add_remapper(name, master, region.origin, region.size)
master = self.add_adapter(name, master, "m2s") master = self.add_adapter(name, master, "m2s")
self.masters[name] = master self.masters[name] = master
self.logger.info("{} {} as Bus Master.".format( self.logger.info("{} {} as Bus Master.".format(
@ -466,7 +495,7 @@ class SoCBusHandler(LiteXModule):
self.add_master(self, name=name, master=controller) self.add_master(self, name=name, master=controller)
def add_slave(self, name=None, slave=None, region=None): def add_slave(self, name=None, slave=None, region=None):
no_name = name is None no_name = name is None
no_region = region is None no_region = region is None
if no_name and no_region: if no_name and no_region:
self.logger.error("Please {} {} or/and {} of Bus Slave.".format( self.logger.error("Please {} {} or/and {} of Bus Slave.".format(

View File

@ -7,6 +7,8 @@
"""AXI4-Full/Lite support for LiteX""" """AXI4-Full/Lite support for LiteX"""
from math import log2
from migen import * from migen import *
from migen.genlib import roundrobin from migen.genlib import roundrobin
@ -138,6 +140,18 @@ class AXIInterface:
def layout_flat(self): def layout_flat(self):
return list(axi_layout_flat(self)) return list(axi_layout_flat(self))
# AXI Remapper -------------------------------------------------------------------------------------
class AXIRemapper(LiteXModule):
def __init__(self, master, slave, origin, size):
# Mask.
mask = 2**int(log2(size)) - 1
# Address Mask and Shift.
self.comb += master.connect(slave)
self.comb += slave.aw.addr.eq(origin | master.aw.addr & mask)
self.comb += slave.ar.addr.eq(origin | master.ar.addr & mask)
# AXI Bursts to Beats ------------------------------------------------------------------------------ # AXI Bursts to Beats ------------------------------------------------------------------------------
class AXIBurst2Beat(LiteXModule): class AXIBurst2Beat(LiteXModule):

View File

@ -7,6 +7,8 @@
"""AXI4-Full/Lite support for LiteX""" """AXI4-Full/Lite support for LiteX"""
from math import log2
from migen import * from migen import *
from migen.genlib import roundrobin from migen.genlib import roundrobin
@ -128,6 +130,19 @@ class AXILiteInterface:
yield self.r.ready.eq(0) yield self.r.ready.eq(0)
return (data, resp) return (data, resp)
# AXI-Lite Remapper --------------------------------------------------------------------------------
class AXILiteRemapper(LiteXModule):
def __init__(self, master, slave, origin, size):
# Mask.
mask = 2**int(log2(size)) - 1
# Address Mask and Shift.
self.comb += master.connect(slave)
self.comb += slave.aw.addr.eq(origin | master.aw.addr & mask)
self.comb += slave.ar.addr.eq(origin | master.ar.addr & mask)
# AXI-Lite to Simple Bus --------------------------------------------------------------------------- # AXI-Lite to Simple Bus ---------------------------------------------------------------------------
def axi_lite_to_simple(axi_lite, port_adr, port_dat_r, port_dat_w=None, port_we=None): def axi_lite_to_simple(axi_lite, port_adr, port_dat_r, port_dat_w=None, port_we=None):

View File

@ -126,6 +126,24 @@ class Interface(Record):
r.append(sig.eq(pad)) r.append(sig.eq(pad))
return r return r
# Wishbone Remapper --------------------------------------------------------------------------------
class Remapper(LiteXModule):
def __init__(self, master, slave, origin, size):
# Parameters.
addressing = master.addressing
assert master.addressing == slave.addressing
# Mask.
log2_size = int(log2(size))
if addressing == "word":
log2_size -= int(log2(len(master.dat_w)//8))
mask = 2**log2_size - 1
# Address Mask and Shift.
self.comb += master.connect(slave, omit={"adr"})
self.comb += slave.adr.eq(origin | (master.adr & mask))
# Wishbone Timeout --------------------------------------------------------------------------------- # Wishbone Timeout ---------------------------------------------------------------------------------
class Timeout(LiteXModule): class Timeout(LiteXModule):