For a larger project, I need to create a list of unconnected cell ports using the Yosys RTLIL API. What is the best strategy for doing so?
The plain RTLIL API does not provide any indexes. You can determine the net connected to a port, but not the ports connected to a net. There are powerful indexers available in Yosys that can help you here, for example ModIndex
from kernel/modtools.h
, but in most cases it is simplest to create a custom index for whatever you need.
In this case we just need a dict<> that counts the number of cells connected to a net bit. We make two passes over all cell ports. In the first pass we count the number of connections for each signal bit, and in a second pass we determine if a cell port is the only port connected to that bit:
void find_unconn_cellports(Module *module)
{
SigMap sigmap(module);
dict<SigBit, int> sigbit_conncounts;
for (auto wire : module->wires()) {
if (wire->port_input)
for (auto bit : sigmap(wire))
sigbit_conncounts[bit]++;
if (wire->port_output)
for (auto bit : sigmap(wire))
sigbit_conncounts[bit]++;
}
for (auto cell : module->cells())
for (auto conn : cell->connections())
for (auto bit : conn.second)
sigbit_conncounts[sigmap(bit)]++;
for (auto cell : module->cells())
for (auto conn : cell->connections())
for (int i = 0; i < GetSize(conn.second); i++)
if (sigbit_conncounts.at(sigmap(conn.second[i])) == 1)
log("Unconnected cell port bit: %s.%s.%s[%d]\n",
log_id(module), log_id(cell), log_id(conn.first), i);
}
Using a similar approach we can find all undriven cell ports:
void find_undriven_cellports(Module *module)
{
SigMap sigmap(module);
pool<SigBit> driven_sigbit;
for (auto wire : module->wires()) {
if (wire->port_input)
for (auto bit : sigmap(wire))
driven_sigbit.insert(bit);
}
for (auto cell : module->cells())
for (auto conn : cell->connections())
if (cell->output(conn.first))
for (auto bit : sigmap(conn.second))
driven_sigbit.insert(bit);
for (auto cell : module->cells())
for (auto conn : cell->connections())
if (cell->input(conn.first))
for (int i = 0; i < GetSize(conn.second); i++) {
auto bit = sigmap(conn.second[i]);
if (bit.wire && !driven_sigbit.count(bit))
log("Undriven cell port bit: %s.%s.%s[%d]\n",
log_id(module), log_id(cell), log_id(conn.first), i);
}
}
Or all unused cell ports:
void find_unused_cellports(Module *module)
{
SigMap sigmap(module);
pool<SigBit> used_sigbit;
for (auto wire : module->wires()) {
if (wire->port_output)
for (auto bit : sigmap(wire))
used_sigbit.insert(bit);
}
for (auto cell : module->cells())
for (auto conn : cell->connections())
if (cell->input(conn.first))
for (auto bit : sigmap(conn.second))
used_sigbit.insert(bit);
for (auto cell : module->cells())
for (auto conn : cell->connections())
if (cell->output(conn.first))
for (int i = 0; i < GetSize(conn.second); i++)
if (used_sigbit.count(sigmap(conn.second[i])) == 0)
log("Unused cell port bit: %s.%s.%s[%d]\n",
log_id(module), log_id(cell), log_id(conn.first), i);
}