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:
parent
36767c66b4
commit
bd7921cda8
|
@ -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(
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Reference in New Issue