m-labs / nmigen

A refreshed Python toolbox for building complex digital hardware. See https://gitlab.com/nmigen/nmigen
https://nmigen.org
Other
652 stars 55 forks source link

AssertionError domain.name not in self.domains #307

Closed nicolas-robin closed 4 years ago

nicolas-robin commented 4 years ago

Since a7be3b4, this code fails :

Code :

from nmigen import *
from nmigen_boards.ice40_hx8k_b_evn import ICE40HX8KBEVNPlatform

platform = ICE40HX8KBEVNPlatform()
top = Module()
top.d.sync += platform.request("led").o.eq(1)
platform.build(top)

Error :

Traceback (most recent call last):
  File "[...]/sandbox.py", line 7, in <module>
    platform.build(top)
  File "[...]/venv/lib/python3.7/site-packages/nmigen/build/plat.py", line 77, in build
    plan = self.prepare(elaboratable, name, **kwargs)
  File "[...]/venv/lib/python3.7/site-packages/nmigen/build/plat.py", line 147, in prepare
    fragment = fragment.prepare(ports=self.iter_ports(), missing_domain=lambda name: None)
  File "[...]/venv/lib/python3.7/site-packages/nmigen/hdl/ir.py", line 556, in prepare
    new_domains = fragment._propagate_domains(missing_domain)
  File "[...]/venv/lib/python3.7/site-packages/nmigen/hdl/ir.py", line 403, in _propagate_domains
    self._propagate_domains_up()
  File "[...]/venv/lib/python3.7/site-packages/nmigen/hdl/ir.py", line 359, in _propagate_domains_up
    self.add_domains(domain)
  File "[...]/venv/lib/python3.7/site-packages/nmigen/hdl/ir.py", line 145, in add_domains
    assert domain.name not in self.domains
AssertionError
smunaut commented 4 years ago

Same error happens when trying to run glasgow with latest nMigen. (seen by me, @esden @miek at least)

smunaut commented 4 years ago

Not sure if this is the correct fix, but this seems to work for me :

diff --git a/nmigen/hdl/ir.py b/nmigen/hdl/ir.py
index 26dec85..2b8b74c 100644
--- a/nmigen/hdl/ir.py
+++ b/nmigen/hdl/ir.py
@@ -142,7 +142,7 @@ class Fragment:
     def add_domains(self, *domains):
         for domain in flatten(domains):
             assert isinstance(domain, ClockDomain)
-            assert domain.name not in self.domains
+            assert (domain.name not in self.domains) or (self.domains[domain.name] == domain)
             self.domains[domain.name] = domain

     def iter_domains(self):
whitequark commented 4 years ago

Likely not the correct fix, but an acceptable workaround.

whitequark commented 4 years ago

Fixed in my fork.