raise ValueError("Subordinate bus has data width {}, which is not the same as "
"multiplexer data width {}"
.format(sub_bus.data_width, self.bus.data_width))
-
- start, end, ratio = window_range = self._map.add_window(sub_bus.memory_map, addr=addr)
- assert ratio == 1
- pattern = "{:0{}b}{}".format(start >> sub_bus.addr_width,
- self.bus.addr_width - sub_bus.addr_width,
- "-" * sub_bus.addr_width)
- self._subs[pattern] = sub_bus
- return window_range
+ self._subs[sub_bus.memory_map] = sub_bus
+ return self._map.add_window(sub_bus.memory_map, addr=addr)
def elaborate(self, platform):
m = Module()
r_data_fanin = 0
with m.Switch(self.bus.addr):
- for sub_pat, sub_bus in self._subs.items():
+ for sub_map, sub_pat in self._map.window_patterns():
+ sub_bus = self._subs[sub_map]
m.d.comb += sub_bus.addr.eq(self.bus.addr[:sub_bus.addr_width])
# The CSR bus interface is defined to output zero when idle, allowing us to avoid
for window, window_range in self._windows.items():
yield window, (window_range.start, window_range.stop, window_range.step)
+ def window_patterns(self):
+ """Iterate local windows and patterns that match their address ranges.
+
+ Non-recursively iterate windows in ascending order of their address.
+
+ Yield values
+ ------------
+ A tuple ``window, pattern`` describing the address range assigned to the window.
+ ``pattern`` is a ``self.addr_width`` wide pattern that may be used in ``Case`` or ``match``
+ to determine if an address signal is within the address range of ``window``.
+ """
+ for window, window_range in self._windows.items():
+ pattern = "{:0{}b}{}".format(window_range.start >> window.addr_width,
+ self.addr_width - window.addr_width,
+ "-" * window.addr_width)
+ yield window, pattern
+
@staticmethod
def _translate(start, end, width, window, window_range):
assert (end - start) % window_range.step == 0
(window_2, (0x1000, 0x2000, 1)),
])
+ def test_iter_window_patterns(self):
+ memory_map = MemoryMap(addr_width=16, data_width=16)
+ window_1 = MemoryMap(addr_width=10, data_width=8)
+ memory_map.add_window(window_1, sparse=False)
+ window_2 = MemoryMap(addr_width=12, data_width=16)
+ memory_map.add_window(window_2)
+ self.assertEqual(list(memory_map.window_patterns()), [
+ (window_1, "000000----------"),
+ (window_2, "0001------------"),
+ ])
+
def test_align_to(self):
memory_map = MemoryMap(addr_width=16, data_width=8)
self.assertEqual(memory_map.add_resource("a", size=1), (0, 1))