From 1bf9530fcc0a83938c69ef95b8f960c2c930f74c Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Wed, 6 Aug 2025 16:51:14 +1200 Subject: [PATCH 01/29] cutpoint_blackbox.ys: Add verific-style unknown module --- tests/various/cutpoint_blackbox.ys | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/various/cutpoint_blackbox.ys b/tests/various/cutpoint_blackbox.ys index ee479b968..61001d6b6 100644 --- a/tests/various/cutpoint_blackbox.ys +++ b/tests/various/cutpoint_blackbox.ys @@ -70,3 +70,20 @@ design -load gold select -read cutpoint.gate.sel # nothing in gold but not gate select -assert-none % %n + +# replacing the blackbox with a verific-style unknown module should work too +# (note this specific example loses the values of SOME_PARAM which would +# normally be retained by verific) +design -load hier +delete =bb +read_rtlil << EOT +attribute \blackbox 1 +module \bb + parameter \SOME_PARAM 0 + wire inout 3 \o + wire inout 2 \b + wire inout 1 \a +end +EOT +cutpoint -blackbox +check -assert From 4ac100fe137e79baf50363e94aa088854c21838f Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Wed, 6 Aug 2025 18:11:05 +1200 Subject: [PATCH 02/29] cutpoint: Track wire drivers Necessary to avoid multiple drivers being inserted when a blackbox has inout ports (like when importing an unknown module with `verific`). If any bits of an inout port have a known driver, treat the port as an input. If there are no bits with a known driver, treat the port as an output, and mark each bit as having a driver. --- passes/sat/cutpoint.cc | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 485e44fd6..41fa9fac4 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -109,13 +109,43 @@ struct CutpointPass : public Pass { SigMap sigmap(module); pool cutpoint_bits; + pool wire_drivers; + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) + if (cell->output(conn.first) && !cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + if (bit.wire) + wire_drivers.insert(bit); + + for (auto wire : module->wires()) + if (wire->port_input) + for (auto bit : sigmap(wire)) + wire_drivers.insert(bit); + for (auto cell : module->selected_cells()) { if (cell->type == ID($anyseq)) continue; log("Removing cell %s.%s, making all cell outputs cutpoints.\n", log_id(module), log_id(cell)); for (auto &conn : cell->connections()) { - if (cell->output(conn.first)) - module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second))); + if (cell->output(conn.first)) { + bool do_cut = true; + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + if (wire_drivers.count(bit)) { + log_debug(" Treating inout port '%s' as input.\n", id2cstr(conn.first)); + do_cut = false; + break; + } + + if (do_cut) { + module->connect(conn.second, flag_undef ? Const(State::Sx, GetSize(conn.second)) : module->Anyseq(NEW_ID, GetSize(conn.second))); + if (cell->input(conn.first)) { + log_debug(" Treating inout port '%s' as output.\n", id2cstr(conn.first)); + for (auto bit : sigmap(conn.second)) + wire_drivers.insert(bit); + } + } + } } RTLIL::Cell *scopeinfo = nullptr; From af7d1d3f4f44c82986e70d7188f7fe24e85b5154 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Wed, 6 Aug 2025 18:11:35 +1200 Subject: [PATCH 03/29] cutpoint_blackbox.ys: Extra edge case --- tests/various/cutpoint_blackbox.ys | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/various/cutpoint_blackbox.ys b/tests/various/cutpoint_blackbox.ys index 61001d6b6..1ba9a95df 100644 --- a/tests/various/cutpoint_blackbox.ys +++ b/tests/various/cutpoint_blackbox.ys @@ -87,3 +87,27 @@ end EOT cutpoint -blackbox check -assert + +# also concatenated signals, and signals between two inout ports +design -load hier +delete top =bb +read_verilog << EOT +module top(input [1:0] a, b, output [1:0] o); + wire [1:0] c, d, e; + bb #(.SOME_PARAM(1)) bb1 (.a ({a[0], e[1]}), .b (b), .o (c)); + bb #(.SOME_PARAM(2)) bb2 (.a ({c[1], a[0]}), .b (c), .o (d)); + wb wb1 (.a (a), .b (b), .o (e)); + some_mod some_inst (.a (c), .b (d), .c (e), .o (o)); +endmodule +EOT +read_rtlil << EOT +attribute \blackbox 1 +module \bb + parameter \SOME_PARAM 0 + wire inout 3 width 2 \o + wire inout 2 width 2 \b + wire inout 1 width 2 \a +end +EOT +cutpoint -blackbox +check -assert From f45255f5a234c46d84b2ac240dbeb86b10f299be Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Tue, 5 Aug 2025 12:23:11 +1200 Subject: [PATCH 04/29] tests: More autoname tests --- tests/various/autoname.ys | 176 +++++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 4 deletions(-) diff --git a/tests/various/autoname.ys b/tests/various/autoname.ys index f12fb7995..88d0837d9 100644 --- a/tests/various/autoname.ys +++ b/tests/various/autoname.ys @@ -1,10 +1,11 @@ +# prefer output name +design -reset read_rtlil < Date: Tue, 5 Aug 2025 12:24:05 +1200 Subject: [PATCH 05/29] autoname.cc: Avoid int overflow --- passes/cmds/autoname.cc | 67 ++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc index 737bd3e58..75e54f4b1 100644 --- a/passes/cmds/autoname.cc +++ b/passes/cmds/autoname.cc @@ -22,11 +22,24 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -int autoname_worker(Module *module, const dict& wire_score) +typedef struct name_proposal { + string name; + unsigned int score; + name_proposal() : name(""), score(-1) { } + name_proposal(string name, unsigned int score) : name(name), score(score) { } + bool operator<(const name_proposal &other) const { + if (score != other.score) + return score < other.score; + else + return name.length() < other.name.length(); + } +} name_proposal; + +int autoname_worker(Module *module, const dict& wire_score) { - dict> proposed_cell_names; - dict> proposed_wire_names; - int best_score = -1; + dict proposed_cell_names; + dict proposed_wire_names; + name_proposal best_name; for (auto cell : module->selected_cells()) { if (cell->name[0] == '$') { @@ -36,14 +49,14 @@ int autoname_worker(Module *module, const dict& wire_score) if (bit.wire != nullptr && bit.wire->name[0] != '$') { if (suffix.empty()) suffix = stringf("_%s_%s", log_id(cell->type), log_id(conn.first)); - string new_name(bit.wire->name.str() + suffix); - int score = wire_score.at(bit.wire); - if (cell->output(conn.first)) score = 0; - score = 10000*score + new_name.size(); - if (!proposed_cell_names.count(cell) || score < proposed_cell_names.at(cell).first) { - if (best_score < 0 || score < best_score) - best_score = score; - proposed_cell_names[cell] = make_pair(score, new_name); + name_proposal proposed_name( + bit.wire->name.str() + suffix, + cell->output(conn.first) ? 0 : wire_score.at(bit.wire) + ); + if (!proposed_cell_names.count(cell) || proposed_name < proposed_cell_names.at(cell)) { + if (proposed_name < best_name) + best_name = proposed_name; + proposed_cell_names[cell] = proposed_name; } } } @@ -54,32 +67,36 @@ int autoname_worker(Module *module, const dict& wire_score) if (bit.wire != nullptr && bit.wire->name[0] == '$' && !bit.wire->port_id) { if (suffix.empty()) suffix = stringf("_%s", log_id(conn.first)); - string new_name(cell->name.str() + suffix); - int score = wire_score.at(bit.wire); - if (cell->output(conn.first)) score = 0; - score = 10000*score + new_name.size(); - if (!proposed_wire_names.count(bit.wire) || score < proposed_wire_names.at(bit.wire).first) { - if (best_score < 0 || score < best_score) - best_score = score; - proposed_wire_names[bit.wire] = make_pair(score, new_name); + name_proposal proposed_name( + cell->name.str() + suffix, + cell->output(conn.first) ? 0 : wire_score.at(bit.wire) + ); + if (!proposed_wire_names.count(bit.wire) || proposed_name < proposed_wire_names.at(bit.wire)) { + if (proposed_name < best_name) + best_name = proposed_name; + proposed_wire_names[bit.wire] = proposed_name; } } } } } + // compare against double best score for following comparisons so we don't + // pre-empt a future iteration + best_name.score *= 2; + for (auto &it : proposed_cell_names) { - if (best_score*2 < it.second.first) + if (best_name < it.second) continue; - IdString n = module->uniquify(IdString(it.second.second)); + IdString n = module->uniquify(IdString(it.second.name)); log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); module->rename(it.first, n); } for (auto &it : proposed_wire_names) { - if (best_score*2 < it.second.first) + if (best_name < it.second) continue; - IdString n = module->uniquify(IdString(it.second.second)); + IdString n = module->uniquify(IdString(it.second.name)); log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); module->rename(it.first, n); } @@ -115,7 +132,7 @@ struct AutonamePass : public Pass { for (auto module : design->selected_modules()) { - dict wire_score; + dict wire_score; for (auto cell : module->selected_cells()) for (auto &conn : cell->connections()) for (auto bit : conn.second) From bc77b6213b1db0455ef443a5a044b5160a219145 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 9 Aug 2025 10:52:52 +1200 Subject: [PATCH 06/29] autoname: Fix selection arg --- passes/cmds/autoname.cc | 1 + tests/various/autoname.ys | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc index 75e54f4b1..d2ff568c3 100644 --- a/passes/cmds/autoname.cc +++ b/passes/cmds/autoname.cc @@ -127,6 +127,7 @@ struct AutonamePass : public Pass { // } break; } + extra_args(args, argidx, design); log_header(design, "Executing AUTONAME pass.\n"); diff --git a/tests/various/autoname.ys b/tests/various/autoname.ys index 88d0837d9..29ca81bbe 100644 --- a/tests/various/autoname.ys +++ b/tests/various/autoname.ys @@ -171,11 +171,14 @@ module \top end end EOT -# wires all named for being cell outputs +# wires are named for being cell outputs logger -expect log "Rename wire .d in top to or_Y" 1 +logger -expect log "Rename cell .name2 in top to or_Y_.or_B" 1 +debug autoname t:$or +logger -check-expected + # $name gets shortest name (otherwise bcd_$__unknown_B) logger -expect log "Rename cell .name in top to a_.__unknown_A" 1 -logger -expect log "Rename cell .name2 in top to or_Y_.or_B" 1 # another output wire logger -expect log "Rename wire .e in top to or_Y_.or_B_Y" 1 # $name3 named for lowest fanout wire (otherwise a_$__unknown_A_Y_$and_A) @@ -183,5 +186,5 @@ logger -expect log "Rename cell .name3 in top to or_Y_.or_B_Y_.and_B" 1 # $c gets shortest name, since the cell driving it doesn't have known port # directions logger -expect log "Rename wire .c in top to or_Y_.or_B_A" 1 -debug autoname t:$and +debug autoname logger -check-expected From 96f87aa2d43aab7c21293cbc32c2699ca0a36276 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 18 Sep 2025 12:59:12 +0200 Subject: [PATCH 07/29] simplemap: fix src attribute transfer --- passes/techmap/simplemap.cc | 44 +++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index ddfd7e03e..86ff5c149 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -18,6 +18,7 @@ */ #include "simplemap.h" +#include "backends/rtlil/rtlil_backend.h" #include "kernel/sigtools.h" #include "kernel/ff.h" #include @@ -27,6 +28,14 @@ USING_YOSYS_NAMESPACE YOSYS_NAMESPACE_BEGIN +static void transfer_attr (Cell* to, const Cell* from, const IdString& attr) { + if (from->has_attribute(attr)) + to->attributes[attr] = from->attributes.at(attr); +} +static void transfer_src (Cell* to, const Cell* from) { + transfer_attr(to, from, ID::src); +} + void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) { RTLIL::SigSpec sig_a = cell->getPort(ID::A); @@ -36,7 +45,7 @@ void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::Y, sig_y[i]); } @@ -96,7 +105,7 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::B, sig_b[i]); gate->setPort(ID::Y, sig_y[i]); @@ -147,11 +156,14 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) } RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->attributes[ID::src] = cell->attributes[ID::src]; + log("huh\n"); + RTLIL_BACKEND::dump_cell(std::cout, "", cell); + transfer_src(gate, cell); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::B, sig_a[i+1]); gate->setPort(ID::Y, sig_t[i/2]); last_output_cell = gate; + RTLIL_BACKEND::dump_cell(std::cout, "", gate); } sig_a = sig_t; @@ -160,7 +172,7 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) if (cell->type == ID($reduce_xnor)) { RTLIL::SigSpec sig_t = module->addWire(NEW_ID); RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig_a); gate->setPort(ID::Y, sig_t); last_output_cell = gate; @@ -188,7 +200,7 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig, RTLIL::Cell } RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_OR_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig[i]); gate->setPort(ID::B, sig[i+1]); gate->setPort(ID::Y, sig_t[i/2]); @@ -217,7 +229,7 @@ void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell) } RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig_a); gate->setPort(ID::Y, sig_y); } @@ -246,7 +258,7 @@ void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell) log_assert(!gate_type.empty()); RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig_a); gate->setPort(ID::B, sig_b); gate->setPort(ID::Y, sig_y); @@ -262,20 +274,20 @@ void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec xor_out = module->addWire(NEW_ID, max(GetSize(sig_a), GetSize(sig_b))); RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed); - xor_cell->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(xor_cell, cell); simplemap_bitop(module, xor_cell); module->remove(xor_cell); RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID); RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out); - reduce_cell->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(reduce_cell, cell); simplemap_reduce(module, reduce_cell); module->remove(reduce_cell); if (!is_ne) { RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y); - not_cell->attributes[ID::src] = cell->attributes[ID::src]; - simplemap_lognot(module, not_cell); + transfer_src(not_cell, cell); + simplemap_lognot(module, not_cell); module->remove(not_cell); } } @@ -288,7 +300,7 @@ void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::B, sig_b[i]); gate->setPort(ID::S, cell->getPort(ID::S)); @@ -305,7 +317,7 @@ void simplemap_bwmux(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::B, sig_b[i]); gate->setPort(ID::S, sig_s[i]); @@ -321,7 +333,7 @@ void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(sig_y); i++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_TBUF_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::E, sig_e); gate->setPort(ID::Y, sig_y[i]); @@ -339,7 +351,7 @@ void simplemap_bmux(RTLIL::Module *module, RTLIL::Cell *cell) for (int i = 0; i < GetSize(new_data); i += width) { for (int k = 0; k < width; k++) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, data[i*2+k]); gate->setPort(ID::B, data[i*2+width+k]); gate->setPort(ID::S, sel[idx]); @@ -362,7 +374,7 @@ void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell) SigSpec new_lut_data = module->addWire(NEW_ID, GetSize(lut_data)/2); for (int i = 0; i < GetSize(lut_data); i += 2) { RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_)); - gate->attributes[ID::src] = cell->attributes[ID::src]; + transfer_src(gate, cell); gate->setPort(ID::A, lut_data[i]); gate->setPort(ID::B, lut_data[i+1]); gate->setPort(ID::S, lut_ctrl[idx]); From 2de641d051f2246f1cea94dab8a452a7afa4c8d9 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 22 Sep 2025 04:50:36 +0000 Subject: [PATCH 08/29] Don't redirect spawned ABCs' stderr to our pipe. popen() doesn't do this and we should emulate the behavior of popen() as much as possible. --- passes/techmap/abc.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index c17f85afd..06b30b9b3 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -244,10 +244,6 @@ std::optional spawn_abc(const char* abc_exe, DeferredLogs &logs) { logs.log_error("posix_spawn_file_actions_adddup2 failed"); return std::nullopt; } - if (posix_spawn_file_actions_adddup2(&file_actions, from_child_pipe[1], STDERR_FILENO) != 0) { - logs.log_error("posix_spawn_file_actions_adddup2 failed"); - return std::nullopt; - } if (posix_spawn_file_actions_addclose(&file_actions, to_child_pipe[0]) != 0) { logs.log_error("posix_spawn_file_actions_addclose failed"); return std::nullopt; From 4fc782ef2b7212b5484c418b72b229e15a62604d Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 22 Sep 2025 04:35:48 +0000 Subject: [PATCH 09/29] Make ABC_DONE detection more robust. 1) Change token from ABC_DONE to YOSYS_ABC_DONE to be a bit more robust against false matches. 2) Emit the token from the sourced script so that we don't have to worry about it showing up in the echoing of the command as it executes. It will only appear in ABC stdout when it executes, i.e. when our script has completed. 3) `set abcout` doesn't actually switch ABC to line buffering on stdout, since HAVE_SETVBUF is not actually set in ABC builds in general. So stop using that. ABC does the necessary flushing when `source` has finished. --- passes/techmap/abc.cc | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 06b30b9b3..ff0aa2975 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1065,6 +1065,9 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module abc_script += stringf("; dress \"%s/input.blif\"", run_abc.tempdir_name); abc_script += stringf("; write_blif %s/output.blif", run_abc.tempdir_name); abc_script = add_echos_to_abc_cmd(abc_script); +#if defined(__linux__) && !defined(YOSYS_DISABLE_SPAWN) + abc_script += "; echo \"YOSYS_ABC_DONE\"\n"; +#endif for (size_t i = 0; i+1 < abc_script.size(); i++) if (abc_script[i] == ';' && abc_script[i+1] == ' ') @@ -1147,9 +1150,7 @@ bool read_until_abc_done(abc_output_filter &filt, int fd, DeferredLogs &logs) { break; } line.append(start, p + 1 - start); - // ABC seems to actually print "ABC_DONE \n", but we probably shouldn't - // rely on that extra space being output. - if (line.substr(0, 8) == "ABC_DONE") { + if (line.substr(0, 14) == "YOSYS_ABC_DONE") { // Ignore any leftover output, there should only be a prompt perhaps return true; } @@ -1344,12 +1345,8 @@ void RunAbcState::run(ConcurrentStack &process_pool) return; } std::string cmd = stringf( - // This makes ABC switch stdout to line buffering, which we need - // to see our ABC_DONE message. - "set abcout /dev/stdout\n" "empty\n" - "source %s\n" - "echo \"ABC_DONE\"\n", tmp_script_name); + "source %s\n", tmp_script_name); int ret = write(process.to_child_pipe, cmd.c_str(), cmd.size()); if (ret != static_cast(cmd.size())) { logs.log_error("write failed"); From 1e5f920dbddd94a762d07b5dc94a16a3e8c38f89 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 22 Sep 2025 22:04:17 +0000 Subject: [PATCH 10/29] Remove .c_str() from parameters to log_debug() --- backends/aiger2/aiger.cc | 2 +- frontends/aiger/aigerparse.cc | 2 +- frontends/rpc/rpc_frontend.cc | 4 ++-- kernel/cost.cc | 20 ++++++++++---------- kernel/fstdata.cc | 4 ++-- passes/cmds/abstract.cc | 4 ++-- passes/cmds/box_derive.cc | 2 +- passes/cmds/linecoverage.cc | 4 ++-- passes/memory/memory_libmap.cc | 26 +++++++++++++------------- passes/opt/opt_clean.cc | 8 ++++---- passes/opt/opt_lut.cc | 14 +++++++------- passes/opt/opt_merge.cc | 6 +++--- passes/techmap/clockgate.cc | 8 ++++---- passes/techmap/dfflibmap.cc | 12 ++++++------ passes/techmap/techmap.cc | 10 +++++----- passes/tests/test_cell.cc | 2 +- techlibs/quicklogic/ql_ioff.cc | 6 +++--- 17 files changed, 67 insertions(+), 67 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 05714bc2e..b63e51bde 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -1017,7 +1017,7 @@ struct XAigerWriter : AigerWriter { auto &minfo = cursor.leaf_minfo(*this); for (auto box : minfo.found_blackboxes) { - log_debug(" - %s.%s (type %s): ", cursor.path().c_str(), + log_debug(" - %s.%s (type %s): ", cursor.path(), RTLIL::unescape_id(box->name), log_id(box->type)); diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index 70d94faff..4df37c0cd 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -476,7 +476,7 @@ void AigerReader::parse_xaiger() else if (c == 'n') { parse_xaiger_literal(f); f >> s; - log_debug("n: '%s'\n", s.c_str()); + log_debug("n: '%s'\n", s); } else if (c == 'h') { f.ignore(sizeof(uint32_t)); diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index 625b2c0e8..c21867b30 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -83,11 +83,11 @@ struct RpcServer { std::string request; json_request.dump(request); request += '\n'; - log_debug("RPC frontend request: %s", request.c_str()); + log_debug("RPC frontend request: %s", request); write(request); std::string response = read(); - log_debug("RPC frontend response: %s", response.c_str()); + log_debug("RPC frontend response: %s", response); std::string error; Json json_response = Json::parse(response, error); if (json_response.is_null()) diff --git a/kernel/cost.cc b/kernel/cost.cc index 29787fa52..4942823d3 100644 --- a/kernel/cost.cc +++ b/kernel/cost.cc @@ -143,14 +143,14 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) return 1; if (design_ && design_->module(cell->type) && cell->parameters.empty()) { - log_debug("%s is a module, recurse\n", cell->name.c_str()); + log_debug("%s is a module, recurse\n", cell->name); return get(design_->module(cell->type)); } else if (cell->is_builtin_ff()) { log_assert(cell->hasPort(ID::Q) && "Weird flip flop"); - log_debug("%s is ff\n", cell->name.c_str()); + log_debug("%s is ff\n", cell->name); return cell->getParam(ID::WIDTH).as_int(); } else if (cell->type.in(ID($mem), ID($mem_v2))) { - log_debug("%s is mem\n", cell->name.c_str()); + log_debug("%s is mem\n", cell->name); return cell->getParam(ID::WIDTH).as_int() * cell->getParam(ID::SIZE).as_int(); } else if (y_coef(cell->type)) { // linear with Y_WIDTH or WIDTH @@ -159,23 +159,23 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) int width = cell->getParam(param).as_int(); if (cell->type == ID($demux)) width <<= cell->getParam(ID::S_WIDTH).as_int(); - log_debug("%s Y*coef %d * %d\n", cell->name.c_str(), width, y_coef(cell->type)); + log_debug("%s Y*coef %d * %d\n", cell->name, width, y_coef(cell->type)); return width * y_coef(cell->type); } else if (sum_coef(cell->type)) { // linear with sum of port widths unsigned int sum = port_width_sum(cell); - log_debug("%s sum*coef %d * %d\n", cell->name.c_str(), sum, sum_coef(cell->type)); + log_debug("%s sum*coef %d * %d\n", cell->name, sum, sum_coef(cell->type)); return sum * sum_coef(cell->type); } else if (max_inp_coef(cell->type)) { // linear with largest input width unsigned int max = max_inp_width(cell); - log_debug("%s max*coef %d * %d\n", cell->name.c_str(), max, max_inp_coef(cell->type)); + log_debug("%s max*coef %d * %d\n", cell->name, max, max_inp_coef(cell->type)); return max * max_inp_coef(cell->type); } else if (is_div_mod(cell->type) || cell->type == ID($mul)) { // quadratic with sum of port widths unsigned int sum = port_width_sum(cell); unsigned int coef = cell->type == ID($mul) ? 3 : 5; - log_debug("%s coef*(sum**2) %d * %d\n", cell->name.c_str(), coef, sum * sum); + log_debug("%s coef*(sum**2) %d * %d\n", cell->name, coef, sum * sum); return coef * sum * sum; } else if (cell->type.in(ID($macc), ID($macc_v2))) { // quadratic per term @@ -196,15 +196,15 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) } else if (cell->type == ID($lut)) { int width = cell->getParam(ID::WIDTH).as_int(); unsigned int cost = 1U << (unsigned int)width; - log_debug("%s is 2**%d\n", cell->name.c_str(), width); + log_debug("%s is 2**%d\n", cell->name, width); return cost; } else if (cell->type == ID($sop)) { int width = cell->getParam(ID::WIDTH).as_int(); int depth = cell->getParam(ID::DEPTH).as_int(); - log_debug("%s is (2*%d + 1)*%d\n", cell->name.c_str(), width, depth); + log_debug("%s is (2*%d + 1)*%d\n", cell->name, width, depth); return (2 * width + 1) * depth; } else if (is_free(cell->type)) { - log_debug("%s is free\n", cell->name.c_str()); + log_debug("%s is free\n", cell->name); return 0; } // TODO: $fsm diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index cc558d418..f0f00181c 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -162,7 +162,7 @@ void FstData::extractVarNames() char *endptr; int mem_addr = strtol(addr.c_str(), &endptr, 16); if (*endptr) { - log_debug("Error parsing memory address in : %s\n", clean_name.c_str()); + log_debug("Error parsing memory address in : %s\n", clean_name); } else { memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; } @@ -176,7 +176,7 @@ void FstData::extractVarNames() char *endptr; int mem_addr = strtol(addr.c_str(), &endptr, 10); if (*endptr) { - log_debug("Error parsing memory address in : %s\n", clean_name.c_str()); + log_debug("Error parsing memory address in : %s\n", clean_name); } else { memory_to_handle[var.scope+"."+mem_cell][mem_addr] = var.id; } diff --git a/passes/cmds/abstract.cc b/passes/cmds/abstract.cc index 88f07a5aa..2ea71268b 100644 --- a/passes/cmds/abstract.cc +++ b/passes/cmds/abstract.cc @@ -156,9 +156,9 @@ dict> gather_selected_reps(Module* mod, const std void explain_selections(const std::vector& reasons) { for (std::variant reason : reasons) { if (Cell** cell_reason = std::get_if(&reason)) - log_debug("\tcell %s\n", (*cell_reason)->name.c_str()); + log_debug("\tcell %s\n", (*cell_reason)->name); else if (Wire** wire_reason = std::get_if(&reason)) - log_debug("\twire %s\n", (*wire_reason)->name.c_str()); + log_debug("\twire %s\n", (*wire_reason)->name); else log_assert(false && "insane reason variant\n"); } diff --git a/passes/cmds/box_derive.cc b/passes/cmds/box_derive.cc index da698b04d..a0faacc9a 100644 --- a/passes/cmds/box_derive.cc +++ b/passes/cmds/box_derive.cc @@ -96,7 +96,7 @@ struct BoxDerivePass : Pass { IdString derived_type = base->derive(d, cell->parameters); Module *derived = d->module(derived_type); log_assert(derived && "Failed to derive module\n"); - log_debug("derived %s\n", derived_type.c_str()); + log_debug("derived %s\n", derived_type); if (!naming_attr.empty() && derived->has_attribute(naming_attr)) { IdString new_name = RTLIL::escape_id(derived->get_string_attribute(naming_attr)); diff --git a/passes/cmds/linecoverage.cc b/passes/cmds/linecoverage.cc index 6898f33f5..26adcce76 100644 --- a/passes/cmds/linecoverage.cc +++ b/passes/cmds/linecoverage.cc @@ -95,7 +95,7 @@ struct CoveragePass : public Pass { { log_debug("Module %s:\n", log_id(module)); for (auto wire: module->wires()) { - log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute().c_str(), log_id(wire->name)); + log_debug("%s\t%s\t%s\n", module->selected(wire) ? "*" : " ", wire->get_src_attribute(), log_id(wire->name)); for (auto src: wire->get_strpool_attribute(ID::src)) { auto filename = extract_src_filename(src); if (filename.empty()) continue; @@ -109,7 +109,7 @@ struct CoveragePass : public Pass { } } for (auto cell: module->cells()) { - log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute().c_str(), log_id(cell->name)); + log_debug("%s\t%s\t%s\n", module->selected(cell) ? "*" : " ", cell->get_src_attribute(), log_id(cell->name)); for (auto src: cell->get_strpool_attribute(ID::src)) { auto filename = extract_src_filename(src); if (filename.empty()) continue; diff --git a/passes/memory/memory_libmap.cc b/passes/memory/memory_libmap.cc index 0fb4608b1..c3c10363b 100644 --- a/passes/memory/memory_libmap.cc +++ b/passes/memory/memory_libmap.cc @@ -392,7 +392,7 @@ void MemMapping::dump_configs(int stage) { void MemMapping::dump_config(MemConfig &cfg) { log_debug("- %s:\n", log_id(cfg.def->id)); for (auto &it: cfg.def->options) - log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second)); + log_debug(" - option %s %s\n", it.first, log_const(it.second)); log_debug(" - emulation score: %d\n", cfg.score_emu); log_debug(" - replicates (for ports): %d\n", cfg.repl_port); log_debug(" - replicates (for data): %d\n", cfg.repl_d); @@ -403,7 +403,7 @@ void MemMapping::dump_config(MemConfig &cfg) { for (int x: cfg.def->dbits) os << " " << x; std::string dbits_s = os.str(); - log_debug(" - abits %d dbits%s\n", cfg.def->abits, dbits_s.c_str()); + log_debug(" - abits %d dbits%s\n", cfg.def->abits, dbits_s); if (cfg.def->byte != 0) log_debug(" - byte width %d\n", cfg.def->byte); log_debug(" - chosen base width %d\n", cfg.def->dbits[cfg.base_width_log2]); @@ -414,25 +414,25 @@ void MemMapping::dump_config(MemConfig &cfg) { else os << " " << x; std::string swizzle_s = os.str(); - log_debug(" - swizzle%s\n", swizzle_s.c_str()); + log_debug(" - swizzle%s\n", swizzle_s); os.str(""); for (int i = 0; (1 << i) <= cfg.hard_wide_mask; i++) if (cfg.hard_wide_mask & 1 << i) os << " " << i; std::string wide_s = os.str(); if (cfg.hard_wide_mask) - log_debug(" - hard wide bits%s\n", wide_s.c_str()); + log_debug(" - hard wide bits%s\n", wide_s); if (cfg.emu_read_first) log_debug(" - emulate read-first behavior\n"); for (int i = 0; i < GetSize(mem.wr_ports); i++) { auto &pcfg = cfg.wr_ports[i]; if (pcfg.rd_port == -1) - log_debug(" - write port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str()); + log_debug(" - write port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0]); else - log_debug(" - write port %d: port group %s (shared with read port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str(), pcfg.rd_port); + log_debug(" - write port %d: port group %s (shared with read port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0], pcfg.rd_port); for (auto &it: pcfg.def->options) - log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second)); + log_debug(" - option %s %s\n", it.first, log_const(it.second)); if (cfg.def->width_mode == WidthMode::PerPort) { std::stringstream os; for (int i = pcfg.def->min_wr_wide_log2; i <= pcfg.def->max_wr_wide_log2; i++) @@ -441,7 +441,7 @@ void MemMapping::dump_config(MemConfig &cfg) { const char *note = ""; if (pcfg.rd_port != -1) note = pcfg.def->width_tied ? " (tied)" : " (independent)"; - log_debug(" - widths%s%s\n", widths_s.c_str(), note); + log_debug(" - widths%s%s\n", widths_s, note); } for (auto i: pcfg.emu_prio) log_debug(" - emulate priority over write port %d\n", i); @@ -449,11 +449,11 @@ void MemMapping::dump_config(MemConfig &cfg) { for (int i = 0; i < GetSize(mem.rd_ports); i++) { auto &pcfg = cfg.rd_ports[i]; if (pcfg.wr_port == -1) - log_debug(" - read port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str()); + log_debug(" - read port %d: port group %s\n", i, cfg.def->port_groups[pcfg.port_group].names[0]); else - log_debug(" - read port %d: port group %s (shared with write port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0].c_str(), pcfg.wr_port); + log_debug(" - read port %d: port group %s (shared with write port %d)\n", i, cfg.def->port_groups[pcfg.port_group].names[0], pcfg.wr_port); for (auto &it: pcfg.def->options) - log_debug(" - option %s %s\n", it.first.c_str(), log_const(it.second)); + log_debug(" - option %s %s\n", it.first, log_const(it.second)); if (cfg.def->width_mode == WidthMode::PerPort) { std::stringstream os; for (int i = pcfg.def->min_rd_wide_log2; i <= pcfg.def->max_rd_wide_log2; i++) @@ -462,7 +462,7 @@ void MemMapping::dump_config(MemConfig &cfg) { const char *note = ""; if (pcfg.wr_port != -1) note = pcfg.def->width_tied ? " (tied)" : " (independent)"; - log_debug(" - widths%s%s\n", widths_s.c_str(), note); + log_debug(" - widths%s%s\n", widths_s, note); } if (pcfg.emu_sync) log_debug(" - emulate data register\n"); @@ -2242,7 +2242,7 @@ struct MemoryLibMapPass : public Pass { if (!map.logic_ok) { if (map.cfgs.empty()) { log_debug("Rejected candidates for mapping memory %s.%s:\n", log_id(module->name), log_id(mem.memid)); - log_debug("%s", map.rejected_cfg_debug_msgs.c_str()); + log_debug("%s", map.rejected_cfg_debug_msgs); log_error("no valid mapping found for memory %s.%s\n", log_id(module->name), log_id(mem.memid)); } idx = 0; diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index a254dc915..dc3f015cd 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -204,7 +204,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto cell : unused) { if (verbose) - log_debug(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str()); + log_debug(" removing unused `%s' cell `%s'.\n", cell->type, cell->name); module->design->scratchpad_set_bool("opt.did_something", true); if (cell->is_builtin_ff()) ffinit.remove_init(cell->getPort(ID::Q)); @@ -215,7 +215,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto it : mem_unused) { if (verbose) - log_debug(" removing unused memory `%s'.\n", it.c_str()); + log_debug(" removing unused memory `%s'.\n", it); delete module->memories.at(it); module->memories.erase(it); } @@ -496,7 +496,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos int del_temp_wires_count = 0; for (auto wire : del_wires_queue) { if (ys_debug() || (check_public_name(wire->name) && verbose)) - log_debug(" removing unused non-port wire %s.\n", wire->name.c_str()); + log_debug(" removing unused non-port wire %s.\n", wire->name); else del_temp_wires_count++; } @@ -636,7 +636,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool } for (auto cell : delcells) { if (verbose) - log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(), + log_debug(" removing buffer cell `%s': %s = %s\n", cell->name, log_signal(cell->getPort(ID::Y)), log_signal(cell->getPort(ID::A))); module->remove(cell); } diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 37ae38225..c0a017748 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -162,7 +162,7 @@ struct OptLutWorker { if (lut_width <= dlogic_conn.first) { - log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first); legal = false; break; @@ -173,8 +173,8 @@ struct OptLutWorker if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic.second->getPort(dlogic_conn.second)[0])) { - log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second)); - log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic.second->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic.second->getPort(dlogic_conn.second))); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic.second->type, dlogic_conn.second, log_signal(lut_dlogic.second->getPort(dlogic_conn.second))); legal = false; break; } @@ -182,7 +182,7 @@ struct OptLutWorker if (legal) { - log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type.c_str(), log_id(module), log_id(lut_dlogic.second)); + log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic.second->type, log_id(module), log_id(lut_dlogic.second)); lut_legal_dlogics.insert(lut_dlogic); for (auto &dlogic_conn : dlogic_map) lut_dlogic_inputs.insert(dlogic_conn.first); @@ -496,9 +496,9 @@ struct OptLutWorker lutM_new_table.set(eval, (RTLIL::State) evaluate_lut(lutB, eval_inputs)); } - log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string().c_str()); - log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID::LUT).as_string().c_str()); - log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); + log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID::LUT).as_string()); + log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID::LUT).as_string()); + log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string()); lutM->setParam(ID::LUT, lutM_new_table); lutM->setPort(ID::A, lutM_new_inputs); diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 1cb499740..541459c27 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -300,11 +300,11 @@ struct OptMergeWorker } did_something = true; - log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), other_cell->name.c_str()); + log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name, other_cell->name); for (auto &it : cell->connections()) { if (cell->output(it.first)) { RTLIL::SigSpec other_sig = other_cell->getPort(it.first); - log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(), + log_debug(" Redirecting output %s: %s = %s\n", it.first, log_signal(it.second), log_signal(other_sig)); Const init = initvals(other_sig); initvals.remove_init(it.second); @@ -314,7 +314,7 @@ struct OptMergeWorker initvals.set_init(other_sig, init); } } - log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); + log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type, cell->name, module->name); module->remove(cell); total_count++; } diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index f4e0b0f03..7c6ca5551 100644 --- a/passes/techmap/clockgate.cc +++ b/passes/techmap/clockgate.cc @@ -85,7 +85,7 @@ static std::pair, std::optional> continue; } - log_debug("maybe valid icg: %s\n", cell_name.c_str()); + log_debug("maybe valid icg: %s\n", cell_name); ClockGateCell icg_interface; icg_interface.name = RTLIL::escape_id(cell_name); @@ -162,9 +162,9 @@ static std::pair, std::optional> winning = cost < goal; if (winning) - log_debug("%s beats %s\n", icg_interface.name.c_str(), icg_to_beat->name.c_str()); + log_debug("%s beats %s\n", icg_interface.name, icg_to_beat->name); } else { - log_debug("%s is the first of its polarity\n", icg_interface.name.c_str()); + log_debug("%s is the first of its polarity\n", icg_interface.name); winning = true; } if (winning) { @@ -395,7 +395,7 @@ struct ClockgatePass : public Pass { if (!it->second.new_net) continue; - log_debug("Fix up FF %s\n", cell->name.c_str()); + log_debug("Fix up FF %s\n", cell->name); // Now we start messing with the design ff.has_ce = false; // Construct the clock gate diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 062a63ec3..f3b96aeec 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -117,11 +117,11 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std // the next_state variable isn't just a pin name; perhaps this is an enable? auto helper = LibertyExpression::Lexer(expr); auto tree = LibertyExpression::parse(helper); - // log_debug("liberty expression:\n%s\n", tree.str().c_str()); + // log_debug("liberty expression:\n%s\n", tree.str()); if (tree.kind == LibertyExpression::Kind::EMPTY) { if (!warned_cells.count(cell_name)) { - log_debug("Invalid expression '%s' in next_state attribute of cell '%s' - skipping.\n", expr.c_str(), cell_name.c_str()); + log_debug("Invalid expression '%s' in next_state attribute of cell '%s' - skipping.\n", expr, cell_name); warned_cells.insert(cell_name); } return false; @@ -140,7 +140,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std // position that gives better diagnostics here. if (!pin_names.count(ff_output)) { if (!warned_cells.count(cell_name)) { - log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not contain ff output '%s' - skipping.\n", expr.c_str(), cell_name.c_str(), ff_output.c_str()); + log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not contain ff output '%s' - skipping.\n", expr, cell_name, ff_output); warned_cells.insert(cell_name); } return false; @@ -189,7 +189,7 @@ static bool parse_next_state(const LibertyAst *cell, const LibertyAst *attr, std } if (!warned_cells.count(cell_name)) { - log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not evaluate to an enable flop - skipping.\n", expr.c_str(), cell_name.c_str()); + log_debug("Inference failed on expression '%s' in next_state attribute of cell '%s' because it does not evaluate to an enable flop - skipping.\n", expr, cell_name); warned_cells.insert(cell_name); } return false; @@ -225,10 +225,10 @@ static bool parse_pin(const LibertyAst *cell, const LibertyAst *attr, std::strin For now, we'll simply produce a warning to let the user know something is up. */ if (pin_name.find_first_of("^*|&") == std::string::npos) { - log_debug("Malformed liberty file - cannot find pin '%s' in cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str()); + log_debug("Malformed liberty file - cannot find pin '%s' in cell '%s' - skipping.\n", pin_name, cell->args[0]); } else { - log_debug("Found unsupported expression '%s' in pin attribute of cell '%s' - skipping.\n", pin_name.c_str(), cell->args[0].c_str()); + log_debug("Found unsupported expression '%s' in pin attribute of cell '%s' - skipping.\n", pin_name, cell->args[0]); } return false; diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 281a8795a..b49a40704 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -582,7 +582,7 @@ struct TechmapWorker log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); + log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); } else { @@ -591,7 +591,7 @@ struct TechmapWorker log_msg_cache.insert(msg); log("%s\n", msg); } - log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str()); + log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), extmapper_name); if (extmapper_name == "simplemap") { if (simplemap_mappers.count(cell->type) == 0) @@ -943,7 +943,7 @@ struct TechmapWorker module_queue.insert(m); } - log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name)); + log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(m_name)); cell->type = m_name; cell->parameters.clear(); } @@ -954,7 +954,7 @@ struct TechmapWorker log_msg_cache.insert(msg); log("%s\n", msg); } - 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)); + log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix, log_id(module), log_id(cell), log_id(cell->type), log_id(tpl)); techmap_module_worker(design, module, cell, tpl); cell = nullptr; } @@ -1285,7 +1285,7 @@ struct TechmapPass : public Pass { std::string maps = ""; for (auto &map : i.second) maps += stringf(" %s", log_id(map)); - log_debug(" %s:%s\n", log_id(i.first), maps.c_str()); + log_debug(" %s:%s\n", log_id(i.first), maps); } log_debug("\n"); diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 9603956a8..73af155bd 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -1185,7 +1185,7 @@ struct TestCellPass : public Pass { // Expected to run once int num_cells_estimate = costs.get(uut); if (num_cells <= num_cells_estimate) { - log_debug("Correct upper bound for %s: %d <= %d\n", cell_type.c_str(), num_cells, num_cells_estimate); + log_debug("Correct upper bound for %s: %d <= %d\n", cell_type, num_cells, num_cells_estimate); } else { failed++; if (worst_abs < num_cells - num_cells_estimate) { diff --git a/techlibs/quicklogic/ql_ioff.cc b/techlibs/quicklogic/ql_ioff.cc index 87b62e855..5574ef4a0 100644 --- a/techlibs/quicklogic/ql_ioff.cc +++ b/techlibs/quicklogic/ql_ioff.cc @@ -42,7 +42,7 @@ struct QlIoffPass : public Pass { for (auto cell : module->selected_cells()) { if (cell->type.in(ID(dffsre), ID(sdffsre))) { - log_debug("Checking cell %s.\n", cell->name.c_str()); + log_debug("Checking cell %s.\n", cell->name); bool e_const = cell->getPort(ID::E).is_fully_ones(); bool r_const = cell->getPort(ID::R).is_fully_ones(); bool s_const = cell->getPort(ID::S).is_fully_ones(); @@ -55,7 +55,7 @@ struct QlIoffPass : public Pass { SigSpec d = cell->getPort(ID::D); log_assert(GetSize(d) == 1); if (modwalker.has_inputs(d)) { - log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name.c_str()); + log_debug("Cell %s is potentially eligible for promotion to input IOFF.\n", cell->name); // check that d_sig has no other consumers pool portbits; modwalker.get_consumers(portbits, d); @@ -70,7 +70,7 @@ struct QlIoffPass : public Pass { SigSpec q = cell->getPort(ID::Q); log_assert(GetSize(q) == 1); if (modwalker.has_outputs(q) && !modwalker.has_consumers(q)) { - log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name.c_str()); + log_debug("Cell %s is potentially eligible for promotion to output IOFF.\n", cell->name); for (SigBit bit : output_bit_aliases[modwalker.sigmap(q)]) { log_assert(bit.is_wire()); output_ffs[bit.wire][bit.offset] = cell; From 398e5d4bf0b02cda6c404c5820d73ed2ce9cc84d Mon Sep 17 00:00:00 2001 From: George Rennie Date: Tue, 23 Sep 2025 14:34:20 +0100 Subject: [PATCH 11/29] docs typo: -dump-cmds-json --- docs/source/cmd/index_internal.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/cmd/index_internal.rst b/docs/source/cmd/index_internal.rst index bfb369dde..ab9c13aba 100644 --- a/docs/source/cmd/index_internal.rst +++ b/docs/source/cmd/index_internal.rst @@ -67,7 +67,7 @@ The ``formatted_help()`` method Dumping command help to json ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `help -dump-cells-json cmds.json` +- `help -dump-cmds-json cmds.json` + generates a ``ContentListing`` for each command registered in Yosys + tries to parse unformatted ``Pass::help()`` output if From d30f7847d84f015f0f71895f3586fe7da4eb5520 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 7 Apr 2025 13:16:49 +0200 Subject: [PATCH 12/29] techmap: map $alu to $fa instead of relying on extract_fa --- techlibs/common/techmap.v | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index 7a9ad7693..c3364e628 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -283,9 +283,16 @@ module _90_alu (A, B, CI, BI, X, Y, CO); \$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); \$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); - \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(X), .G(AA & BB), .CI(CI), .CO(CO)); + (* force_downto *) + wire [Y_WIDTH-1:0] P; + wire [Y_WIDTH-1:0] G; + wire [Y_WIDTH-1:0] Cnull; + assign Cnull = 1'b0; - assign X = AA ^ BB; + \$fa #(.WIDTH(Y_WIDTH)) fa (.A(AA), .B(BB), .C(Cnull), .X(G), .Y(P)); + \$lcu #(.WIDTH(Y_WIDTH)) lcu (.P(P), .G(G), .CI(CI), .CO(CO)); + + assign X = P; assign Y = X ^ {CO, CI}; endmodule From fcc3d7132d39ab9e03a927b72c55ebdfbfcd270d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miodrag=20Milanovi=C4=87?= Date: Tue, 23 Sep 2025 17:10:18 +0200 Subject: [PATCH 13/29] Fix building and running unit tests (#5374) * Fix building and running unit tests * Enable unit tests * Add gtest always * test-sanitizers.yml: Use makefile.conf * proper test setup * make it run on macOS * Run libyosys build only for unit tests after testing is done * Disable LTO on public CI --------- Co-authored-by: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> --- .github/actions/setup-build-env/action.yml | 2 +- .github/workflows/prepare-docs.yml | 2 +- .github/workflows/test-build.yml | 2 +- .github/workflows/test-sanitizers.yml | 9 +++-- .github/workflows/test-verific.yml | 5 +++ Brewfile | 1 + tests/unit/Makefile | 42 +++++++++++++++++----- tests/unit/kernel/rtlilTest.cc | 3 ++ 8 files changed, 53 insertions(+), 13 deletions(-) diff --git a/.github/actions/setup-build-env/action.yml b/.github/actions/setup-build-env/action.yml index 1c2386b06..e4bc8ec58 100644 --- a/.github/actions/setup-build-env/action.yml +++ b/.github/actions/setup-build-env/action.yml @@ -8,7 +8,7 @@ runs: shell: bash run: | sudo apt-get update - sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev + sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev libgtest-dev - name: Install macOS Dependencies if: runner.os == 'macOS' diff --git a/.github/workflows/prepare-docs.yml b/.github/workflows/prepare-docs.yml index 17d37d08c..f19b1c7af 100644 --- a/.github/workflows/prepare-docs.yml +++ b/.github/workflows/prepare-docs.yml @@ -48,7 +48,7 @@ jobs: echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf echo "ENABLE_CCACHE := 1" >> Makefile.conf echo "ENABLE_HELP_SOURCE := 1" >> Makefile.conf - make -j$procs ENABLE_LTO=1 + make -j$procs - name: Prepare docs shell: bash diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index d7f2073fe..2d4a7a6c8 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -67,7 +67,7 @@ jobs: mkdir build cd build make -f ../Makefile config-$CC - make -f ../Makefile -j$procs ENABLE_LTO=1 + make -f ../Makefile -j$procs - name: Log yosys-config output run: | diff --git a/.github/workflows/test-sanitizers.yml b/.github/workflows/test-sanitizers.yml index 2ffd2db15..9c0f6d746 100644 --- a/.github/workflows/test-sanitizers.yml +++ b/.github/workflows/test-sanitizers.yml @@ -97,7 +97,7 @@ jobs: run: | make config-$CC echo 'SANITIZER = ${{ matrix.sanitizer }}' >> Makefile.conf - make -j$procs ENABLE_LTO=1 + make -j$procs - name: Log yosys-config output run: | @@ -106,10 +106,15 @@ jobs: - name: Run tests shell: bash run: | - make -j$procs test TARGETS= EXTRA_TARGETS= CONFIG=$CC + make -j$procs test TARGETS= EXTRA_TARGETS= - name: Report errors if: ${{ failure() }} shell: bash run: | find tests/**/*.err -print -exec cat {} \; + + - name: Run unit tests + shell: bash + run: | + make -j$procs unit-test ENABLE_LIBYOSYS=1 diff --git a/.github/workflows/test-verific.yml b/.github/workflows/test-verific.yml index c2e4228c4..503d6c31b 100644 --- a/.github/workflows/test-verific.yml +++ b/.github/workflows/test-verific.yml @@ -78,3 +78,8 @@ jobs: if: ${{ github.ref == 'refs/heads/main' }} run: | make -C sby run_ci + + - name: Run unit tests + shell: bash + run: | + make -j$procs unit-test ENABLE_LTO=1 ENABLE_LIBYOSYS=1 diff --git a/Brewfile b/Brewfile index 7ed3fb906..c90434e62 100644 --- a/Brewfile +++ b/Brewfile @@ -11,3 +11,4 @@ brew "bash" brew "boost-python3" brew "llvm@20" brew "lld" +brew "googletest" diff --git a/tests/unit/Makefile b/tests/unit/Makefile index 48635eb0d..eee60ef9f 100644 --- a/tests/unit/Makefile +++ b/tests/unit/Makefile @@ -1,11 +1,27 @@ -GTESTFLAG := -lgtest -lgtest_main -RPATH := -Wl,-rpath -EXTRAFLAGS := -lyosys -pthreads +UNAME_S := $(shell uname -s) + +# GoogleTest flags +GTEST_PREFIX := $(shell brew --prefix googletest 2>/dev/null) +ifeq ($(GTEST_PREFIX),) + GTEST_CXXFLAGS := + GTEST_LDFLAGS := -lgtest -lgtest_main +else + GTEST_CXXFLAGS := -I$(GTEST_PREFIX)/include + GTEST_LDFLAGS := -L$(GTEST_PREFIX)/lib -lgtest -lgtest_main +endif + +ifeq ($(UNAME_S),Darwin) + RPATH = -Wl,-rpath,$(ROOTPATH) +else + RPATH = -Wl,-rpath=$(ROOTPATH) +endif + +EXTRAFLAGS := -lyosys -pthread OBJTEST := objtest BINTEST := bintest -ALLTESTFILE := $(shell find -name '*Test.cc' -printf '%P ') +ALLTESTFILE := $(shell find . -name '*Test.cc' | sed 's|^\./||' | tr '\n' ' ') TESTDIRS := $(sort $(dir $(ALLTESTFILE))) TESTS := $(addprefix $(BINTEST)/, $(basename $(ALLTESTFILE:%Test.cc=%Test.o))) @@ -15,16 +31,26 @@ TESTS := $(addprefix $(BINTEST)/, $(basename $(ALLTESTFILE:%Test.cc=%Test.o))) all: prepare $(TESTS) run-tests $(BINTEST)/%: $(OBJTEST)/%.o - $(CXX) -L$(ROOTPATH) $(RPATH)=$(ROOTPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \ - $(GTESTFLAG) $(EXTRAFLAGS) + $(CXX) -L$(ROOTPATH) $(RPATH) $(LINKFLAGS) -o $@ $^ $(LIBS) \ + $(GTEST_LDFLAGS) $(EXTRAFLAGS) $(OBJTEST)/%.o: $(basename $(subst $(OBJTEST),.,%)).cc - $(CXX) -o $@ -c -I$(ROOTPATH) $(CPPFLAGS) $(CXXFLAGS) $^ + $(CXX) -o $@ -c -I$(ROOTPATH) $(CPPFLAGS) $(CXXFLAGS) $(GTEST_CXXFLAGS) $^ .PHONY: prepare run-tests clean run-tests: $(TESTS) - $(subst Test ,Test&& ,$^) +ifeq ($(UNAME_S),Darwin) + @for t in $^; do \ + echo "Running $$t"; \ + DYLD_LIBRARY_PATH=$(ROOTPATH) $$t || exit 1; \ + done +else + @for t in $^; do \ + echo "Running $$t"; \ + $$t || exit 1; \ + done +endif prepare: mkdir -p $(addprefix $(BINTEST)/,$(TESTDIRS)) diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 97cc936de..557355ed9 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -20,6 +20,9 @@ namespace RTLIL { KernelRtlilTest() { if (log_files.empty()) log_files.emplace_back(stdout); } + virtual void SetUp() override { + IdString::ensure_prepopulated(); + } }; TEST_F(KernelRtlilTest, ConstAssignCompare) From 9409a11be46ae1d582c0c92b7b50fd2ea2092278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Ji=C5=99=C3=AD=20Tywoniak?= Date: Tue, 23 Sep 2025 19:25:55 +0200 Subject: [PATCH 14/29] CONTRIBUTING: don't mention dead slack, add link to dev jf doc --- CONTRIBUTING.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 74f9ab10d..6e7b8f221 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,13 +61,10 @@ merge; please do not use these labels if you are not a maintainer. # Asking questions If you have a question about how to use Yosys, please ask on our [discussions -page](https://github.com/YosysHQ/yosys/discussions) or in our [community -slack](https://join.slack.com/t/yosyshq/shared_invite/zt-1aopkns2q-EiQ97BeQDt_pwvE41sGSuA). -The slack is also a great place to ask questions about developing or +page](https://github.com/YosysHQ/yosys/discussions) or in our [Discourse forum](https://yosyshq.discourse.group/). +The Discourse is also a great place to ask questions about developing or contributing to Yosys. -We have open dev 'jour fixe' (JF) meetings where developers from YosysHQ and the +We have open [dev 'jour fixe' (JF) meetings](https://docs.google.com/document/d/1SapA6QAsJcsgwsdKJDgnGR2mr97pJjV4eeXg_TVJhRU/edit?usp=sharing) where developers from YosysHQ and the community come together to discuss open issues and PRs. This is also a good -place to talk to us about how to implement larger PRs. Please join the -community slack if you would like to join the next meeting, the link is -available in the description of the #devel-discuss channel. +place to talk to us about how to implement larger PRs. From 6527cc2134c818b0084a47c82e664c8d198725dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Ji=C5=99=C3=AD=20Tywoniak?= Date: Tue, 23 Sep 2025 20:03:50 +0200 Subject: [PATCH 15/29] gowin: fix test --- tests/arch/gowin/mux.ys | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/arch/gowin/mux.ys b/tests/arch/gowin/mux.ys index d5978f4ea..2ca973520 100644 --- a/tests/arch/gowin/mux.ys +++ b/tests/arch/gowin/mux.ys @@ -32,8 +32,8 @@ proc equiv_opt -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) cd mux8 # Constrain all select calls below inside the top module -select -assert-count 1 t:LUT1 -select -assert-count 10 t:LUT3 +select -assert-count 3 t:LUT1 +select -assert-count 2 t:LUT3 select -assert-count 1 t:LUT4 select -assert-count 5 t:MUX2_LUT5 select -assert-count 2 t:MUX2_LUT6 From 3f4b6dc5d31d8f790ad4d5fb7696f10f77d3362e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Tue, 23 Sep 2025 20:34:08 +0200 Subject: [PATCH 16/29] Support multiple lib files in abc9_exe --- passes/techmap/abc9_exe.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index ac723fdbb..4449065f8 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -181,8 +181,10 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe for (std::string dont_use_cell : dont_use_cells) { dont_use_args += stringf("-X \"%s\" ", dont_use_cell); } + bool first_lib = true; for (std::string liberty_file : liberty_files) { - abc9_script += stringf("read_lib %s -w \"%s\" ; ", dont_use_args, liberty_file); + abc9_script += stringf("read_lib %s %s -w \"%s\" ; ", dont_use_args, first_lib ? "" : "-m", liberty_file); + first_lib = false; } if (!constr_file.empty()) abc9_script += stringf("read_constr -v \"%s\"; ", constr_file); From 0a17205a955eb9eb95c2e89764d354b82bfc22f4 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 17 Sep 2025 22:27:16 +0000 Subject: [PATCH 17/29] Fix off-by-one error in bounds check --- kernel/rtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 7d53fdd32..3c6843aaa 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -4399,7 +4399,7 @@ RTLIL::SigChunk RTLIL::SigChunk::extract(int offset, int length) const RTLIL::SigBit RTLIL::SigChunk::operator[](int offset) const { log_assert(offset >= 0); - log_assert(offset <= width); + log_assert(offset < width); RTLIL::SigBit ret; if (wire) { ret.wire = wire; From ef22c6ee735ee22f50a1bd6c6430c618cc8afc51 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 00:22:58 +0000 Subject: [PATCH 18/29] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 02f8fa0e9..406a6d196 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+178 +YOSYS_VER := 0.57+198 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 6de21a8999bb44e3b845a0aafeca3e672408577b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Ji=C5=99=C3=AD=20Tywoniak?= Date: Wed, 24 Sep 2025 11:07:26 +0200 Subject: [PATCH 19/29] CONTRIBUTING: prefer Discourse over GitHub Discussions --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6e7b8f221..403292b0b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,8 +60,8 @@ merge; please do not use these labels if you are not a maintainer. # Asking questions -If you have a question about how to use Yosys, please ask on our [discussions -page](https://github.com/YosysHQ/yosys/discussions) or in our [Discourse forum](https://yosyshq.discourse.group/). +If you have a question about how to use Yosys, please ask on our [Discourse forum](https://yosyshq.discourse.group/) or in our [discussions +page](https://github.com/YosysHQ/yosys/discussions). The Discourse is also a great place to ask questions about developing or contributing to Yosys. From 904d49c6d818897bb4c854e64c6c395861146e0d Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 23 Sep 2025 14:38:15 +0200 Subject: [PATCH 20/29] abc9_ops: Remove temporary debug log message I missed this when adding the -replace_zbufs option. --- passes/techmap/abc9_ops.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index ecba519bf..2e762d7b9 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -1600,7 +1600,6 @@ static void replace_zbufs(Design *design) sig[i] = w; } } - log("XXX %s -> %s\n", log_signal(cell->getPort(ID::A)), log_signal(sig)); cell->setPort(ID::A, sig); } From 71882debe78cda10a963b89404ac4decbedca8f2 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Wed, 24 Sep 2025 13:15:36 +0200 Subject: [PATCH 21/29] simplemap: Remove leftover debug output --- passes/techmap/simplemap.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 86ff5c149..938ed5355 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -18,7 +18,6 @@ */ #include "simplemap.h" -#include "backends/rtlil/rtlil_backend.h" #include "kernel/sigtools.h" #include "kernel/ff.h" #include @@ -156,14 +155,11 @@ void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell) } RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type); - log("huh\n"); - RTLIL_BACKEND::dump_cell(std::cout, "", cell); transfer_src(gate, cell); gate->setPort(ID::A, sig_a[i]); gate->setPort(ID::B, sig_a[i+1]); gate->setPort(ID::Y, sig_t[i/2]); last_output_cell = gate; - RTLIL_BACKEND::dump_cell(std::cout, "", gate); } sig_a = sig_t; From 86a46b9e5c122a4f6463390e8e9bbac8f48f4bea Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 23 Sep 2025 14:19:30 +0200 Subject: [PATCH 22/29] log: Flush stdout before printing a fatal error to stderr This hasn't been an issue when using -l to redirect or when stdout is line buffered, explaining how we didn't notice this earlier, but for `yosys ... > log` that extra flush is required to ensure all messages preceding the fatal error are flushed. --- kernel/log.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/log.cc b/kernel/log.cc index 0085980b1..af083860a 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -331,10 +331,12 @@ static void log_error_with_prefix(std::string_view prefix, std::string str) if (log_errfile != NULL) log_files.push_back(log_errfile); - if (log_error_stderr) + if (log_error_stderr) { + log_flush(); // Make sure we flush stdout before replacing it with stderr for (auto &f : log_files) if (f == stdout) f = stderr; + } log_last_error = std::move(str); log("%s%s", prefix, log_last_error); From 2dce50516b218b28a34b838810709fa0ee24d256 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 23 Sep 2025 14:26:53 +0200 Subject: [PATCH 23/29] log: Print static message as fatal error for YOSYS_ABORT --- kernel/log.cc | 5 +++++ kernel/yosys_common.h | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/kernel/log.cc b/kernel/log.cc index af083860a..34e56f8ac 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -407,6 +407,11 @@ void log_abort_internal(const char *file, int line) log_error("Abort in %s:%d.\n", file, line); } +void log_yosys_abort_message(std::string_view file, int line, std::string_view func, std::string_view message) +{ + log_error("Abort in %s:%d (%s): %s\n", file, line, func, message); +} + void log_formatted_cmd_error(std::string str) { if (log_cmd_error_throw) { diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index fd84dd74e..d69e02a59 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -142,7 +142,12 @@ #define YOSYS_CONSTEVAL constexpr #endif -#define YOSYS_ABORT(s) abort() +#define YOSYS_ABORT(s) YOSYS_NAMESPACE_PREFIX log_yosys_abort_message(__FILE__, __LINE__, __FUNCTION__, s) + +// This has to precede including "kernel/io.h" +YOSYS_NAMESPACE_BEGIN +[[noreturn]] void log_yosys_abort_message(std::string_view file, int line, std::string_view func, std::string_view message); +YOSYS_NAMESPACE_END #include "kernel/io.h" From 3f29cd7f4ede44092c0a2b2a3e20d32c642c6a49 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 00:22:44 +0000 Subject: [PATCH 24/29] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 406a6d196..45b3a09f3 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+198 +YOSYS_VER := 0.57+212 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 1c73011e7e8236c88157d37bd22a456b47c459d1 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 25 Sep 2025 03:04:17 +0000 Subject: [PATCH 25/29] Swap SigSpecs using std::swap with moves --- kernel/rtlil.h | 6 +++++- passes/opt/opt_merge.cc | 9 +++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 88594859a..e240cf885 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1244,7 +1244,8 @@ private: public: SigSpec() : width_(0), hash_(0) {} SigSpec(std::initializer_list parts); - + SigSpec(const SigSpec &) = default; + SigSpec(SigSpec &&) = default; SigSpec(const RTLIL::Const &value); SigSpec(RTLIL::Const &&value); SigSpec(const RTLIL::SigChunk &chunk); @@ -1261,6 +1262,9 @@ public: SigSpec(const std::set &bits); explicit SigSpec(bool bit); + SigSpec &operator=(const SigSpec &rhs) = default; + SigSpec &operator=(SigSpec &&rhs) = default; + inline const std::vector &chunks() const { pack(); return chunks_; } inline const std::vector &bits() const { inline_unpack(); return bits_; } diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 541459c27..e1c3f0269 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -25,6 +25,7 @@ #include "libs/sha1/sha1.h" #include #include +#include #include #include #include @@ -173,14 +174,10 @@ struct OptMergeWorker if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) || cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) { if (conn1.at(ID::A) < conn1.at(ID::B)) { - RTLIL::SigSpec tmp = conn1[ID::A]; - conn1[ID::A] = conn1[ID::B]; - conn1[ID::B] = tmp; + std::swap(conn1[ID::A], conn1[ID::B]); } if (conn2.at(ID::A) < conn2.at(ID::B)) { - RTLIL::SigSpec tmp = conn2[ID::A]; - conn2[ID::A] = conn2[ID::B]; - conn2[ID::B] = tmp; + std::swap(conn2[ID::A], conn2[ID::B]); } } else if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) { From 4d209c187d02cb858701a1b4777d73c90cb80592 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 17 Sep 2025 02:52:30 +0000 Subject: [PATCH 26/29] Switch OptMergeWorker cell type switching to use IdString::in() --- passes/opt/opt_merge.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index e1c3f0269..13b1cb293 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -171,8 +171,8 @@ struct OptMergeWorker } } - if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) || - cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) { + if (cell1->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul), + ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) { if (conn1.at(ID::A) < conn1.at(ID::B)) { std::swap(conn1[ID::A], conn1[ID::B]); } @@ -180,11 +180,11 @@ struct OptMergeWorker std::swap(conn2[ID::A], conn2[ID::B]); } } else - if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) { + if (cell1->type.in(ID($reduce_xor), ID($reduce_xnor))) { conn1[ID::A].sort(); conn2[ID::A].sort(); } else - if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) { + if (cell1->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) { conn1[ID::A].sort_and_unify(); conn2[ID::A].sort_and_unify(); } else From fef6bdae6cda277a022381c2f325ba374a94f377 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 26 Sep 2025 11:05:50 +1200 Subject: [PATCH 27/29] autoname.cc: Return number of renames Was previously the number of proposed renames, but since renames can be skipped this causes the final count to differ from the number of actually renamed objects. Check counts in `tests/various/autoname.ys`. --- passes/cmds/autoname.cc | 5 ++++- tests/various/autoname.ys | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/passes/cmds/autoname.cc b/passes/cmds/autoname.cc index d2ff568c3..1ad2eab3c 100644 --- a/passes/cmds/autoname.cc +++ b/passes/cmds/autoname.cc @@ -81,6 +81,7 @@ int autoname_worker(Module *module, const dict& wire_score) } } + int count = 0; // compare against double best score for following comparisons so we don't // pre-empt a future iteration best_name.score *= 2; @@ -91,6 +92,7 @@ int autoname_worker(Module *module, const dict& wire_score) IdString n = module->uniquify(IdString(it.second.name)); log_debug("Rename cell %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); module->rename(it.first, n); + count++; } for (auto &it : proposed_wire_names) { @@ -99,9 +101,10 @@ int autoname_worker(Module *module, const dict& wire_score) IdString n = module->uniquify(IdString(it.second.name)); log_debug("Rename wire %s in %s to %s.\n", log_id(it.first), log_id(module), log_id(n)); module->rename(it.first, n); + count++; } - return proposed_cell_names.size() + proposed_wire_names.size(); + return count; } struct AutonamePass : public Pass { diff --git a/tests/various/autoname.ys b/tests/various/autoname.ys index 29ca81bbe..fccecb1c2 100644 --- a/tests/various/autoname.ys +++ b/tests/various/autoname.ys @@ -18,6 +18,7 @@ module \top end EOT logger -expect log "Rename cell .name in top to y_.and_Y" 1 +logger -expect log "Renamed 1 objects" 1 debug autoname logger -check-expected @@ -42,6 +43,7 @@ module \top end EOT logger -expect log "Rename cell .name in top to ab_.or_A" 1 +logger -expect log "Renamed 1 objects" 1 debug autoname logger -check-expected @@ -78,6 +80,7 @@ end EOT logger -expect log "Rename cell .name in top to bcd_.and_B" 1 logger -expect log "Rename cell .name2 in top to c_has_a_long_name_.or_B" 1 +logger -expect log "Renamed 2 objects" 1 debug autoname logger -check-expected @@ -113,6 +116,7 @@ end EOT logger -expect log "Rename cell .name in top to y_.and_Y" 1 logger -expect log "Rename cell .name2 in top to y_.and_Y_1" 1 +logger -expect log "Renamed 2 objects" 1 debug autoname logger -check-expected @@ -174,6 +178,7 @@ EOT # wires are named for being cell outputs logger -expect log "Rename wire .d in top to or_Y" 1 logger -expect log "Rename cell .name2 in top to or_Y_.or_B" 1 +logger -expect log "Renamed 2 objects" 1 debug autoname t:$or logger -check-expected @@ -186,5 +191,6 @@ logger -expect log "Rename cell .name3 in top to or_Y_.or_B_Y_.and_B" 1 # $c gets shortest name, since the cell driving it doesn't have known port # directions logger -expect log "Rename wire .c in top to or_Y_.or_B_A" 1 +logger -expect log "Renamed 4 objects" 1 debug autoname logger -check-expected From 941ba3b7454a2f2ccaf8fdf70489e5c3f4136195 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 26 Sep 2025 11:27:17 +1200 Subject: [PATCH 28/29] autoname.ys: Extra check for rename order Disabling comparison with best score will cause this check to fail. Preferred names will not be possible if $name2 has not yet been renamed. --- tests/various/autoname.ys | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/various/autoname.ys b/tests/various/autoname.ys index fccecb1c2..7df1571b2 100644 --- a/tests/various/autoname.ys +++ b/tests/various/autoname.ys @@ -175,6 +175,8 @@ module \top end end EOT +design -save order_test + # wires are named for being cell outputs logger -expect log "Rename wire .d in top to or_Y" 1 logger -expect log "Rename cell .name2 in top to or_Y_.or_B" 1 @@ -186,11 +188,18 @@ logger -check-expected logger -expect log "Rename cell .name in top to a_.__unknown_A" 1 # another output wire logger -expect log "Rename wire .e in top to or_Y_.or_B_Y" 1 -# $name3 named for lowest fanout wire (otherwise a_$__unknown_A_Y_$and_A) -logger -expect log "Rename cell .name3 in top to or_Y_.or_B_Y_.and_B" 1 -# $c gets shortest name, since the cell driving it doesn't have known port -# directions -logger -expect log "Rename wire .c in top to or_Y_.or_B_A" 1 logger -expect log "Renamed 4 objects" 1 debug autoname logger -check-expected + +# don't rename prematurely (some objects should be named after $name2) +design -load order_test + +# $c gets shortest name, since the cell driving it doesn't have known port +# directions (otherwise a_$__unknown_A_Y) +logger -expect log "Rename wire .c in top to or_Y_.or_B_A" 1 +# $name3 named for lowest fanout wire (otherwise a_$__unknown_A_Y_$and_A) +logger -expect log "Rename cell .name3 in top to or_Y_.or_B_Y_.and_B" 1 +logger -expect log "Renamed 6 objects" 1 +debug autoname +logger -check-expected From 6a5d9567472363019065410d05f47bc6169c8598 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 00:22:24 +0000 Subject: [PATCH 29/29] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 45b3a09f3..7a2e8419b 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+212 +YOSYS_VER := 0.57+218 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2)