fhdl.ir: a subfragment's input that we don't drive is also our input.
authorwhitequark <cz@m-labs.hk>
Thu, 13 Dec 2018 11:50:56 +0000 (11:50 +0000)
committerwhitequark <cz@m-labs.hk>
Thu, 13 Dec 2018 11:50:56 +0000 (11:50 +0000)
nmigen/fhdl/ir.py
nmigen/test/test_fhdl_ir.py

index 4676c48259dbb833190fc8c6e7eeb068765c4761..a3d1d1d11ce495b79a9f0d2c4b96f50020281515 100644 (file)
@@ -152,8 +152,10 @@ class Fragment:
             # to provide. If the subfragment is not driving it, it will silently ignore it.
             sub_ins, sub_outs = subfrag._propagate_ports(ports=self_used | ports)
             # Refine the input port approximation: if a subfragment is driving a signal,
-            # it is definitely not our input.
+            # it is definitely not our input. But, if a subfragment requires a signal as an input,
+            # and we aren't driving it, it has to be our input as well.
             ins  -= sub_outs
+            ins  |= sub_ins - self_driven
             # Refine the output port approximation: if a subfragment is driving a signal,
             # and we're asked to provide it, we can provide it now.
             outs |= ports & sub_outs
index 2bf592bf25b577180fa63bb75dd79f7bf73f40a1..35fdbf2c3f16c57480e572ceab8acdd9e9d6fcf0 100644 (file)
@@ -71,6 +71,19 @@ class FragmentPortsTestCase(FHDLTestCase):
         self.assertEqual(f1.ports, ValueSet())
         self.assertEqual(f2.ports, ValueSet((self.s1,)))
 
+    def test_input_only_in_subfragment(self):
+        f1 = Fragment()
+        f2 = Fragment()
+        f2.add_statements(
+            self.c1.eq(self.s1)
+        )
+        f1.add_subfragment(f2)
+        ins, outs = f1._propagate_ports(ports=())
+        self.assertEqual(ins, ValueSet((self.s1,)))
+        self.assertEqual(outs, ValueSet())
+        self.assertEqual(f1.ports, ValueSet((self.s1,)))
+        self.assertEqual(f2.ports, ValueSet((self.s1,)))
+
     def test_output_from_subfragment(self):
         f1 = Fragment()
         f1.add_statements(