hdl.ir: correctly handle named output and inout ports.

This commit is contained in:
whitequark 2018-12-21 04:03:03 +00:00
parent 2b4a8510ca
commit b0bd7bfaca
2 changed files with 41 additions and 17 deletions

View file

@ -239,14 +239,20 @@ class Fragment:
# (on RHS of statements, or in clock domains). # (on RHS of statements, or in clock domains).
self_driven = union((s._lhs_signals() for s in self.statements), start=SignalSet()) self_driven = union((s._lhs_signals() for s in self.statements), start=SignalSet())
self_used = union((s._rhs_signals() for s in self.statements), start=SignalSet()) self_used = union((s._rhs_signals() for s in self.statements), start=SignalSet())
if isinstance(self, Instance):
self_used |= union((p._rhs_signals() for p in self.named_ports.values()),
start=SignalSet())
for domain, _ in self.iter_sync(): for domain, _ in self.iter_sync():
cd = self.domains[domain] cd = self.domains[domain]
self_used.add(cd.clk) self_used.add(cd.clk)
if cd.rst is not None: if cd.rst is not None:
self_used.add(cd.rst) self_used.add(cd.rst)
if isinstance(self, Instance):
# Named ports contain signals for input, output and bidirectional ports. Output
# and bidirectional ports are already added to the main port dict, however, for
# input ports this has to be done lazily as any expression is valid there, including
# ones with deferred resolution to signals, such as ClockSignal().
for named_port_used in union((p._rhs_signals() for p in self.named_ports.values()),
start=SignalSet()):
if named_port_used not in self.ports:
self_used.add(named_port_used)
# Our input ports are all the signals we're using but not driving. This is an over- # Our input ports are all the signals we're using but not driving. This is an over-
# approximation: some of these signals may be driven by our subfragments. # approximation: some of these signals may be driven by our subfragments.

View file

@ -408,21 +408,39 @@ class FragmentDriverConflictTestCase(FHDLTestCase):
class InstanceTestCase(FHDLTestCase): class InstanceTestCase(FHDLTestCase):
def test_init(self): def setUp_cpu(self):
rst = Signal() self.rst = Signal()
stb = Signal() self.stb = Signal()
pins = Signal(8) self.pins = Signal(8)
inst = Instance("cpu", self.inst = Instance("cpu",
p_RESET=0x1234, p_RESET=0x1234,
i_clk=ClockSignal(), i_clk=ClockSignal(),
i_rst=rst, i_rst=self.rst,
o_stb=stb, o_stb=self.stb,
io_pins=pins io_pins=self.pins
) )
self.assertEqual(inst.type, "cpu")
self.assertEqual(inst.parameters, OrderedDict([("RESET", 0x1234)])) def test_init(self):
self.assertEqual(list(inst.named_ports.keys()), ["clk", "rst", "stb", "pins"]) self.setUp_cpu()
self.assertEqual(inst.ports, SignalDict([ f = self.inst
(stb, "o"), self.assertEqual(f.type, "cpu")
(pins, "io"), self.assertEqual(f.parameters, OrderedDict([("RESET", 0x1234)]))
self.assertEqual(list(f.named_ports.keys()), ["clk", "rst", "stb", "pins"])
self.assertEqual(f.ports, SignalDict([
(self.stb, "o"),
(self.pins, "io"),
]))
def test_prepare(self):
self.setUp_cpu()
f = self.inst.prepare()
clk = f.domains["sync"].clk
self.assertEqual(f.type, "cpu")
self.assertEqual(f.parameters, OrderedDict([("RESET", 0x1234)]))
self.assertEqual(list(f.named_ports.keys()), ["clk", "rst", "stb", "pins"])
self.assertEqual(f.ports, SignalDict([
(clk, "i"),
(self.rst, "i"),
(self.stb, "o"),
(self.pins, "io"),
])) ]))