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
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 7cb3095334f7
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a7be3b480adb
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Jan 18, 2020

  1. hdl.ir: resolve hierarchy conflicts before creating missing domains.

    Otherwise, code such as:
    
        m.submodules.a = (something with cd_sync)
        m.submodules.b = (something with cd_sync)
        m.d.b_sync += x.eq(y)
    
    causes an assertion failure.
    
    Fixes #304 (again).
    whitequark committed Jan 18, 2020
    Copy the full SHA
    a7be3b4 View commit details
Showing with 29 additions and 2 deletions.
  1. +13 −2 nmigen/hdl/ir.py
  2. +16 −0 nmigen/test/test_hdl_ir.py
15 changes: 13 additions & 2 deletions nmigen/hdl/ir.py
Original file line number Diff line number Diff line change
@@ -203,6 +203,15 @@ def _resolve_hierarchy_conflicts(self, hierarchy=("top",), mode="warn"):
driver_subfrags = SignalDict()
memory_subfrags = OrderedDict()
def add_subfrag(registry, entity, entry):
# Because of missing domain insertion, at the point when this code runs, we have
# a mixture of bound and unbound {Clock,Reset}Signals. Map the bound ones to
# the actual signals (because the signal itself can be driven as well); but leave
# the unbound ones as it is, because there's no concrete signal for it yet anyway.
if isinstance(entity, ClockSignal) and entity.domain in self.domains:
entity = self.domains[entity.domain].clk
elif isinstance(entity, ResetSignal) and entity.domain in self.domains:
entity = self.domains[entity.domain].rst

if entity not in registry:
registry[entity] = set()
registry[entity].add(entry)
@@ -387,12 +396,15 @@ def create_missing_domains(self, missing_domain, *, platform=None):
"requested domain '{}' (defines {})."
.format(domain_name, ", ".join("'{}'".format(n) for n in defined)))
self.add_subfragment(new_fragment, "cd_{}".format(domain_name))
self.add_domains(new_fragment.domains.values())
return new_domains

def _propagate_domains(self, missing_domain):
new_domains = self.create_missing_domains(missing_domain)
self._propagate_domains_up()
self._propagate_domains_down()
self._resolve_hierarchy_conflicts()
new_domains = self.create_missing_domains(missing_domain)
self._propagate_domains_down()
return new_domains

def _prepare_use_def_graph(self, parent, level, uses, defs, ios, top):
@@ -543,7 +555,6 @@ def prepare(self, ports=None, missing_domain=lambda name: ClockDomain(name)):
fragment = SampleLowerer()(self)
new_domains = fragment._propagate_domains(missing_domain)
fragment = DomainLowerer()(fragment)
fragment._resolve_hierarchy_conflicts()
if ports is None:
fragment._propagate_ports(ports=(), all_undef_as_ports=True)
else:
16 changes: 16 additions & 0 deletions nmigen/test/test_hdl_ir.py
Original file line number Diff line number Diff line change
@@ -408,6 +408,22 @@ def test_domain_conflict_rename_drivers(self):
None: SignalSet((ResetSignal("b_sync"),))
}))

def test_domain_conflict_rename_drivers(self):
cda = ClockDomain("sync")
cdb = ClockDomain("sync")
s = Signal()

fa = Fragment()
fa.add_domains(cda)
fb = Fragment()
fb.add_domains(cdb)
f = Fragment()
f.add_subfragment(fa, "a")
f.add_subfragment(fb, "b")
f.add_driver(s, "b_sync")

f._propagate_domains(lambda name: ClockDomain(name))

def test_propagate_down(self):
cd = ClockDomain()