Source code for hwtLib.abstract.busStaticRemap
from hwt.code import SwitchLogic, Concat
from hwt.hdl.types.bits import HBits
from hwt.hwModule import HwModule
from hwt.hwParam import HwParam
from hwt.math import inRange, isPow2
from hwt.pyUtils.typingFuture import override
[docs]
class BusStaticRemap(HwModule):
"""
Abstract class for component which remaps memory regions on bus interfaces
:ivar ~.MEM_MAP: list of tuples (addr_from, size, addr_to) for each memory region on second interface
:ivar ~.m: slave interface of first HwIO class where master should be connected
:ivar ~.s: slave interface of second HwIO class where master slave be connected
"""
@override
def hwConfig(self):
self.MEM_MAP = HwParam([])
[docs]
def _normalize_mem_map(self, mem_map):
assert mem_map, "This would mean that second interface is entirely disconnected"
# sort by addr from input interface
mem_map = sorted(mem_map, key=lambda x: x[0])
# assert the mapped segments are not overlapping on input interface
last_end = 0x0
for (offset, size, _) in mem_map:
assert offset >= 0, offset
assert size > 0, size
assert offset >= last_end
last_end = offset + size
return mem_map
[docs]
def translate_addr_val(self, mem_map, addr: int):
for (offset_in, size, offset_out) in mem_map:
if inRange(addr, offset_in, offset_in + size):
return addr - (offset_in - offset_out)
return addr
[docs]
def translate_addr_signal(self, mem_map, sig_in, sig_out):
cases = []
AW = sig_in._dtype.bit_length()
for (offset_in, size, offset_out) in mem_map:
in_is_aligned = offset_in % size == 0 and isPow2(size)
out_is_aligned = offset_out % size == 0 and isPow2(size)
if in_is_aligned:
L = (size - 1).bit_length()
en_sig = sig_in[:L]._eq(offset_in >> L)
_sig_in = sig_in[L:]
if out_is_aligned:
addr_drive = Concat(
HBits(AW - L).from_py(offset_out), _sig_in)
else:
addr_drive = Concat(HBits(AW - L).from_py(0),
_sig_in) + offset_out
else:
en_sig = inRange(sig_in, offset_in, offset_in + size)
if offset_in == offset_out:
addr_drive = sig_in
elif offset_in < offset_out:
addr_drive = sig_in + (offset_out - offset_in)
else:
# offset_in > offset_out:
addr_drive = sig_in - (offset_in - offset_out)
cases.append((en_sig, sig_out(addr_drive)))
SwitchLogic(cases, default=sig_out(sig_in))
@override
def hwDeclr(self):
with self._hwParamsShared():
self.m = self.hwIOCls()._m()
self.s = self.hwIOCls()
self.MEM_MAP = self._normalize_mem_map(self.MEM_MAP)