Source code for hwt.synthesizer.rtlLevel.remove_unconnected_signals
from collections import deque
from hwt.doc_markers import internal
from hwt.hdl.operator import Operator
from hwt.hdl.portItem import HdlPortItem
from hwt.hdl.statements.assignmentContainer import HdlAssignmentContainer
from hwt.hdl.statements.codeBlockContainer import HdlStmCodeBlockContainer
from hwt.hdl.statements.ifContainter import IfContainer
from hwt.hdl.statements.statement import HdlStatement
from hwt.hdl.statements.switchContainer import SwitchContainer
from hwt.synthesizer.interfaceLevel.interfaceUtils.utils import walkPhysInterfaces
from hwt.synthesizer.rtlLevel.mainBases import RtlSignalBase
from hwt.synthesizer.rtlLevel.rtlSignal import RtlSignal
from ipCorePackager.constants import DIRECTION
[docs]@internal
def removeUnconnectedSignals(netlist: "RtlNetlist"):
"""
Remove signal if does not affect output
:attention: does not remove signals in cycles which does not affect outputs
"""
# walk circuit from outputs to inputs and collect seen signals
toSearch = deque(s for s, d in netlist.interfaces.items() if d != DIRECTION.IN)
seen = set(toSearch)
for c in netlist.subUnits:
for sig in walkPhysInterfaces(c):
s = sig._sig
assert s is not None, (netlist.parent, sig, "broken Interface instance")
assert s.ctx is netlist, (netlist.parent, s, "must be in the same netlist")
toSearch.append(s)
while toSearch:
sig = toSearch.popleft()
for e in sig.drivers:
if isinstance(e, Operator):
inputs = e.operands
elif isinstance(e, HdlPortItem):
# we are already added inputs of all components
continue
else:
assert e in netlist.statements, ("Statement must be registered in the netlist", e)
inputs = walkInputsForSpecificOutput(sig, e)
for i in inputs:
if isinstance(i, RtlSignalBase) and i not in seen:
assert i.ctx is netlist, (netlist.parent, e, "all inputs must be in the same netlist", i)
seen.add(i)
toSearch.append(i)
nv = sig._nop_val
if isinstance(nv, RtlSignalBase):
if nv not in seen:
assert nv.ctx is netlist, nv
seen.add(nv)
toSearch.append(nv)
# add all io because it can not be removed
seen.update(s for s, d in netlist.interfaces.items() if d == DIRECTION.IN)
for c in netlist.subUnits:
for sig in walkPhysInterfaces(c):
s = sig._sig
assert s is not None, (netlist.parent, sig, "broken Interface instance after initial scan")
assert s.ctx is netlist, (netlist.parent, s, "must be in the same netlist")
seen.add(s)
# remove signals which were not seen
for sig in netlist.signals:
sig: RtlSignal
if sig in seen:
# if it was seen it was used and it should not be removed
continue
assert sig.ctx is netlist, (netlist.parent, sig, "must be in the same netlist")
for e in tuple(sig.drivers):
# drivers of this signal are useless rm them
if isinstance(e, Operator):
removed_e = e
elif isinstance(e, HdlPortItem):
raise NotImplementedError(sig)
else:
removed_e = e._cut_off_drivers_of(sig)
if removed_e is not None:
# must not destroy before processing inputs
removed_e._destroy()
intf = getattr(sig, "_interface", None)
if intf:
if intf._sig is sig:
intf._sig = None
else:
assert intf._sigInside is None or intf._sigInside is sig, (intf, intf._sigInside, sig)
intf._sigInside = None
netlist.signals = seen