From 50bfb5c5c9bfd464bf2c33b6e2b3bd2c755ed78f Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 12 Nov 2025 20:19:42 +0100 Subject: [PATCH 1/8] constids: add $input_port and $connect --- kernel/constids.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/constids.inc b/kernel/constids.inc index 7aed897e173..c99aa788d1e 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -196,6 +196,7 @@ X($bweqx) X($bwmux) X($check) X($concat) +X($connect) X($cover) X($demux) X($dff) @@ -222,6 +223,7 @@ X($get_tag) X($gt) X($initstate) X($input) +X($input_port) X($lcu) X($le) X($live) From 1ee4fc9d27292a1508029c188814ddc043741e44 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 12 Nov 2025 20:20:51 +0100 Subject: [PATCH 2/8] fix YOSYS_XTRACE_GET_PUT --- kernel/rtlil.cc | 2 +- kernel/rtlil.h | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index bc89fc6a488..d18a709c94d 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -130,7 +130,7 @@ int RTLIL::IdString::really_insert(std::string_view p, std::unordered_map(size)}; } }; - #undef YOSYS_XTRACE_GET_PUT - #undef YOSYS_SORT_ID_FREE_LIST - #undef YOSYS_NO_IDS_REFCNT - // the global id string cache static bool destruct_guard_ok; // POD, will be initialized to zero @@ -178,7 +174,7 @@ struct RTLIL::IdString if (global_id_storage_.at(idx).buf == nullptr) log("#X# DB-DUMP index %d: FREE\n", idx); else - log("#X# DB-DUMP index %d: '%s' (ref %u)\n", idx, refcount(idx).buf, refcount); + log("#X# DB-DUMP index %d: '%s' (ref %u)\n", idx, global_id_storage_.at(idx).buf, refcount(idx)); } #endif } From 8c76f93fcef412605d0ef01e7987a903be6c9e99 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 12 Nov 2025 20:22:30 +0100 Subject: [PATCH 3/8] rtlil: make tracing optional in IdString garbage collection --- kernel/rtlil.cc | 9 +++++---- kernel/rtlil.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d18a709c94d..ee53afe4159 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -246,14 +246,15 @@ struct IdStringCollector { int64_t RTLIL::OwningIdString::gc_ns; int RTLIL::OwningIdString::gc_count; -void RTLIL::OwningIdString::collect_garbage() +void RTLIL::OwningIdString::collect_garbage(bool trace) { int64_t start = PerformanceTimer::query(); #ifndef YOSYS_NO_IDS_REFCNT IdStringCollector collector; - for (auto &[idx, design] : *RTLIL::Design::get_all_designs()) { - collector.trace(*design); - } + if (trace) + for (auto &[idx, design] : *RTLIL::Design::get_all_designs()) { + collector.trace(*design); + } int size = GetSize(global_id_storage_); for (int i = static_cast(StaticId::STATIC_ID_END); i < size; ++i) { RTLIL::IdString::Storage &storage = global_id_storage_.at(i); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 584c4e11b28..6098d916b01 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -574,7 +574,7 @@ struct RTLIL::OwningIdString : public RTLIL::IdString { } // Collect all non-owning references. - static void collect_garbage(); + static void collect_garbage(bool trace = true); static int64_t garbage_collection_ns() { return gc_ns; } static int garbage_collection_count() { return gc_count; } From bc3fc212480abf0ccdf475761bf7a4131074cef5 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 13 Nov 2025 02:02:02 +0100 Subject: [PATCH 4/8] microchip: fix IdString memory leak --- techlibs/microchip/microchip_dsp.pmg | 2 +- techlibs/microchip/microchip_dsp_cascade.pmg | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/techlibs/microchip/microchip_dsp.pmg b/techlibs/microchip/microchip_dsp.pmg index 9a6b9e1fa07..2573135eec3 100644 --- a/techlibs/microchip/microchip_dsp.pmg +++ b/techlibs/microchip/microchip_dsp.pmg @@ -268,7 +268,7 @@ endmatch code if (postAdd) { - if (postAdd->type.in(ID($sub)) && postAddAB == \A) { + if (postAdd->type.in($sub) && postAddAB == \A) { // if $sub, the multiplier output must match to $sub.B, otherwise no match } else { u_postAddAB = postAddAB; diff --git a/techlibs/microchip/microchip_dsp_cascade.pmg b/techlibs/microchip/microchip_dsp_cascade.pmg index d7ea5911e09..fa276d5b545 100644 --- a/techlibs/microchip/microchip_dsp_cascade.pmg +++ b/techlibs/microchip/microchip_dsp_cascade.pmg @@ -115,9 +115,9 @@ finally Wire *cascade = module->addWire(NEW_ID, 48); // zero port C and move wire to cascade - dsp_pcin->setPort(ID(C), Const(0, 48)); - dsp_pcin->setPort(ID(CDIN), cascade); - dsp->setPort(ID(CDOUT), cascade); + dsp_pcin->setPort(\C, Const(0, 48)); + dsp_pcin->setPort(\CDIN, cascade); + dsp->setPort(\CDOUT, cascade); // Configure wire to cascade the dsps add_siguser(cascade, dsp_pcin); From 1dd5b150e545d9b22e790d649dc46a9d433864e0 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 13 Nov 2025 11:10:13 +0100 Subject: [PATCH 5/8] driver: garbage collect IdStrings without tracing at exit --- kernel/driver.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/driver.cc b/kernel/driver.cc index eae9c527657..792f78b7f51 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -158,6 +158,7 @@ extern "C" { void yosys_atexit() { + RTLIL::OwningIdString::collect_garbage(false); #if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE) if (!yosys_history_file.empty()) { #if defined(YOSYS_ENABLE_READLINE) From c48bc56f4aa8873e8f32d2a7542ade803cc3043c Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 13 Nov 2025 11:10:50 +0100 Subject: [PATCH 6/8] driver: fix timing data divison by zero when no passes run --- kernel/driver.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index 792f78b7f51..d8b10411754 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -707,11 +707,16 @@ int main(int argc, char **argv) for (auto &it : pass_register) if (it.second->call_counter) { - total_ns += it.second->runtime_ns + 1; - timedat.insert(make_tuple(it.second->runtime_ns + 1, it.second->call_counter, it.first)); + auto pass_ns = it.second->runtime_ns + 1; + total_ns += pass_ns; + timedat.insert(make_tuple(pass_ns, it.second->call_counter, it.first)); } - timedat.insert(make_tuple(RTLIL::OwningIdString::garbage_collection_ns() + 1, - RTLIL::OwningIdString::garbage_collection_count(), "id_gc")); + { + auto gc_ns = RTLIL::OwningIdString::garbage_collection_ns() + 1; + total_ns += gc_ns; + timedat.insert(make_tuple(gc_ns, + RTLIL::OwningIdString::garbage_collection_count(), "id_gc")); + } if (timing_details) { From a9151437688b06b068114170066d1242e4721dbc Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 13 Nov 2025 12:40:04 +0100 Subject: [PATCH 7/8] ice40: fix IdString memory leak --- techlibs/ice40/ice40_opt.cc | 4 ++-- techlibs/ice40/ice40_wrapcarry.cc | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index b13d3301856..c88fd69b68d 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -117,7 +117,7 @@ static void run_ice40_opts(Module *module) if (GetSize(replacement_output)) { optimized_co.insert(sigmap(cell->getPort(ID::CO)[0])); - auto it = cell->attributes.find(ID(SB_LUT4.name)); + auto it = cell->attributes.find(IdString{"\\SB_LUT4.name"}); if (it != cell->attributes.end()) { module->rename(cell, it->second.decode_string()); decltype(Cell::attributes) new_attr; @@ -126,7 +126,7 @@ static void run_ice40_opts(Module *module) new_attr[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; else if (a.first == ID::src) new_attr.insert(std::make_pair(a.first, a.second)); - else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID::module_not_derived)) + else if (a.first.in(IdString{"\\SB_LUT4.name"}, ID::keep, ID::module_not_derived)) continue; else if (a.first.begins_with("\\SB_CARRY.\\")) continue; diff --git a/techlibs/ice40/ice40_wrapcarry.cc b/techlibs/ice40/ice40_wrapcarry.cc index fe928ba6da1..82218ff1105 100644 --- a/techlibs/ice40/ice40_wrapcarry.cc +++ b/techlibs/ice40/ice40_wrapcarry.cc @@ -62,7 +62,7 @@ void create_ice40_wrapcarry(ice40_wrapcarry_pm &pm) cell->attributes[stringf("\\SB_CARRY.%s", a.first)] = a.second; for (const auto &a : st.lut->attributes) cell->attributes[stringf("\\SB_LUT4.%s", a.first)] = a.second; - cell->attributes[ID(SB_LUT4.name)] = Const(st.lut->name.str()); + cell->attributes[IdString{"\\SB_LUT4.name"}] = Const(st.lut->name.str()); if (st.carry->get_bool_attribute(ID::keep) || st.lut->get_bool_attribute(ID::keep)) cell->attributes[ID::keep] = true; @@ -122,7 +122,7 @@ struct Ice40WrapCarryPass : public Pass { carry->setPort(ID::CI, cell->getPort(ID::CI)); carry->setPort(ID::CO, cell->getPort(ID::CO)); module->swap_names(carry, cell); - auto lut_name = cell->attributes.at(ID(SB_LUT4.name), Const(NEW_ID.str())).decode_string(); + auto lut_name = cell->attributes.at(IdString{"\\SB_LUT4.name"}, Const(NEW_ID.str())).decode_string(); auto lut = module->addCell(lut_name, ID($lut)); lut->setParam(ID::WIDTH, 4); lut->setParam(ID::LUT, cell->getParam(ID::LUT)); @@ -138,7 +138,7 @@ struct Ice40WrapCarryPass : public Pass { lut->attributes[a.first.c_str() + strlen("\\SB_LUT4.")] = a.second; else if (a.first == ID::src) src = a.second; - else if (a.first.in(ID(SB_LUT4.name), ID::keep, ID::module_not_derived)) + else if (a.first.in(IdString{"\\SB_LUT4.name"}, ID::keep, ID::module_not_derived)) continue; else log_abort(); From f2263642a4de789069edcefb4a0a1c68e0b01446 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Thu, 13 Nov 2025 12:42:06 +0100 Subject: [PATCH 8/8] xilinx: fix IdString memory leak --- techlibs/xilinx/xilinx_dsp_cascade.pmg | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/techlibs/xilinx/xilinx_dsp_cascade.pmg b/techlibs/xilinx/xilinx_dsp_cascade.pmg index 29fc27dfed6..9eebd33c3a3 100644 --- a/techlibs/xilinx/xilinx_dsp_cascade.pmg +++ b/techlibs/xilinx/xilinx_dsp_cascade.pmg @@ -90,9 +90,9 @@ finally if (i % MAX_DSP_CASCADE > 0) { if (P >= 0) { Wire *cascade = module->addWire(NEW_ID, 48); - dsp_pcin->setPort(ID(C), Const(0, 48)); - dsp_pcin->setPort(ID(PCIN), cascade); - dsp->setPort(ID(PCOUT), cascade); + dsp_pcin->setPort(\C, Const(0, 48)); + dsp_pcin->setPort(\PCIN, cascade); + dsp->setPort(\PCOUT, cascade); add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); @@ -118,15 +118,15 @@ finally } if (AREG >= 0) { Wire *cascade = module->addWire(NEW_ID, 30); - dsp_pcin->setPort(ID(A), Const(0, 30)); - dsp_pcin->setPort(ID(ACIN), cascade); - dsp->setPort(ID(ACOUT), cascade); + dsp_pcin->setPort(\A, Const(0, 30)); + dsp_pcin->setPort(\ACIN, cascade); + dsp->setPort(\ACOUT, cascade); add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); if (dsp->type.in(\DSP48E1)) - dsp->setParam(ID(ACASCREG), AREG); - dsp_pcin->setParam(ID(A_INPUT), Const("CASCADE")); + dsp->setParam(\ACASCREG, AREG); + dsp_pcin->setParam(\A_INPUT, Const("CASCADE")); log_debug("ACOUT -> ACIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin)); } @@ -138,18 +138,18 @@ finally // BCOUT from an adjacent DSP48A1 slice. The tools then // translate BCOUT cascading to the dedicated BCIN input // and set the B_INPUT attribute for implementation." - dsp_pcin->setPort(ID(B), cascade); + dsp_pcin->setPort(\B, cascade); } else { - dsp_pcin->setPort(ID(B), Const(0, 18)); - dsp_pcin->setPort(ID(BCIN), cascade); + dsp_pcin->setPort(\B, Const(0, 18)); + dsp_pcin->setPort(\BCIN, cascade); } - dsp->setPort(ID(BCOUT), cascade); + dsp->setPort(\BCOUT, cascade); add_siguser(cascade, dsp_pcin); add_siguser(cascade, dsp); if (dsp->type.in(\DSP48E1)) { - dsp->setParam(ID(BCASCREG), BREG); + dsp->setParam(\BCASCREG, BREG); // According to UG389 p13 [https://www.xilinx.com/support/documentation/user_guides/ug389.pdf] // "The attribute is only used by place and route tools and // is not necessary for the users to set for synthesis. The @@ -158,7 +158,7 @@ finally // BCOUT of another DSP48A1 slice, then the tools automatically // set the attribute to 'CASCADE', otherwise it is set to // 'DIRECT'". - dsp_pcin->setParam(ID(B_INPUT), Const("CASCADE")); + dsp_pcin->setParam(\B_INPUT, Const("CASCADE")); } log_debug("BCOUT -> BCIN cascade for %s -> %s\n", log_id(dsp), log_id(dsp_pcin));