Be more precise when connecting during ABC9 re-integration
[yosys.git] / passes / techmap / abc9.cc
index af9439e41ac2112f8f1db7f57b31f86162756674..c3145dbe59416ed575927d73dd33e44ed17cb3a1 100644 (file)
@@ -2,7 +2,7 @@
  *  yosys -- Yosys Open SYnthesis Suite
  *
  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *  Copyright (C) 2019  Eddie Hung <eddie@fpgeh.com>
+ *                2019  Eddie Hung <eddie@fpgeh.com>
  *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
@@ -25,7 +25,7 @@
 #define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
 #define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
 //#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
-#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if -W 160 -v; &ps -l"
+#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if {W} -v; &ps -l"
 #define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
 #define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
 
@@ -246,33 +246,11 @@ struct abc_output_filter
        }
 };
 
-static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
-{
-       int pos = -1;
-
-       if (name.empty() || name.back() != ']')
-               goto failed;
-
-       for (int i = 0; i+1 < GetSize(name); i++) {
-               if (name[i] == '[')
-                       pos = i;
-               else if (name[i] < '0' || name[i] > '9')
-                       pos = -1;
-               else if (i == pos+1 && name[i] == '0' && name[i+1] != ']')
-                       pos = -1;
-       }
-
-       if (pos >= 0)
-               return std::pair<RTLIL::IdString, int>(RTLIL::escape_id(name.substr(0, pos)), atoi(name.c_str() + pos+1));
-
-failed:
-       return std::pair<RTLIL::IdString, int>(name, 0);
-}
-
 void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
                std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
                bool keepff, std::string delay_target, std::string sop_inputs, std::string sop_products, std::string lutin_shared, bool fast_mode,
-               const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file)
+               const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file,
+               std::string wire_delay)
 {
        module = current_module;
        map_autoidx = autoidx++;
@@ -387,6 +365,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
        for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
                abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3);
 
+       for (size_t pos = abc_script.find("{W}"); pos != std::string::npos; pos = abc_script.find("{W}", pos))
+               abc_script = abc_script.substr(0, pos) + wire_delay + abc_script.substr(pos+3);
+
        abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str());
        abc_script = add_echos_to_abc_cmd(abc_script);
 
@@ -410,64 +391,77 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                }
        }
 
-       design->selection_stack.emplace_back(false);
-       RTLIL::Selection& sel = design->selection_stack.back();
-       sel.select(module);
+       bool count_output = false;
+       for (auto port_name : module->ports) {
+               RTLIL::Wire *port_wire = module->wire(port_name);
+               log_assert(port_wire);
+               if (port_wire->port_output) {
+                       count_output = true;
+                       break;
+               }
+       }
 
-       // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero
-       Pass::call(design, "setundef -zero");
+       log_push();
 
-       Pass::call(design, "aigmap");
+       if (count_output)
+       {
+               design->selection_stack.emplace_back(false);
+               RTLIL::Selection& sel = design->selection_stack.back();
+               sel.select(module);
 
-       handle_loops(design);
+               // Behave as for "abc" where BLIF writer implicitly outputs all undef as zero
+               Pass::call(design, "setundef -zero");
 
-       Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str()));
+               Pass::call(design, "aigmap");
 
-#if 0
-       std::string buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig");
-       std::ifstream ifs;
-       ifs.open(buffer);
-       if (ifs.fail())
-               log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
-       buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
-       log_assert(!design->module("$__abc9__"));
-       AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
-       reader.parse_xaiger();
-       ifs.close();
-       Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v"));
-       design->remove(design->module("$__abc9__"));
-#endif
+               handle_loops(design);
 
-       design->selection_stack.pop_back();
+               //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
+               //              count_gates, GetSize(signal_list), count_input, count_output);
+
+               Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str()));
 
-       // Now 'unexpose' those wires by undoing
-       // the expose operation -- remove them from PO/PI
-       // and re-connecting them back together
-       for (auto wire : module->wires()) {
-               auto it = wire->attributes.find("\\abc_scc_break");
-               if (it != wire->attributes.end()) {
-                       wire->attributes.erase(it);
-                       log_assert(wire->port_output);
-                       wire->port_output = false;
-                       RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
-                       log_assert(i_wire);
-                       log_assert(i_wire->port_input);
-                       i_wire->port_input = false;
-                       module->connect(i_wire, wire);
+               std::string buffer;
+               std::ifstream ifs;
+#if 0
+               buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig");
+               ifs.open(buffer);
+               if (ifs.fail())
+                       log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
+               buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
+               log_assert(!design->module("$__abc9__"));
+               {
+                       AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
+                       reader.parse_xaiger();
                }
-       }
-       module->fixup_ports();
+               ifs.close();
+               Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v"));
+               design->remove(design->module("$__abc9__"));
+#endif
 
-       //log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
-       //              count_gates, GetSize(signal_list), count_input, count_output);
+               design->selection_stack.pop_back();
+
+               // Now 'unexpose' those wires by undoing
+               // the expose operation -- remove them from PO/PI
+               // and re-connecting them back together
+               for (auto wire : module->wires()) {
+                       auto it = wire->attributes.find("\\abc_scc_break");
+                       if (it != wire->attributes.end()) {
+                               wire->attributes.erase(it);
+                               log_assert(wire->port_output);
+                               wire->port_output = false;
+                               RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
+                               log_assert(i_wire);
+                               log_assert(i_wire->port_input);
+                               i_wire->port_input = false;
+                               module->connect(i_wire, wire);
+                       }
+               }
+               module->fixup_ports();
 
-       log_push();
 
-       //if (count_output > 0)
-       {
                log_header(design, "Executing ABC9.\n");
 
-        std::string buffer;
                if (!lut_costs.empty()) {
                        buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
                        f = fopen(buffer.c_str(), "wt");
@@ -503,7 +497,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                        log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
 
                buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig");
-               std::ifstream ifs;
                ifs.open(buffer);
                if (ifs.fail())
                        log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
@@ -512,7 +505,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                //parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
                buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
                log_assert(!design->module("$__abc9__"));
-               AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
+               AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
                reader.parse_xaiger();
                ifs.close();
 
@@ -532,21 +525,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                        if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx;
                        if (w->port_output) {
                                RTLIL::Wire *wire = module->wire(w->name);
-                               if (wire) {
-                                       for (int i = 0; i < GetSize(wire); i++)
-                                               output_bits.insert({wire, i});
-                               }
-                               else {
-                                       // Attempt another wideports_split here because there
-                                       // exists the possibility that different bits of a port
-                                       // could be an input and output, therefore parse_xaiger()
-                                       // could not combine it into a wideport
-                                       auto r = wideports_split(w->name.str());
-                                       wire = module->wire(r.first);
-                                       log_assert(wire);
-                                       int i = r.second;
+                               log_assert(wire);
+                               for (int i = 0; i < GetSize(wire); i++)
                                        output_bits.insert({wire, i});
-                               }
                        }
                }
 
@@ -588,7 +569,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                                        RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit();
                                        if (!a_bit.wire) {
                                                c->setPort("\\Y", module->addWire(NEW_ID));
-                                               module->connect(module->wires_[remap_name(y_bit.wire->name)], RTLIL::S1);
+                                               RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
+                                               log_assert(wire);
+                                               module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1);
                                        }
                                        else if (!lut_costs.empty() || !lut_file.empty()) {
                                                RTLIL::Cell* driving_lut = nullptr;
@@ -639,7 +622,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                                        continue;
                                }
                        }
-            cell_stats[RTLIL::unescape_id(c->type)]++;
+                       cell_stats[RTLIL::unescape_id(c->type)]++;
 
                        if (c->type == "$lut") {
                                if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
@@ -650,10 +633,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                                }
                        }
                        else {
-                auto it = erased_boxes.find(c->name);
-                log_assert(it != erased_boxes.end());
-                c->parameters = std::move(it->second);
-            }
+                               auto it = erased_boxes.find(c->name);
+                               log_assert(it != erased_boxes.end());
+                               c->parameters = std::move(it->second);
+                       }
 
                        RTLIL::Cell* cell = module->addCell(remap_name(c->name), c->type);
                        if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
@@ -709,22 +692,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
                        if (!w->port_input && !w->port_output)
                                continue;
                        RTLIL::Wire *wire = module->wire(w->name);
+                       log_assert(wire);
                        RTLIL::Wire *remap_wire = module->wire(remap_name(w->name));
-                       RTLIL::SigSpec signal;
-                       if (wire) {
-                               signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
-                       }
-                       else {
-                               // Attempt another wideports_split here because there
-                               // exists the possibility that different bits of a port
-                               // could be an input and output, therefore parse_xaiger()
-                               // could not combine it into a wideport
-                               auto r = wideports_split(w->name.str());
-                               wire = module->wire(r.first);
-                               log_assert(wire);
-                               int i = r.second;
-                               signal = RTLIL::SigSpec(wire, i);
-                       }
+                       RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
                        log_assert(GetSize(signal) >= GetSize(remap_wire));
 
                        log_assert(w->port_input || w->port_output);
@@ -749,10 +719,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 
                design->remove(mapped_mod);
        }
-       //else
-       //{
-       //      log("Don't call ABC as there is nothing to map.\n");
-       //}
+       else
+       {
+               log("Don't call ABC as there is nothing to map.\n");
+       }
 
        if (cleanup)
        {
@@ -960,7 +930,7 @@ struct Abc9Pass : public Pass {
                std::string exe_file = proc_self_dirname() + "yosys-abc";
 #endif
                std::string script_file, liberty_file, constr_file, clk_str, box_file, lut_file;
-               std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1";
+               std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1", wire_delay;
                bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
                bool show_tempdir = false, sop_mode = false;
                vector<int> lut_costs;
@@ -1214,6 +1184,10 @@ struct Abc9Pass : public Pass {
                                        box_file = std::string(pwd) + "/" + box_file;
                                continue;
                        }
+                       if (arg == "-W" && argidx+1 < args.size()) {
+                               wire_delay = "-W " + args[++argidx];
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -1256,7 +1230,7 @@ struct Abc9Pass : public Pass {
                        if (!dff_mode || !clk_str.empty()) {
                                abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
                                                delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode,
-                                               box_file, lut_file);
+                                               box_file, lut_file, wire_delay);
                                continue;
                        }
 
@@ -1402,7 +1376,7 @@ struct Abc9Pass : public Pass {
                                en_sig = assign_map(std::get<3>(it.first));
                                abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
                                                keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode,
-                                               box_file, lut_file);
+                                               box_file, lut_file, wire_delay);
                                assign_map.set(mod);
                        }
                }