diff options
36 files changed, 550 insertions, 359 deletions
diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000..a73779920 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,37 @@ +## CODE NOTIFICATIONS +# Register yourself here to be notified about modifications +# for any files you have an interest in/know your way around. + +# Each line is a file pattern followed by one or more users. +# Both github usernames and email addresses are supported. +# Order is important; the last matching pattern takes the most +# precedence. Previous matches will not be applied. + + +# PATH (can use glob) USERNAME(S) + +passes/cmds/scratchpad.cc @nakengelhardt +frontends/rpc/ @whitequark +backends/cxxrtl/ @whitequark +passes/cmds/bugpoint.cc @whitequark +passes/techmap/flowmap.cc @whitequark +passes/opt/opt_lut.cc @whitequark + + +## External Contributors +# Only users with write permission to the repository get review +# requests automatically, but we add information for other +# contributors here too, so we know who to ask to take a look. +# These still override previous lines, so be careful not to +# accidentally disable any of the above rules. + +techlibs/intel_alm/ @ZirconiumX + +# pyosys +misc/*.py @btut + +backends/firrtl @ucbjrl @azidar + +passes/sat/qbfsat.cc @boqwxp +passes/cmds/exec.cc @boqwxp +passes/cmds/printattrs.cc @boqwxp diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 6b910eecd..8bbadbc91 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -85,7 +85,7 @@ struct XAigerWriter dict<SigBit, SigBit> not_map, alias_map; dict<SigBit, pair<SigBit, SigBit>> and_map; vector<SigBit> ci_bits, co_bits; - dict<SigBit, Cell*> ff_bits; + vector<Cell*> ff_list; dict<SigBit, float> arrival_times; vector<pair<int, int>> aig_gates; @@ -156,7 +156,7 @@ struct XAigerWriter // promote keep wires for (auto wire : module->wires()) - if (wire->get_bool_attribute(ID::keep)) + if (wire->get_bool_attribute(ID::keep) || wire->get_bool_attribute(ID::abc9_keep)) sigmap.add(wire); for (auto wire : module->wires()) { @@ -232,8 +232,7 @@ struct XAigerWriter unused_bits.erase(D); undriven_bits.erase(Q); alias_map[Q] = D; - auto r YS_ATTRIBUTE(unused) = ff_bits.insert(std::make_pair(D, cell)); - log_assert(r.second); + ff_list.emplace_back(cell); continue; } @@ -420,8 +419,7 @@ struct XAigerWriter aig_map[bit] = 2*aig_m; } - for (const auto &i : ff_bits) { - const Cell *cell = i.second; + for (auto cell : ff_list) { const SigBit &q = sigmap(cell->getPort(ID::Q)); aig_m++, aig_i++; log_assert(!aig_map.count(q)); @@ -468,8 +466,8 @@ struct XAigerWriter aig_outputs.push_back(aig); } - for (auto &i : ff_bits) { - const SigBit &d = i.first; + for (auto cell : ff_list) { + const SigBit &d = sigmap(cell->getPort(ID::D)); aig_o++; aig_outputs.push_back(aig_map.at(d)); } @@ -541,16 +539,16 @@ struct XAigerWriter 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 = %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 = %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("ciNum = %d\n", GetSize(input_bits) + GetSize(ff_list) + GetSize(ci_bits)); + write_h_buffer(GetSize(input_bits) + GetSize(ff_list) + GetSize(ci_bits)); + log_debug("coNum = %d\n", GetSize(output_bits) + GetSize(ff_list) + GetSize(co_bits)); + write_h_buffer(GetSize(output_bits) + GetSize(ff_list) + GetSize(co_bits)); + log_debug("piNum = %d\n", GetSize(input_bits) + GetSize(ff_list)); + write_h_buffer(GetSize(input_bits) + GetSize(ff_list)); + log_debug("poNum = %d\n", GetSize(output_bits) + GetSize(ff_list)); + write_h_buffer(GetSize(output_bits) + GetSize(ff_list)); log_debug("boxNum = %d\n", GetSize(box_list)); - write_h_buffer(box_list.size()); + write_h_buffer(GetSize(box_list)); auto write_buffer_float = [](std::stringstream &buffer, float f32) { buffer.write(reinterpret_cast<const char*>(&f32), sizeof(f32)); @@ -564,7 +562,7 @@ struct XAigerWriter //for (auto bit : output_bits) // write_o_buffer(0); - if (!box_list.empty() || !ff_bits.empty()) { + if (!box_list.empty() || !ff_list.empty()) { dict<IdString, std::tuple<int,int,int>> cell_cache; int box_count = 0; @@ -601,17 +599,17 @@ struct XAigerWriter std::stringstream r_buffer; auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1); - log_debug("flopNum = %d\n", GetSize(ff_bits)); - write_r_buffer(ff_bits.size()); + log_debug("flopNum = %d\n", GetSize(ff_list)); + write_r_buffer(ff_list.size()); std::stringstream s_buffer; auto write_s_buffer = std::bind(write_buffer, std::ref(s_buffer), std::placeholders::_1); - write_s_buffer(ff_bits.size()); + write_s_buffer(ff_list.size()); dict<SigSpec, int> clk_to_mergeability; - for (const auto &i : ff_bits) { - const SigBit &d = i.first; - const Cell *cell = i.second; + for (const auto cell : ff_list) { + const SigBit &d = sigmap(cell->getPort(ID::D)); + const SigBit &q = sigmap(cell->getPort(ID::Q)); SigSpec clk_and_pol{sigmap(cell->getPort(ID::C)), cell->type[6] == 'P' ? State::S1 : State::S0}; auto r = clk_to_mergeability.insert(std::make_pair(clk_and_pol, clk_to_mergeability.size()+1)); @@ -619,8 +617,7 @@ struct XAigerWriter log_assert(mergeability > 0); write_r_buffer(mergeability); - SigBit Q = sigmap(cell->getPort(ID::Q)); - State init = init_map.at(Q, State::Sx); + State init = init_map.at(q, State::Sx); log_debug("Cell '%s' (type %s) has (* init *) value '%s'.\n", log_id(cell), log_id(cell->type), log_signal(init)); if (init == State::S1) write_s_buffer(1); @@ -700,8 +697,6 @@ struct XAigerWriter for (auto wire : module->wires()) { - SigSpec sig = sigmap(wire); - for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit b(wire, i); @@ -714,7 +709,6 @@ struct XAigerWriter if (output_bits.count(b)) { int o = ordered_outputs.at(b); output_lines[o] += stringf("output %d %d %s\n", o - GetSize(co_bits), wire->start_offset+i, log_id(wire)); - continue; } } } diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 2816d3246..bbdcfb70a 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -40,6 +40,7 @@ struct BtorWorker bool verbose; bool single_bad; bool cover_mode; + bool print_internal_names; int next_nid = 1; int initstate_nid = -1; @@ -78,7 +79,7 @@ struct BtorWorker vector<string> info_lines; dict<int, int> info_clocks; - void btorf(const char *fmt, ...) + void btorf(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 2, 3)) { va_list ap; va_start(ap, fmt); @@ -86,7 +87,7 @@ struct BtorWorker va_end(ap); } - void infof(const char *fmt, ...) + void infof(const char *fmt, ...) YS_ATTRIBUTE(format(printf, 2, 3)) { va_list ap; va_start(ap, fmt); @@ -98,6 +99,7 @@ struct BtorWorker string getinfo(T *obj, bool srcsym = false) { string infostr = log_id(obj); + if (!srcsym && !print_internal_names && infostr[0] == '$') return ""; if (obj->attributes.count(ID::src)) { string src = obj->attributes.at(ID::src).decode_string().c_str(); if (srcsym && infostr[0] == '$') { @@ -117,7 +119,7 @@ struct BtorWorker infostr += " ; " + src; } } - return infostr; + return " " + infostr; } void btorf_push(const string &id) @@ -242,7 +244,7 @@ struct BtorWorker btorf("%d slt %d %d %d\n", nid_b_ltz, sid_bit, nid_b, nid_zero); nid = next_nid++; - btorf("%d ite %d %d %d %d %s\n", nid, sid, nid_b_ltz, nid_l, nid_r, getinfo(cell).c_str()); + btorf("%d ite %d %d %d %d%s\n", nid, sid, nid_b_ltz, nid_l, nid_r, getinfo(cell).c_str()); } else { @@ -250,7 +252,7 @@ struct BtorWorker int nid_b = get_sig_nid(cell->getPort(ID::B), width, b_signed); nid = next_nid++; - btorf("%d %s %d %d %d %s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); } SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -291,7 +293,7 @@ struct BtorWorker int sid = get_bv_sid(width); int nid = next_nid++; - btorf("%d %c%s %d %d %d %s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %c%s %d %d %d%s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -317,12 +319,12 @@ struct BtorWorker if (cell->type == ID($_ANDNOT_)) { btorf("%d not %d %d\n", nid1, sid, nid_b); - btorf("%d and %d %d %d %s\n", nid2, sid, nid_a, nid1, getinfo(cell).c_str()); + btorf("%d and %d %d %d%s\n", nid2, sid, nid_a, nid1, getinfo(cell).c_str()); } if (cell->type == ID($_ORNOT_)) { btorf("%d not %d %d\n", nid1, sid, nid_b); - btorf("%d or %d %d %d %s\n", nid2, sid, nid_a, nid1, getinfo(cell).c_str()); + btorf("%d or %d %d %d%s\n", nid2, sid, nid_a, nid1, getinfo(cell).c_str()); } SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -344,13 +346,13 @@ struct BtorWorker if (cell->type == ID($_OAI3_)) { btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b); btorf("%d and %d %d %d\n", nid2, sid, nid1, nid_c); - btorf("%d not %d %d %s\n", nid3, sid, nid2, getinfo(cell).c_str()); + btorf("%d not %d %d%s\n", nid3, sid, nid2, getinfo(cell).c_str()); } if (cell->type == ID($_AOI3_)) { btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b); btorf("%d or %d %d %d\n", nid2, sid, nid1, nid_c); - btorf("%d not %d %d %s\n", nid3, sid, nid2, getinfo(cell).c_str()); + btorf("%d not %d %d%s\n", nid3, sid, nid2, getinfo(cell).c_str()); } SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -375,14 +377,14 @@ struct BtorWorker btorf("%d or %d %d %d\n", nid1, sid, nid_a, nid_b); btorf("%d or %d %d %d\n", nid2, sid, nid_c, nid_d); btorf("%d and %d %d %d\n", nid3, sid, nid1, nid2); - btorf("%d not %d %d %s\n", nid4, sid, nid3, getinfo(cell).c_str()); + btorf("%d not %d %d%s\n", nid4, sid, nid3, getinfo(cell).c_str()); } if (cell->type == ID($_AOI4_)) { btorf("%d and %d %d %d\n", nid1, sid, nid_a, nid_b); btorf("%d and %d %d %d\n", nid2, sid, nid_c, nid_d); btorf("%d or %d %d %d\n", nid3, sid, nid1, nid2); - btorf("%d not %d %d %s\n", nid4, sid, nid3, getinfo(cell).c_str()); + btorf("%d not %d %d%s\n", nid4, sid, nid3, getinfo(cell).c_str()); } SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -414,9 +416,9 @@ struct BtorWorker int nid = next_nid++; if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt))) { - btorf("%d %c%s %d %d %d %s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %c%s %d %d %d%s\n", nid, a_signed || b_signed ? 's' : 'u', btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); } else { - btorf("%d %s %d %d %d %s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); } SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -447,7 +449,7 @@ struct BtorWorker int nid_a = get_sig_nid(cell->getPort(ID::A), width, a_signed); int nid = next_nid++; - btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); + btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -488,9 +490,9 @@ struct BtorWorker int nid = next_nid++; if (btor_op != "not") - btorf("%d %s %d %d %d\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); + btorf("%d %s %d %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, nid_b, getinfo(cell).c_str()); else - btorf("%d %s %d %d\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); + btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -521,11 +523,11 @@ struct BtorWorker if (cell->type == ID($reduce_xnor)) { int nid2 = next_nid++; - btorf("%d %s %d %d %s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); - btorf("%d not %d %d %d\n", nid2, sid, nid); + btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); + btorf("%d not %d %d\n", nid2, sid, nid); nid = nid2; } else { - btorf("%d %s %d %d %s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); + btorf("%d %s %d %d%s\n", nid, btor_op.c_str(), sid, nid_a, getinfo(cell).c_str()); } SigSpec sig = sigmap(cell->getPort(ID::Y)); @@ -560,9 +562,9 @@ struct BtorWorker int tmp = nid; nid = next_nid++; btorf("%d ite %d %d %d %d\n", tmp, sid, nid_s, nid_b, nid_a); - btorf("%d not %d %d %s\n", nid, sid, tmp, getinfo(cell).c_str()); + btorf("%d not %d %d%s\n", nid, sid, tmp, getinfo(cell).c_str()); } else { - btorf("%d ite %d %d %d %d %s\n", nid, sid, nid_s, nid_b, nid_a, getinfo(cell).c_str()); + btorf("%d ite %d %d %d %d%s\n", nid, sid, nid_s, nid_b, nid_a, getinfo(cell).c_str()); } add_nid_sig(nid, sig_y); @@ -585,7 +587,7 @@ struct BtorWorker int nid_s = get_sig_nid(sig_s.extract(i)); int nid2 = next_nid++; if (i == GetSize(sig_s)-1) - btorf("%d ite %d %d %d %d %s\n", nid2, sid, nid_s, nid_b, nid, getinfo(cell).c_str()); + btorf("%d ite %d %d %d %d%s\n", nid2, sid, nid_s, nid_b, nid, getinfo(cell).c_str()); else btorf("%d ite %d %d %d %d\n", nid2, sid, nid_s, nid_b, nid); nid = nid2; @@ -640,7 +642,7 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig_q)); int nid = next_nid++; - if (symbol.empty()) + if (symbol.empty() || (!print_internal_names && symbol[0] == '$')) btorf("%d state %d\n", nid, sid); else btorf("%d state %d %s\n", nid, sid, log_id(symbol)); @@ -1049,8 +1051,8 @@ struct BtorWorker return nid; } - BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose, bool single_bad, bool cover_mode, string info_filename) : - f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), info_filename(info_filename) + BtorWorker(std::ostream &f, RTLIL::Module *module, bool verbose, bool single_bad, bool cover_mode, bool print_internal_names, string info_filename) : + f(f), sigmap(module), module(module), verbose(verbose), single_bad(single_bad), cover_mode(cover_mode), print_internal_names(print_internal_names), info_filename(info_filename) { if (!info_filename.empty()) infof("name %s\n", log_id(module)); @@ -1073,7 +1075,7 @@ struct BtorWorker int sid = get_bv_sid(GetSize(sig)); int nid = next_nid++; - btorf("%d input %d %s\n", nid, sid, getinfo(wire).c_str()); + btorf("%d input %d%s\n", nid, sid, getinfo(wire).c_str()); add_nid_sig(nid, sig); } @@ -1097,7 +1099,7 @@ struct BtorWorker btorf_push(stringf("output %s", log_id(wire))); int nid = get_sig_nid(wire); - btorf("%d output %d %s\n", next_nid++, nid, getinfo(wire).c_str()); + btorf("%d output %d%s\n", next_nid++, nid, getinfo(wire).c_str()); btorf_pop(stringf("output %s", log_id(wire))); } @@ -1139,10 +1141,10 @@ struct BtorWorker bad_properties.push_back(nid_en_and_not_a); } else { if (cover_mode) { - infof("bad %d %s\n", nid_en_and_not_a, getinfo(cell, true).c_str()); + infof("bad %d%s\n", nid_en_and_not_a, getinfo(cell, true).c_str()); } else { int nid = next_nid++; - btorf("%d bad %d %s\n", nid, nid_en_and_not_a, getinfo(cell, true).c_str()); + btorf("%d bad %d%s\n", nid, nid_en_and_not_a, getinfo(cell, true).c_str()); } } @@ -1164,7 +1166,7 @@ struct BtorWorker bad_properties.push_back(nid_en_and_a); } else { int nid = next_nid++; - btorf("%d bad %d %s\n", nid, nid_en_and_a, getinfo(cell, true).c_str()); + btorf("%d bad %d%s\n", nid, nid_en_and_a, getinfo(cell, true).c_str()); } btorf_pop(log_id(cell)); @@ -1185,7 +1187,7 @@ struct BtorWorker continue; int this_nid = next_nid++; - btorf("%d uext %d %d %d %s\n", this_nid, sid, nid, 0, getinfo(wire).c_str()); + btorf("%d uext %d %d %d%s\n", this_nid, sid, nid, 0, getinfo(wire).c_str()); btorf_pop(stringf("wire %s", log_id(wire))); continue; @@ -1256,14 +1258,14 @@ struct BtorWorker } int nid2 = next_nid++; - btorf("%d next %d %d %d %s\n", nid2, sid, nid, nid_head, getinfo(cell).c_str()); + btorf("%d next %d %d %d%s\n", nid2, sid, nid, nid_head, getinfo(cell).c_str()); } else { SigSpec sig = sigmap(cell->getPort(ID::D)); int nid_q = get_sig_nid(sig); int sid = get_bv_sid(GetSize(sig)); - btorf("%d next %d %d %d %s\n", next_nid++, sid, nid, nid_q, getinfo(cell).c_str()); + btorf("%d next %d %d %d%s\n", next_nid++, sid, nid, nid_q, getinfo(cell).c_str()); } btorf_pop(stringf("next %s", log_id(cell))); @@ -1353,10 +1355,13 @@ struct BtorBackend : public Backend { log(" -i <filename>\n"); log(" Create additional info file with auxiliary information\n"); log("\n"); + log(" -n\n"); + log(" Don't identify internal netnames\n"); + log("\n"); } void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { - bool verbose = false, single_bad = false, cover_mode = false; + bool verbose = false, single_bad = false, cover_mode = false, print_internal_names = true; string info_filename; log_header(design, "Executing BTOR backend.\n"); @@ -1380,6 +1385,10 @@ struct BtorBackend : public Backend { info_filename = args[++argidx]; continue; } + if (args[argidx] == "-n") { + print_internal_names = false; + continue; + } break; } extra_args(f, filename, args, argidx); @@ -1392,7 +1401,7 @@ struct BtorBackend : public Backend { *f << stringf("; BTOR description generated by %s for module %s.\n", yosys_version_str, log_id(topmod)); - BtorWorker(*f, topmod, verbose, single_bad, cover_mode, info_filename); + BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename); *f << stringf("; end of yosys output\n"); } diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 6e3882d2d..3a418de3c 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -131,6 +131,8 @@ void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL:: f << stringf("output %d ", wire->port_id); if (wire->port_input && wire->port_output) f << stringf("inout %d ", wire->port_id); + if (wire->is_signed) + f << stringf("signed "); f << stringf("%s\n", wire->name.c_str()); } diff --git a/backends/json/json.cc b/backends/json/json.cc index 1a8b757ef..5edc50f60 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -160,6 +160,8 @@ struct JsonWriter f << stringf(" \"offset\": %d,\n", w->start_offset); if (w->upto) f << stringf(" \"upto\": 1,\n"); + if (w->is_signed) + f << stringf(" \"signed\": %d,\n", w->is_signed); f << stringf(" \"bits\": %s\n", get_bits(w).c_str()); f << stringf(" }"); first = false; @@ -227,6 +229,8 @@ struct JsonWriter f << stringf(" \"offset\": %d,\n", w->start_offset); if (w->upto) f << stringf(" \"upto\": 1,\n"); + if (w->is_signed) + f << stringf(" \"signed\": %d,\n", w->is_signed); f << stringf(" \"attributes\": {"); write_parameters(w->attributes); f << stringf("\n }\n"); diff --git a/backends/smt2/smtbmc.py b/backends/smt2/smtbmc.py index cc3ebb129..03f001bfd 100644 --- a/backends/smt2/smtbmc.py +++ b/backends/smt2/smtbmc.py @@ -1557,8 +1557,9 @@ else: # not tempind, covermode smt_assert(get_constr_expr(constr_asserts, i)) print_msg("Solving for step %d.." % (last_check_step)) - if smt_check_sat() != "sat": - print("%s No solution found!" % smt.timestamp()) + status = smt_check_sat() + if status != "sat": + print("%s No solution found! (%s)" % (smt.timestamp(), status)) retstatus = "FAILED" break diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 62dfe7c11..9f7c8c6d9 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -121,6 +121,7 @@ class SmtIo: self.logic_bv = True self.logic_dt = False self.forall = False + self.timeout = 0 self.produce_models = True self.smt2cache = [list()] self.p = None @@ -135,6 +136,7 @@ class SmtIo: self.debug_file = opts.debug_file self.dummy_file = opts.dummy_file self.timeinfo = opts.timeinfo + self.timeout = opts.timeout self.unroll = opts.unroll self.noincr = opts.noincr self.info_stmts = opts.info_stmts @@ -147,6 +149,7 @@ class SmtIo: self.debug_file = None self.dummy_file = None self.timeinfo = os.name != "nt" + self.timeout = 0 self.unroll = False self.noincr = False self.info_stmts = list() @@ -176,18 +179,28 @@ class SmtIo: self.popen_vargs = ['yices-smt2'] + self.solver_opts else: self.popen_vargs = ['yices-smt2', '--incremental'] + self.solver_opts + if self.timeout != 0: + self.popen_vargs.append('-t') + self.popen_vargs.append('%d' % self.timeout); if self.solver == "z3": self.popen_vargs = ['z3', '-smt2', '-in'] + self.solver_opts + if self.timeout != 0: + self.popen_vargs.append('-T:%d' % self.timeout); if self.solver == "cvc4": if self.noincr: self.popen_vargs = ['cvc4', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts else: self.popen_vargs = ['cvc4', '--incremental', '--lang', 'smt2.6' if self.logic_dt else 'smt2'] + self.solver_opts + if self.timeout != 0: + self.popen_vargs.append('--tlimit=%d000' % self.timeout); if self.solver == "mathsat": self.popen_vargs = ['mathsat'] + self.solver_opts + if self.timeout != 0: + print('timeout option is not supported for mathsat.') + sys.exit(1) if self.solver == "boolector": if self.noincr: @@ -195,6 +208,9 @@ class SmtIo: else: self.popen_vargs = ['boolector', '--smt2', '-i'] + self.solver_opts self.unroll = True + if self.timeout != 0: + print('timeout option is not supported for boolector.') + sys.exit(1) if self.solver == "abc": if len(self.solver_opts) > 0: @@ -204,6 +220,9 @@ class SmtIo: self.logic_ax = False self.unroll = True self.noincr = True + if self.timeout != 0: + print('timeout option is not supported for abc.') + sys.exit(1) if self.solver == "dummy": assert self.dummy_file is not None @@ -710,7 +729,7 @@ class SmtIo: if self.forall: result = self.read() - while result not in ["sat", "unsat", "unknown"]: + while result not in ["sat", "unsat", "unknown", "timeout", "interrupted", ""]: print("%s %s: %s" % (self.timestamp(), self.solver, result)) result = self.read() else: @@ -721,7 +740,7 @@ class SmtIo: print("(check-sat)", file=self.debug_file) self.debug_file.flush() - if result not in ["sat", "unsat"]: + if result not in ["sat", "unsat", "unknown", "timeout", "interrupted"]: if result == "": print("%s Unexpected EOF response from solver." % (self.timestamp()), flush=True) else: @@ -931,7 +950,7 @@ class SmtIo: class SmtOpts: def __init__(self): self.shortopts = "s:S:v" - self.longopts = ["unroll", "noincr", "noprogress", "dump-smt2=", "logic=", "dummy=", "info=", "nocomments"] + self.longopts = ["unroll", "noincr", "noprogress", "timeout=", "dump-smt2=", "logic=", "dummy=", "info=", "nocomments"] self.solver = "yices" self.solver_opts = list() self.debug_print = False @@ -940,6 +959,7 @@ class SmtOpts: self.unroll = False self.noincr = False self.timeinfo = os.name != "nt" + self.timeout = 0 self.logic = None self.info_stmts = list() self.nocomments = False @@ -949,6 +969,8 @@ class SmtOpts: self.solver = a elif o == "-S": self.solver_opts.append(a) + elif o == "--timeout": + self.timeout = int(a) elif o == "-v": self.debug_print = True elif o == "--unroll": @@ -980,6 +1002,9 @@ class SmtOpts: -S <opt> pass <opt> as command line argument to the solver + --timeout <value> + set the solver timeout to the specified value (in seconds). + --logic <smt2_logic> use the specified SMT2 logic (e.g. QF_AUFBV) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index d25587e48..fef788267 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -775,7 +775,6 @@ void AigerReader::post_process() } } - dict<int, Wire*> mergeability_to_clock; for (uint32_t i = 0; i < flopNum; i++) { RTLIL::Wire *d = outputs[outputs.size() - flopNum + i]; log_assert(d); @@ -895,7 +894,9 @@ void AigerReader::post_process() } else if (type == "box") { RTLIL::Cell* cell = module->cell(stringf("$box%d", variable)); - if (cell) // ABC could have optimised this box away + if (!cell) + log_debug("Box %d (%s) no longer exists.\n", variable, log_id(escaped_s)); + else module->rename(cell, escaped_s); } else @@ -907,6 +908,8 @@ void AigerReader::post_process() auto name = wp.first; int min = wp.second.first; int max = wp.second.second; + if (min == 0 && max == 0) + continue; RTLIL::Wire *wire = module->wire(name); if (wire) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index cdc3adc9c..78e6fe5e0 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1065,6 +1065,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->port_input = is_input; wire->port_output = is_output; wire->upto = range_swapped; + wire->is_signed = is_signed; for (auto &attr : attributes) { if (attr.second->type != AST_CONSTANT) diff --git a/frontends/ilang/ilang_parser.y b/frontends/ilang/ilang_parser.y index 118f13de9..879ef4af9 100644 --- a/frontends/ilang/ilang_parser.y +++ b/frontends/ilang/ilang_parser.y @@ -192,6 +192,9 @@ wire_options: wire_options TOK_UPTO { current_wire->upto = true; } | + wire_options TOK_SIGNED { + current_wire->is_signed = true; + } | wire_options TOK_OFFSET TOK_INT { current_wire->start_offset = $3; } | diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index 7aceffbfc..8ae7c6578 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -309,6 +309,12 @@ void json_import(Design *design, string &modname, JsonNode *node) port_wire->upto = val->data_number != 0; } + if (port_node->data_dict.count("signed") != 0) { + JsonNode *val = port_node->data_dict.at("signed"); + if (val->type == 'N') + port_wire->is_signed = val->data_number != 0; + } + if (port_node->data_dict.count("offset") != 0) { JsonNode *val = port_node->data_dict.at("offset"); if (val->type == 'N') @@ -573,4 +579,3 @@ struct JsonFrontend : public Frontend { } JsonFrontend; YOSYS_NAMESPACE_END - diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index fe4bda68e..cb0368fd5 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -974,6 +974,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se module->memories[memory->name] = memory; int number_of_bits = net->Size(); + number_of_bits = 1 << ceil_log2(number_of_bits); int bits_in_word = number_of_bits; FOREACH_PORTREF_OF_NET(net, si, pr) { if (pr->GetInst()->Type() == OPER_READ_PORT) { @@ -1265,9 +1266,6 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se int numchunks = int(inst->OutputSize()) / memory->width; int chunksbits = ceil_log2(numchunks); - if ((numchunks * memory->width) != int(inst->OutputSize()) || (numchunks & (numchunks - 1)) != 0) - log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetInput()->Name()); - for (int i = 0; i < numchunks; i++) { RTLIL::SigSpec addr = {operatorInput1(inst), RTLIL::Const(i, chunksbits)}; @@ -1295,9 +1293,6 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::se int numchunks = int(inst->Input2Size()) / memory->width; int chunksbits = ceil_log2(numchunks); - if ((numchunks * memory->width) != int(inst->Input2Size()) || (numchunks & (numchunks - 1)) != 0) - log_error("Import of asymmetric memories of this type is not supported yet: %s %s\n", inst->Name(), inst->GetOutput()->Name()); - for (int i = 0; i < numchunks; i++) { RTLIL::SigSpec addr = {operatorInput1(inst), RTLIL::Const(i, chunksbits)}; diff --git a/kernel/constids.inc b/kernel/constids.inc index 93c3a7609..383d7c615 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -171,6 +171,7 @@ X(techmap_autopurge) X(_TECHMAP_BITS_CONNMAP_) X(_TECHMAP_CELLTYPE_) X(techmap_celltype) +X(_TECHMAP_FAIL_) X(techmap_maccmap) X(_TECHMAP_REPLACE_) X(techmap_simplemap) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 592d6e577..5c87b55f5 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -207,6 +207,7 @@ class dict entry_t() { } entry_t(const std::pair<K, T> &udata, int next) : udata(udata), next(next) { } entry_t(std::pair<K, T> &&udata, int next) : udata(std::move(udata)), next(next) { } + bool operator<(const entry_t &other) const { return udata.first < other.udata.first; } }; std::vector<int> hashtable; @@ -615,6 +616,15 @@ public: return !operator==(other); } + unsigned int hash() const { + unsigned int h = mkhash_init; + for (auto &entry : entries) { + h ^= hash_ops<K>::hash(entry.udata.first); + h ^= hash_ops<T>::hash(entry.udata.second); + } + return h; + } + void reserve(size_t n) { entries.reserve(n); } size_t size() const { return entries.size(); } bool empty() const { return entries.empty(); } diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index ca4201b53..397edc4e7 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -1862,6 +1862,7 @@ RTLIL::Wire *RTLIL::Module::addWire(RTLIL::IdString name, const RTLIL::Wire *oth wire->port_input = other->port_input; wire->port_output = other->port_output; wire->upto = other->upto; + wire->is_signed = other->is_signed; wire->attributes = other->attributes; return wire; } @@ -2447,6 +2448,7 @@ RTLIL::Wire::Wire() port_input = false; port_output = false; upto = false; + is_signed = false; #ifdef WITH_PYTHON RTLIL::Wire::get_all_wires()->insert(std::pair<unsigned int, RTLIL::Wire*>(hashidx_, this)); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 8228523d5..51e573e76 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1236,13 +1236,10 @@ public: RTLIL::Cell* addFf (RTLIL::IdString name, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, const std::string &src = ""); RTLIL::Cell* addDff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, const std::string &src = ""); RTLIL::Cell* addDffe (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool en_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDffsr (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); - RTLIL::Cell* addAdff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, - RTLIL::Const arst_value, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDffsr (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool clk_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); + RTLIL::Cell* addAdff (RTLIL::IdString name, const RTLIL::SigSpec &sig_clk, const RTLIL::SigSpec &sig_arst, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, RTLIL::Const arst_value, bool clk_polarity = true, bool arst_polarity = true, const std::string &src = ""); RTLIL::Cell* addDlatch (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, const std::string &src = ""); - RTLIL::Cell* addDlatchsr (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, - RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); + RTLIL::Cell* addDlatchsr (RTLIL::IdString name, const RTLIL::SigSpec &sig_en, const RTLIL::SigSpec &sig_set, const RTLIL::SigSpec &sig_clr, RTLIL::SigSpec sig_d, const RTLIL::SigSpec &sig_q, bool en_polarity = true, bool set_polarity = true, bool clr_polarity = true, const std::string &src = ""); RTLIL::Cell* addBufGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const std::string &src = ""); RTLIL::Cell* addNotGate (RTLIL::IdString name, const RTLIL::SigBit &sig_a, const RTLIL::SigBit &sig_y, const std::string &src = ""); @@ -1371,7 +1368,7 @@ public: RTLIL::Module *module; RTLIL::IdString name; int width, start_offset, port_id; - bool port_input, port_output, upto; + bool port_input, port_output, upto, is_signed; #ifdef WITH_PYTHON static std::map<unsigned int, RTLIL::Wire*> *get_all_wires(void); diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index fac5b48a4..fa23e3b2c 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -312,16 +312,16 @@ class PythonListTranslator(Translator): text += prefix + "\t" + known_containers[types[0].name].typename + " " + tmp_name + " = boost::python::extract<" + known_containers[types[0].name].typename + ">(" + varname + "[" + cntr_name + "]);" text += known_containers[types[0].name].translate(tmp_name, types[0].cont.args, prefix+"\t") tmp_name = tmp_name + "___tmp" - text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + ");" + text += prefix + "\t" + varname + "___tmp" + c.insert_name + "(" + tmp_name + ");" elif types[0].name in classnames: text += prefix + "\t" + types[0].name + "* " + tmp_name + " = boost::python::extract<" + types[0].name + "*>(" + varname + "[" + cntr_name + "]);" if types[0].attr_type == attr_types.star: - text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + "->get_cpp_obj());" + text += prefix + "\t" + varname + "___tmp" + c.insert_name + "(" + tmp_name + "->get_cpp_obj());" else: - text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(*" + tmp_name + "->get_cpp_obj());" + text += prefix + "\t" + varname + "___tmp" + c.insert_name + "(*" + tmp_name + "->get_cpp_obj());" else: text += prefix + "\t" + types[0].name + " " + tmp_name + " = boost::python::extract<" + types[0].name + ">(" + varname + "[" + cntr_name + "]);" - text += prefix + "\t" + varname + "___tmp." + c.insert_name + "(" + tmp_name + ");" + text += prefix + "\t" + varname + "___tmp" + c.insert_name + "(" + tmp_name + ");" text += prefix + "}" return text @@ -349,19 +349,24 @@ class PythonListTranslator(Translator): text += prefix + "}" return text +class IDictTranslator(PythonListTranslator): + typename = "boost::python::list" + orig_name = "idict" + insert_name = "" + #Sub-type for std::set class SetTranslator(PythonListTranslator): - insert_name = "insert" + insert_name = ".insert" orig_name = "std::set" #Sub-type for std::vector class VectorTranslator(PythonListTranslator): - insert_name = "push_back" + insert_name = ".push_back" orig_name = "std::vector" #Sub-type for pool class PoolTranslator(PythonListTranslator): - insert_name = "insert" + insert_name = ".insert" orig_name = "pool" #Translates dict-types (dict, std::map), that only differ in their name and @@ -528,6 +533,7 @@ known_containers = { "std::set" : SetTranslator, "std::vector" : VectorTranslator, "pool" : PoolTranslator, + "idict" : IDictTranslator, "dict" : DictTranslator, "std::pair" : TupleTranslator, "std::map" : MapTranslator diff --git a/passes/cmds/blackbox.cc b/passes/cmds/blackbox.cc index 5c0405f15..b8297cd77 100644 --- a/passes/cmds/blackbox.cc +++ b/passes/cmds/blackbox.cc @@ -48,31 +48,7 @@ struct BlackboxPass : public Pass { for (auto module : design->selected_whole_modules_warn()) { - pool<Cell*> remove_cells; - pool<Wire*> remove_wires; - - for (auto cell : module->cells()) - remove_cells.insert(cell); - - for (auto wire : module->wires()) - if (wire->port_id == 0) - remove_wires.insert(wire); - - for (auto it = module->memories.begin(); it != module->memories.end(); ++it) - delete it->second; - module->memories.clear(); - - for (auto it = module->processes.begin(); it != module->processes.end(); ++it) - delete it->second; - module->processes.clear(); - - module->new_connections(std::vector<RTLIL::SigSig>()); - - for (auto cell : remove_cells) - module->remove(cell); - - module->remove(remove_wires); - + module->makeblackbox(); module->set_bool_attribute(ID::blackbox); } } diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc index 712a46cbc..d6dbf8ef4 100644 --- a/passes/sat/qbfsat.cc +++ b/passes/sat/qbfsat.cc @@ -42,6 +42,7 @@ struct QbfSolveOptions { bool nooptimize, nobisection; bool sat, unsat, show_smtbmc; enum Solver{Z3, Yices, CVC4} solver; + int timeout; std::string specialize_soln_file; std::string write_soln_soln_file; std::string dump_final_smt2_file; @@ -49,7 +50,7 @@ struct QbfSolveOptions { QbfSolveOptions() : specialize(false), specialize_from_file(false), write_solution(false), nocleanup(false), dump_final_smt2(false), assume_outputs(false), assume_neg(false), nooptimize(false), nobisection(false), sat(false), unsat(false), show_smtbmc(false), - solver(Yices), argidx(0) {}; + solver(Yices), timeout(0), argidx(0) {}; }; std::string get_solver_name(const QbfSolveOptions &opt) { @@ -67,6 +68,11 @@ std::string get_solver_name(const QbfSolveOptions &opt) { void recover_solution(QbfSolutionType &sol) { YS_REGEX_TYPE sat_regex = YS_REGEX_COMPILE("Status: PASSED"); YS_REGEX_TYPE unsat_regex = YS_REGEX_COMPILE("Solver Error.*model is not available"); + YS_REGEX_TYPE unsat_regex2 = YS_REGEX_COMPILE("Status: FAILED"); + YS_REGEX_TYPE timeout_regex = YS_REGEX_COMPILE("No solution found! \\(timeout\\)"); + YS_REGEX_TYPE timeout_regex2 = YS_REGEX_COMPILE("No solution found! \\(interrupted\\)"); + YS_REGEX_TYPE unknown_regex = YS_REGEX_COMPILE("No solution found! \\(unknown\\)"); + YS_REGEX_TYPE unknown_regex2 = YS_REGEX_COMPILE("Unexpected EOF response from solver"); YS_REGEX_TYPE memout_regex = YS_REGEX_COMPILE("Solver Error:.*error \"out of memory\""); YS_REGEX_TYPE hole_value_regex = YS_REGEX_COMPILE_WITH_SUBS("Value for anyconst in [a-zA-Z0-9_]* \\(([^:]*:[^\\)]*)\\): (.*)"); #ifndef NDEBUG @@ -87,14 +93,40 @@ void recover_solution(QbfSolutionType &sol) { #endif sol.hole_to_value[loc] = val; } - else if (YS_REGEX_NS::regex_search(x, sat_regex)) + else if (YS_REGEX_NS::regex_search(x, sat_regex)) { sat_regex_found = true; - else if (YS_REGEX_NS::regex_search(x, unsat_regex)) + sol.sat = true; + sol.unknown = false; + } + else if (YS_REGEX_NS::regex_search(x, unsat_regex)) { unsat_regex_found = true; + sol.sat = false; + sol.unknown = false; + } else if (YS_REGEX_NS::regex_search(x, memout_regex)) { sol.unknown = true; log_warning("solver ran out of memory\n"); } + else if (YS_REGEX_NS::regex_search(x, timeout_regex)) { + sol.unknown = true; + log_warning("solver timed out\n"); + } + else if (YS_REGEX_NS::regex_search(x, timeout_regex2)) { + sol.unknown = true; + log_warning("solver timed out\n"); + } + else if (YS_REGEX_NS::regex_search(x, unknown_regex)) { + sol.unknown = true; + log_warning("solver returned \"unknown\"\n"); + } + else if (YS_REGEX_NS::regex_search(x, unsat_regex2)) { + unsat_regex_found = true; + sol.sat = false; + sol.unknown = false; + } + else if (YS_REGEX_NS::regex_search(x, unknown_regex2)) { + sol.unknown = true; + } } #ifndef NDEBUG log_assert(!sol.unknown && sol.sat? sat_regex_found : true); @@ -329,7 +361,7 @@ QbfSolutionType call_qbf_solver(RTLIL::Module *mod, const QbfSolveOptions &opt, const std::string yosys_smtbmc_exe = proc_self_dirname() + "yosys-smtbmc"; const std::string smt2_command = "write_smt2 -stbv -wires " + tempdir_name + "/problem" + (iter_num != 0? stringf("%d", iter_num) : "") + ".smt2"; const std::string smtbmc_warning = "z3: WARNING:"; - const std::string smtbmc_cmd = yosys_smtbmc_exe + " -s " + (get_solver_name(opt)) + " -t 1 -g --binary " + (opt.dump_final_smt2? "--dump-smt2 " + opt.dump_final_smt2_file + " " : "") + tempdir_name + "/problem" + (iter_num != 0? stringf("%d", iter_num) : "") + ".smt2 2>&1"; + const std::string smtbmc_cmd = yosys_smtbmc_exe + " -s " + (get_solver_name(opt)) + (opt.timeout != 0? stringf(" --timeout %d", opt.timeout) : "") + " -t 1 -g --binary " + (opt.dump_final_smt2? "--dump-smt2 " + opt.dump_final_smt2_file + " " : "") + tempdir_name + "/problem" + (iter_num != 0? stringf("%d", iter_num) : "") + ".smt2 2>&1"; Pass::call(mod->design, smt2_command); @@ -344,14 +376,7 @@ QbfSolutionType call_qbf_solver(RTLIL::Module *mod, const QbfSolveOptions &opt, }; log_header(mod->design, "Solving QBF-SAT problem.\n"); if (!quiet) log("Launching \"%s\".\n", smtbmc_cmd.c_str()); - int retval = run_command(smtbmc_cmd, process_line); - if (retval == 0) { - ret.sat = true; - ret.unknown = false; - } else if (retval == 1) { - ret.sat = false; - ret.unknown = false; - } + run_command(smtbmc_cmd, process_line); recover_solution(ret); return ret; @@ -514,6 +539,19 @@ QbfSolveOptions parse_args(const std::vector<std::string> &args) { } continue; } + else if (args[opt.argidx] == "-timeout") { + if (args.size() <= opt.argidx + 1) + log_cmd_error("timeout not specified.\n"); + else { + int timeout = atoi(args[opt.argidx+1].c_str()); + if (timeout > 0) + opt.timeout = timeout; + else + log_cmd_error("timeout must be greater than 0.\n"); + opt.argidx++; + } + continue; + } else if (args[opt.argidx] == "-sat") { opt.sat = true; continue; @@ -625,6 +663,9 @@ struct QbfSatPass : public Pass { log(" -solver <solver>\n"); log(" Use a particular solver. Choose one of: \"z3\", \"yices\", and \"cvc4\".\n"); log("\n"); + log(" -timeout <value>\n"); + log(" Set the per-iteration timeout in seconds.\n"); + log("\n"); log(" -sat\n"); log(" Generate an error if the solver does not return \"sat\".\n"); log("\n"); @@ -672,7 +713,6 @@ struct QbfSatPass : public Pass { QbfSolutionType ret = qbf_solve(module, opt); module = design->module(module_name); if (ret.unknown) { - log_warning("solver did not give an answer\n"); if (opt.sat || opt.unsat) log_cmd_error("expected problem to be %s\n", opt.sat? "SAT" : "UNSAT"); } diff --git a/passes/techmap/.gitignore b/passes/techmap/.gitignore deleted file mode 100644 index e6dcc6bc0..000000000 --- a/passes/techmap/.gitignore +++ /dev/null @@ -1 +0,0 @@ -techmap.inc diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 1802ba0de..873286608 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -45,18 +45,6 @@ OBJS += passes/techmap/flowmap.o OBJS += passes/techmap/extractinv.o endif -GENFILES += passes/techmap/techmap.inc - -passes/techmap/techmap.inc: techlibs/common/techmap.v - $(Q) mkdir -p $(dir $@) - $(P) echo "// autogenerated from $<" > $@.new - $(Q) echo "static char stdcells_code[] = {" >> $@.new - $(Q) od -v -td1 -An $< | $(SED) -e 's/[0-9][0-9]*/&,/g' >> $@.new - $(Q) echo "0};" >> $@.new - $(Q) mv $@.new $@ - -passes/techmap/techmap.o: passes/techmap/techmap.inc - ifeq ($(DISABLE_SPAWN),0) TARGETS += $(PROGRAM_PREFIX)yosys-filterlib$(EXE) EXTRA_OBJS += passes/techmap/filterlib.o diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 8d55b18a0..873c37b9a 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -102,8 +102,6 @@ void check(RTLIL::Design *design, bool dff_mode) auto inst_module = design->module(cell->type); if (!inst_module) continue; - if (!inst_module->get_blackbox_attribute()) - continue; IdString derived_type; Module *derived_module; if (cell->parameters.empty()) { @@ -111,6 +109,10 @@ void check(RTLIL::Design *design, bool dff_mode) derived_module = inst_module; } else { + // Check potential (since its value may depend on a parameter, + // but not its existence) + if (!inst_module->has_attribute(ID::abc9_flop)) + continue; derived_type = inst_module->derive(design, cell->parameters); derived_module = design->module(derived_type); log_assert(derived_module); @@ -127,20 +129,20 @@ void check(RTLIL::Design *design, bool dff_mode) for (auto derived_cell : derived_module->cells()) { if (derived_cell->type.in(ID($dff), ID($_DFF_N_), ID($_DFF_P_))) { if (found) - log_error("Module '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module)); + log_error("Whitebox '%s' with (* abc9_flop *) contains more than one $_DFF_[NP]_ cell.\n", log_id(derived_module)); found = true; SigBit Q = derived_cell->getPort(ID::Q); log_assert(GetSize(Q.wire) == 1); if (!Q.wire->port_output) - log_error("Module '%s' contains a %s cell where its 'Q' port does not drive a module output!\n", log_id(derived_module), log_id(derived_cell->type)); + log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell where its 'Q' port does not drive a module output.\n", log_id(derived_module), log_id(derived_cell->type)); Const init = Q.wire->attributes.at(ID::init, State::Sx); log_assert(GetSize(init) == 1); } else if (unsupported.count(derived_cell->type)) - log_error("Module '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type)); + log_error("Whitebox '%s' with (* abc9_flop *) contains a %s cell, which is not supported for sequential synthesis.\n", log_id(derived_module), log_id(derived_cell->type)); } } } @@ -173,8 +175,6 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) auto inst_module = design->module(cell->type); if (!inst_module) continue; - if (!inst_module->get_blackbox_attribute()) - continue; IdString derived_type; Module *derived_module; if (cell->parameters.empty()) { @@ -182,6 +182,10 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) derived_module = inst_module; } else { + // Check potential for any one of those three + // (since its value may depend on a parameter, but not its existence) + if (!inst_module->has_attribute(ID::abc9_flop) && !inst_module->has_attribute(ID::abc9_box) && !inst_module->get_bool_attribute(ID::abc9_bypass)) + continue; derived_type = inst_module->derive(design, cell->parameters); derived_module = design->module(derived_type); } @@ -211,7 +215,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) // Block sequential synthesis on cells with (* init *) != 1'b0 // because ABC9 doesn't support them if (init != State::S0) { - log_warning("Module '%s' contains a %s cell with non-zero initial state -- this is not unsupported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type)); + log_warning("Whitebox '%s' with (* abc9_flop *) contains a %s cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox.\n", log_id(derived_module), log_id(derived_cell->type)); derived_module->set_bool_attribute(ID::abc9_flop, false); } break; @@ -232,10 +236,8 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) auto w = unmap_module->addWire(port, derived_module->wire(port)); // Do not propagate (* init *) values into the box, // in fact, remove it from outside too - if (w->port_output && w->attributes.erase(ID::init)) { - auto r = unmap_module->addWire(stringf("\\_TECHMAP_REMOVEINIT_%s_", log_id(port))); - unmap_module->connect(r, State::S1); - } + if (w->port_output) + w->attributes.erase(ID::init); } unmap_module->ports = derived_module->ports; unmap_module->check(); @@ -719,8 +721,10 @@ void prep_xaiger(RTLIL::Module *module, bool dff) bit_users[bit].insert(cell->name); if (cell->output(conn.first) && !abc9_flop) - for (auto bit : sigmap(conn.second)) - bit_drivers[bit].insert(cell->name); + for (const auto &chunk : conn.second.chunks()) + if (!chunk.wire->get_bool_attribute(ID::abc9_keep)) + for (auto b : sigmap(SigSpec(chunk))) + bit_drivers[b].insert(cell->name); } toposort.node(cell->name); } @@ -1110,7 +1114,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) for (auto w : mapped_mod->wires()) { auto nw = module->addWire(remap_name(w->name), GetSize(w)); nw->start_offset = w->start_offset; - // Remove all (* init *) since they only existon $_DFF_[NP]_ + // Remove all (* init *) since they only exist on $_DFF_[NP]_ w->attributes.erase(ID::init); } @@ -1147,16 +1151,36 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) } } + SigMap initmap; + if (dff_mode) { + // Build a sigmap prioritising bits with (* init *) + initmap.set(module); + for (auto w : module->wires()) { + auto it = w->attributes.find(ID::init); + if (it == w->attributes.end()) + continue; + for (auto i = 0; i < GetSize(w); i++) + if (it->second[i] == State::S0 || it->second[i] == State::S1) + initmap.add(w); + } + } + std::vector<Cell*> boxes; for (auto cell : module->cells().to_vector()) { if (cell->has_keep_attr()) continue; - // Short out $_DFF_[NP]_ cells since the flop box already has - // all the information we need to reconstruct cell + // Short out (so that existing name can be preserved) and remove + // $_DFF_[NP]_ cells since flop box already has all the information + // we need to reconstruct them if (dff_mode && cell->type.in(ID($_DFF_N_), ID($_DFF_P_)) && !cell->get_bool_attribute(ID::abc9_keep)) { - module->connect(cell->getPort(ID::Q), cell->getPort(ID::D)); + SigBit Q = cell->getPort(ID::Q); + module->connect(Q, cell->getPort(ID::D)); module->remove(cell); + auto Qi = initmap(Q); + auto it = Qi.wire->attributes.find(ID::init); + if (it != Qi.wire->attributes.end()) + it->second[Qi.offset] = State::Sx; } else if (cell->type.in(ID($_AND_), ID($_NOT_))) module->remove(cell); @@ -1299,7 +1323,25 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) mapped_cell->connections_.erase(jt); auto abc9_flop = box_module->get_bool_attribute(ID::abc9_flop); - if (!abc9_flop) { + if (abc9_flop) { + // Link this sole flop box output to the output of the existing + // flop box, so that any (public) signal it drives will be + // preserved + SigBit old_q; + for (const auto &port_name : box_ports.at(existing_cell->type)) { + RTLIL::Wire *w = box_module->wire(port_name); + log_assert(w); + if (!w->port_output) + continue; + log_assert(old_q == SigBit()); + log_assert(GetSize(w) == 1); + old_q = existing_cell->getPort(port_name); + } + auto new_q = outputs[0]; + new_q.wire = module->wires_.at(remap_name(new_q.wire->name)); + module->connect(old_q, new_q); + } + else { for (const auto &i : inputs) bit_users[i].insert(mapped_cell->name); for (const auto &i : outputs) @@ -1332,11 +1374,12 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) c.wire = module->wires_.at(remap_name(c.wire->name)); newsig.append(c); } - cell->setPort(port_name, newsig); if (w->port_input && !abc9_flop) for (const auto &i : newsig) bit2sinks[i].push_back(cell); + + cell->setPort(port_name, std::move(newsig)); } } @@ -1398,7 +1441,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) // treated as being "free"), in particular driving primary // outputs (real primary outputs, or cells treated as blackboxes) // or driving box inputs. - // Instead of just mapping those $_NOT_ gates into 2-input $lut-s + // Instead of just mapping those $_NOT_ gates into 1-input $lut-s // at an area and delay cost, see if it is possible to push // this $_NOT_ into the driving LUT, or into all sink LUTs. // When this is not possible, (i.e. this signal drives two primary diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index b65b3e972..214157a64 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -522,7 +522,7 @@ void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell) } } -void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers) +void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers) { mappers[ID($not)] = simplemap_not; mappers[ID($pos)] = simplemap_pos; @@ -559,7 +559,7 @@ void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTL void simplemap(RTLIL::Module *module, RTLIL::Cell *cell) { - static std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers; + static dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers; static bool initialized_mappers = false; if (!initialized_mappers) { @@ -595,7 +595,7 @@ struct SimplemapPass : public Pass { log_header(design, "Executing SIMPLEMAP pass (map simple cells to gate primitives).\n"); extra_args(args, 1, design); - std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers; + dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers; simplemap_get_mappers(mappers); for (auto mod : design->modules()) { diff --git a/passes/techmap/simplemap.h b/passes/techmap/simplemap.h index c2d73ea79..5091050a1 100644 --- a/passes/techmap/simplemap.h +++ b/passes/techmap/simplemap.h @@ -42,7 +42,7 @@ extern void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell); extern void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell); extern void simplemap(RTLIL::Module *module, RTLIL::Cell *cell); -extern void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers); +extern void simplemap_get_mappers(dict<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers); YOSYS_NAMESPACE_END diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index a554be257..c88f7bd0a 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -27,7 +27,6 @@ #include <string.h> #include "simplemap.h" -#include "passes/techmap/techmap.inc" YOSYS_NAMESPACE_BEGIN @@ -51,21 +50,21 @@ void apply_prefix(IdString prefix, RTLIL::SigSpec &sig, RTLIL::Module *module) { vector<SigChunk> chunks = sig; for (auto &chunk : chunks) - if (chunk.wire != NULL) { + if (chunk.wire != nullptr) { IdString wire_name = chunk.wire->name; apply_prefix(prefix, wire_name); - log_assert(module->wires_.count(wire_name) > 0); - chunk.wire = module->wires_[wire_name]; + log_assert(module->wire(wire_name) != nullptr); + chunk.wire = module->wire(wire_name); } sig = chunks; } struct TechmapWorker { - std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> simplemap_mappers; - std::map<std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>>, RTLIL::Module*> techmap_cache; - std::map<RTLIL::Module*, bool> techmap_do_cache; - std::set<RTLIL::Module*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Module>> module_queue; + dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> simplemap_mappers; + dict<std::pair<IdString, dict<IdString, RTLIL::Const>>, RTLIL::Module*> techmap_cache; + dict<RTLIL::Module*, bool> techmap_do_cache; + pool<RTLIL::Module*> module_queue; dict<Module*, SigMap> sigmaps; pool<IdString> flatten_do_list; @@ -79,31 +78,21 @@ struct TechmapWorker RTLIL::SigSpec value; }; - typedef std::map<std::string, std::vector<TechmapWireData>> TechmapWires; + typedef dict<IdString, std::vector<TechmapWireData>> TechmapWires; - bool extern_mode; - bool assert_mode; - bool flatten_mode; - bool recursive_mode; - bool autoproc_mode; - bool ignore_wb; - - TechmapWorker() - { - extern_mode = false; - assert_mode = false; - flatten_mode = false; - recursive_mode = false; - autoproc_mode = false; - ignore_wb = false; - } + bool extern_mode = false; + bool assert_mode = false; + bool flatten_mode = false; + bool recursive_mode = false; + bool autoproc_mode = false; + bool ignore_wb = false; std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose) { std::string constmap_info; - std::map<RTLIL::SigBit, std::pair<RTLIL::IdString, int>> connbits_map; + dict<RTLIL::SigBit, std::pair<IdString, int>> connbits_map; - for (auto conn : cell->connections()) + for (auto &conn : cell->connections()) for (int i = 0; i < GetSize(conn.second); i++) { RTLIL::SigBit bit = sigmap(conn.second[i]); if (bit.wire == nullptr) { @@ -117,7 +106,7 @@ struct TechmapWorker constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i, log_id(connbits_map.at(bit).first), connbits_map.at(bit).second); } else { - connbits_map[bit] = std::pair<RTLIL::IdString, int>(conn.first, i); + connbits_map.emplace(bit, std::make_pair(conn.first, i)); constmap_info += stringf("|%s %d", log_id(conn.first), i); } } @@ -129,24 +118,25 @@ struct TechmapWorker { TechmapWires result; - if (module == NULL) + if (module == nullptr) return result; - for (auto &it : module->wires_) { - const char *p = it.first.c_str(); + for (auto w : module->wires()) { + const char *p = w->name.c_str(); if (*p == '$') continue; const char *q = strrchr(p+1, '.'); - p = q ? q+1 : p+1; + if (q) + p = q; - if (!strncmp(p, "_TECHMAP_", 9)) { + if (!strncmp(p, "\\_TECHMAP_", 10)) { TechmapWireData record; - record.wire = it.second; - record.value = it.second; + record.wire = w; + record.value = w; result[p].push_back(record); - it.second->attributes[ID::keep] = RTLIL::Const(1); - it.second->attributes[ID::_techmap_special_] = RTLIL::Const(1); + w->set_bool_attribute(ID::keep); + w->set_bool_attribute(ID::_techmap_special_); } } @@ -165,7 +155,7 @@ struct TechmapWorker if (tpl->processes.size() != 0) { log("Technology map yielded processes:"); for (auto &it : tpl->processes) - log(" %s",RTLIL::id2cstr(it.first)); + log(" %s",log_id(it.first)); log("\n"); if (autoproc_mode) { Pass::call_on_module(tpl->design, tpl, "proc"); @@ -179,8 +169,8 @@ struct TechmapWorker orig_cell_name = cell->name.str(); if (!flatten_mode) { - for (auto &it : tpl->cells_) - if (it.first == ID::_TECHMAP_REPLACE_) { + for (auto tpl_cell : tpl->cells()) + if (tpl_cell->name == ID::_TECHMAP_REPLACE_) { module->rename(cell, stringf("$techmap%d", autoidx++) + cell->name.str()); break; } @@ -204,30 +194,30 @@ struct TechmapWorker design->select(module, m); } - std::map<RTLIL::IdString, RTLIL::IdString> positional_ports; + dict<IdString, IdString> positional_ports; dict<Wire*, IdString> temp_renamed_wires; pool<SigBit> autopurge_tpl_bits; - for (auto &it : tpl->wires_) + for (auto tpl_w : tpl->wires()) { - if (it.second->port_id > 0) + if (tpl_w->port_id > 0) { - IdString posportname = stringf("$%d", it.second->port_id); - positional_ports[posportname] = it.first; + IdString posportname = stringf("$%d", tpl_w->port_id); + positional_ports.emplace(posportname, tpl_w->name); - if (!flatten_mode && it.second->get_bool_attribute(ID::techmap_autopurge) && - (!cell->hasPort(it.second->name) || !GetSize(cell->getPort(it.second->name))) && + if (!flatten_mode && tpl_w->get_bool_attribute(ID::techmap_autopurge) && + (!cell->hasPort(tpl_w->name) || !GetSize(cell->getPort(tpl_w->name))) && (!cell->hasPort(posportname) || !GetSize(cell->getPort(posportname)))) { if (sigmaps.count(tpl) == 0) sigmaps[tpl].set(tpl); - for (auto bit : sigmaps.at(tpl)(it.second)) + for (auto bit : sigmaps.at(tpl)(tpl_w)) if (bit.wire != nullptr) autopurge_tpl_bits.insert(bit); } } - IdString w_name = it.second->name; + IdString w_name = tpl_w->name; apply_prefix(cell->name, w_name); RTLIL::Wire *w = module->wire(w_name); if (w != nullptr) { @@ -237,30 +227,30 @@ struct TechmapWorker w = nullptr; } else { w->attributes.erase(ID::hierconn); - if (GetSize(w) < GetSize(it.second)) { + if (GetSize(w) < GetSize(tpl_w)) { log_warning("Widening signal %s.%s to match size of %s.%s (via %s.%s).\n", log_id(module), log_id(w), - log_id(tpl), log_id(it.second), log_id(module), log_id(cell)); - w->width = GetSize(it.second); + log_id(tpl), log_id(tpl_w), log_id(module), log_id(cell)); + w->width = GetSize(tpl_w); } } } if (w == nullptr) { - w = module->addWire(w_name, it.second); + w = module->addWire(w_name, tpl_w); w->port_input = false; w->port_output = false; w->port_id = 0; if (!flatten_mode) w->attributes.erase(ID::techmap_autopurge); - if (it.second->get_bool_attribute(ID::_techmap_special_)) + if (tpl_w->get_bool_attribute(ID::_techmap_special_)) w->attributes.clear(); if (w->attributes.count(ID::src)) w->add_strpool_attribute(ID::src, extra_src_attrs); } design->select(module, w); - if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) { - IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), it.second->name.c_str() + strlen("\\_TECHMAP_REPLACE_")); - Wire *replace_w = module->addWire(replace_name, it.second); + if (tpl_w->name.begins_with("\\_TECHMAP_REPLACE_.")) { + IdString replace_name = stringf("%s%s", orig_cell_name.c_str(), tpl_w->name.c_str() + strlen("\\_TECHMAP_REPLACE_")); + Wire *replace_w = module->addWire(replace_name, tpl_w); module->connect(replace_w, w); } } @@ -268,24 +258,23 @@ struct TechmapWorker SigMap tpl_sigmap(tpl); pool<SigBit> tpl_written_bits; - for (auto &it1 : tpl->cells_) - for (auto &it2 : it1.second->connections_) - if (it1.second->output(it2.first)) - for (auto bit : tpl_sigmap(it2.second)) + for (auto tpl_cell : tpl->cells()) + for (auto &conn : tpl_cell->connections()) + if (tpl_cell->output(conn.first)) + for (auto bit : tpl_sigmap(conn.second)) tpl_written_bits.insert(bit); - for (auto &it1 : tpl->connections_) - for (auto bit : tpl_sigmap(it1.first)) + for (auto &conn : tpl->connections()) + for (auto bit : tpl_sigmap(conn.first)) tpl_written_bits.insert(bit); SigMap port_signal_map; - SigSig port_signal_assign; for (auto &it : cell->connections()) { - RTLIL::IdString portname = it.first; + IdString portname = it.first; if (positional_ports.count(portname) > 0) portname = positional_ports.at(portname); - if (tpl->wires_.count(portname) == 0 || tpl->wires_.at(portname)->port_id == 0) { + if (tpl->wire(portname) == nullptr || tpl->wire(portname)->port_id == 0) { if (portname.begins_with("$")) log_error("Can't map port `%s' of cell `%s' to template `%s'!\n", portname.c_str(), cell->name.c_str(), tpl->name.c_str()); continue; @@ -294,7 +283,7 @@ struct TechmapWorker if (GetSize(it.second) == 0) continue; - RTLIL::Wire *w = tpl->wires_.at(portname); + RTLIL::Wire *w = tpl->wire(portname); RTLIL::SigSig c, extra_connect; if (w->port_output && !w->port_input) { @@ -377,19 +366,19 @@ struct TechmapWorker } } - for (auto &it : tpl->cells_) + for (auto tpl_cell : tpl->cells()) { - IdString c_name = it.second->name.str(); + IdString c_name = tpl_cell->name; bool techmap_replace_cell = (!flatten_mode) && (c_name == ID::_TECHMAP_REPLACE_); if (techmap_replace_cell) c_name = orig_cell_name; - else if (it.second->name.begins_with("\\_TECHMAP_REPLACE_.")) + else if (tpl_cell->name.begins_with("\\_TECHMAP_REPLACE_.")) c_name = stringf("%s%s", orig_cell_name.c_str(), c_name.c_str() + strlen("\\_TECHMAP_REPLACE_")); else apply_prefix(cell->name, c_name); - RTLIL::Cell *c = module->addCell(c_name, it.second); + RTLIL::Cell *c = module->addCell(c_name, tpl_cell); design->select(module, c); if (!flatten_mode && c->type.begins_with("\\$")) @@ -397,12 +386,12 @@ struct TechmapWorker vector<IdString> autopurge_ports; - for (auto &it2 : c->connections_) + for (auto &conn : c->connections()) { bool autopurge = false; if (!autopurge_tpl_bits.empty()) { - autopurge = GetSize(it2.second) != 0; - for (auto &bit : sigmaps.at(tpl)(it2.second)) + autopurge = GetSize(conn.second) != 0; + for (auto &bit : sigmaps.at(tpl)(conn.second)) if (!autopurge_tpl_bits.count(bit)) { autopurge = false; break; @@ -410,10 +399,12 @@ struct TechmapWorker } if (autopurge) { - autopurge_ports.push_back(it2.first); + autopurge_ports.push_back(conn.first); } else { - apply_prefix(cell->name, it2.second, module); - port_signal_map.apply(it2.second); + RTLIL::SigSpec new_conn = conn.second; + apply_prefix(cell->name, new_conn, module); + port_signal_map.apply(new_conn); + c->setPort(conn.first, std::move(new_conn)); } } @@ -463,8 +454,8 @@ struct TechmapWorker } } - bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, std::set<RTLIL::Cell*> &handled_cells, - const std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> &celltypeMap, bool in_recursion) + bool techmap_module(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Design *map, pool<RTLIL::Cell*> &handled_cells, + const dict<IdString, pool<IdString>> &celltypeMap, bool in_recursion) { std::string mapmsg_prefix = in_recursion ? "Recursively mapping" : "Mapping"; @@ -489,13 +480,13 @@ struct TechmapWorker } } - TopoSort<RTLIL::Cell*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell>> cells; - std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_inbit; - std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> outbit_to_cell; + TopoSort<RTLIL::Cell*, IdString::compare_ptr_by_name<RTLIL::Cell>> cells; + dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_to_inbit; + dict<RTLIL::SigBit, pool<RTLIL::Cell*>> outbit_to_cell; - for (auto cell : module->cells()) + for (auto cell : module->selected_cells()) { - if (!design->selected(module, cell) || handled_cells.count(cell) > 0) + if (handled_cells.count(cell) > 0) continue; std::string cell_type = cell->type.str(); @@ -511,7 +502,7 @@ struct TechmapWorker if (flatten_mode) { bool keepit = cell->get_bool_attribute(ID::keep_hierarchy); for (auto &tpl_name : celltypeMap.at(cell_type)) - if (map->modules_[tpl_name]->get_bool_attribute(ID::keep_hierarchy)) + if (map->module(tpl_name)->get_bool_attribute(ID::keep_hierarchy)) keepit = true; if (keepit) { if (!flatten_keep_list[cell]) { @@ -533,7 +524,7 @@ struct TechmapWorker continue; for (auto &tpl_name : celltypeMap.at(cell_type)) { - RTLIL::Module *tpl = map->modules_[tpl_name]; + RTLIL::Module *tpl = map->module(tpl_name); RTLIL::Wire *port = tpl->wire(conn.first); if (port && port->port_input) cell_to_inbit[cell].insert(sig.begin(), sig.end()); @@ -566,9 +557,9 @@ struct TechmapWorker for (auto &tpl_name : celltypeMap.at(cell_type)) { - RTLIL::IdString derived_name = tpl_name; - RTLIL::Module *tpl = map->modules_[tpl_name]; - std::map<RTLIL::IdString, RTLIL::Const> parameters(cell->parameters.begin(), cell->parameters.end()); + IdString derived_name = tpl_name; + RTLIL::Module *tpl = map->module(tpl_name); + dict<IdString, RTLIL::Const> parameters(cell->parameters); if (tpl->get_blackbox_attribute(ignore_wb)) continue; @@ -675,7 +666,7 @@ struct TechmapWorker if (extmapper_name == "simplemap") { if (simplemap_mappers.count(cell->type) == 0) - log_error("No simplemap mapper for cell type %s found!\n", RTLIL::id2cstr(cell->type)); + log_error("No simplemap mapper for cell type %s found!\n", log_id(cell->type)); simplemap_mappers.at(cell->type)(module, cell); } @@ -686,7 +677,7 @@ struct TechmapWorker } module->remove(cell); - cell = NULL; + cell = nullptr; } did_something = true; @@ -694,10 +685,10 @@ struct TechmapWorker break; } - for (auto conn : cell->connections()) { + for (auto &conn : cell->connections()) { if (conn.first.begins_with("$")) continue; - if (tpl->wires_.count(conn.first) > 0 && tpl->wires_.at(conn.first)->port_id > 0) + if (tpl->wire(conn.first) != nullptr && tpl->wire(conn.first)->port_id > 0) continue; if (!conn.second.is_fully_const() || parameters.count(conn.first) > 0 || tpl->avail_parameters.count(conn.first) == 0) goto next_tpl; @@ -710,23 +701,23 @@ struct TechmapWorker } if (tpl->avail_parameters.count(ID::_TECHMAP_CELLTYPE_) != 0) - parameters[ID::_TECHMAP_CELLTYPE_] = RTLIL::unescape_id(cell->type); + parameters.emplace(ID::_TECHMAP_CELLTYPE_, RTLIL::unescape_id(cell->type)); - for (auto conn : cell->connections()) { - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))) != 0) { + for (auto &conn : cell->connections()) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first))) != 0) { std::vector<RTLIL::SigBit> v = sigmap(conn.second).to_sigbit_vector(); for (auto &bit : v) - bit = RTLIL::SigBit(bit.wire == NULL ? RTLIL::State::S1 : RTLIL::State::S0); - parameters[stringf("\\_TECHMAP_CONSTMSK_%s_", RTLIL::id2cstr(conn.first))] = RTLIL::SigSpec(v).as_const(); + bit = RTLIL::SigBit(bit.wire == nullptr ? RTLIL::State::S1 : RTLIL::State::S0); + parameters.emplace(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const()); } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", RTLIL::id2cstr(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first))) != 0) { std::vector<RTLIL::SigBit> v = sigmap(conn.second).to_sigbit_vector(); for (auto &bit : v) - if (bit.wire != NULL) + if (bit.wire != nullptr) bit = RTLIL::SigBit(RTLIL::State::Sx); - parameters[stringf("\\_TECHMAP_CONSTVAL_%s_", RTLIL::id2cstr(conn.first))] = RTLIL::SigSpec(v).as_const(); + parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const()); } - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", RTLIL::id2cstr(conn.first))) != 0) { + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first))) != 0) { auto sig = sigmap(conn.second); RTLIL::Const value(State::Sx, sig.size()); for (int i = 0; i < sig.size(); i++) { @@ -735,20 +726,20 @@ struct TechmapWorker value[i] = it->second; } } - parameters[stringf("\\_TECHMAP_WIREINIT_%s_", RTLIL::id2cstr(conn.first))] = value; + parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), value); } } int unique_bit_id_counter = 0; - std::map<RTLIL::SigBit, int> unique_bit_id; + dict<RTLIL::SigBit, int> unique_bit_id; unique_bit_id[RTLIL::State::S0] = unique_bit_id_counter++; unique_bit_id[RTLIL::State::S1] = unique_bit_id_counter++; unique_bit_id[RTLIL::State::Sx] = unique_bit_id_counter++; unique_bit_id[RTLIL::State::Sz] = unique_bit_id_counter++; - for (auto conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) { - for (auto &bit : sigmap(conn.second).to_sigbit_vector()) + for (auto &conn : cell->connections()) + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { + for (auto &bit : sigmap(conn.second)) if (unique_bit_id.count(bit) == 0) unique_bit_id[bit] = unique_bit_id_counter++; } @@ -763,14 +754,17 @@ struct TechmapWorker if (tpl->avail_parameters.count(ID::_TECHMAP_BITS_CONNMAP_)) parameters[ID::_TECHMAP_BITS_CONNMAP_] = bits; - for (auto conn : cell->connections()) - if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))) != 0) { + for (auto &conn : cell->connections()) + if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { RTLIL::Const value; - for (auto &bit : sigmap(conn.second).to_sigbit_vector()) { - RTLIL::Const chunk(unique_bit_id.at(bit), bits); - value.bits.insert(value.bits.end(), chunk.bits.begin(), chunk.bits.end()); + for (auto &bit : sigmap(conn.second)) { + int val = unique_bit_id.at(bit); + for (int i = 0; i < bits; i++) { + value.bits.push_back((val & 1) != 0 ? State::S1 : State::S0); + val = val >> 1; + } } - parameters[stringf("\\_TECHMAP_CONNMAP_%s_", RTLIL::id2cstr(conn.first))] = value; + parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), value); } } @@ -778,17 +772,18 @@ struct TechmapWorker use_wrapper_tpl:; // do not register techmap_wrap modules with techmap_cache } else { - std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>> key(tpl_name, parameters); - if (techmap_cache.count(key) > 0) { - tpl = techmap_cache[key]; + std::pair<IdString, dict<IdString, RTLIL::Const>> key(tpl_name, parameters); + auto it = techmap_cache.find(key); + if (it != techmap_cache.end()) { + tpl = it->second; } else { if (parameters.size() != 0) { mkdebug.on(); - derived_name = tpl->derive(map, dict<RTLIL::IdString, RTLIL::Const>(parameters.begin(), parameters.end())); + derived_name = tpl->derive(map, parameters); tpl = map->module(derived_name); log_continue = true; } - techmap_cache[key] = tpl; + techmap_cache.emplace(std::move(key), tpl); } } @@ -805,7 +800,7 @@ struct TechmapWorker bool keep_running = true; techmap_do_cache[tpl] = true; - std::set<std::string> techmap_wire_names; + pool<IdString> techmap_wire_names; while (keep_running) { @@ -815,11 +810,11 @@ struct TechmapWorker for (auto &it : twd) techmap_wire_names.insert(it.first); - for (auto &it : twd["_TECHMAP_FAIL_"]) { + for (auto &it : twd[ID::_TECHMAP_FAIL_]) { RTLIL::SigSpec value = it.value; if (value.is_fully_const() && value.as_bool()) { log("Not using module `%s' from techmap as it contains a %s marker wire with non-zero value %s.\n", - derived_name.c_str(), RTLIL::id2cstr(it.wire->name), log_signal(value)); + derived_name.c_str(), log_id(it.wire->name), log_signal(value)); techmap_do_cache[tpl] = false; } } @@ -829,13 +824,13 @@ struct TechmapWorker for (auto &it : twd) { - if (it.first.compare(0, 12, "_TECHMAP_DO_") != 0 || it.second.empty()) + if (!it.first.begins_with("\\_TECHMAP_DO_") || it.second.empty()) continue; auto &data = it.second.front(); if (!data.value.is_fully_const()) - log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(data.wire->name), log_signal(data.value)); + log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(data.wire->name), log_signal(data.value)); techmap_wire_names.erase(it.first); @@ -851,7 +846,7 @@ struct TechmapWorker cmd_string = cmd_string.substr(strlen("CONSTMAP; ")); log("Analyzing pattern of constant bits for this cell:\n"); - RTLIL::IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true); + IdString new_tpl_name = constmap_tpl_name(sigmap, tpl, cell, true); log("Creating constmapped module `%s'.\n", log_id(new_tpl_name)); log_assert(map->module(new_tpl_name) == nullptr); @@ -862,16 +857,16 @@ struct TechmapWorker techmap_do_cache[new_tpl] = true; tpl = new_tpl; - std::map<RTLIL::SigBit, RTLIL::SigBit> port_new2old_map; - std::map<RTLIL::SigBit, RTLIL::SigBit> port_connmap; - std::map<RTLIL::SigBit, RTLIL::SigBit> cellbits_to_tplbits; + dict<RTLIL::SigBit, RTLIL::SigBit> port_new2old_map; + dict<RTLIL::SigBit, RTLIL::SigBit> port_connmap; + dict<RTLIL::SigBit, RTLIL::SigBit> cellbits_to_tplbits; for (auto wire : tpl->wires().to_vector()) { if (!wire->port_input || wire->port_output) continue; - RTLIL::IdString port_name = wire->name; + IdString port_name = wire->name; tpl->rename(wire, NEW_ID); RTLIL::Wire *new_wire = tpl->addWire(port_name, wire); @@ -879,12 +874,12 @@ struct TechmapWorker wire->port_id = 0; for (int i = 0; i < wire->width; i++) { - port_new2old_map[RTLIL::SigBit(new_wire, i)] = RTLIL::SigBit(wire, i); - port_connmap[RTLIL::SigBit(wire, i)] = RTLIL::SigBit(new_wire, i); + port_new2old_map.emplace(RTLIL::SigBit(new_wire, i), RTLIL::SigBit(wire, i)); + port_connmap.emplace(RTLIL::SigBit(wire, i), RTLIL::SigBit(new_wire, i)); } } - for (auto conn : cell->connections()) + for (auto &conn : cell->connections()) for (int i = 0; i < GetSize(conn.second); i++) { RTLIL::SigBit bit = sigmap(conn.second[i]); @@ -926,7 +921,7 @@ struct TechmapWorker log_assert(!strncmp(q, "_TECHMAP_DO_", 12)); std::string new_name = data.wire->name.substr(0, q-p) + "_TECHMAP_DONE_" + data.wire->name.substr(q-p+12); - while (tpl->wires_.count(new_name)) + while (tpl->wire(new_name) != nullptr) new_name += "_"; tpl->rename(data.wire->name, new_name); @@ -937,17 +932,17 @@ struct TechmapWorker TechmapWires twd = techmap_find_special_wires(tpl); for (auto &it : twd) { - if (it.first != "_TECHMAP_FAIL_" && (it.first.substr(0, 20) != "_TECHMAP_REMOVEINIT_" || it.first[it.first.size()-1] != '_') && it.first.substr(0, 12) != "_TECHMAP_DO_" && it.first.substr(0, 14) != "_TECHMAP_DONE_") - log_error("Techmap yielded unknown config wire %s.\n", it.first.c_str()); + if (it.first != ID::_TECHMAP_FAIL_ && (!it.first.begins_with("\\_TECHMAP_REMOVEINIT_") || !it.first.ends_with("_")) && !it.first.begins_with("\\_TECHMAP_DO_") && !it.first.begins_with("\\_TECHMAP_DONE_")) + log_error("Techmap yielded unknown config wire %s.\n", log_id(it.first)); if (techmap_do_cache[tpl]) for (auto &it2 : it.second) if (!it2.value.is_fully_const()) - log_error("Techmap yielded config wire %s with non-const value %s.\n", RTLIL::id2cstr(it2.wire->name), log_signal(it2.value)); + log_error("Techmap yielded config wire %s with non-const value %s.\n", log_id(it2.wire->name), log_signal(it2.value)); techmap_wire_names.erase(it.first); } for (auto &it : techmap_wire_names) - log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", RTLIL::id2cstr(it)); + log_error("Techmap special wire %s disappeared. This is considered a fatal error.\n", log_id(it)); if (recursive_mode) { if (log_continue) { @@ -970,10 +965,10 @@ struct TechmapWorker TechmapWires twd = techmap_find_special_wires(tpl); for (auto &it : twd) { - if (it.first.substr(0, 20) == "_TECHMAP_REMOVEINIT_") { + if (it.first.begins_with("\\_TECHMAP_REMOVEINIT_")) { for (auto &it2 : it.second) { auto val = it2.value.as_const(); - auto wirename = RTLIL::escape_id(it.first.substr(20, it.first.size() - 20 - 1)); + auto wirename = RTLIL::escape_id(it.first.substr(21, it.first.size() - 21 - 1)); auto it = cell->connections().find(wirename); if (it != cell->connections().end()) { auto sig = sigmap(it->second); @@ -1015,7 +1010,7 @@ struct TechmapWorker } log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(tpl)); techmap_module_worker(design, module, cell, tpl); - cell = NULL; + cell = nullptr; } did_something = true; mapped_cell = true; @@ -1275,8 +1270,7 @@ struct TechmapPass : public Pass { RTLIL::Design *map = new RTLIL::Design; if (map_files.empty()) { - std::istringstream f(stdcells_code); - Frontend::frontend_call(map, &f, "<techmap.v>", verilog_frontend); + Frontend::frontend_call(map, nullptr, "+/techmap.v", verilog_frontend); } else { for (auto &fn : map_files) if (fn.compare(0, 1, "%") == 0) { @@ -1285,35 +1279,30 @@ struct TechmapPass : public Pass { log_cmd_error("Can't open saved design `%s'.\n", fn.c_str()+1); } for (auto mod : saved_designs.at(fn.substr(1))->modules()) - if (!map->has(mod->name)) + if (!map->module(mod->name)) map->add(mod->clone()); } else { - std::ifstream f; - rewrite_filename(fn); - f.open(fn.c_str()); - yosys_input_files.insert(fn); - if (f.fail()) - log_cmd_error("Can't open map file `%s'\n", fn.c_str()); - Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "ilang" : verilog_frontend)); + Frontend::frontend_call(map, nullptr, fn, (fn.size() > 3 && fn.compare(fn.size()-3, std::string::npos, ".il") == 0 ? "ilang" : verilog_frontend)); } } log_header(design, "Continuing TECHMAP pass.\n"); - std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap; - for (auto &it : map->modules_) { - if (it.second->attributes.count(ID::techmap_celltype) && !it.second->attributes.at(ID::techmap_celltype).bits.empty()) { - char *p = strdup(it.second->attributes.at(ID::techmap_celltype).decode_string().c_str()); - for (char *q = strtok(p, " \t\r\n"); q; q = strtok(NULL, " \t\r\n")) - celltypeMap[RTLIL::escape_id(q)].insert(it.first); + dict<IdString, pool<IdString>> celltypeMap; + for (auto module : map->modules()) { + if (module->attributes.count(ID::techmap_celltype) && !module->attributes.at(ID::techmap_celltype).bits.empty()) { + char *p = strdup(module->attributes.at(ID::techmap_celltype).decode_string().c_str()); + for (char *q = strtok(p, " \t\r\n"); q; q = strtok(nullptr, " \t\r\n")) + celltypeMap[RTLIL::escape_id(q)].insert(module->name); free(p); } else { - string module_name = it.first.str(); - if (it.first.begins_with("\\$")) - module_name = module_name.substr(1); - celltypeMap[module_name].insert(it.first); + IdString module_name = module->name.begins_with("\\$") ? + module->name.substr(1) : module->name.str(); + celltypeMap[module_name].insert(module->name); } } + for (auto &i : celltypeMap) + i.second.sort(RTLIL::sort_by_id_str()); for (auto module : design->modules()) worker.module_queue.insert(module); @@ -1325,7 +1314,7 @@ struct TechmapPass : public Pass { int module_max_iter = max_iter; bool did_something = true; - std::set<RTLIL::Cell*> handled_cells; + pool<RTLIL::Cell*> handled_cells; while (did_something) { did_something = false; if (worker.techmap_module(design, module, map, handled_cells, celltypeMap, false)) @@ -1382,18 +1371,20 @@ struct FlattenPass : public Pass { extra_args(args, argidx, design); - std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap; + dict<IdString, pool<IdString>> celltypeMap; for (auto module : design->modules()) celltypeMap[module->name].insert(module->name); + for (auto &i : celltypeMap) + i.second.sort(RTLIL::sort_by_id_str()); - RTLIL::Module *top_mod = NULL; + RTLIL::Module *top_mod = nullptr; if (design->full_selection()) for (auto mod : design->modules()) if (mod->get_bool_attribute(ID::top)) top_mod = mod; - std::set<RTLIL::Cell*> handled_cells; - if (top_mod != NULL) { + pool<RTLIL::Cell*> handled_cells; + if (top_mod != nullptr) { worker.flatten_do_list.insert(top_mod->name); while (!worker.flatten_do_list.empty()) { auto mod = design->module(*worker.flatten_do_list.begin()); @@ -1402,20 +1393,19 @@ struct FlattenPass : public Pass { worker.flatten_do_list.erase(mod->name); } } else { - for (auto mod : vector<Module*>(design->modules())) { + for (auto mod : design->modules().to_vector()) while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { } - } } log_suppressed(); log("No more expansions possible.\n"); - if (top_mod != NULL) + if (top_mod != nullptr) { - pool<RTLIL::IdString> used_modules, new_used_modules; + pool<IdString> used_modules, new_used_modules; new_used_modules.insert(top_mod->name); while (!new_used_modules.empty()) { - pool<RTLIL::IdString> queue; + pool<IdString> queue; queue.swap(new_used_modules); for (auto modname : queue) used_modules.insert(modname); @@ -1425,15 +1415,11 @@ struct FlattenPass : public Pass { new_used_modules.insert(cell->type); } - dict<RTLIL::IdString, RTLIL::Module*> new_modules; - for (auto mod : vector<Module*>(design->modules())) - if (used_modules[mod->name] || mod->get_blackbox_attribute(worker.ignore_wb)) { - new_modules[mod->name] = mod; - } else { + for (auto mod : design->modules().to_vector()) + if (!used_modules[mod->name] && !mod->get_blackbox_attribute(worker.ignore_wb)) { log("Deleting now unused module %s.\n", log_id(mod)); - delete mod; + design->remove(mod); } - design->modules_.swap(new_modules); } log_pop(); diff --git a/techlibs/common/abc9_unmap.v b/techlibs/common/abc9_unmap.v index bcbe91477..c39648c62 100644 --- a/techlibs/common/abc9_unmap.v +++ b/techlibs/common/abc9_unmap.v @@ -1,5 +1,5 @@ (* techmap_celltype = "$__DFF_N__$abc9_flop $__DFF_P__$abc9_flop" *) -module $__DFF_x__$abc9_flop (input C, D, Q, output n1); +module $__DFF_x__$abc9_flop (input C, D, (* init = 1'b0 *) input Q, output n1); parameter _TECHMAP_CELLTYPE_ = ""; generate if (_TECHMAP_CELLTYPE_ == "$__DFF_N__$abc9_flop") $_DFF_N_ _TECHMAP_REPLACE_ (.C(C), .D(D), .Q(Q)); diff --git a/tests/arch/ecp5/latches_abc9.ys b/tests/arch/ecp5/latches_abc9.ys new file mode 100644 index 000000000..4daf04050 --- /dev/null +++ b/tests/arch/ecp5/latches_abc9.ys @@ -0,0 +1,13 @@ +read_verilog <<EOT +module top(input e, d, output q); +reg l; +always @* + if (e) + l = ~d; +assign q = ~l; +endmodule +EOT +# Can't run any sort of equivalence check because latches are blown to LUTs +synth_ecp5 -abc9 +select -assert-count 2 t:LUT4 +select -assert-none t:LUT4 %% t:* %D diff --git a/tests/arch/ice40/mux.ys b/tests/arch/ice40/mux.ys index 99822391d..2b661fd6b 100644 --- a/tests/arch/ice40/mux.ys +++ b/tests/arch/ice40/mux.ys @@ -35,6 +35,7 @@ proc equiv_opt -assert -map +/ice40/cells_sim.v synth_ice40 # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux16 # Constrain all select calls below inside the top module -select -assert-count 11 t:SB_LUT4 +select -assert-min 11 t:SB_LUT4 +select -assert-max 12 t:SB_LUT4 select -assert-none t:SB_LUT4 %% t:* %D diff --git a/tests/arch/xilinx/abc9_dff.ys b/tests/arch/xilinx/abc9_dff.ys index fd343969b..210e87477 100644 --- a/tests/arch/xilinx/abc9_dff.ys +++ b/tests/arch/xilinx/abc9_dff.ys @@ -50,10 +50,10 @@ FDCE_1 /*#(.INIT(1))*/ fd7(.C(C), .CE(1'b0), .D(D), .CLR(1'b0), .Q(Q[6])); FDPE_1 #(.INIT(1)) fd8(.C(C), .CE(1'b0), .D(D), .PRE(1'b0), .Q(Q[7])); endmodule EOT -logger -expect warning "Module '\$paramod\\FDRE\\INIT=1' contains a \$dff cell .*" 1 -logger -expect warning "Module '\$paramod\\FDRE_1\\INIT=1' contains a \$dff cell .*" 1 -logger -expect warning "Module 'FDSE' contains a \$dff cell .*" 1 -logger -expect warning "Module '\$paramod\\FDSE_1\\INIT=1' contains a \$dff cell .*" 1 +logger -expect warning "Whitebox '\$paramod\\FDRE\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 +logger -expect warning "Whitebox '\$paramod\\FDRE_1\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 +logger -expect warning "Whitebox 'FDSE' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 +logger -expect warning "Whitebox '\$paramod\\FDSE_1\\INIT=1' with \(\* abc9_flop \*\) contains a \$dff cell with non-zero initial state -- this is not supported for ABC9 sequential synthesis. Treating as a blackbox\." 1 equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf design -load postopt select -assert-count 8 t:FD* @@ -82,4 +82,53 @@ select -assert-count 1 t:FDPE select -assert-count 2 t:INV select -assert-count 0 t:FD* t:INV %% t:* %D + +design -reset +read_verilog <<EOT +module top(input clk, input d, output q); +reg r; +always @(posedge clk) begin +r <= d; +end +assign q = ~r; +endmodule +EOT +proc +equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf +design -load postopt +select -assert-count 1 t:FDRE %co w:r %i + + +design -reset +read_verilog <<EOT +module top(input clk, input a, b, output reg q1, output q2); +reg r; +always @(posedge clk) begin + q1 <= a | b; + r <= ~(~a & ~b); +end +assign q2 = r; +endmodule +EOT +proc +equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf +design -load postopt +select -assert-count 1 t:FDRE %co %a w:r %i + + +design -reset +read_verilog <<EOT +module top(input clk, input a, b, output o); +reg r1, r2; +always @(posedge clk) begin + r1 <= a | b; + r2 <= ~(~a & ~b); +end +assign o = r1 | r2; +endmodule +EOT +proc +equiv_opt -assert -multiclock -map +/xilinx/cells_sim.v synth_xilinx -abc9 -dff -noiopad -noclkbuf + + logger -expect-no-warnings diff --git a/tests/arch/xilinx/pmgen_xilinx_srl.ys b/tests/arch/xilinx/pmgen_xilinx_srl.ys index ea2f20487..e76fb20ab 100644 --- a/tests/arch/xilinx/pmgen_xilinx_srl.ys +++ b/tests/arch/xilinx/pmgen_xilinx_srl.ys @@ -1,6 +1,6 @@ read_verilog -icells <<EOT module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, output SO); - parameter DEPTH = 1; + parameter DEPTH = 2; parameter [DEPTH-1:0] INIT = 0; parameter CLKPOL = 1; parameter ENPOL = 2; diff --git a/tests/arch/xilinx/xilinx_srl.v b/tests/arch/xilinx/xilinx_srl.v index bc2a15ab2..29920da41 100644 --- a/tests/arch/xilinx/xilinx_srl.v +++ b/tests/arch/xilinx/xilinx_srl.v @@ -29,7 +29,7 @@ endmodule module $__XILINX_SHREG_(input C, D, E, input [1:0] L, output Q); parameter CLKPOL = 1; parameter ENPOL = 1; -parameter DEPTH = 1; +parameter DEPTH = 2; parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}}; reg [DEPTH-1:0] r = INIT; wire clk = C ^ CLKPOL; diff --git a/tests/various/abc9.ys b/tests/various/abc9.ys index ac714665f..a9880c722 100644 --- a/tests/various/abc9.ys +++ b/tests/various/abc9.ys @@ -97,4 +97,5 @@ select -assert-count 3 t:$_DFF_N_ select -assert-none c:ff1 c:ff2 c:ff4 %% c:* %D clean select -assert-count 2 a:init -select -assert-none w:w w:z %% a:init %D +select -assert-count 1 w:w a:init %i +select -assert-count 1 c:ff4 %co c:ff4 %d %a a:init %i diff --git a/tests/various/attrib07_func_call.v b/tests/various/attrib07_func_call.v index f55ef2316..8c9fb2926 100644 --- a/tests/various/attrib07_func_call.v +++ b/tests/various/attrib07_func_call.v @@ -11,7 +11,7 @@ module foo(clk, rst, inp_a, inp_b, out); input wire rst; input wire [7:0] inp_a; input wire [7:0] inp_b; - output wire [7:0] out; + output reg [7:0] out; always @(posedge clk) if (rst) out <= 0; diff --git a/tests/various/constmsk_testmap.v b/tests/various/constmsk_testmap.v index fab1b1bbc..b6809c7c0 100644 --- a/tests/various/constmsk_testmap.v +++ b/tests/various/constmsk_testmap.v @@ -1,7 +1,7 @@ (* techmap_celltype = "$reduce_or" *) module my_opt_reduce_or(...); parameter A_SIGNED = 0; - parameter A_WIDTH = 1; + parameter A_WIDTH = 2; parameter Y_WIDTH = 1; input [A_WIDTH-1:0] A; diff --git a/tests/various/shregmap.v b/tests/various/shregmap.v index 604c2c976..dc828eda7 100644 --- a/tests/various/shregmap.v +++ b/tests/various/shregmap.v @@ -13,7 +13,7 @@ assign q = {shift2[3], shift1[3]}; endmodule module $__SHREG_DFF_P_(input C, D, output Q); -parameter DEPTH = 1; +parameter DEPTH = 2; parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}}; reg [DEPTH-1:0] r = INIT; always @(posedge C) @@ -38,7 +38,7 @@ endmodule module $__XILINX_SHREG_(input C, D, input [1:0] L, output Q); parameter CLKPOL = 1; parameter ENPOL = 1; -parameter DEPTH = 1; +parameter DEPTH = 2; parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}}; reg [DEPTH-1:0] r = INIT; wire clk = C ^ CLKPOL; diff --git a/tests/verilog/bug2042-sv.ys b/tests/verilog/bug2042-sv.ys index e815d7fc5..91989f412 100644 --- a/tests/verilog/bug2042-sv.ys +++ b/tests/verilog/bug2042-sv.ys @@ -2,7 +2,7 @@ read_verilog -sv <<EOT module Task_Test_Top ( input a, -output b +output reg b ); task SomeTaskName(a); |