interconnect/wishbone: Enhance Remapper to also integrate RegionsRemapper functionnality and apply operation sequentially.

This commit is contained in:
Florent Kermarrec 2024-02-20 16:50:09 +01:00
parent d78dbd6935
commit ef256c9cc2
1 changed files with 39 additions and 31 deletions

View File

@ -128,46 +128,54 @@ class Interface(Record):
# Wishbone Remapper -------------------------------------------------------------------------------- # Wishbone Remapper --------------------------------------------------------------------------------
class Remapper(LiteXModule): class Remapper(Module):
"""Remaps Wishbone addresses by applying an origin offset and address mask.""" """
def __init__(self, master, slave, origin, size): Wishbone Remapper that supports sequential application of:
- An initial origin offset and address mask.
- Region-based remapping from specified source regions to destination regions.
This allows for an initial origin remap followed by more complex/specific region-based remapping.
"""
def __init__(self, master, slave, origin=0, size=None, src_regions=[], dst_regions=[]):
# Parameters. # Parameters.
addressing = master.addressing # -----------
assert master.addressing == slave.addressing assert master.addressing == slave.addressing
# Compute Mask.
log2_size = int(log2(size))
if addressing == "word":
log2_size -= int(log2(len(master.dat_w)//8))
mask = 2**log2_size - 1
# Connect Master to Slave.
self.comb += master.connect(slave, omit={"adr"})
# Connect Address with Mask and Shift.
self.comb += slave.adr.eq(origin | (master.adr & mask))
class RegionsRemapper(LiteXModule):
"""Remaps Wishbone addresses from specified source regions to destination regions"""
def __init__(self, master, slave, src_regions=[], dst_regions=[]):
assert len(src_regions) == len(dst_regions) assert len(src_regions) == len(dst_regions)
assert master.addressing == slave.addressing
# Parameters. # Master to Slave.
# ----------------
self.comb += master.connect(slave)
# Origin Remapping.
# -----------------
# Compute Address Mask.
if size is None:
size = 2**master.address_width
log2_size = int(log2(size))
if master.addressing == "word":
log2_size -= int(log2(len(master.dat_w)//8))
adr_mask = 2**log2_size - 1
# Apply Address Origin/Mask Remapping.
adr_remap = (origin | (master.adr & adr_mask))
self.comb += slave.adr.eq(adr_remap)
# Regions Remapping.
# ------------------
# Compute Address Shift.
adr_shift = { adr_shift = {
"byte" : 0, "byte" : 0,
"word" : int(log2(len(master.dat_w)//8)), "word" : int(log2(len(master.dat_w)//8)),
}[master.addressing] }[master.addressing]
# Apply Address Regions Remapping.
# Connect Master to Slave.
self.comb += master.connect(slave)
# Remap Regions.
for src_region, dst_region in zip(src_regions, dst_regions): for src_region, dst_region in zip(src_regions, dst_regions):
src_adr = master.adr << adr_shift src_adr = Signal.like(master.adr)
dst_adr = dst_region.origin + src_adr - src_region.origin dst_adr = Signal.like(master.adr)
active = (src_adr >= src_region.origin) & (src_adr < (src_region.origin + src_region.size)) active = Signal()
self.comb += If(active, slave.adr.eq(dst_adr >> adr_shift)) self.comb += [
src_adr.eq(adr_remap << adr_shift),
dst_adr.eq(dst_region.origin + src_adr - src_region.origin),
active.eq((src_adr >= src_region.origin) & (src_adr < (src_region.origin + src_region.size))),
If(active, slave.adr.eq(dst_adr >> adr_shift))
]
# Wishbone Timeout --------------------------------------------------------------------------------- # Wishbone Timeout ---------------------------------------------------------------------------------