Skip to content

Commit 921d740

Browse files
committed
memory: add Memory.window_patterns(), to simplify decoders.
1 parent 6be732c commit 921d740

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

nmigen_soc/csr/bus.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -330,14 +330,8 @@ def add(self, sub_bus, *, addr=None):
330330
raise ValueError("Subordinate bus has data width {}, which is not the same as "
331331
"multiplexer data width {}"
332332
.format(sub_bus.data_width, self.bus.data_width))
333-
334-
start, end, ratio = window_range = self._map.add_window(sub_bus.memory_map, addr=addr)
335-
assert ratio == 1
336-
pattern = "{:0{}b}{}".format(start >> sub_bus.addr_width,
337-
self.bus.addr_width - sub_bus.addr_width,
338-
"-" * sub_bus.addr_width)
339-
self._subs[pattern] = sub_bus
340-
return window_range
333+
self._subs[sub_bus.memory_map] = sub_bus
334+
return self._map.add_window(sub_bus.memory_map, addr=addr)
341335

342336
def elaborate(self, platform):
343337
m = Module()
@@ -346,7 +340,8 @@ def elaborate(self, platform):
346340
r_data_fanin = 0
347341

348342
with m.Switch(self.bus.addr):
349-
for sub_pat, sub_bus in self._subs.items():
343+
for sub_map, sub_pat in self._map.window_patterns():
344+
sub_bus = self._subs[sub_map]
350345
m.d.comb += sub_bus.addr.eq(self.bus.addr[:sub_bus.addr_width])
351346

352347
# The CSR bus interface is defined to output zero when idle, allowing us to avoid

nmigen_soc/memory.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,23 @@ def windows(self):
321321
for window, window_range in self._windows.items():
322322
yield window, (window_range.start, window_range.stop, window_range.step)
323323

324+
def window_patterns(self):
325+
"""Iterate local windows and patterns that match their address ranges.
326+
327+
Non-recursively iterate windows in ascending order of their address.
328+
329+
Yield values
330+
------------
331+
A tuple ``window, pattern`` describing the address range assigned to the window.
332+
``pattern`` is a ``self.addr_width`` wide pattern that may be used in ``Case`` or ``match``
333+
to determine if an address signal is within the address range of ``window``.
334+
"""
335+
for window, window_range in self._windows.items():
336+
pattern = "{:0{}b}{}".format(window_range.start >> window.addr_width,
337+
self.addr_width - window.addr_width,
338+
"-" * window.addr_width)
339+
yield window, pattern
340+
324341
@staticmethod
325342
def _translate(start, end, width, window, window_range):
326343
assert (end - start) % window_range.step == 0

nmigen_soc/test/test_memory.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@ def test_iter_windows(self):
209209
(window_2, (0x1000, 0x2000, 1)),
210210
])
211211

212+
def test_iter_window_patterns(self):
213+
memory_map = MemoryMap(addr_width=16, data_width=16)
214+
window_1 = MemoryMap(addr_width=10, data_width=8)
215+
memory_map.add_window(window_1, sparse=False)
216+
window_2 = MemoryMap(addr_width=12, data_width=16)
217+
memory_map.add_window(window_2)
218+
self.assertEqual(list(memory_map.window_patterns()), [
219+
(window_1, "000000----------"),
220+
(window_2, "0001------------"),
221+
])
222+
212223
def test_align_to(self):
213224
memory_map = MemoryMap(addr_width=16, data_width=8)
214225
self.assertEqual(memory_map.add_resource("a", size=1), (0, 1))

0 commit comments

Comments
 (0)