From a7be3b480adbf18006b34f8aae1b73e17d092e26 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 18 Jan 2020 10:30:36 +0000 Subject: [PATCH] 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). --- nmigen/hdl/ir.py | 15 +++++++++++++-- nmigen/test/test_hdl_ir.py | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/nmigen/hdl/ir.py b/nmigen/hdl/ir.py index a43e222..26dec85 100644 --- a/nmigen/hdl/ir.py +++ b/nmigen/hdl/ir.py @@ -203,6 +203,15 @@ class Fragment: 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 @@ class Fragment: "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 @@ class Fragment: 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: diff --git a/nmigen/test/test_hdl_ir.py b/nmigen/test/test_hdl_ir.py index 4685523..42395cc 100644 --- a/nmigen/test/test_hdl_ir.py +++ b/nmigen/test/test_hdl_ir.py @@ -408,6 +408,22 @@ class FragmentDomainsTestCase(FHDLTestCase): 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() -- 2.30.2