scc: Add -specify option to find loops in boxes
authorDan Ravensloft <dan.ravensloft@gmail.com>
Mon, 11 Jan 2021 18:37:27 +0000 (18:37 +0000)
committerDan Ravensloft <dan.ravensloft@gmail.com>
Tue, 26 Jan 2021 16:23:08 +0000 (16:23 +0000)
passes/cmds/scc.cc
passes/techmap/abc9.cc

index 8e7f3f9909c63a2125544b7607ee9b2d6c882209..7aa9a484f32bfe8cd5984211b9219db15725d3af 100644 (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;
+
+                                       if (ct.cell_known(cell->type)) {
+                                               isInput = ct.cell_input(cell->type, conn.first);
+                                               isOutput = ct.cell_output(cell->type, conn.first);
+                                       }
 
-                               RTLIL::SigSpec sig = selectedSignals.extract(sigmap(conn.second));
-                               sig.sort_and_unify();
+                                       RTLIL::SigSpec sig = selectedSignals.extract(sigmap(conn.second));
+                                       sig.sort_and_unify();
 
-                               if (isInput)
-                                       inputSignals.append(sig);
-                               if (isOutput)
-                                       outputSignals.append(sig);
+                                       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())
                        {
index 7d017ac403358f080ef49cea22e019aea36e3d9d..56bb1549578babb116892a2d4b29b3697dcf163f 100644 (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