abc9_map: drop padding in box connections
[yosys.git] / passes / techmap / abc9_map.cc
index 9b56f04a8cfa1c2c55ebc11649f84fc65f588768..4ed3419f087dd8ed2e28cc520b6454dda330cca6 100644 (file)
@@ -63,7 +63,6 @@ extern "C" int Abc_RealMain(int argc, char *argv[]);
 USING_YOSYS_NAMESPACE
 PRIVATE_NAMESPACE_BEGIN
 
-bool markgroups;
 int map_autoidx;
 
 inline std::string remap_name(RTLIL::IdString abc9_name)
@@ -198,7 +197,7 @@ struct abc9_output_filter
 
 void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string script_file, std::string exe_file,
                vector<int> lut_costs, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
-               const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, std::string box_file, std::string lut_file,
+               bool show_tempdir, std::string box_file, std::string lut_file,
                std::string wire_delay, bool nomfs, std::string tempdir_name
 )
 {
@@ -266,8 +265,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
        fprintf(f, "%s\n", abc9_script.c_str());
        fclose(f);
 
-       log_push();
-
        int count_outputs = design->scratchpad_get_int("write_xaiger.num_outputs");
        log("Extracted %d AND gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
                        design->scratchpad_get_int("write_xaiger.num_ands"),
@@ -351,35 +348,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
                if (mapped_mod == NULL)
                        log_error("ABC output file does not contain a module `$__abc9__'.\n");
 
-               for (auto &it : mapped_mod->wires_) {
-                       RTLIL::Wire *w = it.second;
-                       RTLIL::Wire *remap_wire = module->addWire(remap_name(w->name), GetSize(w));
-                       if (markgroups) remap_wire->attributes[ID(abcgroup)] = map_autoidx;
-               }
+               for (auto w : mapped_mod->wires())
+                       module->addWire(remap_name(w->name), GetSize(w));
 
-               dict<IdString, bool> abc9_box;
-               vector<RTLIL::Cell*> boxes;
-               for (auto cell : cells) {
-                       if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_))) {
-                               module->remove(cell);
-                               continue;
-                       }
-                       auto jt = abc9_box.find(cell->type);
-                       if (jt == abc9_box.end()) {
-                               RTLIL::Module* box_module = design->module(cell->type);
-                               jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first;
-                       }
-                       if (jt->second) {
-                               auto kt = cell->attributes.find("\\abc9_keep");
-                               bool abc9_keep = false;
-                               if (kt != cell->attributes.end()) {
-                                       abc9_keep = kt->second.as_bool();
-                                       cell->attributes.erase(kt);
-                               }
-                               if (!abc9_keep)
-                                       boxes.emplace_back(cell);
-                       }
-               }
+               for (auto it = module->cells_.begin(); it != module->cells_.end(); )
+                       if (it->second->type.in(ID($_AND_), ID($_NOT_), ID($__ABC9_FF_)))
+                               it = module->cells_.erase(it);
+                       else
+                               ++it;
 
                dict<SigBit, pool<IdString>> bit_drivers, bit_users;
                TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
@@ -436,7 +412,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
                                }
                                else
                                        log_abort();
-                               if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
                                continue;
                        }
                        cell_stats[mapped_cell->type]++;
@@ -449,7 +424,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
                                        SigSpec my_a = module->wires_.at(remap_name(mapped_cell->getPort(ID::A).as_wire()->name));
                                        SigSpec my_y = module->wires_.at(remap_name(mapped_cell->getPort(ID::Y).as_wire()->name));
                                        module->connect(my_y, my_a);
-                                       if (markgroups) mapped_cell->attributes[ID(abcgroup)] = map_autoidx;
                                        log_abort();
                                        continue;
                                }
@@ -461,21 +435,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
                                cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
                        }
 
-                       if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx;
-                       if (existing_cell) {
-                               cell->parameters = existing_cell->parameters;
-                               cell->attributes = existing_cell->attributes;
-                       }
-                       else {
-                               cell->parameters = mapped_cell->parameters;
-                               cell->attributes = mapped_cell->attributes;
-                       }
-
                        RTLIL::Module* box_module = design->module(mapped_cell->type);
                        auto abc9_flop = box_module && box_module->attributes.count("\\abc9_flop");
-                       for (auto &conn : mapped_cell->connections()) {
+                       for (auto &mapped_conn : mapped_cell->connections()) {
                                RTLIL::SigSpec newsig;
-                               for (auto c : conn.second.chunks()) {
+                               for (auto c : mapped_conn.second.chunks()) {
                                        if (c.width == 0)
                                                continue;
                                        //log_assert(c.width == 1);
@@ -483,37 +447,41 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *module, std::string scrip
                                                c.wire = module->wires_.at(remap_name(c.wire->name));
                                        newsig.append(c);
                                }
-                               cell->setPort(conn.first, newsig);
-
-                               if (!abc9_flop) {
-                                       if (cell->input(conn.first)) {
-                                               for (auto i : newsig)
-                                                       bit2sinks[i].push_back(cell);
-                                               for (auto i : conn.second)
-                                                       bit_users[i].insert(mapped_cell->name);
-                                       }
-                                       if (cell->output(conn.first))
-                                               for (auto i : conn.second)
-                                                       bit_drivers[i].insert(mapped_cell->name);
+                               if (existing_cell) {
+                                       auto it = existing_cell->connections_.find(mapped_conn.first);
+                                       if (it == existing_cell->connections_.end())
+                                               continue;
+                                       log_assert(GetSize(newsig) >= GetSize(it->second));
+                                       newsig = newsig.extract(0, GetSize(it->second));
+                               }
+                               cell->setPort(mapped_conn.first, newsig);
+
+                               if (abc9_flop)
+                                       continue;
+
+                               if (cell->input(mapped_conn.first)) {
+                                       for (auto i : newsig)
+                                               bit2sinks[i].push_back(cell);
+                                       for (auto i : mapped_conn.second)
+                                               bit_users[i].insert(mapped_cell->name);
                                }
+                               if (cell->output(mapped_conn.first))
+                                       for (auto i : mapped_conn.second)
+                                               bit_drivers[i].insert(mapped_cell->name);
                        }
-               }
 
-               for (auto existing_cell : boxes) {
-                       Cell *cell = module->cell(remap_name(existing_cell->name));
-                       if (cell) {
-                               for (auto &conn : existing_cell->connections()) {
-                                       if (!conn.second.is_wire())
-                                               continue;
-                                       Wire *wire = conn.second.as_wire();
-                                       if (!wire->get_bool_attribute(ID(abc9_padding)))
-                                               continue;
-                                       cell->unsetPort(conn.first);
-                                       log_debug("Dropping padded port connection for %s (%s) .%s (%s )\n", log_id(cell), cell->type.c_str(), log_id(conn.first), log_signal(conn.second));
+                       if (existing_cell) {
+                               cell->parameters = existing_cell->parameters;
+                               cell->attributes = existing_cell->attributes;
+                               if (cell->attributes.erase("\\abc9_box_seq")) {
+                                       module->swap_names(cell, existing_cell);
+                                       module->remove(existing_cell);
                                }
-                               module->swap_names(cell, existing_cell);
                        }
-                       module->remove(existing_cell);
+                       else {
+                               cell->parameters = mapped_cell->parameters;
+                               cell->attributes = mapped_cell->attributes;
+                       }
                }
 
                // Copy connections (and rename) from mapped_mod to module
@@ -645,8 +613,6 @@ clone_lut:
        //{
        //      log("Don't call ABC as there is nothing to map.\n");
        //}
-
-       log_pop();
 }
 
 struct Abc9MapPass : public Pass {
@@ -695,8 +661,6 @@ struct Abc9MapPass : public Pass {
                log("        set delay target. the string {D} in the default scripts above is\n");
                log("        replaced by this option when used, and an empty string otherwise\n");
                log("        (indicating best possible delay).\n");
-//             log("        This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n");
-//             log("        default scripts above.\n");
                log("\n");
 //             log("    -S <num>\n");
 //             log("        maximum number of LUT inputs shared.\n");
@@ -718,28 +682,14 @@ struct Abc9MapPass : public Pass {
                log("        generate netlist using luts. Use the specified costs for luts with 1,\n");
                log("        2, 3, .. inputs.\n");
                log("\n");
-//             log("    -dff\n");
-//             log("        also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");
-//             log("        clock domains are automatically partitioned in clock domains and each\n");
-//             log("        domain is passed through ABC independently.\n");
-//             log("\n");
-//             log("    -clk [!]<clock-signal-name>[,[!]<enable-signal-name>]\n");
-//             log("        use only the specified clock domain. this is like -dff, but only FF\n");
-//             log("        cells that belong to the specified clock domain are used.\n");
-//             log("\n");
-//             log("    -keepff\n");
-//             log("        set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n");
-//             log("        them, for example for equivalence checking.)\n");
-//             log("\n");
+               log("    -dff\n");
+               log("        also pass $_ABC9_FF_ cells through to ABC. modules with many clock\n");
+               log("        domains are marked as such and automatically partitioned by ABC.\n");
+               log("\n");
                log("    -showtmp\n");
                log("        print the temp dir name in log. usually this is suppressed so that the\n");
                log("        command output is identical across runs.\n");
                log("\n");
-               log("    -markgroups\n");
-               log("        set a 'abcgroup' attribute on all objects created by ABC. The value of\n");
-               log("        this attribute is a unique integer for each ABC process started. This\n");
-               log("        is useful for debugging the partitioning of clock domains.\n");
-               log("\n");
                log("    -box <file>\n");
                log("        pass this file with box library to ABC. Use with -lut.\n");
                log("\n");
@@ -759,7 +709,6 @@ struct Abc9MapPass : public Pass {
        void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
        {
                log_header(design, "Executing ABC9_MAP pass (technology mapping using ABC9).\n");
-               log_push();
 
 #ifdef ABCEXTERNAL
                std::string exe_file = ABCEXTERNAL;
@@ -773,7 +722,6 @@ struct Abc9MapPass : public Pass {
                bool show_tempdir = false;
                bool nomfs = false;
                vector<int> lut_costs;
-               markgroups = false;
 
 #if 0
                cleanup = false;
@@ -787,6 +735,22 @@ struct Abc9MapPass : public Pass {
 #endif
 #endif
 
+               std::string lut_arg, luts_arg;
+               exe_file = design->scratchpad_get_string("abc9.exe", exe_file /* inherit default value if not set */);
+               script_file = design->scratchpad_get_string("abc9.script", script_file);
+               if (design->scratchpad.count("abc9.D")) {
+                       delay_target = "-D " + design->scratchpad_get_string("abc9.D");
+               }
+               lut_arg = design->scratchpad_get_string("abc9.lut", lut_arg);
+               luts_arg = design->scratchpad_get_string("abc9.luts", luts_arg);
+               fast_mode = design->scratchpad_get_bool("abc9.fast", fast_mode);
+               show_tempdir = design->scratchpad_get_bool("abc9.showtmp", show_tempdir);
+               box_file = design->scratchpad_get_string("abc9.box", box_file);
+               if (design->scratchpad.count("abc9.W")) {
+                       wire_delay = "-W " + design->scratchpad_get_string("abc9.W");
+               }
+               nomfs = design->scratchpad_get_bool("abc9.nomfs", nomfs);
+
                size_t argidx;
                char pwd [PATH_MAX];
                if (!getcwd(pwd, sizeof(pwd))) {
@@ -801,9 +765,6 @@ struct Abc9MapPass : public Pass {
                        }
                        if (arg == "-script" && argidx+1 < args.size()) {
                                script_file = args[++argidx];
-                               rewrite_filename(script_file);
-                               if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
-                                       script_file = std::string(pwd) + "/" + script_file;
                                continue;
                        }
                        if (arg == "-D" && argidx+1 < args.size()) {
@@ -815,45 +776,11 @@ struct Abc9MapPass : public Pass {
                        //      continue;
                        //}
                        if (arg == "-lut" && argidx+1 < args.size()) {
-                               string arg = args[++argidx];
-                               if (arg.find_first_not_of("0123456789:") == std::string::npos) {
-                                       size_t pos = arg.find_first_of(':');
-                                       int lut_mode = 0, lut_mode2 = 0;
-                                       if (pos != string::npos) {
-                                               lut_mode = atoi(arg.substr(0, pos).c_str());
-                                               lut_mode2 = atoi(arg.substr(pos+1).c_str());
-                                       } else {
-                                               lut_mode = atoi(arg.c_str());
-                                               lut_mode2 = lut_mode;
-                                       }
-                                       lut_costs.clear();
-                                       for (int i = 0; i < lut_mode; i++)
-                                               lut_costs.push_back(1);
-                                       for (int i = lut_mode; i < lut_mode2; i++)
-                                               lut_costs.push_back(2 << (i - lut_mode));
-                               }
-                               else {
-                                       lut_file = arg;
-                                       rewrite_filename(lut_file);
-                                       if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+')
-                                               lut_file = std::string(pwd) + "/" + lut_file;
-                               }
+                               lut_arg = args[++argidx];
                                continue;
                        }
                        if (arg == "-luts" && argidx+1 < args.size()) {
-                               lut_costs.clear();
-                               for (auto &tok : split_tokens(args[++argidx], ",")) {
-                                       auto parts = split_tokens(tok, ":");
-                                       if (GetSize(parts) == 0 && !lut_costs.empty())
-                                               lut_costs.push_back(lut_costs.back());
-                                       else if (GetSize(parts) == 1)
-                                               lut_costs.push_back(atoi(parts.at(0).c_str()));
-                                       else if (GetSize(parts) == 2)
-                                               while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
-                                                       lut_costs.push_back(atoi(parts.at(1).c_str()));
-                                       else
-                                               log_cmd_error("Invalid -luts syntax.\n");
-                               }
+                               lut_arg = args[++argidx];
                                continue;
                        }
                        if (arg == "-fast") {
@@ -864,10 +791,6 @@ struct Abc9MapPass : public Pass {
                                show_tempdir = true;
                                continue;
                        }
-                       if (arg == "-markgroups") {
-                               markgroups = true;
-                               continue;
-                       }
                        if (arg == "-box" && argidx+1 < args.size()) {
                                box_file = args[++argidx];
                                continue;
@@ -888,6 +811,52 @@ struct Abc9MapPass : public Pass {
                }
                extra_args(args, argidx, design);
 
+               rewrite_filename(script_file);
+               if (!script_file.empty() && !is_absolute_path(script_file) && script_file[0] != '+')
+                       script_file = std::string(pwd) + "/" + script_file;
+
+               // handle -lut / -luts args
+               if (!lut_arg.empty()) {
+                       string arg = lut_arg;
+                       if (arg.find_first_not_of("0123456789:") == std::string::npos) {
+                               size_t pos = arg.find_first_of(':');
+                               int lut_mode = 0, lut_mode2 = 0;
+                               if (pos != string::npos) {
+                                       lut_mode = atoi(arg.substr(0, pos).c_str());
+                                       lut_mode2 = atoi(arg.substr(pos+1).c_str());
+                               } else {
+                                       lut_mode = atoi(arg.c_str());
+                                       lut_mode2 = lut_mode;
+                               }
+                               lut_costs.clear();
+                               for (int i = 0; i < lut_mode; i++)
+                                       lut_costs.push_back(1);
+                               for (int i = lut_mode; i < lut_mode2; i++)
+                                       lut_costs.push_back(2 << (i - lut_mode));
+                       }
+                       else {
+                               lut_file = arg;
+                               rewrite_filename(lut_file);
+                               if (!lut_file.empty() && !is_absolute_path(lut_file) && lut_file[0] != '+')
+                                       lut_file = std::string(pwd) + "/" + lut_file;
+                       }
+               }
+               if (!luts_arg.empty()) {
+                       lut_costs.clear();
+                       for (auto &tok : split_tokens(luts_arg, ",")) {
+                               auto parts = split_tokens(tok, ":");
+                               if (GetSize(parts) == 0 && !lut_costs.empty())
+                                       lut_costs.push_back(lut_costs.back());
+                               else if (GetSize(parts) == 1)
+                                       lut_costs.push_back(atoi(parts.at(0).c_str()));
+                               else if (GetSize(parts) == 2)
+                                       while (GetSize(lut_costs) < atoi(parts.at(0).c_str()))
+                                               lut_costs.push_back(atoi(parts.at(1).c_str()));
+                               else
+                                       log_cmd_error("Invalid -luts syntax.\n");
+                       }
+               }
+
                // ABC expects a box file for XAIG
                if (box_file.empty())
                        box_file = "+/dummy.box";
@@ -907,14 +876,13 @@ struct Abc9MapPass : public Pass {
                                continue;
                        }
 
-                       const std::vector<RTLIL::Cell*> all_cells = mod->selected_cells();
+                       if (!design->selected_whole_module(mod))
+                               log_error("Can't handle partially selected module %s!\n", log_id(mod));
 
                        abc9_module(design, mod, script_file, exe_file, lut_costs,
-                                       delay_target, lutin_shared, fast_mode, all_cells, show_tempdir,
+                                       delay_target, lutin_shared, fast_mode, show_tempdir,
                                        box_file, lut_file, wire_delay, nomfs, tempdir_name);
                }
-
-               log_pop();
        }
 } Abc9MapPass;