Move Pass::call() out of abc9_ops into abc9
authorEddie Hung <eddie@fpgeh.com>
Tue, 31 Dec 2019 03:23:54 +0000 (19:23 -0800)
committerEddie Hung <eddie@fpgeh.com>
Tue, 31 Dec 2019 03:23:54 +0000 (19:23 -0800)
backends/aiger/xaiger.cc
passes/techmap/abc9.cc
passes/techmap/abc9_ops.cc

index 9e0a5696379325a9d71328ed3802d4ca931544b3..830c867878b53b4842d6d327fd77d01177aa1b55 100644 (file)
@@ -710,6 +710,10 @@ struct XAigerWriter
                        RTLIL::Module *holes_module = module->design->module(stringf("%s$holes", module->name.c_str()));
                        log_assert(holes_module);
 
+                       for (auto cell : holes_module->cells())
+                               if (!cell->type.in("$_NOT_", "$_AND_"))
+                                       log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n");
+
                        module->design->selection_stack.emplace_back(false);
                        module->design->selection().select(holes_module);
 
index e11b150652e8fdfefe18698d859e6eee864090d6..7d922df56f8c9030738d6aeeb3fd9a18770a8516 100644 (file)
@@ -185,11 +185,21 @@ struct Abc9Pass : public ScriptPass
 
        void script() YS_OVERRIDE
        {
+               run("abc9_ops -prep_holes");
+               run("select -set abc9_holes A:abc9_holes");
+               run("flatten -wb @abc9_holes");
+               run("techmap @abc9_holes");
+               run("aigmap @abc9_holes");
+               run("select -list @abc9_holes");
+               run("abc9_ops -prep_dff");
+               run("opt -purge @abc9_holes");
+               run("setattr -mod -set whitebox 1 @abc9_holes");
+
                auto selected_modules = active_design->selected_modules();
                active_design->selection_stack.emplace_back(false);
 
                for (auto mod : selected_modules) {
-                       if (mod->attributes.count(ID(abc9_box_id)))
+                       if (mod->get_blackbox_attribute())
                                continue;
 
                        if (mod->processes.size() > 0) {
@@ -207,7 +217,7 @@ struct Abc9Pass : public ScriptPass
                        tempdir_name = make_temp_dir(tempdir_name);
 
                        run("scc -set_attr abc9_scc_id {}");
-                       run("abc9_ops -break_scc -prep_dff -prep_holes");
+                       run("abc9_ops -break_scc");
                        run("aigmap");
                        run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()),
                                        "write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig");
index e65b16fc63667376da15849f81da87aef7de0cde..b5238297222cf8b7624c4f62829638dca9fc3812 100644 (file)
@@ -135,6 +135,50 @@ void prep_dff(RTLIL::Module *module)
                r2 = cell->attributes.insert(std::make_pair(ID(abc9_init), abc9_init.as_const()));
                log_assert(r2.second);
        }
+
+       RTLIL::Module *holes_module = design->module(stringf("%s$holes", module->name.c_str()));
+       log_assert(holes_module);
+
+       dict<SigSig, SigSig> replace;
+       for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) {
+               auto cell = it->second;
+               if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
+                                       "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) {
+                       SigBit D = cell->getPort("\\D");
+                       SigBit Q = cell->getPort("\\Q");
+                       // Remove the DFF cell from what needs to be a combinatorial box
+                       it = holes_module->cells_.erase(it);
+                       Wire *port;
+                       if (GetSize(Q.wire) == 1)
+                               port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str()));
+                       else
+                               port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset));
+                       log_assert(port);
+                       // Prepare to replace "assign <port> = DFF.Q;" with "assign <port> = DFF.D;"
+                       //   in order to extract the combinatorial control logic that feeds the box
+                       //   (i.e. clock enable, synchronous reset, etc.)
+                       replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,D)));
+                       // Since `flatten` above would have created wires named "<cell>.Q",
+                       //   extract the pre-techmap cell name
+                       auto pos = Q.wire->name.str().rfind(".");
+                       log_assert(pos != std::string::npos);
+                       IdString driver = Q.wire->name.substr(0, pos);
+                       // And drive the signal that was previously driven by "DFF.Q" (typically
+                       //   used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
+                       //   wire (which itself is driven an input port) we inserted above
+                       Wire *currQ = holes_module->wire(stringf("%s.$abc9_currQ", driver.c_str()));
+                       log_assert(currQ);
+                       holes_module->connect(Q, currQ);
+               }
+               else
+                       ++it;
+       }
+
+       for (auto &conn : holes_module->connections_) {
+               auto it = replace.find(conn);
+               if (it != replace.end())
+                       conn = it->second;
+       }
 }
 
 void prep_holes(RTLIL::Module *module)
@@ -280,6 +324,7 @@ void prep_holes(RTLIL::Module *module)
 
        RTLIL::Module *holes_module = design->addModule(stringf("%s$holes", module->name.c_str()));
        log_assert(holes_module);
+       holes_module->set_bool_attribute("\\abc9_holes");
 
        dict<IdString, Cell*> cell_cache;
 
@@ -371,72 +416,6 @@ void prep_holes(RTLIL::Module *module)
                        holes_module->connect(w, holes_wire);
                }
        }
-
-       log_push();
-
-       // NB: fixup_ports() will sort ports by name
-       //holes_module->fixup_ports();
-       holes_module->check();
-
-       // Cannot techmap/aigmap/check all lib_whitebox-es outside of write_xaiger
-       //   since boxes may contain parameters in which case `flatten` would have
-       //   created a new $paramod ...
-       Pass::call_on_module(design, holes_module, "flatten -wb; techmap; aigmap");
-
-       dict<SigSig, SigSig> replace;
-       for (auto it = holes_module->cells_.begin(); it != holes_module->cells_.end(); ) {
-               auto cell = it->second;
-               if (cell->type.in("$_DFF_N_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_",
-                                       "$_DFF_P_", "$_DFF_PN0_", "$_DFF_PN1", "$_DFF_PP0_", "$_DFF_PP1_")) {
-                       SigBit D = cell->getPort("\\D");
-                       SigBit Q = cell->getPort("\\Q");
-                       // Remove the DFF cell from what needs to be a combinatorial box
-                       it = holes_module->cells_.erase(it);
-                       Wire *port;
-                       if (GetSize(Q.wire) == 1)
-                               port = holes_module->wire(stringf("$abc%s", Q.wire->name.c_str()));
-                       else
-                               port = holes_module->wire(stringf("$abc%s[%d]", Q.wire->name.c_str(), Q.offset));
-                       log_assert(port);
-                       // Prepare to replace "assign <port> = DFF.Q;" with "assign <port> = DFF.D;"
-                       //   in order to extract the combinatorial control logic that feeds the box
-                       //   (i.e. clock enable, synchronous reset, etc.)
-                       replace.insert(std::make_pair(SigSig(port,Q), SigSig(port,D)));
-                       // Since `flatten` above would have created wires named "<cell>.Q",
-                       //   extract the pre-techmap cell name
-                       auto pos = Q.wire->name.str().rfind(".");
-                       log_assert(pos != std::string::npos);
-                       IdString driver = Q.wire->name.substr(0, pos);
-                       // And drive the signal that was previously driven by "DFF.Q" (typically
-                       //   used to implement clock-enable functionality) with the "<cell>.$abc9_currQ"
-                       //   wire (which itself is driven an input port) we inserted above
-                       Wire *currQ = holes_module->wire(stringf("%s.$abc9_currQ", driver.c_str()));
-                       log_assert(currQ);
-                       holes_module->connect(Q, currQ);
-                       continue;
-               }
-               else if (!cell->type.in("$_NOT_", "$_AND_"))
-                       log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n");
-               ++it;
-       }
-
-       for (auto &conn : holes_module->connections_) {
-               auto it = replace.find(conn);
-               if (it != replace.end())
-                       conn = it->second;
-       }
-
-       // Move into a new (temporary) design so that "clean" will only
-       // operate (and run checks on) this one module
-       RTLIL::Design *holes_design = new RTLIL::Design;
-       holes_design->add(holes_module);
-       Pass::call(holes_design, "opt -purge");
-       holes_design->modules_.erase(holes_module->name);
-       holes_module->design = design;
-
-       holes_module->set_bool_attribute(ID::whitebox);
-
-       log_pop();
 }
 
 struct Abc9PrepPass : public Pass {
@@ -484,6 +463,8 @@ struct Abc9PrepPass : public Pass {
                for (auto mod : design->selected_modules()) {
                        if (mod->get_blackbox_attribute())
                                continue;
+                       if (mod->get_bool_attribute("\\abc9_holes"))
+                               continue;
 
                        if (mod->processes.size() > 0) {
                                log("Skipping module %s as it contains processes.\n", log_id(mod));