Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen-soc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 66548b1fe57c
Choose a base ref
...
head repository: m-labs/nmigen-soc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 921d740daf59
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Oct 26, 2019

  1. Copy the full SHA
    6be732c View commit details
  2. Copy the full SHA
    921d740 View commit details
Showing with 39 additions and 11 deletions.
  1. +4 −9 nmigen_soc/csr/bus.py
  2. +17 −0 nmigen_soc/memory.py
  3. +11 −0 nmigen_soc/test/test_memory.py
  4. +2 −1 nmigen_soc/test/test_wishbone_bus.py
  5. +5 −1 nmigen_soc/wishbone/bus.py
13 changes: 4 additions & 9 deletions nmigen_soc/csr/bus.py
Original file line number Diff line number Diff line change
@@ -330,14 +330,8 @@ def add(self, sub_bus, *, addr=None):
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()
@@ -346,7 +340,8 @@ def elaborate(self, platform):
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
17 changes: 17 additions & 0 deletions nmigen_soc/memory.py
Original file line number Diff line number Diff line change
@@ -321,6 +321,23 @@ def windows(self):
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
11 changes: 11 additions & 0 deletions nmigen_soc/test/test_memory.py
Original file line number Diff line number Diff line change
@@ -209,6 +209,17 @@ def test_iter_windows(self):
(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))
3 changes: 2 additions & 1 deletion nmigen_soc/test/test_wishbone_bus.py
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ def test_granularity(self):

def test_optional(self):
iface = Interface(addr_width=32, data_width=32,
optional={"rty", "err", "stall", "cti", "bte"})
optional={"rty", "err", "stall", "lock", "cti", "bte"})
self.assertEqual(iface.layout, Layout.cast([
("adr", 32, DIR_FANOUT),
("dat_w", 32, DIR_FANOUT),
@@ -57,6 +57,7 @@ def test_optional(self):
("err", 1, DIR_FANIN),
("rty", 1, DIR_FANIN),
("stall", 1, DIR_FANIN),
("lock", 1, DIR_FANOUT),
("cti", CycleType, DIR_FANOUT),
("bte", BurstTypeExt, DIR_FANOUT),
]))
6 changes: 5 additions & 1 deletion nmigen_soc/wishbone/bus.py
Original file line number Diff line number Diff line change
@@ -80,6 +80,8 @@ class Interface(Record):
Optional. Corresponds to Wishbone signal ``RTY_I`` (initiator) or ``RTY_O`` (target).
stall : Signal()
Optional. Corresponds to Wishbone signal ``STALL_I`` (initiator) or ``STALL_O`` (target).
lock : Signal()
Optional. Corresponds to Wishbone signal ``LOCK_O`` (initiator) or ``LOCK_I`` (target).
cti : Signal()
Optional. Corresponds to Wishbone signal ``CTI_O`` (initiator) or ``CTI_I`` (target).
bte : Signal()
@@ -110,7 +112,7 @@ def __init__(self, *, addr_width, data_width, granularity=None, optional=frozens
alignment=alignment)

optional = set(optional)
unknown = optional - {"rty", "err", "stall", "cti", "bte"}
unknown = optional - {"rty", "err", "stall", "lock", "cti", "bte"}
if unknown:
raise ValueError("Optional signal(s) {} are not supported"
.format(", ".join(map(repr, unknown))))
@@ -130,6 +132,8 @@ def __init__(self, *, addr_width, data_width, granularity=None, optional=frozens
layout += [("rty", 1, Direction.FANIN)]
if "stall" in optional:
layout += [("stall", 1, Direction.FANIN)]
if "lock" in optional:
layout += [("lock", 1, Direction.FANOUT)]
if "cti" in optional:
layout += [("cti", CycleType, Direction.FANOUT)]
if "bte" in optional: