From 8f0ecce53f4293e324dfe6cefbed26b6c86d6ade Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 24 Nov 2025 22:29:06 +0000 Subject: [PATCH] Forbid creating IdStrings and incrementing autoidx during multithreaded phases, and add dynamic checks for that We could make it safe to increment autoidx during multithreaded passes, but that's actually undesirable because it would lead to nondeterminism. If/when we need new IDs during parallel passes, we'll have to figure out how to allocate them in a deterministic way, and that will depend on the details of what the pass does. So don't try to tackle that now. --- frontends/blif/blifparse.cc | 2 +- kernel/rtlil.cc | 2 +- kernel/rtlil.h | 6 ++++++ kernel/yosys.cc | 24 +++++++++++++++++++++++- kernel/yosys_common.h | 25 ++++++++++++++++++++++++- 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index 0aa3a173d..bff347ea2 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -245,7 +245,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (undef_wire != nullptr) module->rename(undef_wire, stringf("$undef$%d", ++blif_maxnum)); - autoidx = std::max(autoidx, blif_maxnum+1); + autoidx.ensure_at_least(blif_maxnum+1); blif_maxnum = 0; } diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index dc851c019..9477b04a8 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -98,7 +98,7 @@ int RTLIL::IdString::really_insert(std::string_view p, std::unordered_map(StaticId::STATIC_ID_END)) return; auto it = global_refcount_storage_.find(idx); @@ -610,6 +614,8 @@ private: void put_reference() { + log_assert(!Multithreading::active()); + // put_reference() may be called from destructors after the destructor of // global_refcount_storage_ has been run. in this case we simply do nothing. if (index_ < static_cast(StaticId::STATIC_ID_END) || !destruct_guard_ok) diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 009da56b9..2c9b8304d 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -19,6 +19,7 @@ #include "kernel/yosys.h" #include "kernel/celltypes.h" +#include "kernel/log.h" #ifdef YOSYS_ENABLE_READLINE # include @@ -80,7 +81,7 @@ extern "C" PyObject* PyInit_pyosys(); YOSYS_NAMESPACE_BEGIN -int autoidx = 1; +Autoidx autoidx(1); int yosys_xtrace = 0; bool yosys_write_versions = true; const char* yosys_maybe_version() { @@ -108,9 +109,30 @@ uint32_t Hasher::fudge = 0; std::string yosys_share_dirname; std::string yosys_abc_executable; +bool Multithreading::active_ = false; + void init_share_dirname(); void init_abc_executable_name(); +Multithreading::Multithreading() { + log_assert(!active_); + active_ = true; +} + +Multithreading::~Multithreading() { + log_assert(active_); + active_ = false; +} + +void Autoidx::ensure_at_least(int v) { + value = std::max(value, v); +} + +int Autoidx::operator++(int) { + log_assert(!Multithreading::active()); + return value++; +} + void memhasher_on() { #if defined(__linux__) || defined(__FreeBSD__) diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index 2374182ee..55e7b71eb 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -267,7 +267,30 @@ int ceil_log2(int x) YS_ATTRIBUTE(const); template int GetSize(const T &obj) { return obj.size(); } inline int GetSize(RTLIL::Wire *wire); -extern int autoidx; +// When multiple threads are accessing RTLIL, one of these guard objects +// must exist. +struct Multithreading +{ + Multithreading(); + ~Multithreading(); + // Returns true when multiple threads are accessing RTLIL. + // autoidx cannot be used during such times. + // IdStrings cannot be created during such times. + static bool active() { return active_; } +private: + static bool active_; +}; + +struct Autoidx { + Autoidx(int value) : value(value) {} + operator int() const { return value; } + void ensure_at_least(int v); + int operator++(int); +private: + int value; +}; + +extern Autoidx autoidx; extern int yosys_xtrace; extern bool yosys_write_versions;