diff options
Diffstat (limited to 'passes/techmap/abc9.cc')
-rw-r--r-- | passes/techmap/abc9.cc | 214 |
1 files changed, 105 insertions, 109 deletions
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc index 6fdf987f0..27106cc5d 100644 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@ -71,22 +71,21 @@ RTLIL::Module *module; bool clk_polarity, en_polarity; RTLIL::SigSpec clk_sig, en_sig; -inline std::string remap_name(RTLIL::IdString abc_name) +inline std::string remap_name(RTLIL::IdString abc9_name) { - return stringf("$abc$%d$%s", map_autoidx, abc_name.c_str()+1); + return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1); } -void handle_loops(RTLIL::Design *design, - const dict<IdString,pool<IdString>> &scc_break_inputs) +void handle_loops(RTLIL::Design *design) { - Pass::call(design, "scc -set_attr abc_scc_id {}"); + Pass::call(design, "scc -set_attr abc9_scc_id {}"); // For every unique SCC found, (arbitrarily) find the first // cell in the component, and select (and mark) all its output // wires pool<RTLIL::Const> ids_seen; for (auto cell : module->cells()) { - auto it = cell->attributes.find(ID(abc_scc_id)); + auto it = cell->attributes.find(ID(abc9_scc_id)); if (it != cell->attributes.end()) { auto r = ids_seen.insert(it->second); if (r.second) { @@ -106,7 +105,7 @@ void handle_loops(RTLIL::Design *design, log_assert(w->port_input); log_assert(b.offset < GetSize(w)); } - w->set_bool_attribute(ID(abc_scc_break)); + w->set_bool_attribute(ID(abc9_scc_break)); module->swap_names(b.wire, w); c.second = RTLIL::SigBit(w, b.offset); } @@ -114,36 +113,12 @@ void handle_loops(RTLIL::Design *design, } cell->attributes.erase(it); } - - auto jt = scc_break_inputs.find(cell->type); - if (jt != scc_break_inputs.end()) - for (auto port_name : jt->second) { - RTLIL::SigSpec sig; - auto &rhs = cell->connections_.at(port_name); - for (auto b : rhs) { - Wire *w = b.wire; - if (!w) continue; - w->port_output = true; - w->set_bool_attribute(ID(abc_scc_break)); - w = module->wire(stringf("%s.abci", w->name.c_str())); - if (!w) { - w = module->addWire(stringf("%s.abci", b.wire->name.c_str()), GetSize(b.wire)); - w->port_input = true; - } - else { - log_assert(b.offset < GetSize(w)); - log_assert(w->port_input); - } - sig.append(RTLIL::SigBit(w, b.offset)); - } - rhs = sig; - } } module->fixup_ports(); } -std::string add_echos_to_abc_cmd(std::string str) +std::string add_echos_to_abc9_cmd(std::string str) { std::string new_str, token; for (size_t i = 0; i < str.size(); i++) { @@ -165,7 +140,7 @@ std::string add_echos_to_abc_cmd(std::string str) return new_str; } -std::string fold_abc_cmd(std::string str) +std::string fold_abc9_cmd(std::string str) { std::string token, new_str = " "; int char_counter = 10; @@ -209,7 +184,7 @@ std::string replace_tempdir(std::string text, std::string tempdir_name, bool sho return text; } -struct abc_output_filter +struct abc9_output_filter { bool got_cr; int escape_seq_state; @@ -217,7 +192,7 @@ struct abc_output_filter std::string tempdir_name; bool show_tempdir; - abc_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) + abc9_output_filter(std::string tempdir_name, bool show_tempdir) : tempdir_name(tempdir_name), show_tempdir(show_tempdir) { got_cr = false; escape_seq_state = 0; @@ -272,8 +247,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str, bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, bool show_tempdir, std::string box_file, std::string lut_file, - std::string wire_delay, const dict<int,IdString> &box_lookup, - const dict<IdString,pool<IdString>> &scc_break_inputs + std::string wire_delay, const dict<int,IdString> &box_lookup, bool nomfs ) { module = current_module; @@ -319,68 +293,72 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n", module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str()); - std::string abc_script; + std::string abc9_script; if (!lut_costs.empty()) { - abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); + abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str()); if (!box_file.empty()) - abc_script += stringf("read_box -v %s; ", box_file.c_str()); + abc9_script += stringf("read_box -v %s; ", box_file.c_str()); } else if (!lut_file.empty()) { - abc_script += stringf("read_lut %s; ", lut_file.c_str()); + abc9_script += stringf("read_lut %s; ", lut_file.c_str()); if (!box_file.empty()) - abc_script += stringf("read_box -v %s; ", box_file.c_str()); + abc9_script += stringf("read_box -v %s; ", box_file.c_str()); } else log_abort(); - abc_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); + abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str()); if (!script_file.empty()) { if (script_file[0] == '+') { for (size_t i = 1; i < script_file.size(); i++) if (script_file[i] == '\'') - abc_script += "'\\''"; + abc9_script += "'\\''"; else if (script_file[i] == ',') - abc_script += " "; + abc9_script += " "; else - abc_script += script_file[i]; + abc9_script += script_file[i]; } else - abc_script += stringf("source %s", script_file.c_str()); + abc9_script += stringf("source %s", script_file.c_str()); } else if (!lut_costs.empty() || !lut_file.empty()) { //bool all_luts_cost_same = true; //for (int this_cost : lut_costs) // if (this_cost != lut_costs.front()) // all_luts_cost_same = false; - abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; + abc9_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT; //if (all_luts_cost_same && !fast_mode) - // abc_script += "; lutpack {S}"; + // abc9_script += "; lutpack {S}"; } else log_abort(); //if (script_file.empty() && !delay_target.empty()) - // for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) - // abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); + // for (size_t pos = abc9_script.find("dretime;"); pos != std::string::npos; pos = abc9_script.find("dretime;", pos+1)) + // abc9_script = abc9_script.substr(0, pos) + "dretime; retime -o {D};" + abc9_script.substr(pos+8); + + for (size_t pos = abc9_script.find("{D}"); pos != std::string::npos; pos = abc9_script.find("{D}", pos)) + abc9_script = abc9_script.substr(0, pos) + delay_target + abc9_script.substr(pos+3); - for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) - abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3); + //for (size_t pos = abc9_script.find("{S}"); pos != std::string::npos; pos = abc9_script.find("{S}", pos)) + // abc9_script = abc9_script.substr(0, pos) + lutin_shared + abc9_script.substr(pos+3); - //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 = abc9_script.find("{W}"); pos != std::string::npos; pos = abc9_script.find("{W}", pos)) + abc9_script = abc9_script.substr(0, pos) + wire_delay + abc9_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); + if (nomfs) + for (size_t pos = abc9_script.find("&mfs"); pos != std::string::npos; pos = abc9_script.find("&mfs", pos)) + abc9_script = abc9_script.erase(pos, strlen("&mfs")); - abc_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); - abc_script = add_echos_to_abc_cmd(abc_script); + abc9_script += stringf("; &write %s/output.aig", tempdir_name.c_str()); + abc9_script = add_echos_to_abc9_cmd(abc9_script); - for (size_t i = 0; i+1 < abc_script.size(); i++) - if (abc_script[i] == ';' && abc_script[i+1] == ' ') - abc_script[i+1] = '\n'; + for (size_t i = 0; i+1 < abc9_script.size(); i++) + if (abc9_script[i] == ';' && abc9_script[i+1] == ' ') + abc9_script[i+1] = '\n'; FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt"); - fprintf(f, "%s\n", abc_script.c_str()); + fprintf(f, "%s\n", abc9_script.c_str()); fclose(f); if (dff_mode || !clk_str.empty()) @@ -413,7 +391,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri RTLIL::Selection& sel = design->selection_stack.back(); sel.select(module); - handle_loops(design, scc_break_inputs); + handle_loops(design); Pass::call(design, "aigmap"); @@ -446,7 +424,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri // the expose operation -- remove them from PO/PI // and re-connecting them back together for (auto wire : module->wires()) { - auto it = wire->attributes.find(ID(abc_scc_break)); + auto it = wire->attributes.find(ID(abc9_scc_break)); if (it != wire->attributes.end()) { wire->attributes.erase(it); log_assert(wire->port_output); @@ -476,28 +454,28 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str()); #ifndef YOSYS_LINK_ABC - abc_output_filter filt(tempdir_name, show_tempdir); - int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1)); + abc9_output_filter filt(tempdir_name, show_tempdir); + int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1)); #else // These needs to be mutable, supposedly due to getopt - char *abc_argv[5]; + char *abc9_argv[5]; string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str()); - abc_argv[0] = strdup(exe_file.c_str()); - abc_argv[1] = strdup("-s"); - abc_argv[2] = strdup("-f"); - abc_argv[3] = strdup(tmp_script_name.c_str()); - abc_argv[4] = 0; - int ret = Abc_RealMain(4, abc_argv); - free(abc_argv[0]); - free(abc_argv[1]); - free(abc_argv[2]); - free(abc_argv[3]); + abc9_argv[0] = strdup(exe_file.c_str()); + abc9_argv[1] = strdup("-s"); + abc9_argv[2] = strdup("-f"); + abc9_argv[3] = strdup(tmp_script_name.c_str()); + abc9_argv[4] = 0; + int ret = Abc_RealMain(4, abc9_argv); + free(abc9_argv[0]); + free(abc9_argv[1]); + free(abc9_argv[2]); + free(abc9_argv[3]); #endif if (ret != 0) 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"); - ifs.open(buffer); + ifs.open(buffer, std::ifstream::binary); if (ifs.fail()) log_error("Can't open ABC output file `%s'.\n", buffer.c_str()); @@ -539,7 +517,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri signal = std::move(bits); } - dict<IdString, bool> abc_box; + dict<IdString, bool> abc9_box; vector<RTLIL::Cell*> boxes; for (const auto &it : module->cells_) { auto cell = it.second; @@ -547,10 +525,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri module->remove(cell); continue; } - auto jt = abc_box.find(cell->type); - if (jt == abc_box.end()) { + auto jt = abc9_box.find(cell->type); + if (jt == abc9_box.end()) { RTLIL::Module* box_module = design->module(cell->type); - jt = abc_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc_box_id)))).first; + jt = abc9_box.insert(std::make_pair(cell->type, box_module && box_module->attributes.count(ID(abc9_box_id)))).first; } if (jt->second) boxes.emplace_back(cell); @@ -632,7 +610,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri existing_cell = module->cell(c->name); log_assert(existing_cell); cell = module->addCell(remap_name(c->name), c->type); - module->swap_names(cell, existing_cell); } if (markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; @@ -668,8 +645,22 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri } } - for (auto cell : boxes) - module->remove(cell); + 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)); + } + module->swap_names(cell, existing_cell); + } + module->remove(existing_cell); + } // Copy connections (and rename) from mapped_mod to module for (auto conn : mapped_mod->connections()) { @@ -840,17 +831,17 @@ struct Abc9Pass : public Pass { log(" if no -script parameter is given, the following scripts are used:\n"); log("\n"); log(" for -lut/-luts (only one LUT size):\n"); - log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str()); log("\n"); log(" for -lut/-luts (different LUT sizes):\n"); - log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT).c_str()); + log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str()); log("\n"); log(" -fast\n"); log(" use different default scripts that are slightly faster (at the cost\n"); log(" of output quality):\n"); log("\n"); log(" for -lut/-luts:\n"); - log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str()); + log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str()); log("\n"); log(" -D <picoseconds>\n"); log(" set delay target. the string {D} in the default scripts above is\n"); @@ -934,6 +925,7 @@ struct Abc9Pass : public Pass { std::string delay_target, lutin_shared = "-S 1", wire_delay; bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true; bool show_tempdir = false; + bool nomfs = false; vector<int> lut_costs; markgroups = false; @@ -1050,23 +1042,31 @@ struct Abc9Pass : public Pass { } if (arg == "-box" && argidx+1 < args.size()) { box_file = args[++argidx]; - rewrite_filename(box_file); - if (!box_file.empty() && !is_absolute_path(box_file)) - box_file = std::string(pwd) + "/" + box_file; continue; } if (arg == "-W" && argidx+1 < args.size()) { wire_delay = "-W " + args[++argidx]; continue; } + if (arg == "-nomfs") { + nomfs = true; + continue; + } break; } extra_args(args, argidx, design); + // ABC expects a box file for XAIG + if (box_file.empty()) + box_file = "+/dummy.box"; + + rewrite_filename(box_file); + if (!box_file.empty() && !is_absolute_path(box_file)) + box_file = std::string(pwd) + "/" + box_file; + dict<int,IdString> box_lookup; - dict<IdString,pool<IdString>> scc_break_inputs; for (auto m : design->modules()) { - auto it = m->attributes.find(ID(abc_box_id)); + auto it = m->attributes.find(ID(abc9_box_id)); if (it == m->attributes.end()) continue; if (m->name.begins_with("$paramod")) @@ -1074,7 +1074,7 @@ struct Abc9Pass : public Pass { auto id = it->second.as_int(); auto r = box_lookup.insert(std::make_pair(id, m->name)); if (!r.second) - log_error("Module '%s' has the same abc_box_id = %d value as '%s'.\n", + log_error("Module '%s' has the same abc9_box_id = %d value as '%s'.\n", log_id(m), id, log_id(r.first->second)); log_assert(r.second); @@ -1082,28 +1082,24 @@ struct Abc9Pass : public Pass { for (auto p : m->ports) { auto w = m->wire(p); log_assert(w); - if (w->port_input) { - if (w->attributes.count(ID(abc_scc_break))) - scc_break_inputs[m->name].insert(p); - if (w->attributes.count(ID(abc_carry))) { + if (w->attributes.count(ID(abc9_carry))) { + if (w->port_input) { if (carry_in) - log_error("Module '%s' contains more than one 'abc_carry' input port.\n", log_id(m)); + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); carry_in = w; } - } - if (w->port_output) { - if (w->attributes.count(ID(abc_carry))) { + else if (w->port_output) { if (carry_out) - log_error("Module '%s' contains more than one 'abc_carry' input port.\n", log_id(m)); + log_error("Module '%s' contains more than one 'abc9_carry' input port.\n", log_id(m)); carry_out = w; } } } if (carry_in || carry_out) { if (carry_in && !carry_out) - log_error("Module '%s' contains an 'abc_carry' input port but no output port.\n", log_id(m)); + log_error("Module '%s' contains an 'abc9_carry' input port but no output port.\n", log_id(m)); if (!carry_in && carry_out) - log_error("Module '%s' contains an 'abc_carry' output port but no input port.\n", log_id(m)); + log_error("Module '%s' contains an 'abc9_carry' output port but no input port.\n", log_id(m)); // Make carry_in the last PI, and carry_out the last PO // since ABC requires it this way auto &ports = m->ports; @@ -1131,7 +1127,7 @@ struct Abc9Pass : public Pass { for (auto mod : design->selected_modules()) { - if (mod->attributes.count(ID(abc_box_id))) + if (mod->attributes.count(ID(abc9_box_id))) continue; if (mod->processes.size() > 0) { @@ -1144,7 +1140,7 @@ struct Abc9Pass : public Pass { if (!dff_mode || !clk_str.empty()) { abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, scc_break_inputs); + box_file, lut_file, wire_delay, box_lookup, nomfs); continue; } @@ -1290,7 +1286,7 @@ struct Abc9Pass : public Pass { en_sig = assign_map(std::get<3>(it.first)); abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$", keepff, delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay, box_lookup, scc_break_inputs); + box_file, lut_file, wire_delay, box_lookup, nomfs); assign_map.set(mod); } } |