scc: Add -specify option to find loops in boxes

This commit is contained in:
Dan Ravensloft 2021-01-11 18:37:27 +00:00
parent b0004911ca
commit 74dad5afe7
2 changed files with 61 additions and 18 deletions

View File

@ -37,7 +37,7 @@ struct SccWorker
RTLIL::Design *design;
RTLIL::Module *module;
SigMap sigmap;
CellTypes ct;
CellTypes ct, specifyCells;
std::set<RTLIL::Cell*> workQueue;
std::map<RTLIL::Cell*, std::set<RTLIL::Cell*>> cellToNextCell;
@ -100,7 +100,7 @@ struct SccWorker
}
}
SccWorker(RTLIL::Design *design, RTLIL::Module *module, bool nofeedbackMode, bool allCellTypes, int maxDepth) :
SccWorker(RTLIL::Design *design, RTLIL::Module *module, bool nofeedbackMode, bool allCellTypes, bool specifyMode, int maxDepth) :
design(design), module(module), sigmap(module)
{
if (module->processes.size() > 0) {
@ -115,6 +115,18 @@ struct SccWorker
ct.setup_stdcells();
}
// Discover boxes with specify rules in them, for special handling.
if (specifyMode) {
for (auto mod : design->modules())
if (mod->get_blackbox_attribute(false))
for (auto cell : mod->cells())
if (cell->type == ID($specify2))
{
specifyCells.setup_module(mod);
break;
}
}
SigPool selectedSignals;
SigSet<RTLIL::Cell*> sigToNextCells;
@ -129,29 +141,52 @@ struct SccWorker
if (!design->selected(module, cell))
continue;
if (!allCellTypes && !ct.cell_known(cell->type))
if (!allCellTypes && !ct.cell_known(cell->type) && !specifyCells.cell_known(cell->type))
continue;
workQueue.insert(cell);
RTLIL::SigSpec inputSignals, outputSignals;
for (auto &conn : cell->connections())
{
bool isInput = true, isOutput = true;
if (specifyCells.cell_known(cell->type)) {
// Use specify rules of the type `(X => Y) = NN` to look for asynchronous paths in boxes.
for (auto subcell : design->module(cell->type)->cells())
{
if (subcell->type != ID($specify2))
continue;
if (ct.cell_known(cell->type)) {
isInput = ct.cell_input(cell->type, conn.first);
isOutput = ct.cell_output(cell->type, conn.first);
for (auto bit : subcell->getPort(ID::SRC))
{
if (!bit.wire || !cell->hasPort(bit.wire->name))
continue;
inputSignals.append(sigmap(cell->getPort(bit.wire->name)));
}
for (auto bit : subcell->getPort(ID::DST))
{
if (!bit.wire || !cell->hasPort(bit.wire->name))
continue;
outputSignals.append(sigmap(cell->getPort(bit.wire->name)));
}
}
} else {
for (auto &conn : cell->connections())
{
bool isInput = true, isOutput = true;
RTLIL::SigSpec sig = selectedSignals.extract(sigmap(conn.second));
sig.sort_and_unify();
if (ct.cell_known(cell->type)) {
isInput = ct.cell_input(cell->type, conn.first);
isOutput = ct.cell_output(cell->type, conn.first);
}
if (isInput)
inputSignals.append(sig);
if (isOutput)
outputSignals.append(sig);
RTLIL::SigSpec sig = selectedSignals.extract(sigmap(conn.second));
sig.sort_and_unify();
if (isInput)
inputSignals.append(sig);
if (isOutput)
outputSignals.append(sig);
}
}
inputSignals.sort_and_unify();
@ -228,7 +263,7 @@ struct SccPass : public Pass {
log("design.\n");
log("\n");
log(" -expect <num>\n");
log(" expect to find exactly <num> SSCs. A different number of SSCs will\n");
log(" expect to find exactly <num> SCCs. A different number of SCCs will\n");
log(" produce an error.\n");
log("\n");
log(" -max_depth <num>\n");
@ -254,6 +289,9 @@ struct SccPass : public Pass {
log(" replace the current selection with a selection of all cells and wires\n");
log(" that are part of a found logic loop\n");
log("\n");
log(" -specify\n");
log(" examine specify rules to detect logic loops in whitebox/blackbox cells\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
@ -261,6 +299,7 @@ struct SccPass : public Pass {
bool allCellTypes = false;
bool selectMode = false;
bool nofeedbackMode = false;
bool specifyMode = false;
int maxDepth = -1;
int expect = -1;
@ -293,6 +332,10 @@ struct SccPass : public Pass {
selectMode = true;
continue;
}
if (args[argidx] == "-specify") {
specifyMode = true;
continue;
}
break;
}
int origSelectPos = design->selection_stack.size() - 1;
@ -303,7 +346,7 @@ struct SccPass : public Pass {
for (auto mod : design->selected_modules())
{
SccWorker worker(design, mod, nofeedbackMode, allCellTypes, maxDepth);
SccWorker worker(design, mod, nofeedbackMode, allCellTypes, specifyMode, maxDepth);
if (!setAttr.empty())
{

View File

@ -339,7 +339,7 @@ struct Abc9Pass : public ScriptPass
if (check_label("pre")) {
run("read_verilog -icells -lib -specify +/abc9_model.v");
run("scc -set_attr abc9_scc_id {}");
run("scc -specify -set_attr abc9_scc_id {}");
if (help_mode)
run("abc9_ops -mark_scc -prep_delays -prep_xaiger [-dff]", "(option for -dff)");
else