hdl.ir: type check ports.
authorwhitequark <whitequark@whitequark.org>
Thu, 6 Feb 2020 17:33:41 +0000 (17:33 +0000)
committerwhitequark <whitequark@whitequark.org>
Thu, 6 Feb 2020 17:33:41 +0000 (17:33 +0000)
Fixes #290.

nmigen/hdl/ir.py
nmigen/test/test_hdl_ir.py

index 8c169ada820ab17b7cd026b3caf1ca1efa359b5b..b9963c1591ae79631d5dafe59a99469251cce855 100644 (file)
@@ -532,13 +532,22 @@ class Fragment:
         if ports is None:
             fragment._propagate_ports(ports=(), all_undef_as_ports=True)
         else:
-            ports = map(DomainLowerer(fragment.domains).on_value, ports)
-            new_ports = []
+            mapped_ports = []
+            # Lower late bound signals like ClockSignal() to ports.
+            port_lowerer = DomainLowerer(fragment.domains)
+            for port in ports:
+                if not isinstance(port, (Signal, ClockSignal, ResetSignal)):
+                    raise TypeError("Only signals may be added as ports, not {!r}"
+                                    .format(port))
+                mapped_ports.append(port_lowerer.on_value(port))
+            # Add ports for all newly created missing clock domains, since not doing so defeats
+            # the purpose of domain auto-creation. (It's possible to refer to these ports before
+            # the domain actually exists through late binding, but it's inconvenient.)
             for cd in new_domains:
-                new_ports.append(cd.clk)
+                mapped_ports.append(cd.clk)
                 if cd.rst is not None:
-                    new_ports.append(cd.rst)
-            fragment._propagate_ports(ports=(*ports, *new_ports), all_undef_as_ports=False)
+                    mapped_ports.append(cd.rst)
+            fragment._propagate_ports(ports=mapped_ports, all_undef_as_ports=False)
         return fragment
 
 
index 42395ccbf4222117a376f9a2af672d313a9e0512..2ea762a7aea63d64614e609bf8df36515f0ee306 100644 (file)
@@ -298,6 +298,11 @@ class FragmentPortsTestCase(FHDLTestCase):
             (sync.rst, "i"),
         ]))
 
+    def test_port_wrong(self):
+        f = Fragment()
+        with self.assertRaises(TypeError,
+                msg="Only signals may be added as ports, not (const 1'd1)"):
+            f.prepare(ports=(Const(1),))
 
 class FragmentDomainsTestCase(FHDLTestCase):
     def test_iter_signals(self):