From: Eddie Hung Date: Fri, 16 Aug 2019 23:51:22 +0000 (-0700) Subject: Merge branch 'eddie/abc9_refactor' into xaig_dff X-Git-Tag: working-ls180~881^2^2~248 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=24c934f1af3859fe64ff4fb87a2a3de97695cde4;p=yosys.git Merge branch 'eddie/abc9_refactor' into xaig_dff --- 24c934f1af3859fe64ff4fb87a2a3de97695cde4 diff --cc backends/aiger/xaiger.cc index 5eeae3b82,41a79d9dd..5d3677ab3 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@@ -768,19 -568,18 +726,18 @@@ struct XAigerWrite std::stringstream h_buffer; auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1); write_h_buffer(1); - log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ci_bits)); - write_h_buffer(input_bits.size() + ci_bits.size()); - log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(co_bits)); - write_h_buffer(output_bits.size() + co_bits.size()); - log_debug("piNum = %d\n", GetSize(input_bits)); - write_h_buffer(input_bits.size()); - log_debug("poNum = %d\n", GetSize(output_bits)); - write_h_buffer(output_bits.size()); ++ log_debug("ciNum = %d\n", GetSize(input_bits) + GetSize(ff_bits) + GetSize(ci_bits)); + write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size()); - log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size()); - write_h_buffer(output_bits.size() + ff_bits.size() + co_bits.size()); - log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size()); - write_h_buffer(input_bits.size()+ ff_bits.size()); - log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size()); ++ log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(ff_bits) + GetSize(co_bits)); ++ write_h_buffer(output_bits.size() + GetSize(ff_bits) + GetSize(co_bits)); ++ log_debug("piNum = %d\n", GetSize(input_bits) + GetSize(ff_bits)); ++ write_h_buffer(input_bits.size() + ff_bits.size()); ++ log_debug("poNum = %d\n", GetSize(output_bits) + GetSize(ff_bits)); + write_h_buffer(output_bits.size() + ff_bits.size()); - log_debug("boxNum = %zu\n", box_list.size()); + log_debug("boxNum = %d\n", GetSize(box_list)); write_h_buffer(box_list.size()); - RTLIL::Module *holes_module = nullptr; - holes_module = module->design->addModule("$__holes__"); + RTLIL::Module *holes_module = module->design->addModule("$__holes__"); log_assert(holes_module); int port_id = 1; @@@ -908,13 -683,20 +865,20 @@@ if (!cell->type.in("$_NOT_", "$_AND_")) log_error("Whitebox contents cannot be represented as AIG. Please verify whiteboxes are synthesisable.\n"); - Pass::call(holes_module->design, "clean -purge"); + holes_module->design->selection_stack.pop_back(); + + // 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_module->design->modules_.erase(holes_module->name); + holes_design->add(holes_module); + Pass::call(holes_design, "clean -purge"); std::stringstream a_buffer; - XAigerWriter writer(holes_module, true /* holes_mode */); + XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */); writer.write_aiger(a_buffer, false /*ascii_mode*/); - holes_module->design->selection_stack.pop_back(); + delete holes_design; f << "a"; std::string buffer_str = a_buffer.str(); @@@ -956,11 -735,7 +919,11 @@@ if (output_bits.count(b)) { int o = ordered_outputs.at(b); - output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), i, log_id(wire)); + int init = 2; + auto it = init_map.find(b); + if (it != init_map.end()) + init = it->second ? 1 : 0; - output_lines[o] += stringf("output %lu %d %s %d\n", o - co_bits.size(), i, log_id(wire), init); ++ output_lines[o] += stringf("output %d %d %s %d\n", o - GetSize(co_bits), i, log_id(wire), init); continue; } diff --cc passes/techmap/abc9.cc index b9eb71cf1,4cdd392b5..50a6e0fe5 --- a/passes/techmap/abc9.cc +++ b/passes/techmap/abc9.cc @@@ -86,8 -85,8 +85,8 @@@ void handle_loops(RTLIL::Design *design // cell in the component, and select (and mark) all its output // wires pool ids_seen; - for (auto cell : module->cells()) { + for (auto cell : module->selected_cells()) { - auto it = cell->attributes.find("\\abc_scc_id"); + auto it = cell->attributes.find(ID(abc_scc_id)); if (it != cell->attributes.end()) { auto r = ids_seen.insert(it->second); if (r.second) { @@@ -285,10 -269,12 +269,12 @@@ struct abc_output_filte }; void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file, - bool cleanup, vector lut_costs, bool dff_mode, std::string clk_str, + bool cleanup, vector lut_costs, bool /*retime_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) + std::string wire_delay, const dict &box_lookup, + const dict> &scc_break_inputs + ) { module = current_module; map_autoidx = autoidx++; @@@ -450,9 -437,11 +440,9 @@@ } ifs.close(); Pass::call(design, stringf("write_verilog -noexpr -norename")); - design->remove(design->module("$__abc9__")); + design->remove(design->module(ID($__abc9__))); #endif - 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 @@@ -557,8 -541,9 +548,8 @@@ dict abc_box; vector boxes; - for (const auto &it : module->cells_) { - auto cell = it.second; - if (cell->type.in(ID($_AND_), ID($_NOT_))) { + for (auto cell : module->selected_cells()) { - if (cell->type.in("$_AND_", "$_NOT_", "$__ABC_FF_")) { ++ if (cell->type.in(ID($_AND_), ID($_NOT_), ID($__ABC_FF_))) { module->remove(cell); continue; } @@@ -571,21 -556,31 +562,31 @@@ boxes.emplace_back(cell); } - std::map cell_stats; + dict> bit_drivers, bit_users; + TopoSort toposort; + dict not2drivers; + dict> bit2sinks; + + std::map cell_stats; for (auto c : mapped_mod->cells()) { + toposort.node(c->name); + RTLIL::Cell *cell = nullptr; - if (c->type == "$_NOT_") { - RTLIL::SigBit a_bit = c->getPort("\\A").as_bit(); - RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit(); + if (c->type == ID($_NOT_)) { + RTLIL::SigBit a_bit = c->getPort(ID(A)); + RTLIL::SigBit y_bit = c->getPort(ID(Y)); + bit_users[a_bit].insert(c->name); + bit_drivers[y_bit].insert(c->name); + if (!a_bit.wire) { - c->setPort("\\Y", module->addWire(NEW_ID)); + c->setPort(ID(Y), module->addWire(NEW_ID)); RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name)); log_assert(wire); - module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1); + module->connect(RTLIL::SigBit(wire, y_bit.offset), State::S1); } - else if (!lut_costs.empty() || !lut_file.empty()) { - RTLIL::Cell* driver_lut = nullptr; + else { + RTLIL::Cell* driving_lut = nullptr; // ABC can return NOT gates that drive POs if (!a_bit.wire->port_input) { // If it's not a NOT gate that that comes from a PI directly, @@@ -597,45 -592,38 +598,36 @@@ driver_name = stringf("%s$lut", a_bit.wire->name.c_str()); else driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset); - driver_lut = mapped_mod->cell(driver_name); + driving_lut = mapped_mod->cell(driver_name); } - if (!driver_lut) { + if (!driving_lut) { - // If a driver couldn't be found (could be from PI, - // or from a box) then implement using a LUT + // If a driver couldn't be found (could be from PI or box CI) + // then implement using a LUT cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset), - RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), - 1); + RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset), + RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset), + RTLIL::Const::from_string("01")); + bit2sinks[cell->getPort(ID(A))].push_back(cell); + cell_stats[ID($lut)]++; } - else { - auto driver_a = driving_lut->getPort("\\A").chunks(); - for (auto &chunk : driver_a) - chunk.wire = module->wires_[remap_name(chunk.wire->name)]; - RTLIL::Const driver_lut = driving_lut->getParam("\\LUT"); - for (auto &b : driver_lut.bits) { - if (b == RTLIL::State::S0) b = RTLIL::State::S1; - else if (b == RTLIL::State::S1) b = RTLIL::State::S0; - } - cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())), - driver_a, - RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset), - driver_lut); - } - cell_stats["$lut"]++; + else - not2drivers[c] = driver_lut; ++ not2drivers[c] = driving_lut; + continue; } - if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx; - else - log_abort(); + if (cell && markgroups) cell->attributes[ID(abcgroup)] = map_autoidx; continue; } - cell_stats[RTLIL::unescape_id(c->type)]++; + cell_stats[c->type]++; - RTLIL::Cell *existing_cell = nullptr; - if (c->type == "$lut") { - if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) { - SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)]; - SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)]; + RTLIL::Cell *existing_cell = nullptr; + if (c->type == ID($lut)) { + if (GetSize(c->getPort(ID(A))) == 1 && c->getParam(ID(LUT)) == RTLIL::Const::from_string("01")) { + SigSpec my_a = module->wires_.at(remap_name(c->getPort(ID(A)).as_wire()->name)); + SigSpec my_y = module->wires_.at(remap_name(c->getPort(ID(Y)).as_wire()->name)); module->connect(my_y, my_a); - if (markgroups) c->attributes["\\abcgroup"] = map_autoidx; + if (markgroups) c->attributes[ID(abcgroup)] = map_autoidx; + log_abort(); continue; } cell = module->addCell(remap_name(c->name), c->type); @@@ -999,12 -1066,75 +1075,78 @@@ struct Abc9Pass : public Pass } extra_args(args, argidx, design); + if (lut_costs.empty() && lut_file.empty()) + log_cmd_error("abc9 must be called with '-lut' or '-luts'\n"); + + dict box_lookup; + dict> scc_break_inputs; + for (auto m : design->modules()) { + auto it = m->attributes.find(ID(abc_box_id)); + if (it == m->attributes.end()) + continue; + if (m->name.begins_with("$paramod")) + continue; + 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_id(m), id, log_id(r.first->second)); + log_assert(r.second); + + RTLIL::Wire *carry_in = nullptr, *carry_out = nullptr; + 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_in))) { + if (carry_in) + log_error("Module '%s' contains more than one 'abc_carry_in' port.\n", log_id(m)); + carry_in = w; + } + } + if (w->port_output) { + if (w->attributes.count(ID(abc_carry_out))) { + if (carry_out) + log_error("Module '%s' contains more than one 'abc_carry_out' 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_in' port but no 'abc_carry_out' port.\n", log_id(m)); + if (!carry_in && carry_out) + log_error("Module '%s' contains an 'abc_carry_out' port but no 'abc_carry_in' 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; + for (auto it = ports.begin(); it != ports.end(); ) { + RTLIL::Wire* w = m->wire(*it); + log_assert(w); + if (w == carry_in || w == carry_out) { + it = ports.erase(it); + continue; + } + if (w->port_id > carry_in->port_id) + --w->port_id; + if (w->port_id > carry_out->port_id) + --w->port_id; + log_assert(w->port_input || w->port_output); + log_assert(ports[w->port_id-1] == w->name); + ++it; + } + ports.push_back(carry_in->name); + carry_in->port_id = ports.size(); + ports.push_back(carry_out->name); + carry_out->port_id = ports.size(); + } + } + for (auto mod : design->selected_modules()) { - if (mod->attributes.count("\\abc_box_id")) + if (mod->attributes.count(ID(abc_box_id))) continue; if (mod->processes.size() > 0) { @@@ -1014,17 -1144,10 +1156,16 @@@ assign_map.set(mod); - if (!dff_mode || !clk_str.empty()) { - abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff, + if (true || /*!dff_mode ||*/ !clk_str.empty()) { + + design->selection_stack.emplace_back(false); + RTLIL::Selection& sel = design->selection_stack.back(); + sel.select(mod); + + abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, false, clk_str, keepff, delay_target, lutin_shared, fast_mode, show_tempdir, - box_file, lut_file, wire_delay); - + box_file, lut_file, wire_delay, box_lookup, scc_break_inputs); + design->selection_stack.pop_back(); continue; } @@@ -1208,25 -1291,18 +1349,26 @@@ clk_sig = assign_map(std::get<1>(it.first)); en_polarity = std::get<2>(it.first); en_sig = assign_map(std::get<3>(it.first)); + + pool assigned_names; + for (auto i : it.second) + assigned_names.insert(i->name); + sel.selected_members[mod->name] = std::move(assigned_names); + 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_file, lut_file, wire_delay, box_lookup, scc_break_inputs); assign_map.set(mod); } + + design->selection_stack.pop_back(); } - Pass::call(design, "clean"); - assign_map.clear(); + // The "clean" pass also contains a design->check() call + Pass::call(design, "clean"); + log_pop(); } } Abc9Pass;