From 9cb3a239cc872e4a4379d00a0191a2760122542e Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 15 Sep 2025 23:13:20 +0000 Subject: [PATCH 01/60] Fix `subcircuit` building without `#define _YOSYS_` We can't use the new stringf functionality with `my_sprintf()` since in some builds that falls back to C-style varargs. --- libs/subcircuit/subcircuit.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/subcircuit/subcircuit.cc b/libs/subcircuit/subcircuit.cc index 8c8d3d92d..60f27fd55 100644 --- a/libs/subcircuit/subcircuit.cc +++ b/libs/subcircuit/subcircuit.cc @@ -411,7 +411,7 @@ class SubCircuit::SolverWorker std::string toString() const { - return my_stringf("%s[%d]:%s[%d]", fromPort, fromBit, toPort, toBit); + return my_stringf("%s[%d]:%s[%d]", fromPort.c_str(), fromBit, toPort.c_str(), toBit); } }; @@ -444,7 +444,7 @@ class SubCircuit::SolverWorker std::string str; bool firstPort = true; for (const auto &it : portSizes) { - str += my_stringf("%s%s[%d]", firstPort ? "" : ",", it.first, it.second); + str += my_stringf("%s%s[%d]", firstPort ? "" : ",", it.first.c_str(), it.second); firstPort = false; } return typeId + "(" + str + ")"; From fe9eed04981a74758a4ab567baa135cbd00bc28d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 00:22:09 +0000 Subject: [PATCH 02/60] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4aae25c3c..281f5a868 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+72 +YOSYS_VER := 0.57+88 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 8492c49f6cf670c5df50f7a0cbf839b3d85ecae2 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 16 Sep 2025 03:06:17 +0000 Subject: [PATCH 03/60] Remove `string_buf` by making `log_signal()` and `log_const()` return `std::string` We only have to fix one caller in-tree so this probably has very low impact on out-of-tree plugins. Resolves #5215 --- kernel/log.cc | 33 ++++----------------------------- kernel/log.h | 4 ++-- passes/techmap/abc.cc | 2 +- 3 files changed, 7 insertions(+), 32 deletions(-) diff --git a/kernel/log.cc b/kernel/log.cc index efdface80..3a44a3ddc 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -68,8 +68,6 @@ int log_debug_suppressed = 0; vector header_count; vector log_id_cache; -vector string_buf; -int string_buf_index = -1; static struct timeval initial_tv = { 0, 0 }; static bool next_print_log = false; @@ -447,8 +445,6 @@ void log_pop() { header_count.pop_back(); log_id_cache_clear(); - string_buf.clear(); - string_buf_index = -1; log_flush(); } @@ -554,8 +550,6 @@ void log_reset_stack() while (header_count.size() > 1) header_count.pop_back(); log_id_cache_clear(); - string_buf.clear(); - string_buf_index = -1; log_flush(); } @@ -580,38 +574,19 @@ void log_dump_val_worker(RTLIL::State v) { log("%s", log_signal(v)); } -const char *log_signal(const RTLIL::SigSpec &sig, bool autoint) +std::string log_signal(const RTLIL::SigSpec &sig, bool autoint) { std::stringstream buf; RTLIL_BACKEND::dump_sigspec(buf, sig, autoint); - - if (string_buf.size() < 100) { - string_buf.push_back(buf.str()); - return string_buf.back().c_str(); - } else { - if (++string_buf_index == 100) - string_buf_index = 0; - string_buf[string_buf_index] = buf.str(); - return string_buf[string_buf_index].c_str(); - } + return buf.str(); } -const char *log_const(const RTLIL::Const &value, bool autoint) +std::string log_const(const RTLIL::Const &value, bool autoint) { if ((value.flags & RTLIL::CONST_FLAG_STRING) == 0) return log_signal(value, autoint); - std::string str = "\"" + value.decode_string() + "\""; - - if (string_buf.size() < 100) { - string_buf.push_back(str); - return string_buf.back().c_str(); - } else { - if (++string_buf_index == 100) - string_buf_index = 0; - string_buf[string_buf_index] = str; - return string_buf[string_buf_index].c_str(); - } + return "\"" + value.decode_string() + "\""; } const char *log_id(const RTLIL::IdString &str) diff --git a/kernel/log.h b/kernel/log.h index a136ec7ac..78b202159 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -253,8 +253,8 @@ extern dict log_expect_log, log_expect_warning, lo extern dict log_expect_prefix_log, log_expect_prefix_warning, log_expect_prefix_error; void log_check_expected(); -const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true); -const char *log_const(const RTLIL::Const &value, bool autoint = true); +std::string log_signal(const RTLIL::SigSpec &sig, bool autoint = true); +std::string log_const(const RTLIL::Const &value, bool autoint = true); const char *log_id(const RTLIL::IdString &id); template static inline const char *log_id(T *obj, const char *nullstr = nullptr) { diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 82a5124ae..c5bdd6ecf 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -755,7 +755,7 @@ void AbcModuleState::handle_loops(AbcSigMap &assign_map, RTLIL::Module *module) log("Breaking loop using new signal %s: %s -> %s\n", log_signal(RTLIL::SigSpec(wire)), run_abc.signal_list[id1].bit_str, run_abc.signal_list[id2].bit_str); else - log(" %*s %s -> %s\n", int(strlen(log_signal(RTLIL::SigSpec(wire)))), "", + log(" %*s %s -> %s\n", int(log_signal(RTLIL::SigSpec(wire)).size()), "", run_abc.signal_list[id1].bit_str, run_abc.signal_list[id2].bit_str); first_line = false; } From 03127173c66b421df9eda632f5d2bc34e515a96c Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 04:33:14 +0000 Subject: [PATCH 04/60] Fix const_iterator postincrement behavior --- kernel/rtlil.h | 4 ++-- tests/unit/kernel/rtlilTest.cc | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index fc0087442..0ec7e0954 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -904,8 +904,8 @@ public: const_iterator& operator++() { ++idx; return *this; } const_iterator& operator--() { --idx; return *this; } - const_iterator& operator++(int) { ++idx; return *this; } - const_iterator& operator--(int) { --idx; return *this; } + const_iterator operator++(int) { const_iterator result(*this); ++idx; return result; } + const_iterator operator--(int) { const_iterator result(*this); --idx; return result; } const_iterator& operator+=(int i) { idx += i; return *this; } const_iterator operator+(int add) { diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index cb773202d..b8ac554b1 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -90,6 +90,30 @@ namespace RTLIL { } + TEST_F(KernelRtlilTest, ConstConstIteratorWorks) { + const Const c(0x2, 2); + Const::const_iterator it = c.begin(); + ASSERT_NE(it, c.end()); + EXPECT_EQ(*it, State::S0); + ++it; + ASSERT_NE(it, c.end()); + EXPECT_EQ(*it, State::S1); + ++it; + EXPECT_EQ(it, c.end()); + } + + TEST_F(KernelRtlilTest, ConstConstIteratorPreincrement) { + const Const c(0x2, 2); + Const::const_iterator it = c.begin(); + EXPECT_EQ(*++it, State::S1); + } + + TEST_F(KernelRtlilTest, ConstConstIteratorPostincrement) { + const Const c(0x2, 2); + Const::const_iterator it = c.begin(); + EXPECT_EQ(*it++, State::S0); + } + class WireRtlVsHdlIndexConversionTest : public KernelRtlilTest, public testing::WithParamInterface> From 514fb8f9015b2895e61e025e8b57509942adef72 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 04:34:41 +0000 Subject: [PATCH 05/60] Fix Const::const_iterator tag to be bidirectional_iterator_tag --- kernel/rtlil.cc | 6 +++--- kernel/rtlil.h | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 3a8b25d1d..8d7f89650 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -615,11 +615,11 @@ void RTLIL::Const::append(const RTLIL::Const &other) { } RTLIL::State RTLIL::Const::const_iterator::operator*() const { - if (auto bv = parent.get_if_bits()) + if (auto bv = parent->get_if_bits()) return (*bv)[idx]; - int char_idx = parent.get_str().size() - idx / 8 - 1; - bool bit = (parent.get_str()[char_idx] & (1 << (idx % 8))); + int char_idx = parent->get_str().size() - idx / 8 - 1; + bool bit = (parent->get_str()[char_idx] & (1 << (idx % 8))); return bit ? State::S1 : State::S0; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 0ec7e0954..e1002fff7 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -888,17 +888,17 @@ public: class const_iterator { private: - const Const& parent; + const Const* parent; size_t idx; public: - using iterator_category = std::input_iterator_tag; + using iterator_category = std::bidirectional_iterator_tag; using value_type = State; using difference_type = std::ptrdiff_t; using pointer = const State*; using reference = const State&; - const_iterator(const Const& c, size_t i) : parent(c), idx(i) {} + const_iterator(const Const& c, size_t i) : parent(&c), idx(i) {} State operator*() const; @@ -909,10 +909,10 @@ public: const_iterator& operator+=(int i) { idx += i; return *this; } const_iterator operator+(int add) { - return const_iterator(parent, idx + add); + return const_iterator(*parent, idx + add); } const_iterator operator-(int sub) { - return const_iterator(parent, idx - sub); + return const_iterator(*parent, idx - sub); } int operator-(const const_iterator& other) { return idx - other.idx; From 662a3df98713244cc35f0145a98f69f98c4fdb99 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 01:54:41 +0000 Subject: [PATCH 06/60] Update Const API with alternatives to direct use of bits() In particular, `Const::resize()`, `Const::set()`, and `Const::iterator`. --- kernel/rtlil.h | 81 ++++++++++++++++++++++++++++++++-- tests/unit/kernel/rtlilTest.cc | 54 +++++++++++++++++++++++ 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index e1002fff7..b7776f378 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -842,13 +842,24 @@ public: Const(const std::string &str); Const(long long val, int width = 32); Const(RTLIL::State bit, int width = 1); - Const(const std::vector &bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(bits) {} + Const(std::vector bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::move(bits)) {} Const(const std::vector &bits); Const(const RTLIL::Const &other); Const(RTLIL::Const &&other); RTLIL::Const &operator =(const RTLIL::Const &other); ~Const(); + struct Builder + { + Builder() {} + Builder(int expected_width) { bits.reserve(expected_width); } + void push_back(RTLIL::State b) { bits.push_back(b); } + int size() const { return static_cast(bits.size()); } + Const build() { return Const(std::move(bits)); } + private: + std::vector bits; + }; + bool operator <(const RTLIL::Const &other) const; bool operator ==(const RTLIL::Const &other) const; bool operator !=(const RTLIL::Const &other) const; @@ -885,6 +896,12 @@ public: void bitvectorize() const; void append(const RTLIL::Const &other); + void set(int i, RTLIL::State state) { + bits()[i] = state; + } + void resize(int size, RTLIL::State fill) { + bits().resize(size, fill); + } class const_iterator { private: @@ -927,12 +944,69 @@ public: } }; + class iterator { + private: + Const* parent; + size_t idx; + + public: + class proxy { + private: + Const* parent; + size_t idx; + public: + proxy(Const* parent, size_t idx) : parent(parent), idx(idx) {} + operator State() const { return (*parent)[idx]; } + proxy& operator=(State s) { parent->set(idx, s); return *this; } + proxy& operator=(const proxy& other) { parent->set(idx, (*other.parent)[other.idx]); return *this; } + }; + + using iterator_category = std::bidirectional_iterator_tag; + using value_type = State; + using difference_type = std::ptrdiff_t; + using pointer = proxy*; + using reference = proxy; + + iterator(Const& c, size_t i) : parent(&c), idx(i) {} + + proxy operator*() const { return proxy(parent, idx); } + iterator& operator++() { ++idx; return *this; } + iterator& operator--() { --idx; return *this; } + iterator operator++(int) { iterator result(*this); ++idx; return result; } + iterator operator--(int) { iterator result(*this); --idx; return result; } + iterator& operator+=(int i) { idx += i; return *this; } + + iterator operator+(int add) { + return iterator(*parent, idx + add); + } + iterator operator-(int sub) { + return iterator(*parent, idx - sub); + } + int operator-(const iterator& other) { + return idx - other.idx; + } + + bool operator==(const iterator& other) const { + return idx == other.idx; + } + + bool operator!=(const iterator& other) const { + return !(*this == other); + } + }; + const_iterator begin() const { return const_iterator(*this, 0); } const_iterator end() const { return const_iterator(*this, size()); } + iterator begin() { + return iterator(*this, 0); + } + iterator end() { + return iterator(*this, size()); + } State back() const { return *(end() - 1); } @@ -964,12 +1038,11 @@ public: std::optional as_int_compress(bool is_signed) const; void extu(int width) { - bits().resize(width, RTLIL::State::S0); + resize(width, RTLIL::State::S0); } void exts(int width) { - bitvectype& bv = bits(); - bv.resize(width, bv.empty() ? RTLIL::State::Sx : bv.back()); + resize(width, empty() ? RTLIL::State::Sx : back()); } [[nodiscard]] Hasher hash_into(Hasher h) const { diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index b8ac554b1..6a5f75a95 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -114,6 +114,60 @@ namespace RTLIL { EXPECT_EQ(*it++, State::S0); } + TEST_F(KernelRtlilTest, ConstIteratorWorks) { + Const c(0x2, 2); + Const::iterator it = c.begin(); + ASSERT_NE(it, c.end()); + EXPECT_EQ(*it, State::S0); + ++it; + ASSERT_NE(it, c.end()); + EXPECT_EQ(*it, State::S1); + ++it; + ASSERT_EQ(it, c.end()); + } + + TEST_F(KernelRtlilTest, ConstIteratorPreincrement) { + Const c(0x2, 2); + Const::iterator it = c.begin(); + EXPECT_EQ(*++it, State::S1); + } + + TEST_F(KernelRtlilTest, ConstIteratorPostincrement) { + Const c(0x2, 2); + Const::iterator it = c.begin(); + EXPECT_EQ(*it++, State::S0); + } + + TEST_F(KernelRtlilTest, ConstIteratorWriteWorks) { + Const c(0x2, 2); + Const::iterator it = c.begin(); + EXPECT_EQ(*it, State::S0); + *it = State::S1; + EXPECT_EQ(*it, State::S1); + } + + TEST_F(KernelRtlilTest, ConstBuilder) { + Const::Builder b; + EXPECT_EQ(GetSize(b), 0); + b.push_back(S0); + EXPECT_EQ(GetSize(b), 1); + b.push_back(S1); + EXPECT_EQ(GetSize(b), 2); + EXPECT_EQ(b.build(), Const(0x2, 2)); + } + + TEST_F(KernelRtlilTest, ConstSet) { + Const c(0x2, 2); + c.set(0, S1); + EXPECT_EQ(c, Const(0x3, 2)); + } + + TEST_F(KernelRtlilTest, ConstResize) { + Const c(0x2, 2); + c.resize(4, S1); + EXPECT_EQ(c, Const(0xe, 4)); + } + class WireRtlVsHdlIndexConversionTest : public KernelRtlilTest, public testing::WithParamInterface> From 34df6569a69f32ae96ed7b7353f484e9b0346bb2 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 01:55:02 +0000 Subject: [PATCH 07/60] Update backends to avoid bits() --- backends/btor/btor.cc | 16 +++++++++------- backends/cxxrtl/cxxrtl_backend.cc | 15 +++++++++------ backends/functional/test_generic.cc | 2 +- backends/simplec/simplec.cc | 2 +- backends/smt2/smt2.cc | 12 ++++++------ backends/verilog/verilog_backend.cc | 12 +++++++----- 6 files changed, 33 insertions(+), 26 deletions(-) diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index 5fd21717e..bba7249c7 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -705,12 +705,13 @@ struct BtorWorker } } - Const initval; + Const::Builder initval_bits(GetSize(sig_q)); for (int i = 0; i < GetSize(sig_q); i++) if (initbits.count(sig_q[i])) - initval.bits().push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0); + initval_bits.push_back(initbits.at(sig_q[i]) ? State::S1 : State::S0); else - initval.bits().push_back(State::Sx); + initval_bits.push_back(State::Sx); + Const initval = initval_bits.build(); int nid_init_val = -1; @@ -1039,10 +1040,11 @@ struct BtorWorker { if (bit.wire == nullptr) { - Const c(bit.data); - - while (i+GetSize(c) < GetSize(sig) && sig[i+GetSize(c)].wire == nullptr) - c.bits().push_back(sig[i+GetSize(c)].data); + Const::Builder c_bits; + c_bits.push_back(bit.data); + while (i + GetSize(c_bits) < GetSize(sig) && sig[i + GetSize(c_bits)].wire == nullptr) + c_bits.push_back(sig[i + GetSize(c_bits)].data); + Const c = c_bits.build(); if (consts.count(c) == 0) { int sid = get_bv_sid(GetSize(c)); diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 0c9f6c054..9a7e1383a 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -1668,26 +1668,29 @@ struct CxxrtlWorker { f << signal_temp << " == "; dump_sigspec(compare, /*is_lhs=*/false, for_debug); } else if (compare.is_fully_const()) { - RTLIL::Const compare_mask, compare_value; + RTLIL::Const::Builder compare_mask_builder(compare.size()); + RTLIL::Const::Builder compare_value_builder(compare.size()); for (auto bit : compare.as_const()) { switch (bit) { case RTLIL::S0: case RTLIL::S1: - compare_mask.bits().push_back(RTLIL::S1); - compare_value.bits().push_back(bit); + compare_mask_builder.push_back(RTLIL::S1); + compare_value_builder.push_back(bit); break; case RTLIL::Sx: case RTLIL::Sz: case RTLIL::Sa: - compare_mask.bits().push_back(RTLIL::S0); - compare_value.bits().push_back(RTLIL::S0); + compare_mask_builder.push_back(RTLIL::S0); + compare_value_builder.push_back(RTLIL::S0); break; default: log_assert(false); } } + RTLIL::Const compare_mask = compare_mask_builder.build(); + RTLIL::Const compare_value = compare_value_builder.build(); f << "and_uu<" << compare.size() << ">(" << signal_temp << ", "; dump_const(compare_mask); f << ") == "; @@ -3042,7 +3045,7 @@ struct CxxrtlWorker { if (init == RTLIL::Const()) { init = RTLIL::Const(State::Sx, GetSize(bit.wire)); } - init.bits()[bit.offset] = port.init_value[i]; + init.set(bit.offset, port.init_value[i]); } } } diff --git a/backends/functional/test_generic.cc b/backends/functional/test_generic.cc index a0474ea2b..c01649a0f 100644 --- a/backends/functional/test_generic.cc +++ b/backends/functional/test_generic.cc @@ -105,7 +105,7 @@ struct MemContentsTest { RTLIL::Const values; for(addr_t addr = low; addr <= high; addr++) { RTLIL::Const word(data_dist(rnd), data_width); - values.bits().insert(values.bits().end(), word.begin(), word.end()); + values.append(word); } insert_concatenated(low, values); } diff --git a/backends/simplec/simplec.cc b/backends/simplec/simplec.cc index ed981f961..8ebc685f0 100644 --- a/backends/simplec/simplec.cc +++ b/backends/simplec/simplec.cc @@ -657,7 +657,7 @@ struct SimplecWorker { SigSpec sig = sigmaps.at(module)(w); Const val = w->attributes.at(ID::init); - val.bits().resize(GetSize(sig), State::Sx); + val.resize(GetSize(sig), State::Sx); for (int i = 0; i < GetSize(sig); i++) if (val[i] == State::S0 || val[i] == State::S1) { diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 1d3757463..d80622029 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -1079,14 +1079,14 @@ struct Smt2Worker RTLIL::SigSpec sig = sigmap(wire); Const val = wire->attributes.at(ID::init); - val.bits().resize(GetSize(sig), State::Sx); + val.resize(GetSize(sig), State::Sx); if (bvmode && GetSize(sig) > 1) { Const mask(State::S1, GetSize(sig)); bool use_mask = false; for (int i = 0; i < GetSize(sig); i++) if (val[i] != State::S0 && val[i] != State::S1) { - val.bits()[i] = State::S0; - mask.bits()[i] = State::S0; + val.set(i, State::S0); + mask.set(i, State::S0); use_mask = true; } if (use_mask) @@ -1361,10 +1361,10 @@ struct Smt2Worker for (int k = 0; k < GetSize(initword); k++) { if (initword[k] == State::S0 || initword[k] == State::S1) { gen_init_constr = true; - initmask.bits()[k] = State::S1; + initmask.set(k, State::S1); } else { - initmask.bits()[k] = State::S0; - initword.bits()[k] = State::S0; + initmask.set(k, State::S0); + initword.set(k, State::S0); } } diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 71969f177..b03639b8d 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -327,19 +327,20 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o void dump_reg_init(std::ostream &f, SigSpec sig) { - Const initval; bool gotinit = false; + Const::Builder initval_bits(sig.size()); for (auto bit : active_sigmap(sig)) { if (active_initdata.count(bit)) { - initval.bits().push_back(active_initdata.at(bit)); + initval_bits.push_back(active_initdata.at(bit)); gotinit = true; } else { - initval.bits().push_back(State::Sx); + initval_bits.push_back(State::Sx); } } if (gotinit) { + Const initval = initval_bits.build(); f << " = "; dump_const(f, initval); } @@ -767,9 +768,10 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem) dump_sigspec(os, port.data.extract(sub * mem.width, mem.width)); os << stringf(" = %s[", mem_id);; if (port.wide_log2) { - Const addr_lo; + Const::Builder addr_lo_builder(port.wide_log2); for (int i = 0; i < port.wide_log2; i++) - addr_lo.bits().push_back(State(sub >> i & 1)); + addr_lo_builder.push_back(State(sub >> i & 1)); + Const addr_lo = addr_lo_builder.build(); os << "{"; os << temp_id; os << ", "; From f65ca488ec41500857f041768a200652a5e90189 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 01:55:26 +0000 Subject: [PATCH 08/60] Update frontends to avoid bits() --- frontends/aiger/aigerparse.cc | 2 +- frontends/ast/ast.cc | 4 +++- frontends/ast/genrtlil.cc | 16 +++++++++------- frontends/ast/simplify.cc | 11 +++++++---- frontends/blif/blifparse.cc | 23 +++++++++++++---------- frontends/rtlil/rtlil_parser.y | 7 ++++--- 6 files changed, 37 insertions(+), 26 deletions(-) diff --git a/frontends/aiger/aigerparse.cc b/frontends/aiger/aigerparse.cc index db4cb12ba..70d94faff 100644 --- a/frontends/aiger/aigerparse.cc +++ b/frontends/aiger/aigerparse.cc @@ -448,7 +448,7 @@ void AigerReader::parse_xaiger() bool success = ce.eval(o); log_assert(success); log_assert(o.wire == nullptr); - lut_mask.bits()[gray] = o.data; + lut_mask.set(gray, o.data); } RTLIL::Cell *output_cell = module->cell(stringf("$and$aiger%d$%d", aiger_autoidx, rootNodeID)); log_assert(output_cell); diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index b61c0bea9..459b50683 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1076,8 +1076,10 @@ RTLIL::Const AstNode::realAsConst(int width) bool is_negative = v < 0; if (is_negative) v *= -1; + RTLIL::Const::Builder b(width); for (int i = 0; i < width; i++, v /= 2) - result.bits().push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0); + b.push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0); + result = b.build(); if (is_negative) result = const_neg(result, result, false, false, result.size()); } diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 41e10cf98..262dda43b 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -732,16 +732,17 @@ struct AST_INTERNAL::ProcessGenerator current_case->actions.push_back(SigSig(en, true)); RTLIL::SigSpec triggers; - RTLIL::Const polarity; + RTLIL::Const::Builder polarity_builder; for (auto sync : proc->syncs) { if (sync->type == RTLIL::STp) { triggers.append(sync->signal); - polarity.bits().push_back(RTLIL::S1); + polarity_builder.push_back(RTLIL::S1); } else if (sync->type == RTLIL::STn) { triggers.append(sync->signal); - polarity.bits().push_back(RTLIL::S0); + polarity_builder.push_back(RTLIL::S0); } } + RTLIL::Const polarity = polarity_builder.build(); RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($print)); set_src_attr(cell, ast); @@ -829,16 +830,17 @@ struct AST_INTERNAL::ProcessGenerator current_case->actions.push_back(SigSig(en, true)); RTLIL::SigSpec triggers; - RTLIL::Const polarity; + RTLIL::Const::Builder polarity_builder; for (auto sync : proc->syncs) { if (sync->type == RTLIL::STp) { triggers.append(sync->signal); - polarity.bits().push_back(RTLIL::S1); + polarity_builder.push_back(RTLIL::S1); } else if (sync->type == RTLIL::STn) { triggers.append(sync->signal); - polarity.bits().push_back(RTLIL::S0); + polarity_builder.push_back(RTLIL::S0); } } + RTLIL::Const polarity = polarity_builder.build(); RTLIL::Cell *cell = current_module->addCell(cellname, ID($check)); set_src_attr(cell, ast); @@ -893,7 +895,7 @@ struct AST_INTERNAL::ProcessGenerator RTLIL::Const priority_mask = RTLIL::Const(0, cur_idx); for (int i = 0; i < portid; i++) { int new_bit = port_map[std::make_pair(memid, i)]; - priority_mask.bits()[new_bit] = orig_priority_mask[i]; + priority_mask.set(new_bit, orig_priority_mask[i]); } action.priority_mask = priority_mask; sync->mem_write_actions.push_back(action); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 7328290ea..2669f83e2 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -4366,7 +4366,7 @@ replace_fcall_later:; log_assert(a.size() == b.size()); for (auto i = 0; i < a.size(); i++) if (a[i] != b[i]) - a.bits()[i] = RTLIL::State::Sx; + a.set(i, RTLIL::State::Sx); newNode = mkconst_bits(location, a.to_bits(), sign_hint); } else if (children[1]->isConst() && children[2]->isConst()) { newNode = std::make_unique(location, AST_REALVALUE); @@ -5368,8 +5368,11 @@ bool AstNode::replace_variables(std::map &varia offset -= variables.at(str).offset; if (variables.at(str).range_swapped) offset = -offset; - std::vector &var_bits = variables.at(str).val.bits(); - std::vector new_bits(var_bits.begin() + offset, var_bits.begin() + offset + width); + const RTLIL::Const &val = variables.at(str).val; + std::vector new_bits; + new_bits.reserve(width); + for (int i = 0; i < width; i++) + new_bits.push_back(val[offset+i]); auto newNode = mkconst_bits(location, new_bits, variables.at(str).is_signed); newNode->cloneInto(*this); return true; @@ -5513,7 +5516,7 @@ std::unique_ptr AstNode::eval_const_function(AstNode *fcall, bool must_ int index = i + offset - v.offset; if (v.range_swapped) index = -index; - v.val.bits().at(index) = r.at(i); + v.val.set(index, r.at(i)); } } diff --git a/frontends/blif/blifparse.cc b/frontends/blif/blifparse.cc index d63044923..741dd07d6 100644 --- a/frontends/blif/blifparse.cc +++ b/frontends/blif/blifparse.cc @@ -149,7 +149,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool if (buffer[0] == '.') { if (lutptr) { - for (auto &bit : lutptr->bits()) + for (auto bit : *lutptr) if (bit == RTLIL::State::Sx) bit = lut_default_state; lutptr = NULL; @@ -321,9 +321,10 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool const_v = Const(str); } else { int n = strlen(v); - const_v.bits().resize(n); + Const::Builder const_v_builder(n); for (int i = 0; i < n; i++) - const_v.bits()[i] = v[n-i-1] != '0' ? State::S1 : State::S0; + const_v_builder.push_back(v[n-i-1] != '0' ? State::S1 : State::S0); + const_v = const_v_builder.build(); } if (!strcmp(cmd, ".attr")) { if (obj_attributes == nullptr) { @@ -563,21 +564,23 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool log_assert(sopcell->parameters[ID::WIDTH].as_int() == input_len); sopcell->parameters[ID::DEPTH] = sopcell->parameters[ID::DEPTH].as_int() + 1; + Const::Builder table_bits_builder(input_len * 2); for (int i = 0; i < input_len; i++) switch (input[i]) { case '0': - sopcell->parameters[ID::TABLE].bits().push_back(State::S1); - sopcell->parameters[ID::TABLE].bits().push_back(State::S0); + table_bits_builder.push_back(State::S1); + table_bits_builder.push_back(State::S0); break; case '1': - sopcell->parameters[ID::TABLE].bits().push_back(State::S0); - sopcell->parameters[ID::TABLE].bits().push_back(State::S1); + table_bits_builder.push_back(State::S0); + table_bits_builder.push_back(State::S1); break; default: - sopcell->parameters[ID::TABLE].bits().push_back(State::S0); - sopcell->parameters[ID::TABLE].bits().push_back(State::S0); + table_bits_builder.push_back(State::S0); + table_bits_builder.push_back(State::S0); break; } + sopcell->parameters[ID::TABLE].append(table_bits_builder.build()); if (sopmode == -1) { sopmode = (*output == '1'); @@ -605,7 +608,7 @@ void parse_blif(RTLIL::Design *design, std::istream &f, IdString dff_name, bool goto try_next_value; } } - lutptr->bits().at(i) = !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1; + lutptr->set(i, !strcmp(output, "0") ? RTLIL::State::S0 : RTLIL::State::S1); try_next_value:; } diff --git a/frontends/rtlil/rtlil_parser.y b/frontends/rtlil/rtlil_parser.y index fc7615364..4f0fb3b97 100644 --- a/frontends/rtlil/rtlil_parser.y +++ b/frontends/rtlil/rtlil_parser.y @@ -455,9 +455,10 @@ constant: } while ((int)bits.size() > width) bits.pop_back(); - $$ = new RTLIL::Const; - for (auto it = bits.begin(); it != bits.end(); it++) - $$->bits().push_back(*it); + RTLIL::Const::Builder builder(bits.size()); + for (RTLIL::State bit : bits) + builder.push_back(bit); + $$ = new RTLIL::Const(builder.build()); if (is_signed) { $$->flags |= RTLIL::CONST_FLAG_SIGNED; } From 1b589b065d889cf53e30e53bd58ee5acde68a595 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:52:40 +0000 Subject: [PATCH 09/60] Update passes/cmds to avoid bits() --- passes/cmds/bugpoint.cc | 6 +++++- passes/cmds/clean_zerowidth.cc | 6 +++--- passes/cmds/dft_tag.cc | 6 ++++-- passes/cmds/setundef.cc | 8 ++++---- passes/cmds/splitnets.cc | 7 ++++--- passes/cmds/xprop.cc | 12 ++++++------ 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc index d48e25d68..8432c27fd 100644 --- a/passes/cmds/bugpoint.cc +++ b/passes/cmds/bugpoint.cc @@ -405,7 +405,11 @@ struct BugpointPass : public Pass { for (auto it2 = sy->mem_write_actions.begin(); it2 != sy->mem_write_actions.end(); ++it2) { auto &mask = it2->priority_mask; if (GetSize(mask) > i) { - mask.bits().erase(mask.bits().begin() + i); + RTLIL::Const::Builder new_mask_builder(GetSize(mask) - 1); + for (int k = 0; k < GetSize(mask); k++) + if (k != i) + new_mask_builder.push_back(mask[k]); + mask = new_mask_builder.build(); } } return design_copy; diff --git a/passes/cmds/clean_zerowidth.cc b/passes/cmds/clean_zerowidth.cc index 48a8864c0..021726450 100644 --- a/passes/cmds/clean_zerowidth.cc +++ b/passes/cmds/clean_zerowidth.cc @@ -158,11 +158,11 @@ struct CleanZeroWidthPass : public Pass { continue; if (GetSize(memwr.address) == 0) memwr.address = State::S0; - Const priority_mask; + RTLIL::Const::Builder new_mask_bits(swizzle.size()); for (auto x : swizzle) { - priority_mask.bits().push_back(memwr.priority_mask[x]); + new_mask_bits.push_back(memwr.priority_mask[x]); } - memwr.priority_mask = priority_mask; + memwr.priority_mask = new_mask_bits.build(); swizzle.push_back(i); new_memwr_actions.push_back(memwr); } diff --git a/passes/cmds/dft_tag.cc b/passes/cmds/dft_tag.cc index 068b5d7d9..5d9756ca0 100644 --- a/passes/cmds/dft_tag.cc +++ b/passes/cmds/dft_tag.cc @@ -884,8 +884,10 @@ struct DftTagWorker { { if (sig_a.is_fully_const()) { auto const_val = sig_a.as_const(); - for (State& bit : const_val.bits()) - bit = bit == State::S0 ? State::S1 : bit == State::S1 ? State::S0 : bit; + for (auto bit : const_val) { + State b = bit; + bit = b == State::S0 ? State::S1 : b == State::S1 ? State::S0 : b; + } return const_val; } return module->Not(name, sig_a); diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index c4a555e6a..6d3e30561 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -243,7 +243,7 @@ struct SetundefPass : public Pass { { for (auto *cell : module->selected_cells()) { for (auto ¶meter : cell->parameters) { - for (auto &bit : parameter.second.bits()) { + for (auto bit : parameter.second) { if (bit > RTLIL::State::S1) bit = worker.next_bit(); } @@ -390,12 +390,12 @@ struct SetundefPass : public Pass { for (auto wire : initwires) { Const &initval = wire->attributes[ID::init]; - initval.bits().resize(GetSize(wire), State::Sx); + initval.resize(GetSize(wire), State::Sx); for (int i = 0; i < GetSize(wire); i++) { SigBit bit = sigmap(SigBit(wire, i)); if (initval[i] == State::Sx && ffbits.count(bit)) { - initval.bits()[i] = worker.next_bit(); + initval.set(i, worker.next_bit()); ffbits.erase(bit); } } @@ -421,7 +421,7 @@ struct SetundefPass : public Pass { continue; Const &initval = wire->attributes[ID::init]; - initval.bits().resize(GetSize(wire), State::Sx); + initval.resize(GetSize(wire), State::Sx); if (initval.is_fully_undef()) { wire->attributes.erase(ID::init); diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 9e606dee1..d61a99ec0 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -75,10 +75,11 @@ struct SplitnetsWorker it = wire->attributes.find(ID::init); if (it != wire->attributes.end()) { - Const old_init = it->second, new_init; + Const old_init = it->second; + RTLIL::Const::Builder new_init_bits_builder(width); for (int i = offset; i < offset+width; i++) - new_init.bits().push_back(i < GetSize(old_init) ? old_init.at(i) : State::Sx); - new_wire->attributes.emplace(ID::init, new_init); + new_init_bits_builder.push_back(i < GetSize(old_init) ? old_init.at(i) : State::Sx); + new_wire->attributes.emplace(ID::init, new_init_bits_builder.build()); } std::vector sigvec = RTLIL::SigSpec(new_wire).to_sigbit_vector(); diff --git a/passes/cmds/xprop.cc b/passes/cmds/xprop.cc index 186e5eec0..8b2e7ae08 100644 --- a/passes/cmds/xprop.cc +++ b/passes/cmds/xprop.cc @@ -828,9 +828,9 @@ struct XpropWorker auto init_q_is_1 = init_q; auto init_q_is_x = init_q; - for (auto &bit : init_q_is_1.bits()) + for (auto bit : init_q_is_1) bit = bit == State::S1 ? State::S1 : State::S0; - for (auto &bit : init_q_is_x.bits()) + for (auto bit : init_q_is_x) bit = bit == State::Sx ? State::S1 : State::S0; initvals.remove_init(sig_q); @@ -865,14 +865,14 @@ struct XpropWorker auto init_q_is_x = init_q; if (ff.is_anyinit) { - for (auto &bit : init_q_is_1.bits()) + for (auto bit : init_q_is_1) bit = State::Sx; - for (auto &bit : init_q_is_x.bits()) + for (auto bit : init_q_is_x) bit = State::S0; } else { - for (auto &bit : init_q_is_1.bits()) + for (auto bit : init_q_is_1) bit = bit == State::S1 ? State::S1 : State::S0; - for (auto &bit : init_q_is_x.bits()) + for (auto bit : init_q_is_x) bit = bit == State::Sx ? State::S1 : State::S0; } From e1d0c010efffe98d127cf742791f955b95de7b21 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:53:05 +0000 Subject: [PATCH 10/60] Update passes/fsm to avoid bits() --- passes/fsm/fsm_extract.cc | 2 +- passes/fsm/fsm_map.cc | 2 +- passes/fsm/fsm_opt.cc | 21 ++++++++++------- passes/fsm/fsm_recode.cc | 2 +- passes/fsm/fsmdata.h | 49 ++++++++++++++------------------------- 5 files changed, 32 insertions(+), 44 deletions(-) diff --git a/passes/fsm/fsm_extract.cc b/passes/fsm/fsm_extract.cc index d83cff5cdc..43a797ff4 100644 --- a/passes/fsm/fsm_extract.cc +++ b/passes/fsm/fsm_extract.cc @@ -171,7 +171,7 @@ undef_bit_in_next_state: if (tr.ctrl_in.at(it.second) == State::S1 && exclusive_ctrls.count(it.first) != 0) for (auto &dc_bit : exclusive_ctrls.at(it.first)) if (ctrl_in_bit_indices.count(dc_bit)) - tr.ctrl_in.bits().at(ctrl_in_bit_indices.at(dc_bit)) = RTLIL::State::Sa; + tr.ctrl_in.set(ctrl_in_bit_indices.at(dc_bit), RTLIL::State::Sa); RTLIL::Const log_state_in = RTLIL::Const(RTLIL::State::Sx, fsm_data.state_bits); if (state_in >= 0) diff --git a/passes/fsm/fsm_map.cc b/passes/fsm/fsm_map.cc index 8a18d259a..c19edcc88 100644 --- a/passes/fsm/fsm_map.cc +++ b/passes/fsm/fsm_map.cc @@ -176,7 +176,7 @@ static void map_fsm(RTLIL::Cell *fsm_cell, RTLIL::Module *module) state_dff->type = ID($adff); state_dff->parameters[ID::ARST_POLARITY] = fsm_cell->parameters[ID::ARST_POLARITY]; state_dff->parameters[ID::ARST_VALUE] = fsm_data.state_table[fsm_data.reset_state]; - for (auto &bit : state_dff->parameters[ID::ARST_VALUE].bits()) + for (auto bit : state_dff->parameters[ID::ARST_VALUE]) if (bit != RTLIL::State::S1) bit = RTLIL::State::S0; state_dff->setPort(ID::ARST, fsm_cell->getPort(ID::ARST)); diff --git a/passes/fsm/fsm_opt.cc b/passes/fsm/fsm_opt.cc index 99771f90a..b61dec890 100644 --- a/passes/fsm/fsm_opt.cc +++ b/passes/fsm/fsm_opt.cc @@ -169,13 +169,16 @@ struct FsmOpt for (auto tr : fsm_data.transition_table) { - RTLIL::State &si = tr.ctrl_in.bits()[i]; - RTLIL::State &sj = tr.ctrl_in.bits()[j]; + RTLIL::State si = tr.ctrl_in[i]; + RTLIL::State sj = tr.ctrl_in[j]; - if (si > RTLIL::State::S1) + if (si > RTLIL::State::S1) { si = sj; - else if (sj > RTLIL::State::S1) + tr.ctrl_in.set(i, si); + } else if (sj > RTLIL::State::S1) { sj = si; + tr.ctrl_in.set(j, sj); + } if (si == sj) { RTLIL::SigSpec tmp(tr.ctrl_in); @@ -207,8 +210,8 @@ struct FsmOpt for (auto tr : fsm_data.transition_table) { - RTLIL::State &si = tr.ctrl_in.bits()[i]; - RTLIL::State &sj = tr.ctrl_out.bits()[j]; + RTLIL::State si = tr.ctrl_in[i]; + RTLIL::State sj = tr.ctrl_out[j]; if (si > RTLIL::State::S1 || si == sj) { RTLIL::SigSpec tmp(tr.ctrl_in); @@ -240,14 +243,14 @@ struct FsmOpt RTLIL::Const other_pattern = pattern; if (pattern[bit] == RTLIL::State::S1) - other_pattern.bits()[bit] = RTLIL::State::S0; + other_pattern.set(bit, RTLIL::State::S0); else - other_pattern.bits()[bit] = RTLIL::State::S1; + other_pattern.set(bit, RTLIL::State::S1); if (set.count(other_pattern) > 0) { log(" Merging pattern %s and %s from group (%d %d %s).\n", log_signal(pattern), log_signal(other_pattern), tr.state_in, tr.state_out, log_signal(tr.ctrl_out)); - other_pattern.bits()[bit] = RTLIL::State::Sa; + other_pattern.set(bit, RTLIL::State::Sa); new_set.insert(other_pattern); did_something = true; continue; diff --git a/passes/fsm/fsm_recode.cc b/passes/fsm/fsm_recode.cc index 8ee03329f..e4cd53a07 100644 --- a/passes/fsm/fsm_recode.cc +++ b/passes/fsm/fsm_recode.cc @@ -106,7 +106,7 @@ static void fsm_recode(RTLIL::Cell *cell, RTLIL::Module *module, FILE *fm_set_fs if (encoding == "one-hot") { new_code = RTLIL::Const(RTLIL::State::Sa, fsm_data.state_bits); - new_code.bits()[state_idx] = RTLIL::State::S1; + new_code.set(state_idx, RTLIL::State::S1); } else if (encoding == "binary") { new_code = RTLIL::Const(state_idx, fsm_data.state_bits); diff --git a/passes/fsm/fsmdata.h b/passes/fsm/fsmdata.h index 9aa12241e..4d824e136 100644 --- a/passes/fsm/fsmdata.h +++ b/passes/fsm/fsmdata.h @@ -45,35 +45,27 @@ struct FsmData cell->parameters[ID::STATE_NUM] = RTLIL::Const(state_table.size()); cell->parameters[ID::STATE_NUM_LOG2] = RTLIL::Const(state_num_log2); cell->parameters[ID::STATE_RST] = RTLIL::Const(reset_state); - cell->parameters[ID::STATE_TABLE] = RTLIL::Const(); - - for (int i = 0; i < int(state_table.size()); i++) { - std::vector &bits_table = cell->parameters[ID::STATE_TABLE].bits(); - std::vector &bits_state = state_table[i].bits(); - bits_table.insert(bits_table.end(), bits_state.begin(), bits_state.end()); - } + RTLIL::Const cell_state_table; + for (const RTLIL::Const &c : state_table) + cell_state_table.append(c); + cell->parameters[ID::STATE_TABLE] = std::move(cell_state_table); cell->parameters[ID::TRANS_NUM] = RTLIL::Const(transition_table.size()); - cell->parameters[ID::TRANS_TABLE] = RTLIL::Const(); + RTLIL::Const cell_trans_table; for (int i = 0; i < int(transition_table.size()); i++) { - std::vector &bits_table = cell->parameters[ID::TRANS_TABLE].bits(); transition_t &tr = transition_table[i]; RTLIL::Const const_state_in = RTLIL::Const(tr.state_in, state_num_log2); RTLIL::Const const_state_out = RTLIL::Const(tr.state_out, state_num_log2); - std::vector &bits_state_in = const_state_in.bits(); - std::vector &bits_state_out = const_state_out.bits(); - - std::vector &bits_ctrl_in = tr.ctrl_in.bits(); - std::vector &bits_ctrl_out = tr.ctrl_out.bits(); // append lsb first - bits_table.insert(bits_table.end(), bits_ctrl_out.begin(), bits_ctrl_out.end()); - bits_table.insert(bits_table.end(), bits_state_out.begin(), bits_state_out.end()); - bits_table.insert(bits_table.end(), bits_ctrl_in.begin(), bits_ctrl_in.end()); - bits_table.insert(bits_table.end(), bits_state_in.begin(), bits_state_in.end()); + cell_trans_table.append(tr.ctrl_out); + cell_trans_table.append(const_state_out); + cell_trans_table.append(tr.ctrl_in); + cell_trans_table.append(const_state_in); } + cell->parameters[ID::TRANS_TABLE] = std::move(cell_trans_table); } void copy_from_cell(RTLIL::Cell *cell) @@ -95,25 +87,18 @@ struct FsmData const RTLIL::Const &trans_table = cell->parameters[ID::TRANS_TABLE]; for (int i = 0; i < state_num; i++) { - RTLIL::Const state_code; - int off_begin = i*state_bits, off_end = off_begin + state_bits; - state_code.bits().insert(state_code.bits().begin(), state_table.begin()+off_begin, state_table.begin()+off_end); + int off_begin = i*state_bits; + RTLIL::Const state_code = state_table.extract(off_begin, state_bits); this->state_table.push_back(state_code); } for (int i = 0; i < trans_num; i++) { - auto off_ctrl_out = trans_table.begin() + i*(num_inputs+num_outputs+2*state_num_log2); - auto off_state_out = off_ctrl_out + num_outputs; - auto off_ctrl_in = off_state_out + state_num_log2; - auto off_state_in = off_ctrl_in + num_inputs; - auto off_end = off_state_in + state_num_log2; - - RTLIL::Const state_in, state_out, ctrl_in, ctrl_out; - ctrl_out.bits().insert(ctrl_out.bits().begin(), off_ctrl_out, off_state_out); - state_out.bits().insert(state_out.bits().begin(), off_state_out, off_ctrl_in); - ctrl_in.bits().insert(ctrl_in.bits().begin(), off_ctrl_in, off_state_in); - state_in.bits().insert(state_in.bits().begin(), off_state_in, off_end); + int base_offset = i*(num_inputs+num_outputs+2*state_num_log2); + RTLIL::Const ctrl_out = trans_table.extract(base_offset, num_outputs); + RTLIL::Const state_out = trans_table.extract(base_offset + num_outputs, state_num_log2); + RTLIL::Const ctrl_in = trans_table.extract(base_offset + num_outputs + state_num_log2, num_inputs); + RTLIL::Const state_in = trans_table.extract(base_offset + num_outputs + state_num_log2 + num_inputs, state_num_log2); transition_t tr; tr.state_in = state_in.as_int(); From 23f196a3b894c28927c244ac0c2160830ab1f1e5 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:53:14 +0000 Subject: [PATCH 11/60] Update passes/memory to avoid bits() --- passes/memory/memory_bram.cc | 10 +++++----- passes/memory/memory_share.cc | 7 ++++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 8ef2c4271..10301b44a 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -848,9 +848,9 @@ grow_read_ports:; for (int i = 0; i < mem.width; i++) if (shuffle_map[i] != -1) { module->connect(port.data[shuffle_map[i]], new_data[i]); - new_init_value.bits()[i] = port.init_value[shuffle_map[i]]; - new_arst_value.bits()[i] = port.arst_value[shuffle_map[i]]; - new_srst_value.bits()[i] = port.srst_value[shuffle_map[i]]; + new_init_value.set(i, port.init_value[shuffle_map[i]]); + new_arst_value.set(i, port.arst_value[shuffle_map[i]]); + new_srst_value.set(i, port.srst_value[shuffle_map[i]]); } port.data = new_data; port.init_value = new_init_value; @@ -887,9 +887,9 @@ grow_read_ports:; for (int i = 0; i < init_size; i++) for (int j = 0; j < bram.dbits; j++) if (init_offset+i < GetSize(initdata) && init_offset+i >= 0) - initparam.bits()[i*bram.dbits+j] = initdata[init_offset+i][init_shift+j]; + initparam.set(i*bram.dbits+j, initdata[init_offset+i][init_shift+j]); else - initparam.bits()[i*bram.dbits+j] = State::Sx; + initparam.set(i*bram.dbits+j, State::Sx); c->setParam(ID::INIT, initparam); } diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc index 6a424952a..fe884772a 100644 --- a/passes/memory/memory_share.cc +++ b/passes/memory/memory_share.cc @@ -60,16 +60,17 @@ struct MemoryShareWorker bool merge_rst_value(Mem &mem, Const &res, int wide_log2, const Const &src1, int sub1, const Const &src2, int sub2) { res = Const(State::Sx, mem.width << wide_log2); for (int i = 0; i < GetSize(src1); i++) - res.bits()[i + sub1 * mem.width] = src1[i]; + res.set(i + sub1 * mem.width, src1[i]); for (int i = 0; i < GetSize(src2); i++) { if (src2[i] == State::Sx) continue; - auto &dst = res.bits()[i + sub2 * mem.width]; + int idx = i + sub2 * mem.width; + RTLIL::State dst = res[idx]; if (dst == src2[i]) continue; if (dst != State::Sx) return false; - dst = src2[i]; + res.set(idx, src2[i]); } return true; } From 5600eb2e5b2640c7966230c7e6cc0e7be454d1b3 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:53:23 +0000 Subject: [PATCH 12/60] Update passes/opt to avoid bits() --- passes/opt/opt_clean.cc | 6 +++--- passes/opt/opt_dff.cc | 22 +++++++++++++--------- passes/opt/opt_expr.cc | 4 ++-- passes/opt/opt_ffinv.cc | 15 ++++++++------- passes/opt/opt_lut.cc | 2 +- passes/opt/opt_lut_ins.cc | 2 +- passes/opt/opt_mem.cc | 30 +++++++++++++++--------------- passes/opt/pmux2shiftx.cc | 16 +++++++++------- passes/opt/share.cc | 26 +++++++++++++++++--------- passes/opt/wreduce.cc | 4 ++-- 10 files changed, 71 insertions(+), 56 deletions(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 4dd5ba616..cef2c0dc3 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -406,7 +406,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos for (int i = 0; i < wire->width; i++) { auto it = init_bits.find(RTLIL::SigBit(wire, i)); if (it != init_bits.end()) { - val.bits()[i] = it->second; + val.set(i, it->second); found = true; } } @@ -425,7 +425,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (wire->attributes.count(ID::init)) initval = wire->attributes.at(ID::init); if (GetSize(initval) != GetSize(wire)) - initval.bits().resize(GetSize(wire), State::Sx); + initval.resize(GetSize(wire), State::Sx); if (initval.is_fully_undef()) wire->attributes.erase(ID::init); @@ -457,7 +457,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (s1[i] != s2[i]) { if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { s2[i] = initval[i]; - initval.bits()[i] = State::Sx; + initval.set(i, State::Sx); } new_conn.first.append(s1[i]); new_conn.second.append(s2[i]); diff --git a/passes/opt/opt_dff.cc b/passes/opt/opt_dff.cc index 2fb0f947f..a364539e4 100644 --- a/passes/opt/opt_dff.cc +++ b/passes/opt/opt_dff.cc @@ -405,27 +405,29 @@ struct OptDffWorker } else if (ff.pol_clr == ff.pol_set) { // Try a more complex conversion to plain async reset. State val_neutral = ff.pol_set ? State::S0 : State::S1; - Const val_arst; SigBit sig_arst; if (ff.sig_clr[0] == val_neutral) sig_arst = ff.sig_set[0]; else sig_arst = ff.sig_clr[0]; bool failed = false; + Const::Builder val_arst_builder(ff.width); for (int i = 0; i < ff.width; i++) { if (ff.sig_clr[i] == sig_arst && ff.sig_set[i] == val_neutral) - val_arst.bits().push_back(State::S0); + val_arst_builder.push_back(State::S0); else if (ff.sig_set[i] == sig_arst && ff.sig_clr[i] == val_neutral) - val_arst.bits().push_back(State::S1); - else + val_arst_builder.push_back(State::S1); + else { failed = true; + break; + } } if (!failed) { log("Converting CLR/SET to ARST on %s (%s) from module %s.\n", log_id(cell), log_id(cell->type), log_id(module)); ff.has_sr = false; ff.has_arst = true; - ff.val_arst = val_arst; + ff.val_arst = val_arst_builder.build(); ff.sig_arst = sig_arst; ff.pol_arst = ff.pol_clr; changed = true; @@ -637,7 +639,7 @@ struct OptDffWorker // Try to merge sync resets. std::map> groups; std::vector remaining_indices; - Const val_srst; + Const::Builder val_srst_builder(ff.width); for (int i = 0 ; i < ff.width; i++) { ctrls_t resets; @@ -679,16 +681,18 @@ struct OptDffWorker groups[resets].push_back(i); } else remaining_indices.push_back(i); - val_srst.bits().push_back(reset_val); + val_srst_builder.push_back(reset_val); } + Const val_srst = val_srst_builder.build(); for (auto &it : groups) { FfData new_ff = ff.slice(it.second); - new_ff.val_srst = Const(); + Const::Builder new_val_srst_builder(new_ff.width); for (int i = 0; i < new_ff.width; i++) { int j = it.second[i]; - new_ff.val_srst.bits().push_back(val_srst[j]); + new_val_srst_builder.push_back(val_srst[j]); } + new_ff.val_srst = new_val_srst_builder.build(); ctrl_t srst = combine_resets(it.first, ff.is_fine); new_ff.has_srst = true; diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index e5957df08..86d96ea7a 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -83,7 +83,7 @@ void replace_undriven(RTLIL::Module *module, const CellTypes &ct) auto cursor = initbits.find(bit); if (cursor != initbits.end()) { revisit_initwires.insert(cursor->second.first); - val.bits()[i] = cursor->second.second; + val.set(i, cursor->second.second); } } @@ -101,7 +101,7 @@ void replace_undriven(RTLIL::Module *module, const CellTypes &ct) Const initval = wire->attributes.at(ID::init); for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { if (SigBit(initval[i]) == sig[i]) - initval.bits()[i] = State::Sx; + initval.set(i, State::Sx); } if (initval.is_fully_undef()) { log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); diff --git a/passes/opt/opt_ffinv.cc b/passes/opt/opt_ffinv.cc index 52e180a20..882221e56 100644 --- a/passes/opt/opt_ffinv.cc +++ b/passes/opt/opt_ffinv.cc @@ -96,10 +96,10 @@ struct OptFfInvWorker } } Const mask = lut->getParam(ID::LUT); - Const new_mask; - for (int j = 0; j < (1 << GetSize(sig_a)); j++) { - new_mask.bits().push_back(mask[j ^ flip_mask]); - } + Const::Builder new_mask_builder(1 << GetSize(sig_a)); + for (int j = 0; j < (1 << GetSize(sig_a)); j++) + new_mask_builder.push_back(mask[j ^ flip_mask]); + Const new_mask = new_mask_builder.build(); if (GetSize(sig_a) == 1 && new_mask.as_int() == 2) { module->connect(lut->getPort(ID::Y), ff.sig_q); module->remove(lut); @@ -178,13 +178,14 @@ struct OptFfInvWorker if (d_lut->type == ID($lut)) { Const mask = d_lut->getParam(ID::LUT); - Const new_mask; + Const::Builder new_mask_builder(GetSize(mask)); for (int i = 0; i < GetSize(mask); i++) { if (mask[i] == State::S0) - new_mask.bits().push_back(State::S1); + new_mask_builder.push_back(State::S1); else - new_mask.bits().push_back(State::S0); + new_mask_builder.push_back(State::S0); } + Const new_mask = new_mask_builder.build(); d_lut->setParam(ID::LUT, new_mask); if (d_lut->getParam(ID::WIDTH) == 1 && new_mask.as_int() == 2) { module->connect(ff.sig_d, d_lut->getPort(ID::A)); diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 97147fc48..248c3dfe9 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -493,7 +493,7 @@ struct OptLutWorker eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1; } eval_inputs[lutA_output] = evaluate_lut(lutA, eval_inputs); - lutM_new_table.bits()[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); + 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()); diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc index 492676ece..9e471c3de 100644 --- a/passes/opt/opt_lut_ins.cc +++ b/passes/opt/opt_lut_ins.cc @@ -213,7 +213,7 @@ struct OptLutInsPass : public Pass { } lidx |= val << j; } - new_lut.bits()[i] = lut[lidx]; + new_lut.set(i, lut[lidx]); } // For lattice, and gowin do not replace with a const driver — the nextpnr // packer requires a complete set of LUTs for wide LUT muxes. diff --git a/passes/opt/opt_mem.cc b/passes/opt/opt_mem.cc index f8354c960..9c5a6d83e 100644 --- a/passes/opt/opt_mem.cc +++ b/passes/opt/opt_mem.cc @@ -175,36 +175,36 @@ struct OptMemPass : public Pass { } for (auto &port: mem.rd_ports) { SigSpec new_data; - Const new_init; - Const new_arst; - Const new_srst; + Const::Builder new_init_bits; + Const::Builder new_arst_bits; + Const::Builder new_srst_bits; for (int sub = 0; sub < (1 << port.wide_log2); sub++) { for (auto i: swizzle) { int bidx = sub * mem.width + i; new_data.append(port.data[bidx]); - new_init.bits().push_back(port.init_value[bidx]); - new_arst.bits().push_back(port.arst_value[bidx]); - new_srst.bits().push_back(port.srst_value[bidx]); + new_init_bits.push_back(port.init_value[bidx]); + new_arst_bits.push_back(port.arst_value[bidx]); + new_srst_bits.push_back(port.srst_value[bidx]); } } port.data = new_data; - port.init_value = new_init; - port.arst_value = new_arst; - port.srst_value = new_srst; + port.init_value = new_init_bits.build(); + port.arst_value = new_arst_bits.build(); + port.srst_value = new_srst_bits.build(); } for (auto &init: mem.inits) { - Const new_data; - Const new_en; + Const::Builder new_data_bits; for (int s = 0; s < GetSize(init.data); s += mem.width) { for (auto i: swizzle) { - new_data.bits().push_back(init.data[s + i]); + new_data_bits.push_back(init.data[s + i]); } } + init.data = new_data_bits.build(); + Const::Builder new_en_bits; for (auto i: swizzle) { - new_en.bits().push_back(init.en[i]); + new_en_bits.push_back(init.en[i]); } - init.data = new_data; - init.en = new_en; + init.en = new_en_bits.build(); } mem.width = GetSize(swizzle); changed = true; diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index e512a5be1..4a0864df0 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -321,11 +321,12 @@ struct Pmux2ShiftxPass : public Pass { bits.sort(); pair entry; - + RTLIL::Const::Builder entry_bits_builder(GetSize(bits)); for (auto it : bits) { entry.first.append(it.first); - entry.second.bits().push_back(it.second); + entry_bits_builder.push_back(it.second); } + entry.second = entry_bits_builder.build(); eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry; goto next_cell; @@ -342,11 +343,12 @@ struct Pmux2ShiftxPass : public Pass { bits.sort(); pair entry; - + RTLIL::Const::Builder entry_bits_builder(GetSize(bits)); for (auto it : bits) { entry.first.append(it.first); - entry.second.bits().push_back(it.second); + entry_bits_builder.push_back(it.second); } + entry.second = entry_bits_builder.build(); eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry; goto next_cell; @@ -591,7 +593,7 @@ struct Pmux2ShiftxPass : public Pass { used_src_columns[best_src_col] = true; perm_new_from_old[dst_col] = best_src_col; - perm_xormask.bits()[dst_col] = best_inv ? State::S1 : State::S0; + perm_xormask.set(dst_col, best_inv ? State::S1 : State::S0); } } @@ -614,7 +616,7 @@ struct Pmux2ShiftxPass : public Pass { Const new_c(State::S0, GetSize(old_c)); for (int i = 0; i < GetSize(old_c); i++) - new_c.bits()[i] = old_c[perm_new_from_old[i]]; + new_c.set(i, old_c[perm_new_from_old[i]]); Const new_c_before_xor = new_c; new_c = const_xor(new_c, perm_xormask, false, false, GetSize(new_c)); @@ -687,7 +689,7 @@ struct Pmux2ShiftxPass : public Pass { if (!full_case) { Const enable_mask(State::S0, max_choice+1); for (auto &it : perm_choices) - enable_mask.bits()[it.first.as_int()] = State::S1; + enable_mask.set(it.first.as_int(), State::S1); en = module->addWire(NEW_ID); module->addShift(NEW_ID, enable_mask, cmp, en, false, src); } diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 1d7ba7d98..307cd299b 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -790,12 +790,13 @@ struct ShareWorker } p.first = RTLIL::SigSpec(); - p.second.bits().clear(); + RTLIL::Const::Builder new_bits(p_bits.size()); for (auto &it : p_bits) { p.first.append(it.first); - p.second.bits().push_back(it.second); + new_bits.push_back(it.second); } + p.second = new_bits.build(); return true; } @@ -818,9 +819,9 @@ struct ShareWorker auto otherval = val; if (otherval[i] == State::S0) - otherval.bits()[i] = State::S1; + otherval.set(i, State::S1); else if (otherval[i] == State::S1) - otherval.bits()[i] = State::S0; + otherval.set(i, State::S0); else continue; @@ -829,8 +830,11 @@ struct ShareWorker auto newsig = sig; newsig.remove(i); - auto newval = val; - newval.bits().erase(newval.bits().begin() + i); + RTLIL::Const::Builder new_bits(val.size() - 1); + for (int j = 0; j < val.size(); ++j) + if (j != i) + new_bits.push_back(val[j]); + RTLIL::Const newval = new_bits.build(); db[newsig].insert(newval); db[sig].erase(otherval); @@ -926,7 +930,8 @@ struct ShareWorker if (used_in_a) for (auto p : c_patterns) { for (int i = 0; i < GetSize(sig_s); i++) - p.first.append(sig_s[i]), p.second.bits().push_back(RTLIL::State::S0); + p.first.append(sig_s[i]); + p.second.append(RTLIL::Const(RTLIL::State::S0, GetSize(sig_s))); if (sort_check_activation_pattern(p)) if (!insert_capped(activation_patterns_cache[cell], p)) { recursion_state.erase(cell); @@ -936,7 +941,8 @@ struct ShareWorker for (int idx : used_in_b_parts) for (auto p : c_patterns) { - p.first.append(sig_s[idx]), p.second.bits().push_back(RTLIL::State::S1); + p.first.append(sig_s[idx]); + p.second.append(RTLIL::Const(RTLIL::State::S1)); if (sort_check_activation_pattern(p)) if (!insert_capped(activation_patterns_cache[cell], p)) { recursion_state.erase(cell); @@ -989,12 +995,14 @@ struct ShareWorker { std::vector p_first = p.first; ssc_pair_t new_p; + RTLIL::Const::Builder new_p_second_bits; for (int i = 0; i < GetSize(p_first); i++) if (filter_bits.count(p_first[i]) == 0) { new_p.first.append(p_first[i]); - new_p.second.bits().push_back(p.second.at(i)); + new_p_second_bits.push_back(p.second.at(i)); } + new_p.second = new_p_second_bits.build(); out.insert(new_p); } diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index fb30f0195..359c76d42 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -220,10 +220,10 @@ struct WreduceWorker // Narrow ARST_VALUE parameter to new size. if (cell->parameters.count(ID::ARST_VALUE)) { - rst_value.bits().resize(GetSize(sig_q)); + rst_value.resize(GetSize(sig_q), State::S0); cell->setParam(ID::ARST_VALUE, rst_value); } else if (cell->parameters.count(ID::SRST_VALUE)) { - rst_value.bits().resize(GetSize(sig_q)); + rst_value.resize(GetSize(sig_q), State::S0); cell->setParam(ID::SRST_VALUE, rst_value); } From 2d5ce8c363ff342f25dfe582318c193b2886f0f0 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:53:34 +0000 Subject: [PATCH 13/60] Update passes/proc to avoid bits() --- passes/proc/proc_init.cc | 12 +++++------- passes/proc/proc_memwr.cc | 2 +- passes/proc/proc_rom.cc | 12 ++++++------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index 99cacf5fd..3d27eaa9a 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -52,17 +52,15 @@ void proc_init(RTLIL::Module *mod, SigMap &sigmap, RTLIL::Process *proc) Const value = valuesig.as_const(); Const &wireinit = lhs_c.wire->attributes[ID::init]; - - while (GetSize(wireinit) < lhs_c.wire->width) - wireinit.bits().push_back(State::Sx); - + if (GetSize(wireinit) < lhs_c.wire->width) + wireinit.resize(lhs_c.wire->width, State::Sx); for (int i = 0; i < lhs_c.width; i++) { - auto &initbit = wireinit.bits()[i + lhs_c.offset]; + int index = i + lhs_c.offset; + State initbit = wireinit[index]; if (initbit != State::Sx && initbit != value[i]) log_cmd_error("Conflicting initialization values for %s.\n", log_signal(lhs_c)); - initbit = value[i]; + wireinit.set(index, value[i]); } - log(" Set init value: %s = %s\n", log_signal(lhs_c.wire), log_signal(wireinit)); } offset += lhs_c.width; diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc index 88aea39bb..a5ae0d6d5 100644 --- a/passes/proc/proc_memwr.cc +++ b/passes/proc/proc_memwr.cc @@ -39,7 +39,7 @@ void proc_memwr(RTLIL::Module *mod, RTLIL::Process *proc, dict &n Const priority_mask(State::S0, port_id); for (int i = 0; i < GetSize(prev_port_ids); i++) if (memwr.priority_mask[i] == State::S1) - priority_mask.bits()[prev_port_ids[i]] = State::S1; + priority_mask.set(prev_port_ids[i], State::S1); prev_port_ids.push_back(port_id); RTLIL::Cell *cell = mod->addCell(NEW_ID, ID($memwr_v2)); diff --git a/passes/proc/proc_rom.cc b/passes/proc/proc_rom.cc index d3b781e60..a7b485194 100644 --- a/passes/proc/proc_rom.cc +++ b/passes/proc/proc_rom.cc @@ -97,7 +97,7 @@ struct RomWorker log_debug("rejecting switch: lhs not uniform\n"); return; } - val.bits()[it2->second] = it.second[i].data; + val.set(it2->second, it.second[i].data); } } for (auto bit: val) { @@ -114,7 +114,7 @@ struct RomWorker } Const c = addr.as_const(); while (GetSize(c) && c.back() == State::S0) - c.bits().pop_back(); + c.resize(c.size() - 1, State::S0); if (GetSize(c) > swsigbits) continue; if (GetSize(c) > 30) { @@ -155,22 +155,22 @@ struct RomWorker Mem mem(module, NEW_ID, GetSize(lhs), 0, 1 << abits); mem.attributes = sw->attributes; - Const init_data; + Const::Builder builder(mem.size * GetSize(lhs)); for (int i = 0; i < mem.size; i++) { auto it = vals.find(i); if (it == vals.end()) { log_assert(got_default); for (auto bit: default_val) - init_data.bits().push_back(bit); + builder.push_back(bit); } else { for (auto bit: it->second) - init_data.bits().push_back(bit); + builder.push_back(bit); } } MemInit init; init.addr = 0; - init.data = init_data; + init.data = builder.build(); init.en = Const(State::S1, GetSize(lhs)); mem.inits.push_back(std::move(init)); From d1642bf510e02bdcff4acca738a6e459c3662f59 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:53:42 +0000 Subject: [PATCH 14/60] Update passes/sat to avoid bits() --- passes/sat/eval.cc | 4 ++-- passes/sat/formalff.cc | 2 +- passes/sat/sat.cc | 29 ++++++++++++++++++----------- passes/sat/sim.cc | 32 ++++++++++++++------------------ 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index bde5e1ecb..f71e8124b 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -256,7 +256,7 @@ struct VlogHammerReporter for (int j = input_widths[i]-1; j >= 0; j--) { ce.set(RTLIL::SigSpec(wire, j), bits.back()); recorded_set_vars.append(RTLIL::SigSpec(wire, j)); - recorded_set_vals.bits().push_back(bits.back()); + recorded_set_vars.append(RTLIL::Const(bits.back())); bits.pop_back(); } if (module == modules.front()) { @@ -346,7 +346,7 @@ struct VlogHammerReporter log_error("Pattern %s is to short!\n", pattern); patterns.push_back(sig.as_const()); if (invert_pattern) { - for (auto &bit : patterns.back().bits()) + for (auto bit : patterns.back()) if (bit == RTLIL::State::S0) bit = RTLIL::State::S1; else if (bit == RTLIL::State::S1) diff --git a/passes/sat/formalff.cc b/passes/sat/formalff.cc index 286bf2976..c0b0cfc15 100644 --- a/passes/sat/formalff.cc +++ b/passes/sat/formalff.cc @@ -851,7 +851,7 @@ struct FormalFfPass : public Pass { auto before = ff.val_init; for (int i = 0; i < ff.width; i++) if (ff.val_init[i] == State::Sx && !worker.is_initval_used(ff.sig_q[i])) - ff.val_init.bits()[i] = State::S0; + ff.val_init.set(i, State::S0); if (ff.val_init != before) { log("Setting unused undefined initial value of %s.%s (%s) from %s to %s\n", diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 967cb0472..5216390da 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -620,14 +620,18 @@ struct SatHelper int last_timestep = -2; for (auto &info : modelInfo) { - RTLIL::Const value; bool found_undef = false; + RTLIL::Const::Builder value_builder(info.width); for (int i = 0; i < info.width; i++) { - value.bits().push_back(modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0); - if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) - value.bits().back() = RTLIL::State::Sx, found_undef = true; + RTLIL::State bit = modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0; + if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) { + bit = RTLIL::State::Sx; + found_undef = true; + } + value_builder.push_back(bit); } + RTLIL::Const value = value_builder.build(); if (info.timestep != last_timestep) { const char *hline = "---------------------------------------------------------------------------------------------------" @@ -732,13 +736,14 @@ struct SatHelper int last_timestep = -2; for (auto &info : modelInfo) { - RTLIL::Const value; - + RTLIL::Const::Builder value_builder(info.width); for (int i = 0; i < info.width; i++) { - value.bits().push_back(modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0); + RTLIL::State bit = modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0; if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) - value.bits().back() = RTLIL::State::Sx; + bit = RTLIL::State::Sx; + value_builder.push_back(bit); } + RTLIL::Const value = value_builder.build(); if (info.timestep != last_timestep) { if(last_timestep == 0) @@ -779,12 +784,14 @@ struct SatHelper for (auto &info : modelInfo) { - Const value; + RTLIL::Const::Builder value_builder(info.width); for (int i = 0; i < info.width; i++) { - value.bits().push_back(modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0); + RTLIL::State bit = modelValues.at(info.offset+i) ? RTLIL::State::S1 : RTLIL::State::S0; if (enable_undef && modelValues.at(modelExpressions.size()/2 + info.offset + i)) - value.bits().back() = RTLIL::State::Sx; + bit = RTLIL::State::Sx; + value_builder.push_back(bit); } + Const value = value_builder.build(); wavedata[info.description].first = info.width; wavedata[info.description].second[info.timestep] = value; diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 0510bc7df..aadea328f 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -127,16 +127,11 @@ struct SimShared bool initstate = true; }; -void zinit(State &v) -{ - if (v != State::S1) - v = State::S0; -} - void zinit(Const &v) { - for (auto &bit : v.bits()) - zinit(bit); + for (auto bit : v) + if (bit != State::S1) + bit = State::S0; } struct SimInstance @@ -419,16 +414,17 @@ struct SimInstance Const get_state(SigSpec sig) { - Const value; + Const::Builder builder(GetSize(sig)); for (auto bit : sigmap(sig)) if (bit.wire == nullptr) - value.bits().push_back(bit.data); + builder.push_back(bit.data); else if (state_nets.count(bit)) - value.bits().push_back(state_nets.at(bit)); + builder.push_back(state_nets.at(bit)); else - value.bits().push_back(State::Sz); + builder.push_back(State::Sz); + Const value = builder.build(); if (shared->debug) log("[%s] get %s: %s\n", hiername(), log_signal(sig), log_signal(value)); return value; @@ -488,7 +484,7 @@ struct SimInstance for (int i = 0; i < GetSize(data); i++) if (0 <= i+offset && i+offset < state.mem->size * state.mem->width && data[i] != State::Sa) if (state.data[i+offset] != data[i]) - dirty = true, state.data.bits()[i+offset] = data[i]; + dirty = true, state.data.set(i+offset, data[i]); if (dirty) dirty_memories.insert(memid); @@ -500,7 +496,7 @@ struct SimInstance if (offset >= state.mem->size * state.mem->width) log_error("Addressing out of bounds bit %d/%d of memory %s\n", offset, state.mem->size * state.mem->width, log_id(memid)); if (state.data[offset] != data) { - state.data.bits()[offset] = data; + state.data.set(offset, data); dirty_memories.insert(memid); } } @@ -717,10 +713,10 @@ struct SimInstance for(int i=0;i= 0 && index < mem.size) for (int i = 0; i < (mem.width << port.wide_log2); i++) if (enable[i] == State::S1 && mdb.data.at(index*mem.width+i) != data[i]) { - mdb.data.bits().at(index*mem.width+i) = data[i]; + mdb.data.set(index*mem.width+i, data[i]); dirty_memories.insert(mem.memid); did_something = true; } @@ -971,7 +967,7 @@ struct SimInstance if (w->attributes.count(ID::init) == 0) w->attributes[ID::init] = Const(State::Sx, GetSize(w)); - w->attributes[ID::init].bits()[sig_q[i].offset] = initval[i]; + w->attributes[ID::init].set(sig_q[i].offset, initval[i]); } } From 8cc86b264355a35c210660d1bb29a0ab0dba23bc Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:53:51 +0000 Subject: [PATCH 15/60] Update passes/techmap to avoid bits() --- passes/techmap/abc9_ops.cc | 11 +++++++---- passes/techmap/dffinit.cc | 6 +++--- passes/techmap/dfflegalize.cc | 8 ++++---- passes/techmap/flowmap.cc | 2 +- passes/techmap/techmap.cc | 9 +++++---- passes/techmap/zinit.cc | 2 +- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 91149ac55..069b94204 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -1216,7 +1216,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) auto Qi = initmap(Q); auto it = Qi.wire->attributes.find(ID::init); if (it != Qi.wire->attributes.end()) - it->second.bits()[Qi.offset] = State::Sx; + it->second.set(Qi.offset, State::Sx); } else if (cell->type.in(ID($_AND_), ID($_NOT_))) module->remove(cell); @@ -1526,8 +1526,11 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) log_assert(index < GetSize(A)); int i = 0; while (i < GetSize(mask)) { - for (int j = 0; j < (1 << index); j++) - std::swap(mask.bits()[i+j], mask.bits()[i+j+(1 << index)]); + for (int j = 0; j < (1 << index); j++) { + State bit = mask[i+j]; + mask.set(i+j, mask[i+j+(1 << index)]); + mask.set(i+j+(1 << index), bit); + } i += 1 << (index+1); } A[index] = y_bit; @@ -1542,7 +1545,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode) // and get cleaned away clone_lut: driver_mask = driver_lut->getParam(ID::LUT); - for (auto &b : driver_mask.bits()) { + for (auto b : driver_mask) { if (b == RTLIL::State::S0) b = RTLIL::State::S1; else if (b == RTLIL::State::S1) b = RTLIL::State::S0; } diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc index ee83105fd..013675c8a 100644 --- a/passes/techmap/dffinit.cc +++ b/passes/techmap/dffinit.cc @@ -118,13 +118,13 @@ struct DffinitPass : public Pass { for (int i = 0; i < GetSize(sig); i++) { if (initval[i] == State::Sx) continue; - while (GetSize(value) <= i) - value.bits().push_back(State::S0); + if (GetSize(value) <= i) + value.resize(i + 1, State::S0); if (noreinit && value[i] != State::Sx && value[i] != initval[i]) log_error("Trying to assign a different init value for %s.%s.%s which technically " "have a conflicted init value.\n", log_id(module), log_id(cell), log_id(it.second)); - value.bits()[i] = initval[i]; + value.set(i, initval[i]); } if (highlow_mode && GetSize(value) != 0) { diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc index facea2e90..5a622c611 100644 --- a/passes/techmap/dfflegalize.cc +++ b/passes/techmap/dfflegalize.cc @@ -869,17 +869,17 @@ struct DffLegalizePass : public Pass { if (ff.has_arst) { if (ff.val_arst[i] == State::Sx) { if (!(supported & (mask << 8))) - ff.val_arst.bits()[i] = State::S0; + ff.val_arst.set(i, State::S0); if (!(supported & (mask << 4))) - ff.val_arst.bits()[i] = State::S1; + ff.val_arst.set(i, State::S1); } } if (ff.has_srst) { if (ff.val_srst[i] == State::Sx) { if (!(supported & (mask << 8))) - ff.val_srst.bits()[i] = State::S0; + ff.val_srst.set(i, State::S0); if (!(supported & (mask << 4))) - ff.val_srst.bits()[i] = State::S1; + ff.val_srst.set(i, State::S1); } } } diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc index 7fbe54849..f5f225a9b 100644 --- a/passes/techmap/flowmap.cc +++ b/passes/techmap/flowmap.cc @@ -1401,7 +1401,7 @@ struct FlowmapWorker log_signal(node), log_signal(undef), env.c_str()); } - lut_table.bits()[i] = value.as_bool() ? State::S1 : State::S0; + lut_table.set(i, value.as_bool() ? State::S1 : State::S0); ce.pop(); } diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 2a22258b7..30b8e17ab 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -680,15 +680,16 @@ struct TechmapWorker for (auto &conn : cell->connections()) if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first))) != 0) { - RTLIL::Const value; - for (auto &bit : sigmap(conn.second)) { + SigSpec sm = sigmap(conn.second); + RTLIL::Const::Builder builder(GetSize(sm) * bits); + for (auto &bit : sm) { int val = unique_bit_id.at(bit); for (int i = 0; i < bits; i++) { - value.bits().push_back((val & 1) != 0 ? State::S1 : State::S0); + builder.push_back((val & 1) != 0 ? State::S1 : State::S0); val = val >> 1; } } - parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), value); + parameters.emplace(stringf("\\_TECHMAP_CONNMAP_%s_", log_id(conn.first)), builder.build()); } } diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc index bf049eab7..38936e64d 100644 --- a/passes/techmap/zinit.cc +++ b/passes/techmap/zinit.cc @@ -76,7 +76,7 @@ struct ZinitPass : public Pass { if (ff.val_init[i] == State::S1) bits.insert(i); else if (ff.val_init[i] != State::S0 && all_mode) - ff.val_init.bits()[i] = State::S0; + ff.val_init.set(i, State::S0); } ff.flip_bits(bits); ff.emit(); From 159ca3ba569d5e850c8610f9a458ae39d0570e6d Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:54:00 +0000 Subject: [PATCH 16/60] Update passes/tests to avoid bits() --- passes/tests/test_cell.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 286ef757d..75a63b2e0 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -641,15 +641,16 @@ static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std:: if (!gold_wire->port_input) continue; - RTLIL::Const in_value; + RTLIL::Const::Builder in_value_builder(GetSize(gold_wire)); for (int i = 0; i < GetSize(gold_wire); i++) - in_value.bits().push_back(xorshift32(2) ? State::S1 : State::S0); + in_value_builder.push_back(xorshift32(2) ? State::S1 : State::S0); + RTLIL::Const in_value = in_value_builder.build(); if (xorshift32(4) == 0) { int inv_chance = 1 + xorshift32(8); for (int i = 0; i < GetSize(gold_wire); i++) if (xorshift32(inv_chance) == 0) - in_value.bits()[i] = RTLIL::Sx; + in_value.set(i, RTLIL::Sx); } if (verbose) From 7f247fb1256ceca143575127169678eee1d1e1af Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 03:54:13 +0000 Subject: [PATCH 17/60] Update passes/hierarchy to avoid bits() --- passes/hierarchy/submod.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index d77d65359..486d21920 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -79,7 +79,7 @@ struct SubmodWorker flag_wire(c.wire, create, set_int_used, set_ext_driven, set_ext_used); if (set_int_driven) for (int i = c.offset; i < c.offset+c.width; i++) { - wire_flags.at(c.wire).is_int_driven.bits()[i] = State::S1; + wire_flags.at(c.wire).is_int_driven.set(i, State::S1); flag_found_something = true; } } @@ -185,8 +185,8 @@ struct SubmodWorker auto it = sig[i].wire->attributes.find(ID::init); if (it != sig[i].wire->attributes.end()) { auto jt = new_wire->attributes.insert(std::make_pair(ID::init, Const(State::Sx, GetSize(sig)))).first; - jt->second.bits()[i] = it->second[sig[i].offset]; - it->second.bits()[sig[i].offset] = State::Sx; + jt->second.set(i, it->second[sig[i].offset]); + it->second.set(sig[i].offset, State::Sx); } } } From 6dc9a8bacfdb9f5c63a420b1aa12afd0f3387301 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 01:55:47 +0000 Subject: [PATCH 18/60] Update kernel to avoid bits() --- kernel/bitpattern.h | 2 +- kernel/calc.cc | 92 +++++++++++++++++++------------------------ kernel/celltypes.h | 8 ++-- kernel/consteval.h | 4 +- kernel/drivertools.cc | 9 ++--- kernel/ff.cc | 31 +++++++++++---- kernel/ffinit.h | 10 ++--- kernel/ffmerge.cc | 24 +++++------ kernel/macc.h | 2 +- kernel/mem.cc | 73 ++++++++++++++++++++++------------ kernel/mem.h | 6 ++- kernel/rtlil.cc | 2 +- kernel/tclapi.cc | 7 ++-- kernel/yw.cc | 3 +- 14 files changed, 151 insertions(+), 122 deletions(-) diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h index 0e12e6dce..e2071436c 100644 --- a/kernel/bitpattern.h +++ b/kernel/bitpattern.h @@ -100,7 +100,7 @@ struct BitPatternPool bits_t sig2bits(RTLIL::SigSpec sig) { bits_t bits; - bits.bitdata = sig.as_const().bits(); + bits.bitdata = sig.as_const().to_bits(); for (auto &b : bits.bitdata) if (b > RTLIL::State::S1) b = RTLIL::State::Sa; diff --git a/kernel/calc.cc b/kernel/calc.cc index f08c97396..9b0885db9 100644 --- a/kernel/calc.cc +++ b/kernel/calc.cc @@ -33,10 +33,7 @@ static void extend_u0(RTLIL::Const &arg, int width, bool is_signed) if (arg.size() > 0 && is_signed) padding = arg.back(); - while (GetSize(arg) < width) - arg.bits().push_back(padding); - - arg.bits().resize(width); + arg.resize(width, padding); } static BigInteger const2big(const RTLIL::Const &val, bool as_signed, int &undef_bit_pos) @@ -79,12 +76,12 @@ static RTLIL::Const big2const(const BigInteger &val, int result_len, int undef_b { mag--; for (auto i = 0; i < result_len; i++) - result.bits()[i] = mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1; + result.set(i, mag.getBit(i) ? RTLIL::State::S0 : RTLIL::State::S1); } else { for (auto i = 0; i < result_len; i++) - result.bits()[i] = mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0; + result.set(i, mag.getBit(i) ? RTLIL::State::S1 : RTLIL::State::S0); } } @@ -140,11 +137,11 @@ RTLIL::Const RTLIL::const_not(const RTLIL::Const &arg1, const RTLIL::Const&, boo RTLIL::Const result(RTLIL::State::Sx, result_len); for (auto i = 0; i < result_len; i++) { if (i >= GetSize(arg1_ext)) - result.bits()[i] = RTLIL::State::S0; - else if (arg1_ext.bits()[i] == RTLIL::State::S0) - result.bits()[i] = RTLIL::State::S1; - else if (arg1_ext.bits()[i] == RTLIL::State::S1) - result.bits()[i] = RTLIL::State::S0; + result.set(i, RTLIL::State::S0); + else if (arg1_ext[i] == RTLIL::State::S0) + result.set(i, RTLIL::State::S1); + else if (arg1_ext[i] == RTLIL::State::S1) + result.set(i, RTLIL::State::S0); } return result; @@ -161,9 +158,9 @@ static RTLIL::Const logic_wrapper(RTLIL::State(*logic_func)(RTLIL::State, RTLIL: RTLIL::Const result(RTLIL::State::Sx, result_len); for (auto i = 0; i < result_len; i++) { - RTLIL::State a = i < GetSize(arg1) ? arg1.bits()[i] : RTLIL::State::S0; - RTLIL::State b = i < GetSize(arg2) ? arg2.bits()[i] : RTLIL::State::S0; - result.bits()[i] = logic_func(a, b); + RTLIL::State a = i < GetSize(arg1) ? arg1[i] : RTLIL::State::S0; + RTLIL::State b = i < GetSize(arg2) ? arg2[i] : RTLIL::State::S0; + result.set(i, logic_func(a, b)); } return result; @@ -197,8 +194,8 @@ static RTLIL::Const logic_reduce_wrapper(RTLIL::State initial, RTLIL::State(*log temp = logic_func(temp, arg1[i]); RTLIL::Const result(temp); - while (GetSize(result) < result_len) - result.bits().push_back(RTLIL::State::S0); + if (GetSize(result) < result_len) + result.resize(result_len, RTLIL::State::S0); return result; } @@ -222,9 +219,9 @@ RTLIL::Const RTLIL::const_reduce_xnor(const RTLIL::Const &arg1, const RTLIL::Con RTLIL::Const buffer = logic_reduce_wrapper(RTLIL::State::S0, logic_xor, arg1, result_len); if (!buffer.empty()) { if (buffer.front() == RTLIL::State::S0) - buffer.bits().front() = RTLIL::State::S1; + buffer.set(0, RTLIL::State::S1); else if (buffer.front() == RTLIL::State::S1) - buffer.bits().front() = RTLIL::State::S0; + buffer.set(0, RTLIL::State::S0); } return buffer; } @@ -239,9 +236,8 @@ RTLIL::Const RTLIL::const_logic_not(const RTLIL::Const &arg1, const RTLIL::Const int undef_bit_pos_a = -1; BigInteger a = const2big(arg1, signed1, undef_bit_pos_a); RTLIL::Const result(a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S1 : RTLIL::State::S0); - - while (GetSize(result) < result_len) - result.bits().push_back(RTLIL::State::S0); + if (GetSize(result) < result_len) + result.resize(result_len, RTLIL::State::S0); return result; } @@ -254,9 +250,8 @@ RTLIL::Const RTLIL::const_logic_and(const RTLIL::Const &arg1, const RTLIL::Const RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; RTLIL::Const result(logic_and(bit_a, bit_b)); - - while (GetSize(result) < result_len) - result.bits().push_back(RTLIL::State::S0); + if (GetSize(result) < result_len) + result.resize(result_len, RTLIL::State::S0); return result; } @@ -269,9 +264,8 @@ RTLIL::Const RTLIL::const_logic_or(const RTLIL::Const &arg1, const RTLIL::Const RTLIL::State bit_a = a.isZero() ? undef_bit_pos_a >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; RTLIL::State bit_b = b.isZero() ? undef_bit_pos_b >= 0 ? RTLIL::State::Sx : RTLIL::State::S0 : RTLIL::State::S1; RTLIL::Const result(logic_or(bit_a, bit_b)); - - while (GetSize(result) < result_len) - result.bits().push_back(RTLIL::State::S0); + if (GetSize(result) < result_len) + result.resize(result_len, RTLIL::State::S0); return result; } @@ -295,11 +289,11 @@ static RTLIL::Const const_shift_worker(const RTLIL::Const &arg1, const RTLIL::Co for (int i = 0; i < result_len; i++) { BigInteger pos = BigInteger(i) + offset; if (pos < 0) - result.bits()[i] = vacant_bits; + result.set(i, vacant_bits); else if (pos >= BigInteger(GetSize(arg1))) - result.bits()[i] = sign_ext ? arg1.back() : vacant_bits; + result.set(i, sign_ext ? arg1.back() : vacant_bits); else - result.bits()[i] = arg1[pos.toInt()]; + result.set(i, arg1[pos.toInt()]); } return result; @@ -346,9 +340,8 @@ RTLIL::Const RTLIL::const_lt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, int undef_bit_pos = -1; bool y = const2big(arg1, signed1, undef_bit_pos) < const2big(arg2, signed2, undef_bit_pos); RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); - - while (GetSize(result) < result_len) - result.bits().push_back(RTLIL::State::S0); + if (GetSize(result) < result_len) + result.resize(result_len, RTLIL::State::S0); return result; } @@ -357,9 +350,8 @@ RTLIL::Const RTLIL::const_le(const RTLIL::Const &arg1, const RTLIL::Const &arg2, int undef_bit_pos = -1; bool y = const2big(arg1, signed1, undef_bit_pos) <= const2big(arg2, signed2, undef_bit_pos); RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); - - while (GetSize(result) < result_len) - result.bits().push_back(RTLIL::State::S0); + if (GetSize(result) < result_len) + result.resize(result_len, RTLIL::State::S0); return result; } @@ -383,7 +375,7 @@ RTLIL::Const RTLIL::const_eq(const RTLIL::Const &arg1, const RTLIL::Const &arg2, matched_status = RTLIL::State::Sx; } - result.bits().front() = matched_status; + result.set(0, matched_status); return result; } @@ -391,9 +383,9 @@ RTLIL::Const RTLIL::const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2, { RTLIL::Const result = RTLIL::const_eq(arg1, arg2, signed1, signed2, result_len); if (result.front() == RTLIL::State::S0) - result.bits().front() = RTLIL::State::S1; + result.set(0, RTLIL::State::S1); else if (result.front() == RTLIL::State::S1) - result.bits().front() = RTLIL::State::S0; + result.set(0, RTLIL::State::S0); return result; } @@ -412,7 +404,7 @@ RTLIL::Const RTLIL::const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2 return result; } - result.bits().front() = RTLIL::State::S1; + result.set(0, RTLIL::State::S1); return result; } @@ -420,9 +412,9 @@ RTLIL::Const RTLIL::const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2 { RTLIL::Const result = RTLIL::const_eqx(arg1, arg2, signed1, signed2, result_len); if (result.front() == RTLIL::State::S0) - result.bits().front() = RTLIL::State::S1; + result.set(0, RTLIL::State::S1); else if (result.front() == RTLIL::State::S1) - result.bits().front() = RTLIL::State::S0; + result.set(0, RTLIL::State::S0); return result; } @@ -431,9 +423,8 @@ RTLIL::Const RTLIL::const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, int undef_bit_pos = -1; bool y = const2big(arg1, signed1, undef_bit_pos) >= const2big(arg2, signed2, undef_bit_pos); RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); - - while (GetSize(result) < result_len) - result.bits().push_back(RTLIL::State::S0); + if (GetSize(result) < result_len) + result.resize(result_len, RTLIL::State::S0); return result; } @@ -442,9 +433,8 @@ RTLIL::Const RTLIL::const_gt(const RTLIL::Const &arg1, const RTLIL::Const &arg2, int undef_bit_pos = -1; bool y = const2big(arg1, signed1, undef_bit_pos) > const2big(arg2, signed2, undef_bit_pos); RTLIL::Const result(undef_bit_pos >= 0 ? RTLIL::State::Sx : y ? RTLIL::State::S1 : RTLIL::State::S0); - - while (GetSize(result) < result_len) - result.bits().push_back(RTLIL::State::S0); + if (GetSize(result) < result_len) + result.resize(result_len, RTLIL::State::S0); return result; } @@ -628,7 +618,7 @@ RTLIL::Const RTLIL::const_mux(const RTLIL::Const &arg1, const RTLIL::Const &arg2 RTLIL::Const ret = arg1; for (auto i = 0; i < ret.size(); i++) if (ret[i] != arg2[i]) - ret.bits()[i] = State::Sx; + ret.set(i, State::Sx); return ret; } @@ -703,7 +693,7 @@ RTLIL::Const RTLIL::const_bweqx(const RTLIL::Const &arg1, const RTLIL::Const &ar log_assert(arg2.size() == arg1.size()); RTLIL::Const result(RTLIL::State::S0, arg1.size()); for (auto i = 0; i < arg1.size(); i++) - result.bits()[i] = arg1[i] == arg2[i] ? State::S1 : State::S0; + result.set(i, arg1[i] == arg2[i] ? State::S1 : State::S0); return result; } @@ -715,7 +705,7 @@ RTLIL::Const RTLIL::const_bwmux(const RTLIL::Const &arg1, const RTLIL::Const &ar RTLIL::Const result(RTLIL::State::Sx, arg1.size()); for (auto i = 0; i < arg1.size(); i++) { if (arg3[i] != State::Sx || arg1[i] == arg2[i]) - result.bits()[i] = arg3[i] == State::S1 ? arg2[i] : arg1[i]; + result.set(i, arg3[i] == State::S1 ? arg2[i] : arg1[i]); } return result; diff --git a/kernel/celltypes.h b/kernel/celltypes.h index f08a695e9..469017029 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -328,7 +328,7 @@ struct CellTypes static RTLIL::Const eval_not(RTLIL::Const v) { - for (auto &bit : v.bits()) + for (auto bit : v) if (bit == State::S0) bit = State::S1; else if (bit == State::S1) bit = State::S0; return v; @@ -421,16 +421,14 @@ struct CellTypes static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool *errp = nullptr) { if (cell->type == ID($slice)) { - RTLIL::Const ret; int width = cell->parameters.at(ID::Y_WIDTH).as_int(); int offset = cell->parameters.at(ID::OFFSET).as_int(); - ret.bits().insert(ret.bits().end(), arg1.begin()+offset, arg1.begin()+offset+width); - return ret; + return arg1.extract(offset, width); } if (cell->type == ID($concat)) { RTLIL::Const ret = arg1; - ret.bits().insert(ret.bits().end(), arg2.begin(), arg2.end()); + ret.append(arg2); return ret; } diff --git a/kernel/consteval.h b/kernel/consteval.h index adcf86f8a..b13c7ea5c 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -115,7 +115,7 @@ struct ConstEval for (int i = 0; i < GetSize(coval); i++) { carry = (sig_g[i] == State::S1) || (sig_p[i] == RTLIL::S1 && carry); - coval.bits()[i] = carry ? State::S1 : State::S0; + coval.set(i, carry ? State::S1 : State::S0); } set(sig_co, coval); @@ -249,7 +249,7 @@ struct ConstEval for (int i = 0; i < GetSize(val_y); i++) if (val_y[i] == RTLIL::Sx) - val_x.bits()[i] = RTLIL::Sx; + val_x.set(i, RTLIL::Sx); set(sig_y, val_y); set(sig_x, val_x); diff --git a/kernel/drivertools.cc b/kernel/drivertools.cc index 6290f4470..90bfb0ee7 100644 --- a/kernel/drivertools.cc +++ b/kernel/drivertools.cc @@ -260,7 +260,7 @@ bool DriveChunkMultiple::try_append(DriveBitMultiple const &bit) switch (single.type()) { case DriveType::CONSTANT: { - single.constant().bits().push_back(constant); + single.constant().append(RTLIL::Const(constant)); } break; case DriveType::WIRE: { single.wire().width += 1; @@ -295,8 +295,7 @@ bool DriveChunkMultiple::try_append(DriveChunkMultiple const &chunk) switch (single.type()) { case DriveType::CONSTANT: { - auto &bits = single.constant().bits(); - bits.insert(bits.end(), constant.bits().begin(), constant.bits().end()); + single.constant().append(constant); } break; case DriveType::WIRE: { single.wire().width += width; @@ -349,7 +348,7 @@ bool DriveChunk::try_append(DriveBit const &bit) none_ += 1; return true; case DriveType::CONSTANT: - constant_.bits().push_back(bit.constant()); + constant_.append(RTLIL::Const(bit.constant())); return true; case DriveType::WIRE: return wire_.try_append(bit.wire()); @@ -375,7 +374,7 @@ bool DriveChunk::try_append(DriveChunk const &chunk) none_ += chunk.none_; return true; case DriveType::CONSTANT: - constant_.bits().insert(constant_.bits().end(), chunk.constant_.begin(), chunk.constant_.end()); + constant_.append(chunk.constant_); return true; case DriveType::WIRE: return wire_.try_append(chunk.wire()); diff --git a/kernel/ff.cc b/kernel/ff.cc index 8b38b84cb..a72e6a65c 100644 --- a/kernel/ff.cc +++ b/kernel/ff.cc @@ -287,6 +287,16 @@ FfData FfData::slice(const std::vector &bits) { res.pol_clr = pol_clr; res.pol_set = pol_set; res.attributes = attributes; + std::optional arst_bits; + if (has_arst) + arst_bits.emplace(bits.size()); + std::optional srst_bits; + if (has_srst) + srst_bits.emplace(bits.size()); + std::optional init_bits; + if (initvals) + init_bits.emplace(bits.size()); + for (int i : bits) { res.sig_q.append(sig_q[i]); if (has_clk || has_gclk) @@ -298,12 +308,19 @@ FfData FfData::slice(const std::vector &bits) { res.sig_set.append(sig_set[i]); } if (has_arst) - res.val_arst.bits().push_back(val_arst[i]); + arst_bits->push_back(val_arst[i]); if (has_srst) - res.val_srst.bits().push_back(val_srst[i]); + srst_bits->push_back(val_srst[i]); if (initvals) - res.val_init.bits().push_back(val_init[i]); + init_bits->push_back(val_init[i]); } + + if (has_arst) + res.val_arst = arst_bits->build(); + if (has_srst) + res.val_srst = srst_bits->build(); + if (initvals) + res.val_init = init_bits->build(); res.width = GetSize(res.sig_q); return res; } @@ -688,10 +705,10 @@ void FfData::flip_rst_bits(const pool &bits) { for (auto bit: bits) { if (has_arst) - val_arst.bits()[bit] = invert(val_arst[bit]); + val_arst.set(bit, invert(val_arst[bit])); if (has_srst) - val_srst.bits()[bit] = invert(val_srst[bit]); - val_init.bits()[bit] = invert(val_init[bit]); + val_srst.set(bit, invert(val_srst[bit])); + val_init.set(bit, invert(val_init[bit])); } } @@ -760,7 +777,7 @@ void FfData::flip_bits(const pool &bits) { Const mask = Const(State::S0, width); for (auto bit: bits) - mask.bits()[bit] = State::S1; + mask.set(bit, State::S1); if (has_clk || has_gclk) sig_d = module->Xor(NEW_ID, sig_d, mask); diff --git a/kernel/ffinit.h b/kernel/ffinit.h index 66c13b68f..920fba307 100644 --- a/kernel/ffinit.h +++ b/kernel/ffinit.h @@ -74,10 +74,10 @@ struct FfInitVals RTLIL::Const operator()(const RTLIL::SigSpec &sig) const { - RTLIL::Const res; + RTLIL::Const::Builder res_bits(GetSize(sig)); for (auto bit : sig) - res.bits().push_back((*this)(bit)); - return res; + res_bits.push_back((*this)(bit)); + return res_bits.build(); } void set_init(RTLIL::SigBit bit, RTLIL::State val) @@ -93,12 +93,12 @@ struct FfInitVals initbits[mbit] = std::make_pair(val,abit); auto it2 = abit.wire->attributes.find(ID::init); if (it2 != abit.wire->attributes.end()) { - it2->second.bits()[abit.offset] = val; + it2->second.set(abit.offset, val); if (it2->second.is_fully_undef()) abit.wire->attributes.erase(it2); } else if (val != State::Sx) { Const cval(State::Sx, GetSize(abit.wire)); - cval.bits()[abit.offset] = val; + cval.set(abit.offset, val); abit.wire->attributes[ID::init] = cval; } } diff --git a/kernel/ffmerge.cc b/kernel/ffmerge.cc index 3b361c1c2..632cba05c 100644 --- a/kernel/ffmerge.cc +++ b/kernel/ffmerge.cc @@ -42,9 +42,9 @@ bool FfMergeHelper::find_output_ff(RTLIL::SigSpec sig, FfData &ff, poolparameters[ID::WIDTH] = Const(width); cell->parameters[ID::OFFSET] = Const(start_offset); cell->parameters[ID::SIZE] = Const(size); - Const rd_wide_continuation, rd_clk_enable, rd_clk_polarity, rd_transparency_mask, rd_collision_x_mask; - Const wr_wide_continuation, wr_clk_enable, wr_clk_polarity, wr_priority_mask; - Const rd_ce_over_srst, rd_arst_value, rd_srst_value, rd_init_value; SigSpec rd_clk, rd_en, rd_addr, rd_data; SigSpec wr_clk, wr_en, wr_addr, wr_data; SigSpec rd_arst, rd_srst; @@ -147,6 +144,15 @@ void Mem::emit() { for (int i = 0; i < GetSize(wr_ports); i++) for (int j = 0; j < (1 << wr_ports[i].wide_log2); j++) wr_port_xlat.push_back(i); + Const::Builder rd_wide_continuation_builder; + Const::Builder rd_clk_enable_builder; + Const::Builder rd_clk_polarity_builder; + Const::Builder rd_transparency_mask_builder; + Const::Builder rd_collision_x_mask_builder; + Const::Builder rd_ce_over_srst_builder; + Const::Builder rd_arst_value_builder; + Const::Builder rd_srst_value_builder; + Const::Builder rd_init_value_builder; for (auto &port : rd_ports) { for (auto attr: port.attributes) if (!cell->has_attribute(attr.first)) @@ -157,10 +163,10 @@ void Mem::emit() { } for (int sub = 0; sub < (1 << port.wide_log2); sub++) { - rd_wide_continuation.bits().push_back(State(sub != 0)); - rd_clk_enable.bits().push_back(State(port.clk_enable)); - rd_clk_polarity.bits().push_back(State(port.clk_polarity)); - rd_ce_over_srst.bits().push_back(State(port.ce_over_srst)); + rd_wide_continuation_builder.push_back(State(sub != 0)); + rd_clk_enable_builder.push_back(State(port.clk_enable)); + rd_clk_polarity_builder.push_back(State(port.clk_polarity)); + rd_ce_over_srst_builder.push_back(State(port.ce_over_srst)); rd_clk.append(port.clk); rd_arst.append(port.arst); rd_srst.append(port.srst); @@ -170,18 +176,27 @@ void Mem::emit() { rd_addr.append(addr); log_assert(GetSize(addr) == abits); for (auto idx : wr_port_xlat) { - rd_transparency_mask.bits().push_back(State(bool(port.transparency_mask[idx]))); - rd_collision_x_mask.bits().push_back(State(bool(port.collision_x_mask[idx]))); + rd_transparency_mask_builder.push_back(State(bool(port.transparency_mask[idx]))); + rd_collision_x_mask_builder.push_back(State(bool(port.collision_x_mask[idx]))); } } rd_data.append(port.data); for (auto bit : port.arst_value) - rd_arst_value.bits().push_back(bit); + rd_arst_value_builder.push_back(bit); for (auto bit : port.srst_value) - rd_srst_value.bits().push_back(bit); + rd_srst_value_builder.push_back(bit); for (auto bit : port.init_value) - rd_init_value.bits().push_back(bit); + rd_init_value_builder.push_back(bit); } + Const rd_wide_continuation = rd_wide_continuation_builder.build(); + Const rd_clk_enable = rd_clk_enable_builder.build(); + Const rd_clk_polarity = rd_clk_polarity_builder.build(); + Const rd_transparency_mask = rd_transparency_mask_builder.build(); + Const rd_collision_x_mask = rd_collision_x_mask_builder.build(); + Const rd_ce_over_srst = rd_ce_over_srst_builder.build(); + Const rd_arst_value = rd_arst_value_builder.build(); + Const rd_srst_value = rd_srst_value_builder.build(); + Const rd_init_value = rd_init_value_builder.build(); if (rd_ports.empty()) { rd_wide_continuation = State::S0; rd_clk_enable = State::S0; @@ -212,6 +227,10 @@ void Mem::emit() { cell->setPort(ID::RD_SRST, rd_srst); cell->setPort(ID::RD_ADDR, rd_addr); cell->setPort(ID::RD_DATA, rd_data); + Const::Builder wr_wide_continuation_builder; + Const::Builder wr_clk_enable_builder; + Const::Builder wr_clk_polarity_builder; + Const::Builder wr_priority_mask_builder; for (auto &port : wr_ports) { for (auto attr: port.attributes) if (!cell->has_attribute(attr.first)) @@ -222,12 +241,12 @@ void Mem::emit() { } for (int sub = 0; sub < (1 << port.wide_log2); sub++) { - wr_wide_continuation.bits().push_back(State(sub != 0)); - wr_clk_enable.bits().push_back(State(port.clk_enable)); - wr_clk_polarity.bits().push_back(State(port.clk_polarity)); + wr_wide_continuation_builder.push_back(State(sub != 0)); + wr_clk_enable_builder.push_back(State(port.clk_enable)); + wr_clk_polarity_builder.push_back(State(port.clk_polarity)); wr_clk.append(port.clk); for (auto idx : wr_port_xlat) - wr_priority_mask.bits().push_back(State(bool(port.priority_mask[idx]))); + wr_priority_mask_builder.push_back(State(bool(port.priority_mask[idx]))); SigSpec addr = port.sub_addr(sub); addr.extend_u0(abits, false); wr_addr.append(addr); @@ -236,6 +255,10 @@ void Mem::emit() { wr_en.append(port.en); wr_data.append(port.data); } + Const wr_wide_continuation = wr_wide_continuation_builder.build(); + Const wr_clk_enable = wr_clk_enable_builder.build(); + Const wr_clk_polarity = wr_clk_polarity_builder.build(); + Const wr_priority_mask = wr_priority_mask_builder.build(); if (wr_ports.empty()) { wr_wide_continuation = State::S0; wr_clk_enable = State::S0; @@ -414,7 +437,7 @@ void Mem::coalesce_inits() { if (!init.en.is_fully_ones()) { for (int i = 0; i < GetSize(init.data); i++) if (init.en[i % width] != State::S1) - init.data.bits()[i] = State::Sx; + init.data.set(i, State::Sx); init.en = Const(State::S1, width); } continue; @@ -427,7 +450,7 @@ void Mem::coalesce_inits() { log_assert(offset + GetSize(init.data) <= GetSize(cdata)); for (int i = 0; i < GetSize(init.data); i++) if (init.en[i % width] == State::S1) - cdata.bits()[i+offset] = init.data[i]; + cdata.set(i+offset, init.data[i]); init.removed = true; } MemInit new_init; @@ -446,7 +469,7 @@ Const Mem::get_init_data() const { int offset = (init.addr.as_int() - start_offset) * width; for (int i = 0; i < GetSize(init.data); i++) if (0 <= i+offset && i+offset < GetSize(init_data) && init.en[i % width] == State::S1) - init_data.bits()[i+offset] = init.data[i]; + init_data.set(i+offset, init.data[i]); } return init_data; } @@ -1700,7 +1723,7 @@ MemContents::MemContents(Mem *mem) : RTLIL::Const previous = (*this)[addr + i]; for(int j = 0; j < _data_width; j++) if(init.en[j] != State::S1) - data.bits()[_data_width * i + j] = previous[j]; + data.set(_data_width * i + j, previous[j]); } insert_concatenated(init.addr.as_int(), data); } @@ -1846,7 +1869,7 @@ std::map::iterator MemContents::_reserve_rang // we have two different ranges touching at either end, we need to merge them auto upper_end = _range_end(upper_it); // make range bigger (maybe reserve here instead of resize?) - lower_it->second.bits().resize(_range_offset(lower_it, upper_end), State::Sx); + lower_it->second.resize(_range_offset(lower_it, upper_end), State::Sx); // copy only the data beyond our range std::copy(_range_data(upper_it, end_addr), _range_data(upper_it, upper_end), _range_data(lower_it, end_addr)); // keep lower_it, but delete upper_it @@ -1854,16 +1877,16 @@ std::map::iterator MemContents::_reserve_rang return lower_it; } else if (lower_touch) { // we have a range to the left, just make it bigger and delete any other that may exist. - lower_it->second.bits().resize(_range_offset(lower_it, end_addr), State::Sx); + lower_it->second.resize(_range_offset(lower_it, end_addr), State::Sx); // keep lower_it and upper_it _values.erase(std::next(lower_it), upper_it); return lower_it; } else if (upper_touch) { // we have a range to the right, we need to expand it // since we need to erase and reinsert to a new address, steal the data - RTLIL::Const data = std::move(upper_it->second); // note that begin_addr is not in upper_it, otherwise the whole range covered check would have tripped - data.bits().insert(data.bits().begin(), (_range_begin(upper_it) - begin_addr) * _data_width, State::Sx); + RTLIL::Const data(State::Sx, (_range_begin(upper_it) - begin_addr) * _data_width); + data.append(std::move(upper_it->second)); // delete lower_it and upper_it, then reinsert _values.erase(lower_it, std::next(upper_it)); return _values.emplace(begin_addr, std::move(data)).first; @@ -1886,7 +1909,7 @@ void MemContents::insert_concatenated(addr_t addr, RTLIL::Const const &values) { std::fill(to_begin + values.size(), to_begin + words * _data_width, State::S0); } -std::vector::iterator MemContents::_range_write(std::vector::iterator it, RTLIL::Const const &word) { +RTLIL::Const::iterator MemContents::_range_write(RTLIL::Const::iterator it, RTLIL::Const const &word) { auto from_end = word.size() <= _data_width ? word.end() : word.begin() + _data_width; auto to_end = std::copy(word.begin(), from_end, it); auto it_next = std::next(it, _data_width); diff --git a/kernel/mem.h b/kernel/mem.h index a06f44bd8..b35ea52c7 100644 --- a/kernel/mem.h +++ b/kernel/mem.h @@ -255,11 +255,13 @@ private: // return the offset the addr would have in the range at `it` size_t _range_offset(std::map::iterator it, addr_t addr) const { return (addr - it->first) * _data_width; } // assuming _range_contains(it, addr), return an iterator pointing to the data at addr - std::vector::iterator _range_data(std::map::iterator it, addr_t addr) { return it->second.bits().begin() + _range_offset(it, addr); } + RTLIL::Const::iterator _range_data(std::map::iterator it, addr_t addr) { + return RTLIL::Const::iterator(it->second, _range_offset(it, addr)); + } // internal version of reserve_range that returns an iterator to the range std::map::iterator _reserve_range(addr_t begin_addr, addr_t end_addr); // write a single word at addr, return iterator to next word - std::vector::iterator _range_write(std::vector::iterator it, RTLIL::Const const &data); + RTLIL::Const::iterator _range_write(RTLIL::Const::iterator it, RTLIL::Const const &data); public: class range { int _data_width; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 8d7f89650..62f7ae4f7 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -486,7 +486,7 @@ int RTLIL::Const::get_min_size(bool is_signed) const void RTLIL::Const::compress(bool is_signed) { auto idx = get_min_size(is_signed); - bits().erase(bits().begin() + idx, bits().end()); + resize(idx, RTLIL::State::S0); } std::optional RTLIL::Const::as_int_compress(bool is_signed) const diff --git a/kernel/tclapi.cc b/kernel/tclapi.cc index 4bdb680ac..729d06ca0 100644 --- a/kernel/tclapi.cc +++ b/kernel/tclapi.cc @@ -214,18 +214,19 @@ bool mp_int_to_const(mp_int *a, Const &b, bool is_signed) buf.resize(mp_unsigned_bin_size(a)); mp_to_unsigned_bin(a, buf.data()); - b.bits().reserve(mp_count_bits(a) + is_signed); + Const::Builder b_bits(mp_count_bits(a) + is_signed); for (int i = 0; i < mp_count_bits(a);) { for (int j = 0; j < 8 && i < mp_count_bits(a); j++, i++) { bool bv = ((buf.back() & (1 << j)) != 0) ^ negative; - b.bits().push_back(bv ? RTLIL::S1 : RTLIL::S0); + b_bits.push_back(bv ? RTLIL::S1 : RTLIL::S0); } buf.pop_back(); } if (is_signed) { - b.bits().push_back(negative ? RTLIL::S1 : RTLIL::S0); + b_bits.push_back(negative ? RTLIL::S1 : RTLIL::S0); } + b = b_bits.build(); return true; } diff --git a/kernel/yw.cc b/kernel/yw.cc index daad53380..560f7dd38 100644 --- a/kernel/yw.cc +++ b/kernel/yw.cc @@ -185,7 +185,6 @@ RTLIL::Const ReadWitness::get_bits(int t, int bits_offset, int width) const const std::string &bits = steps[t].bits; RTLIL::Const result(State::Sa, width); - result.bits().reserve(width); int read_begin = GetSize(bits) - 1 - bits_offset; int read_end = max(-1, read_begin - width); @@ -200,7 +199,7 @@ RTLIL::Const ReadWitness::get_bits(int t, int bits_offset, int width) const default: log_abort(); } - result.bits()[j] = bit; + result.set(j, bit); } return result; From 09b493cfcd6ec79320e9a1f660b93ebd6a80085e Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 01:55:56 +0000 Subject: [PATCH 19/60] Update techlibs to avoid bits() --- techlibs/gatemate/gatemate_foldinv.cc | 4 ++-- techlibs/greenpak4/greenpak4_dffinv.cc | 8 ++++---- techlibs/microchip/microchip_dffopt.cc | 2 +- techlibs/microchip/microchip_dsp.cc | 4 ++-- techlibs/quicklogic/ql_dsp_simd.cc | 6 ++---- techlibs/xilinx/xilinx_dffopt.cc | 6 +++--- techlibs/xilinx/xilinx_dsp.cc | 8 ++++---- techlibs/xilinx/xilinx_srl.cc | 10 ++++------ 8 files changed, 22 insertions(+), 26 deletions(-) diff --git a/techlibs/gatemate/gatemate_foldinv.cc b/techlibs/gatemate/gatemate_foldinv.cc index cce5d2c4f..1af6a8987 100644 --- a/techlibs/gatemate/gatemate_foldinv.cc +++ b/techlibs/gatemate/gatemate_foldinv.cc @@ -82,7 +82,7 @@ struct FoldInvWorker { Const result(State::S0, GetSize(lut)); for (int i = 0; i < GetSize(lut); i++) { int j = i ^ (1 << bit); - result.bits()[j] = lut[i]; + result.set(j, lut[i]); } return result; } @@ -91,7 +91,7 @@ struct FoldInvWorker { { Const result(State::S0, GetSize(lut)); for (int i = 0; i < GetSize(lut); i++) - result.bits()[i] = (lut[i] == State::S1) ? State::S0 : State::S1; + result.set(i, (lut[i] == State::S1) ? State::S0 : State::S1); return result; } diff --git a/techlibs/greenpak4/greenpak4_dffinv.cc b/techlibs/greenpak4/greenpak4_dffinv.cc index 37f6d8d9b..4f60a5c37 100644 --- a/techlibs/greenpak4/greenpak4_dffinv.cc +++ b/techlibs/greenpak4/greenpak4_dffinv.cc @@ -36,9 +36,9 @@ void invert_gp_dff(Cell *cell, bool invert_input) Const initval = cell->getParam(ID::INIT); if (GetSize(initval) >= 1) { if (initval[0] == State::S0) - initval.bits()[0] = State::S1; + initval.set(0, State::S1); else if (initval[0] == State::S1) - initval.bits()[0] = State::S0; + initval.set(0, State::S0); cell->setParam(ID::INIT, initval); } @@ -47,9 +47,9 @@ void invert_gp_dff(Cell *cell, bool invert_input) Const srmode = cell->getParam(ID(SRMODE)); if (GetSize(srmode) >= 1) { if (srmode[0] == State::S0) - srmode.bits()[0] = State::S1; + srmode.set(0, State::S1); else if (srmode[0] == State::S1) - srmode.bits()[0] = State::S0; + srmode.set(0, State::S0); cell->setParam(ID(SRMODE), srmode); } } diff --git a/techlibs/microchip/microchip_dffopt.cc b/techlibs/microchip/microchip_dffopt.cc index 8a13c4325..98e2f17a7 100644 --- a/techlibs/microchip/microchip_dffopt.cc +++ b/techlibs/microchip/microchip_dffopt.cc @@ -93,7 +93,7 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); new_bit = data.first[lut_idx] == State::S1; } - result.first.bits()[i] = new_bit ? State::S1 : State::S0; + result.first.set(i, new_bit ? State::S1 : State::S0); } return true; } diff --git a/techlibs/microchip/microchip_dsp.cc b/techlibs/microchip/microchip_dsp.cc index 3dfcb8905..df7093bc5 100644 --- a/techlibs/microchip/microchip_dsp.cc +++ b/techlibs/microchip/microchip_dsp.cc @@ -128,7 +128,7 @@ void microchip_dsp_pack(microchip_dsp_pm &pm) continue; for (int i = c.offset; i < c.offset + c.width; i++) { log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); - it->second.bits()[i] = State::Sx; + it->second.set(i, State::Sx); } } }; @@ -244,7 +244,7 @@ void microchip_dsp_packC(microchip_dsp_CREG_pm &pm) continue; for (int i = c.offset; i < c.offset + c.width; i++) { log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); - it->second.bits()[i] = State::Sx; + it->second.set(i, State::Sx); } } }; diff --git a/techlibs/quicklogic/ql_dsp_simd.cc b/techlibs/quicklogic/ql_dsp_simd.cc index fdd2de406..cd509ce7f 100644 --- a/techlibs/quicklogic/ql_dsp_simd.cc +++ b/techlibs/quicklogic/ql_dsp_simd.cc @@ -200,10 +200,8 @@ struct QlDspSimdPass : public Pass { auto val_a = dsp_a->getParam(it); auto val_b = dsp_b->getParam(it); - mode_bits.bits().insert(mode_bits.bits().end(), - val_a.begin(), val_a.end()); - mode_bits.bits().insert(mode_bits.bits().end(), - val_b.begin(), val_b.end()); + mode_bits.append(val_a); + mode_bits.append(val_b); } // Enable the fractured mode by connecting the control diff --git a/techlibs/xilinx/xilinx_dffopt.cc b/techlibs/xilinx/xilinx_dffopt.cc index bca3deef9..8a6d3e015 100644 --- a/techlibs/xilinx/xilinx_dffopt.cc +++ b/techlibs/xilinx/xilinx_dffopt.cc @@ -92,7 +92,7 @@ bool merge_lut(LutData &result, const LutData &data, const LutData select, bool int lut_idx = i >> idx_data & ((1 << GetSize(data.second)) - 1); new_bit = data.first[lut_idx] == State::S1; } - result.first.bits()[i] = new_bit ? State::S1 : State::S0; + result.first.set(i, new_bit ? State::S1 : State::S0); } return true; } @@ -211,8 +211,8 @@ lut_sigin_done: Cell *cell_d = it_D->second.second; if (cell->hasParam(ID(IS_D_INVERTED)) && cell->getParam(ID(IS_D_INVERTED)).as_bool()) { // Flip all bits in the LUT. - for (int i = 0; i < GetSize(lut_d.first); i++) - lut_d.first.bits()[i] = (lut_d.first[i] == State::S1) ? State::S0 : State::S1; + for (auto bit : lut_d.first) + bit = (bit == State::S1) ? State::S0 : State::S1; } LutData lut_d_post_ce; diff --git a/techlibs/xilinx/xilinx_dsp.cc b/techlibs/xilinx/xilinx_dsp.cc index f95930a90..22e6bce5b 100644 --- a/techlibs/xilinx/xilinx_dsp.cc +++ b/techlibs/xilinx/xilinx_dsp.cc @@ -343,7 +343,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) // Since B is an exact power of 2, subtract 1 // by inverting all bits up until hitting // that one hi bit - for (auto &b : B.bits()) + for (auto b : B) if (b == State::S0) b = State::S1; else if (b == State::S1) { b = State::S0; @@ -392,7 +392,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm) continue; for (int i = c.offset; i < c.offset+c.width; i++) { log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); - it->second.bits()[i] = State::Sx; + it->second.set(i, State::Sx); } } }; @@ -579,7 +579,7 @@ void xilinx_dsp48a_pack(xilinx_dsp48a_pm &pm) continue; for (int i = c.offset; i < c.offset+c.width; i++) { log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); - it->second.bits()[i] = State::Sx; + it->second.set(i, State::Sx); } } }; @@ -702,7 +702,7 @@ void xilinx_dsp_packC(xilinx_dsp_CREG_pm &pm) continue; for (int i = c.offset; i < c.offset+c.width; i++) { log_assert(it->second[i] == State::S0 || it->second[i] == State::Sx); - it->second.bits()[i] = State::Sx; + it->second.set(i, State::Sx); } } }; diff --git a/techlibs/xilinx/xilinx_srl.cc b/techlibs/xilinx/xilinx_srl.cc index 32a0064a6..2c23f8f42 100644 --- a/techlibs/xilinx/xilinx_srl.cc +++ b/techlibs/xilinx/xilinx_srl.cc @@ -40,9 +40,8 @@ void run_fixed(xilinx_srl_pm &pm) log_assert(Q.wire); auto it = Q.wire->attributes.find(ID::init); if (it != Q.wire->attributes.end()) { - auto &i = it->second.bits()[Q.offset]; - initval.append(i); - i = State::Sx; + initval.append(it->second[Q.offset]); + it->second.set(Q.offset, State::Sx); } else initval.append(State::Sx); @@ -121,9 +120,8 @@ void run_variable(xilinx_srl_pm &pm) log_assert(Q.wire); auto it = Q.wire->attributes.find(ID::init); if (it != Q.wire->attributes.end()) { - auto &i = it->second.bits()[Q.offset]; - initval.append(i); - i = State::Sx; + initval.append(it->second[Q.offset]); + it->second.set(Q.offset, State::Sx); } else initval.append(State::Sx); From 9493292690544ad6f0dc76ddcd04d8e677e2211a Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 01:56:27 +0000 Subject: [PATCH 20/60] Update tests to avoid bits() --- tests/unit/kernel/rtlilTest.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 6a5f75a95..a9b7c3ada 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -80,10 +80,10 @@ namespace RTLIL { EXPECT_EQ(i, 16); EXPECT_TRUE(cs1.is_str()); - // It can be mutated with the bits() view - // and decays into unpacked - for (auto& bit : cs1.bits()) { - bit = State::Sx; + // It can be mutated via bit iteration and decays into unpacked + // when an non-defined bit is set. + for (auto b : cs1) { + b = State::Sx; } EXPECT_TRUE(cs1.is_bits()); } From 1e244cd78acc6695154f925369ac1109e5e249ed Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 05:21:21 +0000 Subject: [PATCH 21/60] Deprecate Const::bits() --- kernel/rtlil.cc | 2 +- kernel/rtlil.h | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 62f7ae4f7..22467fa8e 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -378,7 +378,7 @@ bool RTLIL::Const::operator !=(const RTLIL::Const &other) const return !(*this == other); } -std::vector& RTLIL::Const::bits() +std::vector& RTLIL::Const::bits_internal() { bitvectorize(); return get_bits(); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index b7776f378..02c8190dc 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -837,6 +837,8 @@ private: bitvectype& get_bits() const; std::string& get_str() const; + std::vector& bits_internal(); + public: Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector()) {} Const(const std::string &str); @@ -864,7 +866,8 @@ public: bool operator ==(const RTLIL::Const &other) const; bool operator !=(const RTLIL::Const &other) const; - std::vector& bits(); + [[deprecated]] + std::vector& bits() { return bits_internal(); } bool as_bool() const; // Convert the constant value to a C++ int. @@ -897,10 +900,10 @@ public: void append(const RTLIL::Const &other); void set(int i, RTLIL::State state) { - bits()[i] = state; + bits_internal()[i] = state; } void resize(int size, RTLIL::State fill) { - bits().resize(size, fill); + bits_internal().resize(size, fill); } class const_iterator { From 61caa5e042ecb59770b2e3bcafdda60bc094cbb2 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 28 Aug 2025 06:00:50 +0000 Subject: [PATCH 22/60] Deprecate Const::bitvectorize() --- kernel/rtlil.cc | 26 +++++++++++++------------- kernel/rtlil.h | 7 +++++-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 22467fa8e..0afe2a3c0 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -380,7 +380,7 @@ bool RTLIL::Const::operator !=(const RTLIL::Const &other) const std::vector& RTLIL::Const::bits_internal() { - bitvectorize(); + bitvectorize_internal(); return get_bits(); } @@ -394,7 +394,7 @@ std::vector RTLIL::Const::to_bits() const bool RTLIL::Const::as_bool() const { - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); for (size_t i = 0; i < bv.size(); i++) if (bv[i] == State::S1) @@ -404,7 +404,7 @@ bool RTLIL::Const::as_bool() const int RTLIL::Const::as_int(bool is_signed) const { - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); int32_t ret = 0; for (size_t i = 0; i < bv.size() && i < 32; i++) @@ -496,7 +496,7 @@ std::optional RTLIL::Const::as_int_compress(bool is_signed) const std::string RTLIL::Const::as_string(const char* any) const { - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); std::string ret; ret.reserve(bv.size()); @@ -534,7 +534,7 @@ std::string RTLIL::Const::decode_string() const if (auto str = get_if_str()) return *str; - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); const int n = GetSize(bv); const int n_over_8 = n / 8; @@ -583,7 +583,7 @@ bool RTLIL::Const::empty() const { } } -void RTLIL::Const::bitvectorize() const { +void RTLIL::Const::bitvectorize_internal() const { if (tag == backing_tag::bits) return; @@ -609,7 +609,7 @@ void RTLIL::Const::bitvectorize() const { } void RTLIL::Const::append(const RTLIL::Const &other) { - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); bv.insert(bv.end(), other.begin(), other.end()); } @@ -625,7 +625,7 @@ RTLIL::State RTLIL::Const::const_iterator::operator*() const { bool RTLIL::Const::is_fully_zero() const { - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); cover("kernel.rtlil.const.is_fully_zero"); @@ -638,7 +638,7 @@ bool RTLIL::Const::is_fully_zero() const bool RTLIL::Const::is_fully_ones() const { - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); cover("kernel.rtlil.const.is_fully_ones"); @@ -653,7 +653,7 @@ bool RTLIL::Const::is_fully_def() const { cover("kernel.rtlil.const.is_fully_def"); - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); for (const auto &bit : bv) @@ -667,7 +667,7 @@ bool RTLIL::Const::is_fully_undef() const { cover("kernel.rtlil.const.is_fully_undef"); - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); for (const auto &bit : bv) @@ -681,7 +681,7 @@ bool RTLIL::Const::is_fully_undef_x_only() const { cover("kernel.rtlil.const.is_fully_undef_x_only"); - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); for (const auto &bit : bv) @@ -695,7 +695,7 @@ bool RTLIL::Const::is_onehot(int *pos) const { cover("kernel.rtlil.const.is_onehot"); - bitvectorize(); + bitvectorize_internal(); bitvectype& bv = get_bits(); bool found = false; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 02c8190dc..0691ac2a6 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -838,6 +838,7 @@ private: bitvectype& get_bits() const; std::string& get_str() const; std::vector& bits_internal(); + void bitvectorize_internal() const; public: Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector()) {} @@ -866,8 +867,11 @@ public: bool operator ==(const RTLIL::Const &other) const; bool operator !=(const RTLIL::Const &other) const; - [[deprecated]] + [[deprecated("Don't use direct access to the internal std::vector, that's an implementation detail.")]] std::vector& bits() { return bits_internal(); } + [[deprecated("Don't call bitvectorize() directly, it's an implementation detail.")]] + void bitvectorize() const { bitvectorize_internal(); } + bool as_bool() const; // Convert the constant value to a C++ int. @@ -896,7 +900,6 @@ public: std::string decode_string() const; int size() const; bool empty() const; - void bitvectorize() const; void append(const RTLIL::Const &other); void set(int i, RTLIL::State state) { From b06085ab6c3db59254c0bd2d8dbbf02775b296e1 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 03:08:31 +0000 Subject: [PATCH 23/60] Make Const::Const(long long) constructor use packed bits internally if possible --- kernel/rtlil.cc | 25 +++++++++++++++++++++++++ kernel/rtlil.h | 3 ++- tests/unit/kernel/rtlilTest.cc | 25 +++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 0afe2a3c0..b07468e12 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -257,9 +257,34 @@ RTLIL::Const::Const(const std::string &str) tag = backing_tag::string; } +RTLIL::Const::Const(long long val) // default width 32 +{ + flags = RTLIL::CONST_FLAG_NONE; + char bytes[] = { + (char)(val >> 24), (char)(val >> 16), (char)(val >> 8), (char)val + }; + new ((void*)&str_) std::string(bytes, 4); + tag = backing_tag::string; +} + RTLIL::Const::Const(long long val, int width) { flags = RTLIL::CONST_FLAG_NONE; + if ((width & 7) == 0) { + new ((void*)&str_) std::string(); + tag = backing_tag::string; + std::string& str = get_str(); + int bytes = width >> 3; + signed char sign_byte = val < 0 ? -1 : 0; + str.resize(bytes, sign_byte); + bytes = std::min(bytes, sizeof(val)); + for (int i = 0; i < bytes; i++) { + str[str.size() - 1 - i] = val; + val = val >> 8; + } + return; + } + new ((void*)&bits_) bitvectype(); tag = backing_tag::bits; bitvectype& bv = get_bits(); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 0691ac2a6..6bb6f1fe1 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -843,7 +843,8 @@ private: public: Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector()) {} Const(const std::string &str); - Const(long long val, int width = 32); + Const(long long val); // default width is 32 + Const(long long val, int width); Const(RTLIL::State bit, int width = 1); Const(std::vector bits) : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::move(bits)) {} Const(const std::vector &bits); diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index a9b7c3ada..0b7fbfd37 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -88,6 +88,31 @@ namespace RTLIL { EXPECT_TRUE(cs1.is_bits()); } + { + Const c(0x12345678); + EXPECT_TRUE(c.is_str()); + EXPECT_EQ(c.as_int(), 0x12345678); + } + + { + Const c(0xab, 8); + EXPECT_TRUE(c.is_str()); + EXPECT_EQ(c.as_int(), 0xab); + } + + { + Const c(0x12345678, 80); + EXPECT_TRUE(c.is_str()); + EXPECT_EQ(c.as_int(), 0x12345678); + EXPECT_EQ(c[79], S0); + } + + { + Const c(-1, 80); + EXPECT_TRUE(c.is_str()); + EXPECT_EQ(c.as_int(), -1); + EXPECT_EQ(c[79], S1); + } } TEST_F(KernelRtlilTest, ConstConstIteratorWorks) { From b597ad777e6ab306f82e3cfa521454f29a8c19c5 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 03:09:19 +0000 Subject: [PATCH 24/60] Make Const::as_bool and Const::as_int work with packed bits without decaying to vector --- kernel/rtlil.cc | 34 +++++++++++++++++++++++++--------- tests/unit/kernel/rtlilTest.cc | 11 +++++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index b07468e12..1228e738f 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -419,7 +419,13 @@ std::vector RTLIL::Const::to_bits() const bool RTLIL::Const::as_bool() const { - bitvectorize_internal(); + if (is_str()) { + for (char ch : get_str()) + if (ch != 0) + return true; + return false; + } + bitvectype& bv = get_bits(); for (size_t i = 0; i < bv.size(); i++) if (bv[i] == State::S1) @@ -429,15 +435,25 @@ bool RTLIL::Const::as_bool() const int RTLIL::Const::as_int(bool is_signed) const { - bitvectorize_internal(); - bitvectype& bv = get_bits(); int32_t ret = 0; - for (size_t i = 0; i < bv.size() && i < 32; i++) + if (const std::string *s = get_if_str()) { + int size = GetSize(*s); + // Ignore any bytes after the first 4 since bits beyond 32 are truncated. + for (int i = std::min(4, size); i > 0; i--) + ret |= static_cast((*s)[size - i]) << ((i - 1) * 8); + // If is_signed and the string is shorter than 4 bytes then apply sign extension. + if (is_signed && size > 0 && size < 4 && ((*s)[0] & 0x80)) + ret |= -1 << size*8; + return ret; + } + + const bitvectype& bv = get_bits(); + int significant_bits = std::min(GetSize(bv), 32); + for (int i = 0; i < significant_bits; i++) if (bv[i] == State::S1) ret |= 1 << i; - if (is_signed && bv.back() == State::S1) - for (size_t i = bv.size(); i < 32; i++) - ret |= 1 << i; + if (is_signed && significant_bits > 0 && significant_bits < 32 && bv.back() == State::S1 ) + ret |= -1 << significant_bits; return ret; } @@ -457,7 +473,7 @@ bool RTLIL::Const::convertible_to_int(bool is_signed) const if (size == 32) { if (is_signed) return true; - return get_bits().at(31) != State::S1; + return back() != State::S1; } return false; @@ -478,7 +494,7 @@ int RTLIL::Const::as_int_saturating(bool is_signed) const const auto min_size = get_min_size(is_signed); log_assert(min_size > 0); - const auto neg = get_bits().at(min_size - 1); + const auto neg = (*this)[min_size - 1]; return neg ? std::numeric_limits::min() : std::numeric_limits::max(); } return as_int(is_signed); diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 0b7fbfd37..99ddf44cc 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -92,12 +92,14 @@ namespace RTLIL { Const c(0x12345678); EXPECT_TRUE(c.is_str()); EXPECT_EQ(c.as_int(), 0x12345678); + EXPECT_TRUE(c.is_str()); } { Const c(0xab, 8); EXPECT_TRUE(c.is_str()); EXPECT_EQ(c.as_int(), 0xab); + EXPECT_TRUE(c.is_str()); } { @@ -105,6 +107,7 @@ namespace RTLIL { EXPECT_TRUE(c.is_str()); EXPECT_EQ(c.as_int(), 0x12345678); EXPECT_EQ(c[79], S0); + EXPECT_TRUE(c.is_str()); } { @@ -112,6 +115,14 @@ namespace RTLIL { EXPECT_TRUE(c.is_str()); EXPECT_EQ(c.as_int(), -1); EXPECT_EQ(c[79], S1); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(1 << 24); + EXPECT_TRUE(c.is_str()); + EXPECT_TRUE(c.as_bool()); + EXPECT_TRUE(c.is_str()); } } From 9ad83cc67b0e1a1f1bbf181a64f2a37450410dab Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 03:29:44 +0000 Subject: [PATCH 25/60] Fast path for Const::operator== --- kernel/rtlil.cc | 5 +++++ tests/unit/kernel/rtlilTest.cc | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 1228e738f..f0653e91a 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -388,6 +388,11 @@ bool RTLIL::Const::operator<(const RTLIL::Const &other) const bool RTLIL::Const::operator ==(const RTLIL::Const &other) const { + if (is_str() && other.is_str()) + return get_str() == other.get_str(); + if (is_bits() && other.is_bits()) + return get_bits() == other.get_bits(); + if (size() != other.size()) return false; diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 99ddf44cc..b2b2e7076 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -204,6 +204,24 @@ namespace RTLIL { EXPECT_EQ(c, Const(0xe, 4)); } + TEST_F(KernelRtlilTest, ConstEqualStr) { + EXPECT_EQ(Const("abc"), Const("abc")); + EXPECT_NE(Const("abc"), Const("def")); + } + + TEST_F(KernelRtlilTest, ConstEqualBits) { + std::vector v1 = {S0, S1}; + std::vector v2 = {S1, S0}; + EXPECT_EQ(Const(v1), Const(v1)); + EXPECT_NE(Const(v1), Const(v2)); + } + + TEST_F(KernelRtlilTest, ConstEqualStrBits) { + std::vector v1 = {S0, S0, S0, S0, S0, S1, S0, S0}; + EXPECT_EQ(Const(v1), Const(" ")); + EXPECT_NE(Const(v1), Const("a")); + } + class WireRtlVsHdlIndexConversionTest : public KernelRtlilTest, public testing::WithParamInterface> From 1a367b907cd5ddb8a0d28457ad9e6f2e3cfb3105 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 03:34:17 +0000 Subject: [PATCH 26/60] Use fast path for 32-bit Const integer constructor in more places --- frontends/json/jsonparse.cc | 2 +- frontends/rtlil/rtlil_parser.y | 2 +- frontends/verific/verific.cc | 8 ++++---- kernel/rtlil.h | 3 ++- techlibs/ice40/ice40_dsp.cc | 2 +- techlibs/quicklogic/ql_bram_merge.cc | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index f2faa669b..743ac5d9e 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -258,7 +258,7 @@ Const json_parse_attr_param_value(JsonNode *node) } } else if (node->type == 'N') { - value = Const(node->data_number, 32); + value = Const(node->data_number); if (node->data_number < 0) value.flags |= RTLIL::CONST_FLAG_SIGNED; } else diff --git a/frontends/rtlil/rtlil_parser.y b/frontends/rtlil/rtlil_parser.y index 4f0fb3b97..2b8d7b7ab 100644 --- a/frontends/rtlil/rtlil_parser.y +++ b/frontends/rtlil/rtlil_parser.y @@ -465,7 +465,7 @@ constant: free($1); } | TOK_INT { - $$ = new RTLIL::Const($1, 32); + $$ = new RTLIL::Const($1); } | TOK_STRING { $$ = new RTLIL::Const($1); diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 9e3436c14..8bb34582e 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -267,13 +267,13 @@ static const RTLIL::Const extract_vhdl_bit_vector(std::string &val, std::string static const RTLIL::Const extract_vhdl_integer(std::string &val) { char *end; - return RTLIL::Const((int)std::strtol(val.c_str(), &end, 10), 32); + return RTLIL::Const((int)std::strtol(val.c_str(), &end, 10)); } static const RTLIL::Const extract_vhdl_char(std::string &val) { if (val.size()==3 && val[0]=='\"' && val.back()=='\"') - return RTLIL::Const((int)val[1], 32); + return RTLIL::Const((int)val[1]); log_error("Error parsing VHDL character.\n"); } @@ -311,7 +311,7 @@ static const RTLIL::Const extract_vhdl_const(const char *value, bool output_sig } else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) && ((decimal = std::strtol(value, &end, 10)), !end[0])) { is_signed = output_signed; - c = RTLIL::Const((int)decimal, 32); + c = RTLIL::Const((int)decimal); } else if (val == "false") { c = RTLIL::Const::from_string("0"); } else if (val == "true") { @@ -344,7 +344,7 @@ static const RTLIL::Const extract_verilog_const(const char *value, bool allow_s } else if ((value[0] == '-' || (value[0] >= '0' && value[0] <= '9')) && ((decimal = std::strtol(value, &end, 10)), !end[0])) { is_signed = output_signed; - c = RTLIL::Const((int)decimal, 32); + c = RTLIL::Const((int)decimal); } else if (allow_string) { c = RTLIL::Const(val); } else { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 6bb6f1fe1..fca32508d 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1112,7 +1112,8 @@ struct RTLIL::SigChunk SigChunk(RTLIL::Wire *wire) : wire(wire), width(GetSize(wire)), offset(0) {} SigChunk(RTLIL::Wire *wire, int offset, int width = 1) : wire(wire), width(width), offset(offset) {} SigChunk(const std::string &str) : SigChunk(RTLIL::Const(str)) {} - SigChunk(int val, int width = 32) : SigChunk(RTLIL::Const(val, width)) {} + SigChunk(int val) /*default width 32*/ : SigChunk(RTLIL::Const(val)) {} + SigChunk(int val, int width) : SigChunk(RTLIL::Const(val, width)) {} SigChunk(RTLIL::State bit, int width = 1) : SigChunk(RTLIL::Const(bit, width)) {} SigChunk(const RTLIL::SigBit &bit); diff --git a/techlibs/ice40/ice40_dsp.cc b/techlibs/ice40/ice40_dsp.cc index 3f00028c3..995cdb97e 100644 --- a/techlibs/ice40/ice40_dsp.cc +++ b/techlibs/ice40/ice40_dsp.cc @@ -82,7 +82,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) SigSpec CD = st.sigCD; if (CD.empty()) - CD = RTLIL::Const(0, 32); + CD = RTLIL::Const(0); else log_assert(GetSize(CD) == 32); diff --git a/techlibs/quicklogic/ql_bram_merge.cc b/techlibs/quicklogic/ql_bram_merge.cc index bed1ba572..7b99d74e5 100644 --- a/techlibs/quicklogic/ql_bram_merge.cc +++ b/techlibs/quicklogic/ql_bram_merge.cc @@ -45,7 +45,7 @@ struct QlBramMergeWorker { { if(cell->type != split_cell_type) continue; if(!cell->hasParam(ID(OPTION_SPLIT))) continue; - if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1, 32)) continue; + if(cell->getParam(ID(OPTION_SPLIT)) != RTLIL::Const(1)) continue; mergeable_groups[get_key(cell)].insert(cell); } } From 67a274ed1f499cec716f4f9a2f163786a85c62ae Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 03:48:16 +0000 Subject: [PATCH 27/60] Optimize Const::hash_into to hash packed bits efficiently --- kernel/rtlil.cc | 34 ++++++++++++++++++++++++++++++++++ kernel/rtlil.h | 7 +------ tests/unit/kernel/rtlilTest.cc | 12 ++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f0653e91a..f2ac1dee8 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -760,6 +760,40 @@ bool RTLIL::Const::is_onehot(int *pos) const return found; } +Hasher RTLIL::Const::hash_into(Hasher h) const +{ + if (auto str = get_if_str()) + return hashlib::hash_ops::hash_into(*str, h); + + // If the bits are all 0/1, hash packed bits using the string hash. + // Otherwise hash the leading packed bits with the rest of the bits individually. + bitvectype &bv = get_bits(); + int size = GetSize(bv); + std::string packed; + int packed_size = (size + 7) >> 3; + packed.resize(packed_size, 0); + for (int bi = 0; bi < packed_size; ++bi) { + char ch = 0; + int end = std::min((bi + 1)*8, size); + for (int i = bi*8; i < end; ++i) { + RTLIL::State b = bv[i]; + if (b > RTLIL::State::S1) { + // Hash the packed bits we've seen so far, plus the remaining bits. + h = hashlib::hash_ops::hash_into(packed, h); + h = hashlib::hash_ops::hash_into(ch, h); + for (; i < size; ++i) { + h = hashlib::hash_ops::hash_into(bv[i], h); + } + h.eat(size); + return h; + } + ch |= static_cast(b) << (i & 7); + } + packed[packed_size - 1 - bi] = ch; + } + return hashlib::hash_ops::hash_into(packed, h); +} + RTLIL::Const RTLIL::Const::extract(int offset, int len, RTLIL::State padding) const { bitvectype ret_bv; ret_bv.reserve(len); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index fca32508d..f4c84dbfa 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1052,12 +1052,7 @@ public: resize(width, empty() ? RTLIL::State::Sx : back()); } - [[nodiscard]] Hasher hash_into(Hasher h) const { - h.eat(size()); - for (auto b : *this) - h.eat(b); - return h; - } + [[nodiscard]] Hasher hash_into(Hasher h) const; }; struct RTLIL::AttrObject diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index b2b2e7076..4d8736ea3 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -222,6 +222,18 @@ namespace RTLIL { EXPECT_NE(Const(v1), Const("a")); } + static Hasher::hash_t hash(const Const &c) { + Hasher h; + h = c.hash_into(h); + return h.yield(); + } + + TEST_F(KernelRtlilTest, ConstEqualHashStrBits) { + std::vector v1 = {S0, S0, S0, S0, S0, S1, S0, S0}; + EXPECT_EQ(hash(Const(v1)), hash(Const(" "))); + EXPECT_NE(hash(Const(v1)), hash(Const("a"))); + } + class WireRtlVsHdlIndexConversionTest : public KernelRtlilTest, public testing::WithParamInterface> From f61e3377a93623934f5368f57ad3286050d155c4 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 04:13:23 +0000 Subject: [PATCH 28/60] Hash strings 8 bytes at a time --- kernel/hashlib.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 92188a220..c95ce1e7b 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -168,8 +168,17 @@ struct hash_ops { } else if constexpr (std::is_pointer_v) { return hash_ops::hash_into((uintptr_t) a, h); } else if constexpr (std::is_same_v) { - for (auto c : a) - h.hash32(c); + int size = a.size(); + int i = 0; + while (i + 8 < size) { + uint64_t v; + memcpy(&v, a.data() + i, 8); + h.hash64(v); + i += 8; + } + uint64_t v = 0; + memcpy(&v, a.data() + i, size - i); + h.hash64(v); return h; } else { return a.hash_into(h); From cb1186aac52a5797e2f5f4ccde3f47b34f4bc7d6 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 04:40:22 +0000 Subject: [PATCH 29/60] Make Const::as_string work without reducing packed bits to vector --- kernel/rtlil.cc | 19 +++++++++---------- tests/unit/kernel/rtlilTest.cc | 7 +++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f2ac1dee8..7a65a6db6 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -542,18 +542,17 @@ std::optional RTLIL::Const::as_int_compress(bool is_signed) const std::string RTLIL::Const::as_string(const char* any) const { - bitvectorize_internal(); - bitvectype& bv = get_bits(); + int sz = size(); std::string ret; - ret.reserve(bv.size()); - for (size_t i = bv.size(); i > 0; i--) - switch (bv[i-1]) { - case S0: ret += "0"; break; - case S1: ret += "1"; break; - case Sx: ret += "x"; break; - case Sz: ret += "z"; break; + ret.reserve(sz); + for (int i = sz - 1; i >= 0; --i) + switch ((*this)[i]) { + case S0: ret.push_back('0'); break; + case S1: ret.push_back('1'); break; + case Sx: ret.push_back('x'); break; + case Sz: ret.push_back('z'); break; case Sa: ret += any; break; - case Sm: ret += "m"; break; + case Sm: ret.push_back('m'); break; } return ret; } diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 4d8736ea3..366d022de 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -124,6 +124,13 @@ namespace RTLIL { EXPECT_TRUE(c.as_bool()); EXPECT_TRUE(c.is_str()); } + + { + Const c(0x2, 8); + EXPECT_TRUE(c.is_str()); + EXPECT_EQ(c.as_string(), "00000010"); + EXPECT_TRUE(c.is_str()); + } } TEST_F(KernelRtlilTest, ConstConstIteratorWorks) { From caaf9a4400e7feb7764120c05a31e57a4c571ff7 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 04:42:52 +0000 Subject: [PATCH 30/60] Const::decode_string() doesn't need to call bitvectorize --- kernel/rtlil.cc | 1 - tests/unit/kernel/rtlilTest.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 7a65a6db6..7530644ec 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -579,7 +579,6 @@ std::string RTLIL::Const::decode_string() const if (auto str = get_if_str()) return *str; - bitvectorize_internal(); bitvectype& bv = get_bits(); const int n = GetSize(bv); const int n_over_8 = n / 8; diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 366d022de..5f8c0dd06 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -131,6 +131,32 @@ namespace RTLIL { EXPECT_EQ(c.as_string(), "00000010"); EXPECT_TRUE(c.is_str()); } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_EQ(c.decode_string(), " "); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_EQ(c.decode_string(), " "); + EXPECT_TRUE(c.is_str()); + } + + { + std::vector v = {S0, S0, S0, S0, S0, S1, S0, S0}; + Const c(v); + EXPECT_EQ(c.decode_string(), " "); + } + + { + std::vector v = {S0, S0, S0, S0, S0, S1, S0, Sx}; + Const c(v); + EXPECT_EQ(c.decode_string(), " "); + } } TEST_F(KernelRtlilTest, ConstConstIteratorWorks) { From 29810f1e7ccb8e934e372d0ec91a987c4c051249 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 04:50:35 +0000 Subject: [PATCH 31/60] Make Const::is_*() functions work on packed bits without decaying to vector --- kernel/rtlil.cc | 44 ++++++++++------ tests/unit/kernel/rtlilTest.cc | 91 ++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 15 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 7530644ec..7ced8fba6 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -669,10 +669,17 @@ RTLIL::State RTLIL::Const::const_iterator::operator*() const { bool RTLIL::Const::is_fully_zero() const { - bitvectorize_internal(); - bitvectype& bv = get_bits(); cover("kernel.rtlil.const.is_fully_zero"); + if (auto str = get_if_str()) { + for (char ch : *str) + if (ch != 0) + return false; + return true; + } + + bitvectype& bv = get_bits(); + for (const auto &bit : bv) if (bit != RTLIL::State::S0) return false; @@ -682,10 +689,16 @@ bool RTLIL::Const::is_fully_zero() const bool RTLIL::Const::is_fully_ones() const { - bitvectorize_internal(); - bitvectype& bv = get_bits(); cover("kernel.rtlil.const.is_fully_ones"); + if (auto str = get_if_str()) { + for (char ch : *str) + if (ch != (char)0xff) + return false; + return true; + } + + bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S1) return false; @@ -697,9 +710,10 @@ bool RTLIL::Const::is_fully_def() const { cover("kernel.rtlil.const.is_fully_def"); - bitvectorize_internal(); - bitvectype& bv = get_bits(); + if (is_str()) + return true; + bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) return false; @@ -711,9 +725,10 @@ bool RTLIL::Const::is_fully_undef() const { cover("kernel.rtlil.const.is_fully_undef"); - bitvectorize_internal(); - bitvectype& bv = get_bits(); + if (auto str = get_if_str()) + return str->empty(); + bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::Sx && bit != RTLIL::State::Sz) return false; @@ -725,9 +740,10 @@ bool RTLIL::Const::is_fully_undef_x_only() const { cover("kernel.rtlil.const.is_fully_undef_x_only"); - bitvectorize_internal(); - bitvectype& bv = get_bits(); + if (auto str = get_if_str()) + return str->empty(); + bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::Sx) return false; @@ -739,12 +755,10 @@ bool RTLIL::Const::is_onehot(int *pos) const { cover("kernel.rtlil.const.is_onehot"); - bitvectorize_internal(); - bitvectype& bv = get_bits(); - bool found = false; - for (int i = 0; i < GetSize(*this); i++) { - auto &bit = bv[i]; + int size = GetSize(*this); + for (int i = 0; i < size; i++) { + State bit = (*this)[i]; if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) return false; if (bit == RTLIL::State::S1) { diff --git a/tests/unit/kernel/rtlilTest.cc b/tests/unit/kernel/rtlilTest.cc index 5f8c0dd06..97cc936de 100644 --- a/tests/unit/kernel/rtlilTest.cc +++ b/tests/unit/kernel/rtlilTest.cc @@ -157,6 +157,50 @@ namespace RTLIL { Const c(v); EXPECT_EQ(c.decode_string(), " "); } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_FALSE(c.is_fully_zero()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_FALSE(c.is_fully_ones()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_TRUE(c.is_fully_def()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_FALSE(c.is_fully_undef()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + EXPECT_FALSE(c.is_fully_undef_x_only()); + EXPECT_TRUE(c.is_str()); + } + + { + Const c(" "); + EXPECT_TRUE(c.is_str()); + int pos; + EXPECT_TRUE(c.is_onehot(&pos)); + EXPECT_EQ(pos, 5); + EXPECT_TRUE(c.is_str()); + } } TEST_F(KernelRtlilTest, ConstConstIteratorWorks) { @@ -267,6 +311,53 @@ namespace RTLIL { EXPECT_NE(hash(Const(v1)), hash(Const("a"))); } + TEST_F(KernelRtlilTest, ConstIsFullyZero) { + EXPECT_TRUE(Const(0, 8).is_fully_zero()); + EXPECT_FALSE(Const(8, 8).is_fully_zero()); + EXPECT_TRUE(Const().is_fully_zero()); + } + + TEST_F(KernelRtlilTest, ConstIsFullyOnes) { + EXPECT_TRUE(Const(0xf, 4).is_fully_ones()); + EXPECT_FALSE(Const(3, 4).is_fully_ones()); + EXPECT_TRUE(Const().is_fully_ones()); + } + + TEST_F(KernelRtlilTest, ConstIsFullyDef) { + EXPECT_TRUE(Const(0xf, 4).is_fully_def()); + std::vector v1 = {S0, Sx}; + EXPECT_FALSE(Const(v1).is_fully_def()); + EXPECT_TRUE(Const().is_fully_def()); + } + + TEST_F(KernelRtlilTest, ConstIsFullyUndef) { + std::vector v1 = {S0, Sx}; + EXPECT_FALSE(Const(v1).is_fully_undef()); + EXPECT_TRUE(Const(Sz, 2).is_fully_undef()); + EXPECT_TRUE(Const().is_fully_undef()); + } + + TEST_F(KernelRtlilTest, ConstIsFullyUndefXOnly) { + std::vector v1 = {Sx, Sz}; + EXPECT_FALSE(Const(v1).is_fully_undef_x_only()); + EXPECT_TRUE(Const(Sx, 2).is_fully_undef_x_only()); + EXPECT_TRUE(Const().is_fully_undef_x_only()); + } + + TEST_F(KernelRtlilTest, ConstIsOnehot) { + int pos; + EXPECT_TRUE(Const(0x80, 8).is_onehot(&pos)); + EXPECT_EQ(pos, 7); + EXPECT_FALSE(Const(0x82, 8).is_onehot(&pos)); + EXPECT_FALSE(Const(0, 8).is_onehot(&pos)); + EXPECT_TRUE(Const(1, 1).is_onehot(&pos)); + EXPECT_EQ(pos, 0); + EXPECT_FALSE(Const(Sx, 1).is_onehot(&pos)); + std::vector v1 = {Sx, S1}; + EXPECT_FALSE(Const(v1).is_onehot(&pos)); + EXPECT_FALSE(Const().is_onehot(&pos)); + } + class WireRtlVsHdlIndexConversionTest : public KernelRtlilTest, public testing::WithParamInterface> From fee2b8992c526fde3a502db2cbd9fb3b614536c8 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 29 Aug 2025 05:56:19 +0000 Subject: [PATCH 32/60] Stop using `mutable` in `Const`. Now that we only call `bitvectorize()` in non-const methods, we can move the casting-away-const to only happen in `bitvectorize()`, which is deprecated so only some plugins (maybe) are using it. This means `const` `Const` methods don't change the underlying data, which means they'll be safe to use from multiple threads if/when we want to do that. --- kernel/rtlil.cc | 36 +++++++++++++++++++++++------------- kernel/rtlil.h | 22 +++++++++++++--------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 7ced8fba6..035701cb9 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -240,12 +240,22 @@ const pool &RTLIL::builtin_ff_cell_types() { #define check(condition) log_assert(condition && "malformed Const union") -Const::bitvectype& Const::get_bits() const { +const Const::bitvectype& Const::get_bits() const { check(is_bits()); return *get_if_bits(); } -std::string& Const::get_str() const { +const std::string& Const::get_str() const { + check(is_str()); + return *get_if_str(); +} + +Const::bitvectype& Const::get_bits() { + check(is_bits()); + return *get_if_bits(); +} + +std::string& Const::get_str() { check(is_str()); return *get_if_str(); } @@ -431,7 +441,7 @@ bool RTLIL::Const::as_bool() const return false; } - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (size_t i = 0; i < bv.size(); i++) if (bv[i] == State::S1) return true; @@ -448,7 +458,7 @@ int RTLIL::Const::as_int(bool is_signed) const ret |= static_cast((*s)[size - i]) << ((i - 1) * 8); // If is_signed and the string is shorter than 4 bytes then apply sign extension. if (is_signed && size > 0 && size < 4 && ((*s)[0] & 0x80)) - ret |= -1 << size*8; + ret |= UINT32_MAX << size*8; return ret; } @@ -458,7 +468,7 @@ int RTLIL::Const::as_int(bool is_signed) const if (bv[i] == State::S1) ret |= 1 << i; if (is_signed && significant_bits > 0 && significant_bits < 32 && bv.back() == State::S1 ) - ret |= -1 << significant_bits; + ret |= UINT32_MAX << significant_bits; return ret; } @@ -579,7 +589,7 @@ std::string RTLIL::Const::decode_string() const if (auto str = get_if_str()) return *str; - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); const int n = GetSize(bv); const int n_over_8 = n / 8; std::string s; @@ -627,7 +637,7 @@ bool RTLIL::Const::empty() const { } } -void RTLIL::Const::bitvectorize_internal() const { +void RTLIL::Const::bitvectorize_internal() { if (tag == backing_tag::bits) return; @@ -678,7 +688,7 @@ bool RTLIL::Const::is_fully_zero() const return true; } - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S0) @@ -698,7 +708,7 @@ bool RTLIL::Const::is_fully_ones() const return true; } - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S1) return false; @@ -713,7 +723,7 @@ bool RTLIL::Const::is_fully_def() const if (is_str()) return true; - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::S0 && bit != RTLIL::State::S1) return false; @@ -728,7 +738,7 @@ bool RTLIL::Const::is_fully_undef() const if (auto str = get_if_str()) return str->empty(); - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::Sx && bit != RTLIL::State::Sz) return false; @@ -743,7 +753,7 @@ bool RTLIL::Const::is_fully_undef_x_only() const if (auto str = get_if_str()) return str->empty(); - bitvectype& bv = get_bits(); + const bitvectype& bv = get_bits(); for (const auto &bit : bv) if (bit != RTLIL::State::Sx) return false; @@ -779,7 +789,7 @@ Hasher RTLIL::Const::hash_into(Hasher h) const // If the bits are all 0/1, hash packed bits using the string hash. // Otherwise hash the leading packed bits with the rest of the bits individually. - bitvectype &bv = get_bits(); + const bitvectype &bv = get_bits(); int size = GetSize(bv); std::string packed; int packed_size = (size + 7) >> 3; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f4c84dbfa..6b4bc0c7d 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -822,23 +822,27 @@ private: using bitvectype = std::vector; enum class backing_tag: bool { bits, string }; // Do not access the union or tag even in Const methods unless necessary - mutable backing_tag tag; + backing_tag tag; union { - mutable bitvectype bits_; - mutable std::string str_; + bitvectype bits_; + std::string str_; }; // Use these private utilities instead bool is_bits() const { return tag == backing_tag::bits; } bool is_str() const { return tag == backing_tag::string; } - bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; } - std::string* get_if_str() const { return is_str() ? &str_ : NULL; } + bitvectype* get_if_bits() { return is_bits() ? &bits_ : NULL; } + std::string* get_if_str() { return is_str() ? &str_ : NULL; } + const bitvectype* get_if_bits() const { return is_bits() ? &bits_ : NULL; } + const std::string* get_if_str() const { return is_str() ? &str_ : NULL; } - bitvectype& get_bits() const; - std::string& get_str() const; + bitvectype& get_bits(); + std::string& get_str(); + const bitvectype& get_bits() const; + const std::string& get_str() const; std::vector& bits_internal(); - void bitvectorize_internal() const; + void bitvectorize_internal(); public: Const() : flags(RTLIL::CONST_FLAG_NONE), tag(backing_tag::bits), bits_(std::vector()) {} @@ -871,7 +875,7 @@ public: [[deprecated("Don't use direct access to the internal std::vector, that's an implementation detail.")]] std::vector& bits() { return bits_internal(); } [[deprecated("Don't call bitvectorize() directly, it's an implementation detail.")]] - void bitvectorize() const { bitvectorize_internal(); } + void bitvectorize() const { const_cast(this)->bitvectorize_internal(); } bool as_bool() const; From 11b829ba70f61a5c59abae8e4b6feec34000b74f Mon Sep 17 00:00:00 2001 From: rhanqtl Date: Thu, 4 Sep 2025 23:19:11 +0800 Subject: [PATCH 33/60] fix(parse): #5234 adjust width of rhs according to lhs --- kernel/rtlil.cc | 6 +++++- tests/sat/fminit_noexpand.ys | 10 ++++++++++ tests/sat/fminit_seq_width.ys | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 tests/sat/fminit_noexpand.ys create mode 100644 tests/sat/fminit_seq_width.ys diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 035701cb9..586262f97 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -5974,7 +5974,11 @@ bool RTLIL::SigSpec::parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, R } } - return parse(sig, module, str); + if (!parse(sig, module, str)) + return false; + if (sig.width_ > lhs.width_) + sig.remove(lhs.width_, sig.width_ - lhs.width_); + return true; } RTLIL::CaseRule::~CaseRule() diff --git a/tests/sat/fminit_noexpand.ys b/tests/sat/fminit_noexpand.ys new file mode 100644 index 000000000..a271c3c59 --- /dev/null +++ b/tests/sat/fminit_noexpand.ys @@ -0,0 +1,10 @@ +read_verilog -sv < Date: Tue, 16 Sep 2025 22:59:08 +0000 Subject: [PATCH 34/60] Remove .c_str() from log_cmd_error() and log_file_error() parameters --- backends/aiger2/aiger.cc | 2 +- backends/cxxrtl/cxxrtl_backend.cc | 4 +-- frontends/ast/ast.cc | 2 +- frontends/ast/genrtlil.cc | 4 +-- frontends/ast/simplify.cc | 2 +- frontends/rpc/rpc_frontend.cc | 14 ++++---- frontends/verific/verific.cc | 16 ++++----- frontends/verilog/const2ast.cc | 2 +- frontends/verilog/preproc.cc | 2 +- kernel/fmt.cc | 14 ++++---- kernel/gzip.cc | 6 ++-- kernel/register.cc | 10 +++--- passes/cmds/abstract.cc | 4 +-- passes/cmds/add.cc | 2 +- passes/cmds/connect.cc | 10 +++--- passes/cmds/connwrappers.cc | 4 +-- passes/cmds/copy.cc | 4 +-- passes/cmds/cover.cc | 2 +- passes/cmds/design.cc | 8 ++--- passes/cmds/exec.cc | 8 ++--- passes/cmds/glift.cc | 2 +- passes/cmds/logger.cc | 8 ++--- passes/cmds/plugin.cc | 4 +-- passes/cmds/rename.cc | 6 ++-- passes/cmds/select.cc | 14 ++++---- passes/cmds/setattr.cc | 2 +- passes/cmds/setenv.cc | 2 +- passes/cmds/show.cc | 2 +- passes/cmds/stat.cc | 4 +-- passes/cmds/tee.cc | 2 +- passes/cmds/viz.cc | 2 +- passes/equiv/equiv_add.cc | 8 ++--- passes/equiv/equiv_make.cc | 14 ++++---- passes/hierarchy/hierarchy.cc | 6 ++-- passes/hierarchy/submod.cc | 2 +- passes/opt/opt_lut.cc | 2 +- passes/opt/opt_lut_ins.cc | 2 +- passes/pmgen/test_pmgen.cc | 2 +- passes/sat/eval.cc | 16 ++++----- passes/sat/miter.cc | 14 ++++---- passes/sat/mutate.cc | 2 +- passes/sat/qbfsat.cc | 8 ++--- passes/sat/sat.cc | 44 ++++++++++++------------- passes/sat/sim.cc | 2 +- passes/techmap/abc.cc | 4 +-- passes/techmap/cellmatch.cc | 2 +- passes/techmap/constmap.cc | 4 +-- passes/techmap/extract.cc | 2 +- passes/tests/test_cell.cc | 4 +-- techlibs/fabulous/synth_fabulous.cc | 2 +- techlibs/greenpak4/synth_greenpak4.cc | 2 +- techlibs/ice40/synth_ice40.cc | 2 +- techlibs/intel/synth_intel.cc | 2 +- techlibs/lattice/synth_lattice.cc | 2 +- techlibs/microchip/synth_microchip.cc | 2 +- techlibs/nanoxplore/synth_nanoxplore.cc | 2 +- techlibs/nexus/synth_nexus.cc | 2 +- techlibs/quicklogic/synth_quicklogic.cc | 2 +- techlibs/xilinx/synth_xilinx.cc | 2 +- 59 files changed, 163 insertions(+), 163 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index c7ed3b81f..bf7497bb5 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -1446,7 +1446,7 @@ struct XAiger2Backend : Backend { if (!map_filename.empty()) { writer.map_file.open(map_filename); if (!writer.map_file) - log_cmd_error("Failed to open '%s' for writing\n", map_filename.c_str()); + log_cmd_error("Failed to open '%s' for writing\n", map_filename); } design->bufNormalize(true); diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 9a7e1383a..48710aff8 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -1533,7 +1533,7 @@ struct CxxrtlWorker { } // Internal cells } else if (is_internal_cell(cell->type)) { - log_cmd_error("Unsupported internal cell `%s'.\n", cell->type.c_str()); + log_cmd_error("Unsupported internal cell `%s'.\n", cell->type); // User cells } else if (for_debug) { // Outlines are called on demand when computing the value of a debug item. Nothing to do here. @@ -3803,7 +3803,7 @@ struct CxxrtlBackend : public Backend { if (args[argidx] == "-print-output" && argidx+1 < args.size()) { worker.print_output = args[++argidx]; if (!(worker.print_output == "std::cout" || worker.print_output == "std::cerr")) { - log_cmd_error("Invalid output stream \"%s\".\n", worker.print_output.c_str()); + log_cmd_error("Invalid output stream \"%s\".\n", worker.print_output); worker.print_output = "std::cout"; } continue; diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 459b50683..488775d2c 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1446,7 +1446,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump if (design->has(child->str)) { RTLIL::Module *existing_mod = design->module(child->str); if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) { - log_file_error(*child->location.begin.filename, child->location.begin.line, "Re-definition of module `%s'!\n", child->str.c_str()); + log_file_error(*child->location.begin.filename, child->location.begin.line, "Re-definition of module `%s'!\n", child->str); } else if (nooverwrite) { log("Ignoring re-definition of module `%s' at %s.\n", child->str.c_str(), child->loc_string().c_str()); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 262dda43b..5fd478ff3 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -795,7 +795,7 @@ struct AST_INTERNAL::ProcessGenerator fmt.append_literal("\n"); fmt.emit_rtlil(cell); } else if (!ast->str.empty()) { - log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str()); + log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Found unsupported invocation of system task `%s'!\n", ast->str); } break; @@ -846,7 +846,7 @@ struct AST_INTERNAL::ProcessGenerator set_src_attr(cell, ast); for (auto &attr : ast->attributes) { if (attr.second->type != AST_CONSTANT) - log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Attribute `%s' with non-constant value!\n", attr.first.c_str()); + log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Attribute `%s' with non-constant value!\n", attr.first); cell->attributes[attr.first] = attr.second->asAttrConst(); } cell->setParam(ID::FLAVOR, flavor); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 2669f83e2..0df09030c 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -164,7 +164,7 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_ log_file_info(*location.begin.filename, location.begin.line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); return Fmt(); } else { - log_file_error(*location.begin.filename, location.begin.line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); + log_file_error(*location.begin.filename, location.begin.line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str, index + 1); } args.push_back(arg); } diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index df64ecd2f..80a6aae6d 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -91,9 +91,9 @@ struct RpcServer { std::string error; Json json_response = Json::parse(response, error); if (json_response.is_null()) - log_cmd_error("parsing JSON failed: %s\n", error.c_str()); + log_cmd_error("parsing JSON failed: %s\n", error); if (json_response["error"].is_string()) - log_cmd_error("RPC frontend returned an error: %s\n", json_response["error"].string_value().c_str()); + log_cmd_error("RPC frontend returned an error: %s\n", json_response["error"].string_value()); return json_response; } @@ -111,7 +111,7 @@ struct RpcServer { } } else is_valid = false; if (!is_valid) - log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump().c_str()); + log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump()); return modules; } @@ -149,7 +149,7 @@ struct RpcServer { source = response["source"].string_value(); else is_valid = false; if (!is_valid) - log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump().c_str()); + log_cmd_error("RPC frontend returned malformed response: %s\n", response.dump()); return std::make_pair(frontend, source); } }; @@ -202,7 +202,7 @@ struct RpcModule : RTLIL::Module { } } if (!found_derived_top) - log_cmd_error("RPC frontend did not return requested module `%s`!\n", stripped_name.c_str()); + log_cmd_error("RPC frontend did not return requested module `%s`!\n", stripped_name); for (auto module : derived_design->modules()) for (auto cell : module->cells()) @@ -256,7 +256,7 @@ struct HandleRpcServer : RpcServer { do { DWORD data_written; if (!WriteFile(hsend, &data[offset], data.length() - offset, &data_written, /*lpOverlapped=*/NULL)) - log_cmd_error("WriteFile failed: %s\n", get_last_error_str().c_str()); + log_cmd_error("WriteFile failed: %s\n", get_last_error_str()); offset += data_written; } while(offset < (ssize_t)data.length()); } @@ -268,7 +268,7 @@ struct HandleRpcServer : RpcServer { data.resize(data.length() + 1024); DWORD data_read; if (!ReadFile(hrecv, &data[offset], data.length() - offset, &data_read, /*lpOverlapped=*/NULL)) - log_cmd_error("ReadFile failed: %s\n", get_last_error_str().c_str()); + log_cmd_error("ReadFile failed: %s\n", get_last_error_str()); offset += data_read; data.resize(offset); size_t term_pos = data.find('\n', offset); diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 8bb34582e..91af38ccd 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1469,7 +1469,7 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma if (design->has(module_name)) { if (!nl->IsOperator() && !is_blackbox(nl)) - log_cmd_error("Re-definition of module `%s'.\n", netlist_name.c_str()); + log_cmd_error("Re-definition of module `%s'.\n", netlist_name); return; } @@ -3824,7 +3824,7 @@ struct VerificPass : public Pass { add_units_to_map(map, work, flag_lib); std::string filename = frontent_rewrite(args, argidx, tmp_files); if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_87)) - log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", filename.c_str()); + log_cmd_error("Reading `%s' in VHDL_87 mode failed.\n", filename); set_units_to_blackbox(map, work, flag_lib); } verific_import_pending = true; @@ -3849,7 +3849,7 @@ struct VerificPass : public Pass { add_units_to_map(map, work, flag_lib); std::string filename = frontent_rewrite(args, argidx, tmp_files); if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_93)) - log_cmd_error("Reading `%s' in VHDL_93 mode failed.\n", filename.c_str()); + log_cmd_error("Reading `%s' in VHDL_93 mode failed.\n", filename); set_units_to_blackbox(map, work, flag_lib); } verific_import_pending = true; @@ -3874,7 +3874,7 @@ struct VerificPass : public Pass { add_units_to_map(map, work, flag_lib); std::string filename = frontent_rewrite(args, argidx, tmp_files); if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_2K)) - log_cmd_error("Reading `%s' in VHDL_2K mode failed.\n", filename.c_str()); + log_cmd_error("Reading `%s' in VHDL_2K mode failed.\n", filename); set_units_to_blackbox(map, work, flag_lib); } verific_import_pending = true; @@ -3899,7 +3899,7 @@ struct VerificPass : public Pass { add_units_to_map(map, work, flag_lib); std::string filename = frontent_rewrite(args, argidx, tmp_files); if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_2019)) - log_cmd_error("Reading `%s' in VHDL_2019 mode failed.\n", filename.c_str()); + log_cmd_error("Reading `%s' in VHDL_2019 mode failed.\n", filename); set_units_to_blackbox(map, work, flag_lib); } verific_import_pending = true; @@ -3924,7 +3924,7 @@ struct VerificPass : public Pass { add_units_to_map(map, work, flag_lib); std::string filename = frontent_rewrite(args, argidx, tmp_files); if (!vhdl_file::Analyze(filename.c_str(), work.c_str(), vhdl_file::VHDL_2008)) - log_cmd_error("Reading `%s' in VHDL_2008 mode failed.\n", filename.c_str()); + log_cmd_error("Reading `%s' in VHDL_2008 mode failed.\n", filename); set_units_to_blackbox(map, work, flag_lib); } verific_import_pending = true; @@ -3938,7 +3938,7 @@ struct VerificPass : public Pass { while (argidx < GetSize(args)) { std::string filename = frontent_rewrite(args, argidx, tmp_files); if (!edif.Read(filename.c_str())) - log_cmd_error("Reading `%s' in EDIF mode failed.\n", filename.c_str()); + log_cmd_error("Reading `%s' in EDIF mode failed.\n", filename); } goto check_error; } @@ -3961,7 +3961,7 @@ struct VerificPass : public Pass { while (argidx < GetSize(args)) { std::string filename = frontent_rewrite(args, argidx, tmp_files); if (!synlib_file::Read(filename.c_str(), is_work_set ? work.c_str() : nullptr)) - log_cmd_error("Reading `%s' in LIBERTY mode failed.\n", filename.c_str()); + log_cmd_error("Reading `%s' in LIBERTY mode failed.\n", filename); SynlibLibrary *lib = synlib_file::GetLastLibraryAnalyzed(); if (lib && flag_lib) { MapIter mi ; diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 9b197b356..661b4ef96 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -45,7 +45,7 @@ using namespace AST; using namespace VERILOG_FRONTEND; void ConstParser::log_maybe_loc_error(std::string msg) { - log_file_error(*loc.begin.filename, loc.begin.line, "%s", msg.c_str()); + log_file_error(*loc.begin.filename, loc.begin.line, "%s", msg); } void ConstParser::log_maybe_loc_warn(std::string msg) { diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index 8674758ab..1858edc97 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -741,7 +741,7 @@ read_define(const std::string &filename, defines_map.add(name, value, (state == 2) ? &args : nullptr); global_defines_cache.add(name, value, (state == 2) ? &args : nullptr); } else { - log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str()); + log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name); } } diff --git a/kernel/fmt.cc b/kernel/fmt.cc index 6e9f2924a..200e7e5ce 100644 --- a/kernel/fmt.cc +++ b/kernel/fmt.cc @@ -401,11 +401,11 @@ void Fmt::parse_verilog(const std::vector &args, bool sformat_lik part = {}; } if (++i == fmt.size()) { - log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1); + log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name, fmtarg - args.begin() + 1); } if (++arg == args.end()) { - log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with fewer arguments than the format specifiers in argument %zu require.\n", task_name.c_str(), fmtarg - args.begin() + 1); + log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with fewer arguments than the format specifiers in argument %zu require.\n", task_name, fmtarg - args.begin() + 1); } part.sig = arg->sig; part.signed_ = arg->signed_; @@ -420,7 +420,7 @@ void Fmt::parse_verilog(const std::vector &args, bool sformat_lik } else break; } if (i == fmt.size()) { - log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1); + log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name, fmtarg - args.begin() + 1); } bool has_leading_zero = false, has_width = false; @@ -465,15 +465,15 @@ void Fmt::parse_verilog(const std::vector &args, bool sformat_lik if (!has_width && !has_leading_zero) part.width = 20; } else { - log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with format character `%c' in argument %zu, but the argument is not $time or $realtime.\n", task_name.c_str(), fmt[i], fmtarg - args.begin() + 1); + log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with format character `%c' in argument %zu, but the argument is not $time or $realtime.\n", task_name, fmt[i], fmtarg - args.begin() + 1); } } else { - log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with unrecognized format character `%c' in argument %zu.\n", task_name.c_str(), fmt[i], fmtarg - args.begin() + 1); + log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with unrecognized format character `%c' in argument %zu.\n", task_name, fmt[i], fmtarg - args.begin() + 1); } break; } if (i == fmt.size()) { - log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1); + log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with incomplete format specifier in argument %zu.\n", task_name, fmtarg - args.begin() + 1); } if (part.padding == '\0') { @@ -486,7 +486,7 @@ void Fmt::parse_verilog(const std::vector &args, bool sformat_lik } if (part.type == FmtPart::INTEGER && part.base != 10 && part.sign != FmtPart::MINUS) - log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with invalid format specifier in argument %zu.\n", task_name.c_str(), fmtarg - args.begin() + 1); + log_file_error(fmtarg->filename, fmtarg->first_line, "System task `%s' called with invalid format specifier in argument %zu.\n", task_name, fmtarg - args.begin() + 1); if (part.base != 10) part.signed_ = false; diff --git a/kernel/gzip.cc b/kernel/gzip.cc index d19c06579..433c35902 100644 --- a/kernel/gzip.cc +++ b/kernel/gzip.cc @@ -103,11 +103,11 @@ gzip_istream::ibuf::~ibuf() { // Never returns nullptr or failed state istream* std::istream* uncompressed(const std::string filename, std::ios_base::openmode mode) { if (!check_file_exists(filename)) - log_cmd_error("File `%s' not found or is a directory\n", filename.c_str()); + log_cmd_error("File `%s' not found or is a directory\n", filename); std::ifstream* f = new std::ifstream(); f->open(filename, mode); if (f->fail()) - log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno)); + log_cmd_error("Can't open input file `%s' for reading: %s\n", filename, strerror(errno)); // Check for gzip magic unsigned char magic[3]; int n = 0; @@ -131,7 +131,7 @@ std::istream* uncompressed(const std::string filename, std::ios_base::openmode m log_assert(ok && "Failed to open gzipped file.\n"); return s; #else - log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename.c_str()); + log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename); #endif // YOSYS_ENABLE_ZLIB } else { f->clear(); diff --git a/kernel/register.cc b/kernel/register.cc index 4afd7ada3..36e312968 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -262,7 +262,7 @@ void Pass::call(RTLIL::Design *design, std::vector args) } if (pass_register.count(args[0]) == 0) - log_cmd_error("No such command: %s (type 'help' for a command overview)\n", args[0].c_str()); + log_cmd_error("No such command: %s (type 'help' for a command overview)\n", args[0]); if (pass_register[args[0]]->experimental_flag) log_experimental(args[0]); @@ -521,7 +521,7 @@ void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string if (args.size() == 0) return; if (frontend_register.count(args[0]) == 0) - log_cmd_error("No such frontend: %s\n", args[0].c_str()); + log_cmd_error("No such frontend: %s\n", args[0]); if (f != NULL) { auto state = frontend_register[args[0]]->pre_execute(); @@ -596,7 +596,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vectoropen(filename)) { delete gf; - log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); + log_cmd_error("Can't open output file `%s' for writing: %s\n", filename, strerror(errno)); } yosys_output_files.insert(filename); f = gf; @@ -609,7 +609,7 @@ void Backend::extra_args(std::ostream *&f, std::string &filename, std::vectorfail()) { delete ff; - log_cmd_error("Can't open output file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); + log_cmd_error("Can't open output file `%s' for writing: %s\n", filename, strerror(errno)); } f = ff; } @@ -641,7 +641,7 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f if (args.size() == 0) return; if (backend_register.count(args[0]) == 0) - log_cmd_error("No such backend: %s\n", args[0].c_str()); + log_cmd_error("No such backend: %s\n", args[0]); size_t orig_sel_stack_pos = design->selection_stack.size(); diff --git a/passes/cmds/abstract.cc b/passes/cmds/abstract.cc index e475ba71c..88f07a5aa 100644 --- a/passes/cmds/abstract.cc +++ b/passes/cmds/abstract.cc @@ -53,7 +53,7 @@ struct Slice { } static void syntax_error(const std::string &slice) { - log_cmd_error("Invalid slice '%s', expected ':' or ''", slice.c_str()); + log_cmd_error("Invalid slice '%s', expected ':' or ''", slice); } std::string to_string() const { @@ -494,7 +494,7 @@ struct AbstractPass : public Pass { case Enable::ActiveHigh: { Wire *enable_wire = mod->wire("\\" + enable_name); if (!enable_wire) - log_cmd_error("Enable wire %s not found in module %s\n", enable_name.c_str(), mod->name.c_str()); + log_cmd_error("Enable wire %s not found in module %s\n", enable_name, mod->name); if (GetSize(enable_wire) != 1) log_cmd_error("Enable wire %s must have width 1 but has width %d in module %s\n", enable_name.c_str(), GetSize(enable_wire), mod->name.c_str()); diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc index 0d395f043..1011a093c 100644 --- a/passes/cmds/add.cc +++ b/passes/cmds/add.cc @@ -77,7 +77,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n wire = nullptr; if (wire == nullptr) - log_cmd_error("Found incompatible object with same name in module %s!\n", module->name.c_str()); + log_cmd_error("Found incompatible object with same name in module %s!\n", module->name); log("Module %s already has such an object.\n", module->name); } diff --git a/passes/cmds/connect.cc b/passes/cmds/connect.cc index 65292ef92..c6d3320ea 100644 --- a/passes/cmds/connect.cc +++ b/passes/cmds/connect.cc @@ -150,9 +150,9 @@ struct ConnectPass : public Pass { RTLIL::SigSpec sig_lhs, sig_rhs; if (!RTLIL::SigSpec::parse_sel(sig_lhs, design, module, set_lhs)) - log_cmd_error("Failed to parse set lhs expression `%s'.\n", set_lhs.c_str()); + log_cmd_error("Failed to parse set lhs expression `%s'.\n", set_lhs); if (!RTLIL::SigSpec::parse_rhs(sig_lhs, sig_rhs, module, set_rhs)) - log_cmd_error("Failed to parse set rhs expression `%s'.\n", set_rhs.c_str()); + log_cmd_error("Failed to parse set rhs expression `%s'.\n", set_rhs); sigmap.apply(sig_lhs); sigmap.apply(sig_rhs); @@ -173,7 +173,7 @@ struct ConnectPass : public Pass { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, unset_expr)) - log_cmd_error("Failed to parse unset expression `%s'.\n", unset_expr.c_str()); + log_cmd_error("Failed to parse unset expression `%s'.\n", unset_expr); sigmap.apply(sig); unset_drivers(design, module, sigmap, sig); @@ -185,11 +185,11 @@ struct ConnectPass : public Pass { log_cmd_error("Can't use -port together with -nounset.\n"); if (module->cell(RTLIL::escape_id(port_cell)) == nullptr) - log_cmd_error("Can't find cell %s.\n", port_cell.c_str()); + log_cmd_error("Can't find cell %s.\n", port_cell); RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, port_expr)) - log_cmd_error("Failed to parse port expression `%s'.\n", port_expr.c_str()); + log_cmd_error("Failed to parse port expression `%s'.\n", port_expr); if (!flag_assert) { module->cell(RTLIL::escape_id(port_cell))->setPort(RTLIL::escape_id(port_port), sigmap(sig)); diff --git a/passes/cmds/connwrappers.cc b/passes/cmds/connwrappers.cc index dbe23ccf1..5677c666d 100644 --- a/passes/cmds/connwrappers.cc +++ b/passes/cmds/connwrappers.cc @@ -42,7 +42,7 @@ struct ConnwrappersWorker decl_celltypes.insert(key.first); if (decls.count(key)) - log_cmd_error("Duplicate port decl: %s %s\n", celltype.c_str(), portname.c_str()); + log_cmd_error("Duplicate port decl: %s %s\n", celltype, portname); portdecl_t decl; decl.widthparam = RTLIL::escape_id(widthparam); @@ -57,7 +57,7 @@ struct ConnwrappersWorker decl_celltypes.insert(key.first); if (decls.count(key)) - log_cmd_error("Duplicate port decl: %s %s\n", celltype.c_str(), portname.c_str()); + log_cmd_error("Duplicate port decl: %s %s\n", celltype, portname); portdecl_t decl; decl.widthparam = RTLIL::escape_id(widthparam); diff --git a/passes/cmds/copy.cc b/passes/cmds/copy.cc index e3fb3a0e6..5a5835a43 100644 --- a/passes/cmds/copy.cc +++ b/passes/cmds/copy.cc @@ -45,10 +45,10 @@ struct CopyPass : public Pass { std::string trg_name = RTLIL::escape_id(args[2]); if (design->module(src_name) == nullptr) - log_cmd_error("Can't find source module %s.\n", src_name.c_str()); + log_cmd_error("Can't find source module %s.\n", src_name); if (design->module(trg_name) != nullptr) - log_cmd_error("Target module name %s already exists.\n", trg_name.c_str()); + log_cmd_error("Target module name %s already exists.\n", trg_name); RTLIL::Module *new_mod = design->module(src_name)->clone(); new_mod->name = trg_name; diff --git a/passes/cmds/cover.cc b/passes/cmds/cover.cc index bab00c287..7f217329c 100644 --- a/passes/cmds/cover.cc +++ b/passes/cmds/cover.cc @@ -118,7 +118,7 @@ struct CoverPass : public Pass { if (f == NULL) { for (auto f : out_files) fclose(f); - log_cmd_error("Can't create file %s%s.\n", args[argidx-1] == "-d" ? "in directory " : "", args[argidx].c_str()); + log_cmd_error("Can't create file %s%s.\n", args[argidx-1] == "-d" ? "in directory " : "", args[argidx]); } out_files.push_back(f); continue; diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index 59cd39c98..ddbd98bfd 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -165,13 +165,13 @@ struct DesignPass : public Pass { got_mode = true; load_name = args[++argidx]; if (saved_designs.count(load_name) == 0) - log_cmd_error("No saved design '%s' found!\n", load_name.c_str()); + log_cmd_error("No saved design '%s' found!\n", load_name); continue; } if (!got_mode && args[argidx] == "-copy-from" && argidx+1 < args.size()) { got_mode = true; if (saved_designs.count(args[++argidx]) == 0) - log_cmd_error("No saved design '%s' found!\n", args[argidx].c_str()); + log_cmd_error("No saved design '%s' found!\n", args[argidx]); copy_from_design = saved_designs.at(args[argidx]); copy_to_design = design; continue; @@ -188,7 +188,7 @@ struct DesignPass : public Pass { got_mode = true; import_mode = true; if (saved_designs.count(args[++argidx]) == 0) - log_cmd_error("No saved design '%s' found!\n", args[argidx].c_str()); + log_cmd_error("No saved design '%s' found!\n", args[argidx]); copy_from_design = saved_designs.at(args[argidx]); copy_to_design = design; as_name = args[argidx]; @@ -202,7 +202,7 @@ struct DesignPass : public Pass { got_mode = true; delete_name = args[++argidx]; if (saved_designs.count(delete_name) == 0) - log_cmd_error("No saved design '%s' found!\n", delete_name.c_str()); + log_cmd_error("No saved design '%s' found!\n", delete_name); continue; } break; diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc index b346fc95d..ff1ef11ff 100644 --- a/passes/cmds/exec.cc +++ b/passes/cmds/exec.cc @@ -127,7 +127,7 @@ struct ExecPass : public Pass { x.re = YS_REGEX_COMPILE(args[argidx]); expect_stdout.push_back(x); } catch (const std::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", args[argidx].c_str()); + log_cmd_error("Error in regex expression '%s' !\n", args[argidx]); } } else if (args[argidx] == "-not-expect-stdout") { flag_expect_stdout = true; @@ -142,11 +142,11 @@ struct ExecPass : public Pass { x.polarity = false; expect_stdout.push_back(x); } catch (const std::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", args[argidx].c_str()); + log_cmd_error("Error in regex expression '%s' !\n", args[argidx]); } } else - log_cmd_error("Unknown option \"%s\" or \"--\" doesn\'t precede command.\n", args[argidx].c_str()); + log_cmd_error("Unknown option \"%s\" or \"--\" doesn\'t precede command.\n", args[argidx]); } } @@ -201,7 +201,7 @@ struct ExecPass : public Pass { if (flag_expect_stdout) for (auto &x : expect_stdout) if (x.polarity ^ x.matched) - log_cmd_error("Command stdout did%s have a line matching given regex \"%s\".\n", (x.polarity? " not" : ""), x.str.c_str()); + log_cmd_error("Command stdout did%s have a line matching given regex \"%s\".\n", (x.polarity? " not" : ""), x.str); log_pop(); } diff --git a/passes/cmds/glift.cc b/passes/cmds/glift.cc index d7264d392..d906c241d 100644 --- a/passes/cmds/glift.cc +++ b/passes/cmds/glift.cc @@ -184,7 +184,7 @@ private: for(auto &cell : module->cells().to_vector()) { if (!cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_MUX_), ID($_NMUX_), ID($_NOT_), ID($anyconst), ID($allconst), ID($assume), ID($assert)) && module->design->module(cell->type) == nullptr) { - log_cmd_error("Unsupported cell type \"%s\" found. Run `techmap` first.\n", cell->type.c_str()); + log_cmd_error("Unsupported cell type \"%s\" found. Run `techmap` first.\n", cell->type); } if (cell->type.in(ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_))) { const unsigned int A = 0, B = 1, Y = 2; diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc index 37240bb7e..cab4ab81c 100644 --- a/passes/cmds/logger.cc +++ b/passes/cmds/logger.cc @@ -112,7 +112,7 @@ struct LoggerPass : public Pass { log_warn_regexes.push_back(YS_REGEX_COMPILE(pattern)); } catch (const std::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); + log_cmd_error("Error in regex expression '%s' !\n", pattern); } continue; } @@ -124,7 +124,7 @@ struct LoggerPass : public Pass { log_nowarn_regexes.push_back(YS_REGEX_COMPILE(pattern)); } catch (const std::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); + log_cmd_error("Error in regex expression '%s' !\n", pattern); } continue; } @@ -136,7 +136,7 @@ struct LoggerPass : public Pass { log_werror_regexes.push_back(YS_REGEX_COMPILE(pattern)); } catch (const std::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); + log_cmd_error("Error in regex expression '%s' !\n", pattern); } continue; } @@ -188,7 +188,7 @@ struct LoggerPass : public Pass { else log_abort(); } catch (const std::regex_error& e) { - log_cmd_error("Error in regex expression '%s' !\n", pattern.c_str()); + log_cmd_error("Error in regex expression '%s' !\n", pattern); } continue; } diff --git a/passes/cmds/plugin.cc b/passes/cmds/plugin.cc index 6c7921d53..afa830552 100644 --- a/passes/cmds/plugin.cc +++ b/passes/cmds/plugin.cc @@ -70,7 +70,7 @@ void load_plugin(std::string filename, std::vector aliases) if(module_p == NULL) { PyErr_Print(); - log_cmd_error("Can't load python module `%s'\n", full_path.filename().c_str()); + log_cmd_error("Can't load python module `%s'\n", full_path.filename()); return; } loaded_python_plugins[orig_filename] = module_p; @@ -100,7 +100,7 @@ void load_plugin(std::string filename, std::vector aliases) } if (hdl == NULL) - log_cmd_error("Can't load module `%s': %s\n", filename.c_str(), dlerror()); + log_cmd_error("Can't load module `%s': %s\n", filename, dlerror()); loaded_plugins[orig_filename] = hdl; Pass::init_register(); diff --git a/passes/cmds/rename.cc b/passes/cmds/rename.cc index c4bb7135e..078ffb769 100644 --- a/passes/cmds/rename.cc +++ b/passes/cmds/rename.cc @@ -31,7 +31,7 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: to_name = RTLIL::escape_id(to_name); if (module->count_id(to_name)) - log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name.c_str(), module->name.c_str()); + log_cmd_error("There is already an object `%s' in module `%s'.\n", to_name, module->name); RTLIL::Wire *wire_to_rename = module->wire(from_name); RTLIL::Cell *cell_to_rename = module->cell(from_name); @@ -55,7 +55,7 @@ static void rename_in_module(RTLIL::Module *module, std::string from_name, std:: return; } - log_cmd_error("Object `%s' not found!\n", from_name.c_str()); + log_cmd_error("Object `%s' not found!\n", from_name); } static std::string derive_name_from_src(const std::string &src, int counter) @@ -632,7 +632,7 @@ struct RenamePass : public Pass { log("Renaming module %s to %s.\n", module_to_rename->name, to_name); design->rename(module_to_rename, to_name); } else - log_cmd_error("Object `%s' not found!\n", from_name.c_str()); + log_cmd_error("Object `%s' not found!\n", from_name); } } } diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 7fcf5cfcd..469e36ef1 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -592,7 +592,7 @@ static void select_op_expand(RTLIL::Design *design, const std::string &arg, char while (pos < int(arg.size())) { if (arg[pos] != ':' || pos+1 == int(arg.size())) - log_cmd_error("Syntax error in expand operator '%s'.\n", arg.c_str()); + log_cmd_error("Syntax error in expand operator '%s'.\n", arg); pos++; if (arg[pos] == '+' || arg[pos] == '-') { expand_rule_t rule; @@ -617,7 +617,7 @@ static void select_op_expand(RTLIL::Design *design, const std::string &arg, char for (auto i2 : i1.second) limits.insert(i2); } else - log_cmd_error("Selection %s is not defined!\n", RTLIL::unescape_id(str).c_str()); + log_cmd_error("Selection %s is not defined!\n", RTLIL::unescape_id(str)); } else limits.insert(RTLIL::escape_id(str)); } @@ -804,7 +804,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp log_cmd_error("Must have at least one element on the stack for operator %%coe.\n"); select_op_expand(design, arg, 'o', true); } else - log_cmd_error("Unknown selection operator '%s'.\n", arg.c_str()); + log_cmd_error("Unknown selection operator '%s'.\n", arg); if (work_stack.size() >= 1) select_filter_active_mod(design, work_stack.back()); return; @@ -815,7 +815,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (design->selection_vars.count(set_name) > 0) work_stack.push_back(design->selection_vars[set_name]); else - log_cmd_error("Selection @%s is not defined!\n", RTLIL::unescape_id(set_name).c_str()); + log_cmd_error("Selection @%s is not defined!\n", RTLIL::unescape_id(set_name)); select_filter_active_mod(design, work_stack.back()); return; } @@ -934,7 +934,7 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (arg_memb.compare(2, 1, "@") == 0) { std::string set_name = RTLIL::escape_id(arg_memb.substr(3)); if (!design->selection_vars.count(set_name)) - log_cmd_error("Selection @%s is not defined!\n", RTLIL::unescape_id(set_name).c_str()); + log_cmd_error("Selection @%s is not defined!\n", RTLIL::unescape_id(set_name)); auto &muster = design->selection_vars[set_name]; for (auto cell : mod->cells()) @@ -1428,7 +1428,7 @@ struct SelectPass : public Pass { continue; } if (arg.size() > 0 && arg[0] == '-') - log_cmd_error("Unknown option %s.\n", arg.c_str()); + log_cmd_error("Unknown option %s.\n", arg); bool disable_empty_warning = count_mode || assert_none || assert_any || (assert_modcount != -1) || (assert_count != -1) || (assert_max != -1) || (assert_min != -1); select_stmt(design, arg, disable_empty_warning); @@ -1762,7 +1762,7 @@ struct CdPass : public Pass { return; } - log_cmd_error("No such module `%s' found!\n", RTLIL::unescape_id(modname).c_str()); + log_cmd_error("No such module `%s' found!\n", RTLIL::unescape_id(modname)); } } CdPass; diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index f590c2fa9..25d8fd34c 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -39,7 +39,7 @@ struct setunset_t } else { RTLIL::SigSpec sig_value; if (!RTLIL::SigSpec::parse(sig_value, nullptr, set_value)) - log_cmd_error("Can't decode value '%s'!\n", set_value.c_str()); + log_cmd_error("Can't decode value '%s'!\n", set_value); value = sig_value.as_const(); } } diff --git a/passes/cmds/setenv.cc b/passes/cmds/setenv.cc index 850d7c961..90eeab702 100644 --- a/passes/cmds/setenv.cc +++ b/passes/cmds/setenv.cc @@ -52,7 +52,7 @@ struct SetenvPass : public Pass { _putenv_s(name.c_str(), value.c_str()); #else if (setenv(name.c_str(), value.c_str(), 1)) - log_cmd_error("Invalid name \"%s\".\n", name.c_str()); + log_cmd_error("Invalid name \"%s\".\n", name); #endif } diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc index c2d446162..d0d9c0f85 100644 --- a/passes/cmds/show.cc +++ b/passes/cmds/show.cc @@ -926,7 +926,7 @@ struct ShowPass : public Pass { if (f == nullptr) { for (auto lib : libs) delete lib; - log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file.c_str()); + log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file); } ShowWorker worker(f, design, libs, colorSeed, flag_width, flag_wireshape, flag_signed, flag_stretch, flag_enum, flag_abbreviate, flag_notitle, flag_href, color_selections, label_selections, colorattr); fclose(f); diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 1b9e6106c..6e46ab5e2 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -949,7 +949,7 @@ struct StatPass : public Pass { } if (args[argidx] == "-top" && argidx + 1 < args.size()) { if (design->module(RTLIL::escape_id(args[argidx + 1])) == nullptr) - log_cmd_error("Can't find module %s.\n", args[argidx + 1].c_str()); + log_cmd_error("Can't find module %s.\n", args[argidx + 1]); top_mod = design->module(RTLIL::escape_id(args[++argidx])); continue; } @@ -969,7 +969,7 @@ struct StatPass : public Pass { log_header(design, "Printing statistics.\n"); if (techname != "" && techname != "xilinx" && techname != "cmos" && !json_mode) - log_cmd_error("Unsupported technology: '%s'\n", techname.c_str()); + log_cmd_error("Unsupported technology: '%s'\n", techname); if (json_mode) { log("{\n"); diff --git a/passes/cmds/tee.cc b/passes/cmds/tee.cc index fbd42e311..cef94b9ce 100644 --- a/passes/cmds/tee.cc +++ b/passes/cmds/tee.cc @@ -83,7 +83,7 @@ struct TeePass : public Pass { if (f == NULL) { for (auto cf : files_to_close) fclose(cf); - log_cmd_error("Can't create file %s.\n", args[argidx].c_str()); + log_cmd_error("Can't create file %s.\n", args[argidx]); } log_files.push_back(f); files_to_close.push_back(f); diff --git a/passes/cmds/viz.cc b/passes/cmds/viz.cc index fd45d6ba0..e3b09d029 100644 --- a/passes/cmds/viz.cc +++ b/passes/cmds/viz.cc @@ -994,7 +994,7 @@ struct VizPass : public Pass { if (f != nullptr) return; f = fopen(dot_file.c_str(), "w"); if (f == nullptr) - log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file.c_str()); + log_cmd_error("Can't open dot file `%s' for writing.\n", dot_file); }; for (auto module : modlist) { VizWorker worker(module, config); diff --git a/passes/equiv/equiv_add.cc b/passes/equiv/equiv_add.cc index 1bcd4a887..4deef6e32 100644 --- a/passes/equiv/equiv_add.cc +++ b/passes/equiv/equiv_add.cc @@ -64,7 +64,7 @@ struct EquivAddPass : public Pass { log_warning("Can't find gold cell '%s'.\n", args[2].c_str()); return; } - log_cmd_error("Can't find gold cell '%s'.\n", args[2].c_str()); + log_cmd_error("Can't find gold cell '%s'.\n", args[2]); } if (gate_cell == nullptr) { @@ -72,7 +72,7 @@ struct EquivAddPass : public Pass { log_warning("Can't find gate cell '%s'.\n", args[3].c_str()); return; } - log_cmd_error("Can't find gate cell '%s'.\n", args[3].c_str()); + log_cmd_error("Can't find gate cell '%s'.\n", args[3]); } for (auto conn : gold_cell->connections()) @@ -129,7 +129,7 @@ struct EquivAddPass : public Pass { log_warning("Error in gate signal: %s\n", args[2].c_str()); return; } - log_cmd_error("Error in gate signal: %s\n", args[2].c_str()); + log_cmd_error("Error in gate signal: %s\n", args[2]); } if (!SigSpec::parse_rhs(gate_signal, gold_signal, module, args[1])) { @@ -137,7 +137,7 @@ struct EquivAddPass : public Pass { log_warning("Error in gold signal: %s\n", args[1].c_str()); return; } - log_cmd_error("Error in gold signal: %s\n", args[1].c_str()); + log_cmd_error("Error in gold signal: %s\n", args[1]); } log_assert(GetSize(gold_signal) == GetSize(gate_signal)); diff --git a/passes/equiv/equiv_make.cc b/passes/equiv/equiv_make.cc index e15e510be..bae7452f7 100644 --- a/passes/equiv/equiv_make.cc +++ b/passes/equiv/equiv_make.cc @@ -47,7 +47,7 @@ struct EquivMakeWorker { std::ifstream f(fn); if (f.fail()) - log_cmd_error("Can't open blacklist file '%s'!\n", fn.c_str()); + log_cmd_error("Can't open blacklist file '%s'!\n", fn); string line, token; while (std::getline(f, line)) { @@ -67,7 +67,7 @@ struct EquivMakeWorker { std::ifstream f(fn); if (f.fail()) - log_cmd_error("Can't open encfile '%s'!\n", fn.c_str()); + log_cmd_error("Can't open encfile '%s'!\n", fn); dict *ed = nullptr; string line, token; @@ -81,7 +81,7 @@ struct EquivMakeWorker IdString modname = RTLIL::escape_id(next_token(line)); IdString signame = RTLIL::escape_id(next_token(line)); if (encdata.count(signame)) - log_cmd_error("Re-definition of signal '%s' in encfile '%s'!\n", signame.c_str(), fn.c_str()); + log_cmd_error("Re-definition of signal '%s' in encfile '%s'!\n", signame, fn); encdata[signame] = dict(); ed = &encdata[signame]; continue; @@ -94,7 +94,7 @@ struct EquivMakeWorker continue; } - log_cmd_error("Syntax error in encfile '%s'!\n", fn.c_str()); + log_cmd_error("Syntax error in encfile '%s'!\n", fn); } } } @@ -492,13 +492,13 @@ struct EquivMakePass : public Pass { worker.equiv_mod = design->module(RTLIL::escape_id(args[argidx+2])); if (worker.gold_mod == nullptr) - log_cmd_error("Can't find gold module %s.\n", args[argidx].c_str()); + log_cmd_error("Can't find gold module %s.\n", args[argidx]); if (worker.gate_mod == nullptr) - log_cmd_error("Can't find gate module %s.\n", args[argidx+1].c_str()); + log_cmd_error("Can't find gate module %s.\n", args[argidx+1]); if (worker.equiv_mod != nullptr) - log_cmd_error("Equiv module %s already exists.\n", args[argidx+2].c_str()); + log_cmd_error("Equiv module %s already exists.\n", args[argidx+2]); if (worker.gold_mod->has_memories() || worker.gold_mod->has_processes()) log_cmd_error("Gold module contains memories or processes. Run 'memory' or 'proc' respectively.\n"); diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 6fec628c2..f670d1fd2 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -957,7 +957,7 @@ struct HierarchyPass : public Pass { for (auto ¶ : parameters) { SigSpec sig_value; if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second)) - log_cmd_error("Can't decode value '%s'!\n", para.second.c_str()); + log_cmd_error("Can't decode value '%s'!\n", para.second); top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const(); } } @@ -991,7 +991,7 @@ struct HierarchyPass : public Pass { } #endif if (top_mod == NULL) - log_cmd_error("Module `%s' not found!\n", load_top_mod.c_str()); + log_cmd_error("Module `%s' not found!\n", load_top_mod); } else { #ifdef YOSYS_ENABLE_VERIFIC if (verific_import_pending) @@ -1045,7 +1045,7 @@ struct HierarchyPass : public Pass { for (auto ¶ : parameters) { SigSpec sig_value; if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second)) - log_cmd_error("Can't decode value '%s'!\n", para.second.c_str()); + log_cmd_error("Can't decode value '%s'!\n", para.second); top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const(); } diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index 486d21920..f979e7acc 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -408,7 +408,7 @@ struct SubmodPass : public Pass { RTLIL::Module *module = nullptr; for (auto mod : design->selected_modules()) { if (module != nullptr) - log_cmd_error("More than one module selected: %s %s\n", module->name.c_str(), mod->name.c_str()); + log_cmd_error("More than one module selected: %s %s\n", module->name, mod->name); module = mod; } if (module == nullptr) diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 248c3dfe9..37ae38225 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -555,7 +555,7 @@ struct OptLutPass : public Pass { { std::string tech = args[++argidx]; if (tech != "ice40") - log_cmd_error("Unsupported -tech argument: %s\n", tech.c_str()); + log_cmd_error("Unsupported -tech argument: %s\n", tech); dlogic = {{ ID(SB_CARRY), diff --git a/passes/opt/opt_lut_ins.cc b/passes/opt/opt_lut_ins.cc index 9e471c3de..fa8eb563b 100644 --- a/passes/opt/opt_lut_ins.cc +++ b/passes/opt/opt_lut_ins.cc @@ -59,7 +59,7 @@ struct OptLutInsPass : public Pass { extra_args(args, argidx, design); if (techname != "" && techname != "xilinx" && techname != "lattice" && techname != "ecp5" && techname != "gowin") - log_cmd_error("Unsupported technology: '%s'\n", techname.c_str()); + log_cmd_error("Unsupported technology: '%s'\n", techname); for (auto module : design->selected_modules()) { diff --git a/passes/pmgen/test_pmgen.cc b/passes/pmgen/test_pmgen.cc index 892500850..f6d6a3f93 100644 --- a/passes/pmgen/test_pmgen.cc +++ b/passes/pmgen/test_pmgen.cc @@ -238,7 +238,7 @@ struct TestPmgenPass : public Pass { if (pattern == "xilinx_srl.variable") return GENERATE_PATTERN(xilinx_srl_pm, variable); - log_cmd_error("Unknown pattern: %s\n", pattern.c_str()); + log_cmd_error("Unknown pattern: %s\n", pattern); } void execute(std::vector args, RTLIL::Design *design) override diff --git a/passes/sat/eval.cc b/passes/sat/eval.cc index f71e8124b..b0eaaca22 100644 --- a/passes/sat/eval.cc +++ b/passes/sat/eval.cc @@ -94,11 +94,11 @@ struct BruteForceEquivChecker continue; if (mod2->wire(w->name) == nullptr) - log_cmd_error("Port %s in module 1 has no counterpart in module 2!\n", w->name.c_str()); + log_cmd_error("Port %s in module 1 has no counterpart in module 2!\n", w->name); RTLIL::Wire *w2 = mod2->wire(w->name); if (w->width != w2->width || w->port_input != w2->port_input || w->port_output != w2->port_output) - log_cmd_error("Port %s in module 1 does not match its counterpart in module 2!\n", w->name.c_str()); + log_cmd_error("Port %s in module 1 does not match its counterpart in module 2!\n", w->name); if (w->port_input) { mod1_inputs.append(w); @@ -454,11 +454,11 @@ struct EvalPass : public Pass { for (auto &it : sets) { RTLIL::SigSpec lhs, rhs; if (!RTLIL::SigSpec::parse_sel(lhs, design, module, it.first)) - log_cmd_error("Failed to parse lhs set expression `%s'.\n", it.first.c_str()); + log_cmd_error("Failed to parse lhs set expression `%s'.\n", it.first); if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, it.second)) - log_cmd_error("Failed to parse rhs set expression `%s'.\n", it.second.c_str()); + log_cmd_error("Failed to parse rhs set expression `%s'.\n", it.second); if (!rhs.is_fully_const()) - log_cmd_error("Right-hand-side set expression `%s' is not constant.\n", it.second.c_str()); + log_cmd_error("Right-hand-side set expression `%s' is not constant.\n", it.second); if (lhs.size() != rhs.size()) log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n", it.first.c_str(), log_signal(lhs), lhs.size(), it.second.c_str(), log_signal(rhs), rhs.size()); @@ -476,7 +476,7 @@ struct EvalPass : public Pass { for (auto &it : shows) { RTLIL::SigSpec signal, value, undef; if (!RTLIL::SigSpec::parse_sel(signal, design, module, it)) - log_cmd_error("Failed to parse show expression `%s'.\n", it.c_str()); + log_cmd_error("Failed to parse show expression `%s'.\n", it); value = signal; if (set_undef) { while (!ce.eval(value, undef)) { @@ -502,14 +502,14 @@ struct EvalPass : public Pass { for (auto &it : shows) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, it)) - log_cmd_error("Failed to parse show expression `%s'.\n", it.c_str()); + log_cmd_error("Failed to parse show expression `%s'.\n", it); signal.append(sig); } for (auto &it : tables) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, it)) - log_cmd_error("Failed to parse table expression `%s'.\n", it.c_str()); + log_cmd_error("Failed to parse table expression `%s'.\n", it); tabsigs.append(sig); } diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc index 9bcf25547..55a41909d 100644 --- a/passes/sat/miter.cc +++ b/passes/sat/miter.cc @@ -76,11 +76,11 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: RTLIL::IdString miter_name = RTLIL::escape_id(args[argidx++]); if (design->module(gold_name) == nullptr) - log_cmd_error("Can't find gold module %s!\n", gold_name.c_str()); + log_cmd_error("Can't find gold module %s!\n", gold_name); if (design->module(gate_name) == nullptr) - log_cmd_error("Can't find gate module %s!\n", gate_name.c_str()); + log_cmd_error("Can't find gate module %s!\n", gate_name); if (design->module(miter_name) != nullptr) - log_cmd_error("There is already a module %s!\n", miter_name.c_str()); + log_cmd_error("There is already a module %s!\n", miter_name); RTLIL::Module *gold_module = design->module(gold_name); RTLIL::Module *gate_module = design->module(gate_name); @@ -105,7 +105,7 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: goto match_gold_port_error; continue; match_gold_port_error: - log_cmd_error("No matching port in gate module was found for %s!\n", gold_wire->name.c_str()); + log_cmd_error("No matching port in gate module was found for %s!\n", gold_wire->name); } for (auto gate_wire : gate_module->wires()) { @@ -125,7 +125,7 @@ void create_miter_equiv(struct Pass *that, std::vector args, RTLIL: goto match_gate_port_error; continue; match_gate_port_error: - log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name.c_str()); + log_cmd_error("No matching port in gold module was found for %s!\n", gate_wire->name); } log("Creating miter cell \"%s\" with gold cell \"%s\" and gate cell \"%s\".\n", RTLIL::id2cstr(miter_name), RTLIL::id2cstr(gold_name), RTLIL::id2cstr(gate_name)); @@ -322,9 +322,9 @@ void create_miter_assert(struct Pass *that, std::vector args, RTLIL IdString miter_name = argidx < args.size() ? RTLIL::escape_id(args[argidx++]) : ""; if (design->module(module_name) == nullptr) - log_cmd_error("Can't find module %s!\n", module_name.c_str()); + log_cmd_error("Can't find module %s!\n", module_name); if (!miter_name.empty() && design->module(miter_name) != nullptr) - log_cmd_error("There is already a module %s!\n", miter_name.c_str()); + log_cmd_error("There is already a module %s!\n", miter_name); Module *module = design->module(module_name); diff --git a/passes/sat/mutate.cc b/passes/sat/mutate.cc index 58d932f20..79ffcd88d 100644 --- a/passes/sat/mutate.cc +++ b/passes/sat/mutate.cc @@ -989,7 +989,7 @@ struct MutatePass : public Pass { return; } - log_cmd_error("Invalid mode: %s\n", opts.mode.c_str()); + log_cmd_error("Invalid mode: %s\n", opts.mode); } } MutatePass; diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc index 20cee7956..ad28884f7 100644 --- a/passes/sat/qbfsat.cc +++ b/passes/sat/qbfsat.cc @@ -87,7 +87,7 @@ void specialize_from_file(RTLIL::Module *module, const std::string &file) { if (!std::regex_search(buf, bit_m, hole_bit_assn_regex)) { bit_assn = false; if (!std::regex_search(buf, m, hole_assn_regex)) - log_cmd_error("solution file is not formatted correctly: \"%s\"\n", buf.c_str()); + log_cmd_error("solution file is not formatted correctly: \"%s\"\n", buf); } std::string hole_loc = bit_assn? bit_m[1].str() : m[1].str(); @@ -108,7 +108,7 @@ void specialize_from_file(RTLIL::Module *module, const std::string &file) { pool hole_loc_pool(locs.begin(), locs.end()); auto hole_cell_it = anyconst_loc_to_cell.find(hole_loc_pool); if (hole_cell_it == anyconst_loc_to_cell.end()) - log_cmd_error("cannot find matching wire name or $anyconst cell location for hole spec \"%s\"\n", buf.c_str()); + log_cmd_error("cannot find matching wire name or $anyconst cell location for hole spec \"%s\"\n", buf); RTLIL::Cell *hole_cell = hole_cell_it->second; hole_sigbit = hole_cell->getPort(ID::Y)[hole_bit]; @@ -420,7 +420,7 @@ QbfSolveOptions parse_args(const std::vector &args) { else if (args[opt.argidx+1] == "cvc5") opt.solver = opt.Solver::CVC5; else - log_cmd_error("Unknown solver \"%s\".\n", args[opt.argidx+1].c_str()); + log_cmd_error("Unknown solver \"%s\".\n", args[opt.argidx+1]); opt.argidx++; } continue; @@ -457,7 +457,7 @@ QbfSolveOptions parse_args(const std::vector &args) { opt.oflag = opt.OptimizationLevel::O2; break; default: - log_cmd_error("unknown argument %s\n", args[opt.argidx].c_str()); + log_cmd_error("unknown argument %s\n", args[opt.argidx]); } continue; } diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 5216390da..90b85d709 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -106,9 +106,9 @@ struct SatHelper RTLIL::SigSpec lhs, rhs; if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first)) - log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first.c_str()); + log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first); if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second)) - log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second.c_str()); + log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second); show_signal_pool.add(sigmap(lhs)); show_signal_pool.add(sigmap(rhs)); @@ -127,9 +127,9 @@ struct SatHelper RTLIL::SigSpec lhs, rhs; if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first)) - log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first.c_str()); + log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first); if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second)) - log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second.c_str()); + log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second); show_signal_pool.add(sigmap(lhs)); show_signal_pool.add(sigmap(rhs)); @@ -148,7 +148,7 @@ struct SatHelper RTLIL::SigSpec lhs; if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s)) - log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.c_str()); + log_cmd_error("Failed to parse lhs set expression `%s'.\n", s); show_signal_pool.add(sigmap(lhs)); log("Import unset-constraint for this timestep: %s\n", log_signal(lhs)); @@ -167,28 +167,28 @@ struct SatHelper for (auto &s : sets_def) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, s)) - log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str()); + log_cmd_error("Failed to parse set-def expression `%s'.\n", s); sets_def_undef[0].insert(sig); } for (auto &s : sets_any_undef) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, s)) - log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str()); + log_cmd_error("Failed to parse set-def expression `%s'.\n", s); sets_def_undef[1].insert(sig); } for (auto &s : sets_all_undef) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, s)) - log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str()); + log_cmd_error("Failed to parse set-def expression `%s'.\n", s); sets_def_undef[2].insert(sig); } for (auto &s : sets_def_at[timestep]) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, s)) - log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str()); + log_cmd_error("Failed to parse set-def expression `%s'.\n", s); sets_def_undef[0].insert(sig); sets_def_undef[1].erase(sig); sets_def_undef[2].erase(sig); @@ -197,7 +197,7 @@ struct SatHelper for (auto &s : sets_any_undef_at[timestep]) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, s)) - log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str()); + log_cmd_error("Failed to parse set-def expression `%s'.\n", s); sets_def_undef[0].erase(sig); sets_def_undef[1].insert(sig); sets_def_undef[2].erase(sig); @@ -206,7 +206,7 @@ struct SatHelper for (auto &s : sets_all_undef_at[timestep]) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, s)) - log_cmd_error("Failed to parse set-def expression `%s'.\n", s.c_str()); + log_cmd_error("Failed to parse set-def expression `%s'.\n", s); sets_def_undef[0].erase(sig); sets_def_undef[1].erase(sig); sets_def_undef[2].insert(sig); @@ -295,9 +295,9 @@ struct SatHelper RTLIL::SigSpec lhs, rhs; if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first)) - log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first.c_str()); + log_cmd_error("Failed to parse lhs set expression `%s'.\n", s.first); if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second)) - log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second.c_str()); + log_cmd_error("Failed to parse rhs set expression `%s'.\n", s.second); show_signal_pool.add(sigmap(lhs)); show_signal_pool.add(sigmap(rhs)); @@ -362,9 +362,9 @@ struct SatHelper RTLIL::SigSpec lhs, rhs; if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first)) - log_cmd_error("Failed to parse lhs proof expression `%s'.\n", s.first.c_str()); + log_cmd_error("Failed to parse lhs proof expression `%s'.\n", s.first); if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second)) - log_cmd_error("Failed to parse rhs proof expression `%s'.\n", s.second.c_str()); + log_cmd_error("Failed to parse rhs proof expression `%s'.\n", s.second); show_signal_pool.add(sigmap(lhs)); show_signal_pool.add(sigmap(rhs)); @@ -390,9 +390,9 @@ struct SatHelper RTLIL::SigSpec lhs, rhs; if (!RTLIL::SigSpec::parse_sel(lhs, design, module, s.first)) - log_cmd_error("Failed to parse lhs proof-x expression `%s'.\n", s.first.c_str()); + log_cmd_error("Failed to parse lhs proof-x expression `%s'.\n", s.first); if (!RTLIL::SigSpec::parse_rhs(lhs, rhs, module, s.second)) - log_cmd_error("Failed to parse rhs proof-x expression `%s'.\n", s.second.c_str()); + log_cmd_error("Failed to parse rhs proof-x expression `%s'.\n", s.second); show_signal_pool.add(sigmap(lhs)); show_signal_pool.add(sigmap(rhs)); @@ -540,7 +540,7 @@ struct SatHelper for (auto &s : shows) { RTLIL::SigSpec sig; if (!RTLIL::SigSpec::parse_sel(sig, design, module, s)) - log_cmd_error("Failed to parse show expression `%s'.\n", s.c_str()); + log_cmd_error("Failed to parse show expression `%s'.\n", s); log("Import show expression: %s\n", log_signal(sig)); modelSig.append(sig); } @@ -670,7 +670,7 @@ struct SatHelper rewrite_filename(vcd_file_name); FILE *f = fopen(vcd_file_name.c_str(), "w"); if (!f) - log_cmd_error("Can't open output file `%s' for writing: %s\n", vcd_file_name.c_str(), strerror(errno)); + log_cmd_error("Can't open output file `%s' for writing: %s\n", vcd_file_name, strerror(errno)); log("Dumping SAT model to VCD file %s\n", vcd_file_name); @@ -775,7 +775,7 @@ struct SatHelper rewrite_filename(json_file_name); FILE *f = fopen(json_file_name.c_str(), "w"); if (!f) - log_cmd_error("Can't open output file `%s' for writing: %s\n", json_file_name.c_str(), strerror(errno)); + log_cmd_error("Can't open output file `%s' for writing: %s\n", json_file_name, strerror(errno)); log("Dumping SAT model to WaveJSON file '%s'.\n", json_file_name); @@ -1535,7 +1535,7 @@ struct SatPass : public Pass { rewrite_filename(cnf_file_name); FILE *f = fopen(cnf_file_name.c_str(), "w"); if (!f) - log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno)); + log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name, strerror(errno)); log("Dumping CNF to file `%s'.\n", cnf_file_name); cnf_file_name.clear(); @@ -1639,7 +1639,7 @@ struct SatPass : public Pass { rewrite_filename(cnf_file_name); FILE *f = fopen(cnf_file_name.c_str(), "w"); if (!f) - log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name.c_str(), strerror(errno)); + log_cmd_error("Can't open output file `%s' for writing: %s\n", cnf_file_name, strerror(errno)); log("Dumping CNF to file `%s'.\n", cnf_file_name); cnf_file_name.clear(); diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index aadea328f..56b207a58 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -2887,7 +2887,7 @@ struct SimPass : public Pass { } else if (filename_trim.size() > 3 && filename_trim.compare(filename_trim.size()-3, std::string::npos, ".yw") == 0) { worker.run_cosim_yw_witness(top_mod, append); } else { - log_cmd_error("Unhandled extension for simulation input file `%s`.\n", worker.sim_filename.c_str()); + log_cmd_error("Unhandled extension for simulation input file `%s`.\n", worker.sim_filename); } } diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index c5bdd6ecf..9cd02b455 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -988,7 +988,7 @@ void AbcModuleState::prepare_module(RTLIL::Design *design, RTLIL::Module *module } if (dff_mode && clk_sig.empty()) - log_cmd_error("Clock domain %s not found.\n", clk_str.c_str()); + log_cmd_error("Clock domain %s not found.\n", clk_str); const AbcConfig &config = run_abc.config; if (config.cleanup) @@ -2322,7 +2322,7 @@ struct AbcPass : public Pass { if (g_arg_from_cmd) cmd_error(args, g_argidx, stringf("Unsupported gate type: %s", g)); else - log_cmd_error("Unsupported gate type: %s", g.c_str()); + log_cmd_error("Unsupported gate type: %s", g); ok_gate: gate_list.push_back(g); ok_alias: diff --git a/passes/techmap/cellmatch.cc b/passes/techmap/cellmatch.cc index a2a4c4b2c..ce1a75193 100644 --- a/passes/techmap/cellmatch.cc +++ b/passes/techmap/cellmatch.cc @@ -173,7 +173,7 @@ struct CellmatchPass : Pass { derive_luts = true; } else if (args[argidx] == "-lib" && argidx + 1 < args.size()) { if (!saved_designs.count(args[++argidx])) - log_cmd_error("No design '%s' found!\n", args[argidx].c_str()); + log_cmd_error("No design '%s' found!\n", args[argidx]); lib = saved_designs.at(args[argidx]); } else { break; diff --git a/passes/techmap/constmap.cc b/passes/techmap/constmap.cc index f0757403d..6d18b8494 100644 --- a/passes/techmap/constmap.cc +++ b/passes/techmap/constmap.cc @@ -82,7 +82,7 @@ struct ConstmapPass : public Pass { } } if (!has_port) - log_cmd_error("Cell type '%s' does not have port '%s'.\n", celltype.c_str(), cell_portname.c_str()); + log_cmd_error("Cell type '%s' does not have port '%s'.\n", celltype, cell_portname); bool has_param = false; for (auto &p : existing->avail_parameters){ @@ -91,7 +91,7 @@ struct ConstmapPass : public Pass { } if (!has_param) - log_cmd_error("Cell type '%s' does not have parameter '%s'.\n", celltype.c_str(), cell_paramname.c_str()); + log_cmd_error("Cell type '%s' does not have parameter '%s'.\n", celltype, cell_paramname); } diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc index 6527b683e..7461e21d8 100644 --- a/passes/techmap/extract.cc +++ b/passes/techmap/extract.cc @@ -605,7 +605,7 @@ struct ExtractPass : public Pass { f.open(filename.c_str()); if (f.fail()) { delete map; - log_cmd_error("Can't open map file `%s'.\n", filename.c_str()); + log_cmd_error("Can't open map file `%s'.\n", filename); } Frontend::frontend_call(map, &f, filename, (filename.size() > 3 && filename.compare(filename.size()-3, std::string::npos, ".il") == 0 ? "rtlil" : "verilog")); f.close(); diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 75a63b2e0..f882aa356 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -958,7 +958,7 @@ struct TestCellPass : public Pass { if (args[argidx] == "-vlog" && argidx+1 < GetSize(args)) { vlog_file.open(args[++argidx], std::ios_base::trunc); if (!vlog_file.is_open()) - log_cmd_error("Failed to open output file `%s'.\n", args[argidx].c_str()); + log_cmd_error("Failed to open output file `%s'.\n", args[argidx]); continue; } if (args[argidx] == "-bloat" && argidx+1 < GetSize(args)) { @@ -1079,7 +1079,7 @@ struct TestCellPass : public Pass { for (; argidx < GetSize(args); argidx++) { if (args[argidx].rfind("-", 0) == 0) - log_cmd_error("Unexpected option: %s\n", args[argidx].c_str()); + log_cmd_error("Unexpected option: %s\n", args[argidx]); if (args[argidx] == "all") { for (auto &it : cell_types) diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 0e6553fa1..3b95ff91e 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -236,7 +236,7 @@ struct SynthPass : public ScriptPass if (args[argidx] == "-carry") { carry_mode = args[++argidx]; if (carry_mode != "none" && carry_mode != "ha") - log_cmd_error("Unsupported carry style: %s\n", carry_mode.c_str()); + log_cmd_error("Unsupported carry style: %s\n", carry_mode); continue; } if (args[argidx] == "-noflatten") { diff --git a/techlibs/greenpak4/synth_greenpak4.cc b/techlibs/greenpak4/synth_greenpak4.cc index 99fe45dc4..fa52ecfc6 100644 --- a/techlibs/greenpak4/synth_greenpak4.cc +++ b/techlibs/greenpak4/synth_greenpak4.cc @@ -123,7 +123,7 @@ struct SynthGreenPAK4Pass : public ScriptPass log_cmd_error("This command only operates on fully selected designs!\n"); if (part != "SLG46140V" && part != "SLG46620V" && part != "SLG46621V") - log_cmd_error("Invalid part name: '%s'\n", part.c_str()); + log_cmd_error("Invalid part name: '%s'\n", part); log_header(design, "Executing SYNTH_GREENPAK4 pass.\n"); log_push(); diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index d433c0408..0a4144451 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -265,7 +265,7 @@ struct SynthIce40Pass : public ScriptPass if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); if (device_opt != "hx" && device_opt != "lp" && device_opt !="u") - log_cmd_error("Invalid or no device specified: '%s'\n", device_opt.c_str()); + log_cmd_error("Invalid or no device specified: '%s'\n", device_opt); if (abc9 && retime) log_cmd_error("-retime option not currently compatible with -abc9!\n"); diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index af0717235..d3202d5cb 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -174,7 +174,7 @@ struct SynthIntelPass : public ScriptPass { family_opt != "cycloneiv" && family_opt != "cycloneive" && family_opt != "cyclone10lp") - log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str()); + log_cmd_error("Invalid or no family specified: '%s'\n", family_opt); log_header(design, "Executing SYNTH_INTEL pass.\n"); log_push(); diff --git a/techlibs/lattice/synth_lattice.cc b/techlibs/lattice/synth_lattice.cc index e1df20dd7..b13c22518 100644 --- a/techlibs/lattice/synth_lattice.cc +++ b/techlibs/lattice/synth_lattice.cc @@ -306,7 +306,7 @@ struct SynthLatticePass : public ScriptPass family == "lifmd" || family == "lifmdf") {*/ } else - log_cmd_error("Invalid Lattice -family setting: '%s'.\n", family.c_str()); + log_cmd_error("Invalid Lattice -family setting: '%s'.\n", family); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); diff --git a/techlibs/microchip/synth_microchip.cc b/techlibs/microchip/synth_microchip.cc index 77cedcd1f..e1d3c393a 100644 --- a/techlibs/microchip/synth_microchip.cc +++ b/techlibs/microchip/synth_microchip.cc @@ -234,7 +234,7 @@ struct SynthMicrochipPass : public ScriptPass { if (family == "polarfire") { lut_size = 4; } else { - log_cmd_error("Invalid Microchip -family setting: '%s'.\n", family.c_str()); + log_cmd_error("Invalid Microchip -family setting: '%s'.\n", family); } if (!design->full_selection()) diff --git a/techlibs/nanoxplore/synth_nanoxplore.cc b/techlibs/nanoxplore/synth_nanoxplore.cc index a8f4a05d1..3445ea1be 100644 --- a/techlibs/nanoxplore/synth_nanoxplore.cc +++ b/techlibs/nanoxplore/synth_nanoxplore.cc @@ -218,7 +218,7 @@ struct SynthNanoXplorePass : public ScriptPass } else if (family == "large") { postfix = "_l"; } else - log_cmd_error("Invalid NanoXplore -family setting: '%s'.\n", family.c_str()); + log_cmd_error("Invalid NanoXplore -family setting: '%s'.\n", family); if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); diff --git a/techlibs/nexus/synth_nexus.cc b/techlibs/nexus/synth_nexus.cc index 83abd156a..c0df06a21 100644 --- a/techlibs/nexus/synth_nexus.cc +++ b/techlibs/nexus/synth_nexus.cc @@ -249,7 +249,7 @@ struct SynthNexusPass : public ScriptPass { if (family != "lifcl" && family != "lfd2nx") - log_cmd_error("Invalid Nexus -family setting: '%s'.\n", family.c_str()); + log_cmd_error("Invalid Nexus -family setting: '%s'.\n", family); if (check_label("begin")) { diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc index 84f9c48a7..ade6f944c 100644 --- a/techlibs/quicklogic/synth_quicklogic.cc +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -176,7 +176,7 @@ struct SynthQuickLogicPass : public ScriptPass { log_cmd_error("This command only operates on fully selected designs!\n"); if (family != "pp3" && family != "qlf_k6n10f") - log_cmd_error("Invalid family specified: '%s'\n", family.c_str()); + log_cmd_error("Invalid family specified: '%s'\n", family); if (abc9 && design->scratchpad_get_int("abc9.D", 0) == 0) { log_warning("delay target has not been set via SDC or scratchpad; assuming 12 MHz clock.\n"); diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 4e422c5cd..20b8c98c3 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -310,7 +310,7 @@ struct SynthXilinxPass : public ScriptPass lut_size = 4; widelut_size = 6; } else - log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family.c_str()); + log_cmd_error("Invalid Xilinx -family setting: '%s'.\n", family); if (widemux != 0 && lut_size != 6) log_cmd_error("-widemux is not currently supported for LUT4-based architectures.\n"); From d1fd6de6da916cc3fbb64c962d94236e02568e71 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 16 Sep 2025 23:00:42 +0000 Subject: [PATCH 35/60] Remove .c_str() calls from parameters to log_header() --- frontends/ast/ast.cc | 2 +- frontends/liberty/liberty.cc | 2 +- frontends/rpc/rpc_frontend.cc | 2 +- frontends/verilog/verilog_frontend.cc | 2 +- kernel/register.cc | 2 +- passes/cmds/exec.cc | 2 +- passes/cmds/logcmd.cc | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 488775d2c..4a16abee9 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -1822,7 +1822,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict rewritten; diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc index 72ad8b2b7..80553347c 100644 --- a/frontends/liberty/liberty.cc +++ b/frontends/liberty/liberty.cc @@ -537,7 +537,7 @@ struct LibertyFrontend : public Frontend { if (flag_wb && flag_lib) log_error("-wb and -lib cannot be specified together!\n"); - log_header(design, "Executing Liberty frontend: %s\n", filename.c_str()); + log_header(design, "Executing Liberty frontend: %s\n", filename); LibertyParser parser(*f, filename); int cell_count = 0; diff --git a/frontends/rpc/rpc_frontend.cc b/frontends/rpc/rpc_frontend.cc index 80a6aae6d..625b2c0e8 100644 --- a/frontends/rpc/rpc_frontend.cc +++ b/frontends/rpc/rpc_frontend.cc @@ -163,7 +163,7 @@ struct RpcModule : RTLIL::Module { stripped_name = stripped_name.substr(9); log_assert(stripped_name[0] == '\\'); - log_header(design, "Executing RPC frontend `%s' for module `%s'.\n", server->name.c_str(), stripped_name.c_str()); + log_header(design, "Executing RPC frontend `%s' for module `%s'.\n", server->name, stripped_name); std::string parameter_info; for (auto ¶m : parameters) { diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 231891271..2bdaf40ce 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -485,7 +485,7 @@ struct VerilogFrontend : public Frontend { extra_args(f, filename, args, argidx); - log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str()); + log_header(design, "Executing Verilog-2005 frontend: %s\n", filename); log("Parsing %s%s input from `%s' to AST representation.\n", parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str()); diff --git a/kernel/register.cc b/kernel/register.cc index 36e312968..fe67cc35c 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -199,7 +199,7 @@ void Pass::call(RTLIL::Design *design, std::string command) while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' || cmd_buf.back() == '\r' || cmd_buf.back() == '\n')) cmd_buf.resize(cmd_buf.size()-1); - log_header(design, "Shell command: %s\n", cmd_buf.c_str()); + log_header(design, "Shell command: %s\n", cmd_buf); int retCode = run_command(cmd_buf); if (retCode != 0) log_cmd_error("Shell command returned error code %d.\n", retCode); diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc index ff1ef11ff..ea82ff908 100644 --- a/passes/cmds/exec.cc +++ b/passes/cmds/exec.cc @@ -150,7 +150,7 @@ struct ExecPass : public Pass { } } - log_header(design, "Executing command \"%s\".\n", cmd.c_str()); + log_header(design, "Executing command \"%s\".\n", cmd); log_push(); fflush(stdout); diff --git a/passes/cmds/logcmd.cc b/passes/cmds/logcmd.cc index 57759fc90..dd2d708d8 100644 --- a/passes/cmds/logcmd.cc +++ b/passes/cmds/logcmd.cc @@ -107,7 +107,7 @@ struct LogPass : public Pass { if (to_stderr) fprintf(stderr, "%s%s", text.c_str(), line_end); if (to_log) { if (!header) log("%s%s", text, line_end); - else log_header(design, "%s%s", text.c_str(), line_end); + else log_header(design, "%s%s", text, line_end); } } } LogPass; From a7c46f7b4afc182af11b6f6ffb7a166d60fe7997 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 16 Sep 2025 23:02:16 +0000 Subject: [PATCH 36/60] Remove .c_str() calls from parameters to log_warning()/log_warning_noprefix() --- backends/edif/edif.cc | 2 +- backends/firrtl/firrtl.cc | 6 +++--- frontends/ast/simplify.cc | 8 ++++---- frontends/verific/verific.cc | 4 ++-- frontends/verific/verificsva.cc | 2 +- kernel/log.cc | 4 ++-- kernel/register.cc | 2 +- kernel/tclapi.cc | 2 +- passes/cmds/check.cc | 6 +++--- passes/cmds/select.cc | 8 ++++---- passes/cmds/stat.cc | 4 ++-- passes/cmds/timeest.cc | 2 +- passes/equiv/equiv_add.cc | 8 ++++---- passes/fsm/fsm_detect.cc | 2 +- passes/hierarchy/hierarchy.cc | 2 +- passes/hierarchy/submod.cc | 4 ++-- passes/memory/memlib.cc | 2 +- passes/opt/opt_clean.cc | 2 +- passes/sat/qbfsat.cc | 2 +- passes/sat/sim.cc | 24 ++++++++++++------------ passes/techmap/abc9_exe.cc | 2 +- passes/techmap/libparse.cc | 4 ++-- passes/tests/test_cell.cc | 2 +- techlibs/intel/synth_intel.cc | 2 +- techlibs/xilinx/synth_xilinx.cc | 2 +- 25 files changed, 54 insertions(+), 54 deletions(-) diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 83d0afaf3..d1be0b37f 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -513,7 +513,7 @@ struct EdifBackend : public Backend { if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1) { if (sig == RTLIL::State::Sx) { for (auto &ref : it.second) - log_warning("Exporting x-bit on %s as zero bit.\n", ref.first.c_str()); + log_warning("Exporting x-bit on %s as zero bit.\n", ref.first); sig = RTLIL::State::S0; } else if (sig == RTLIL::State::Sz) { continue; diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index e54b46e63..577d95ad7 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -465,7 +465,7 @@ struct FirrtlWorker // If there is no instance for this, just return. if (instModule == NULL) { - log_warning("No instance for %s.%s\n", cell_type.c_str(), cell_name.c_str()); + log_warning("No instance for %s.%s\n", cell_type, cell_name); return; } @@ -490,7 +490,7 @@ struct FirrtlWorker const SigSpec *sinkSig = nullptr; switch (dir) { case FD_INOUT: - log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type.c_str(), log_signal(it->second)); + log_warning("Instance port connection %s.%s is INOUT; treating as OUT\n", cell_type, log_signal(it->second)); YS_FALLTHROUGH case FD_OUT: sourceExpr = firstName; @@ -498,7 +498,7 @@ struct FirrtlWorker sinkSig = &secondSig; break; case FD_NODIRECTION: - log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type.c_str(), log_signal(it->second)); + log_warning("Instance port connection %s.%s is NODIRECTION; treating as IN\n", cell_type, log_signal(it->second)); YS_FALLTHROUGH case FD_IN: sourceExpr = secondExpr; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 0df09030c..9b679d0aa 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -974,7 +974,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin message += stringf("%s%s", first_element ? " See " : ", ", place); first_element = false; } - log_warning("%s\n", message.c_str()); + log_warning("%s\n", message); } silent_activate: @@ -1144,7 +1144,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin i--; // Adjust index since we removed an element } else { // If we can't find the package, just remove the import node to avoid errors later - log_warning("Package `%s' not found for import, removing import statement\n", child->str.c_str()); + log_warning("Package `%s' not found for import, removing import statement\n", child->str); children.erase(children.begin() + i); i--; // Adjust index since we removed an element } @@ -1438,7 +1438,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic) children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) - log_warning("wire '%s' is assigned in a block at %s.\n", children[0]->str.c_str(), loc_string().c_str()); + log_warning("wire '%s' is assigned in a block at %s.\n", children[0]->str, loc_string()); if (type == AST_ASSIGN && children[0]->id2ast->is_reg) { bool is_rand_reg = false; if (children[1]->type == AST_FCALL) { @@ -1452,7 +1452,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin is_rand_reg = true; } if (!is_rand_reg) - log_warning("reg '%s' is assigned in a continuous assignment at %s.\n", children[0]->str.c_str(), loc_string().c_str()); + log_warning("reg '%s' is assigned in a continuous assignment at %s.\n", children[0]->str, loc_string()); } children[0]->was_checked = true; } diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 91af38ccd..279b0dd52 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -141,7 +141,7 @@ void msg_func(msg_type_t msg_type, const char *message_id, linefile_type linefil #endif } else { if (msg_type == VERIFIC_ERROR || msg_type == VERIFIC_WARNING || msg_type == VERIFIC_PROGRAM_ERROR) - log_warning_noprefix("%s%s\n", message_prefix.c_str(), message.c_str()); + log_warning_noprefix("%s%s\n", message_prefix, message); else log("%s%s\n", message_prefix, message); } @@ -4098,7 +4098,7 @@ struct VerificPass : public Pass { unsigned new_insertion = parameters.Insert(key.c_str(), value.c_str(), 1 /* force_overwrite */); if (!new_insertion) - log_warning_noprefix("-chparam %s already specified: overwriting.\n", key.c_str()); + log_warning_noprefix("-chparam %s already specified: overwriting.\n", key); continue; } if (args[argidx] == "-V") { diff --git a/frontends/verific/verificsva.cc b/frontends/verific/verificsva.cc index cc5f07004..3908947eb 100644 --- a/frontends/verific/verificsva.cc +++ b/frontends/verific/verificsva.cc @@ -1025,7 +1025,7 @@ struct VerificSvaImporter { if (!importer->mode_keep) log_error("%s", errmsg); - log_warning("%s", errmsg.c_str()); + log_warning("%s", errmsg); throw ParserErrorException(); } diff --git a/kernel/log.cc b/kernel/log.cc index 3a44a3ddc..0085980b1 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -187,7 +187,7 @@ static void logv_string(std::string_view format, std::string str) { if (!linebuffer.empty() && linebuffer.back() == '\n') { for (auto &re : log_warn_regexes) if (std::regex_search(linebuffer, re)) - log_warning("Found log message matching -W regex:\n%s", str.c_str()); + log_warning("Found log message matching -W regex:\n%s", str); for (auto &[_, item] : log_expect_log) if (std::regex_search(linebuffer, item.pattern)) @@ -704,7 +704,7 @@ dict> get_coverage_data() for (auto &it : extra_coverage_data) { if (coverage_data.count(it.first)) - log_warning("found duplicate coverage id \"%s\".\n", it.first.c_str()); + log_warning("found duplicate coverage id \"%s\".\n", it.first); coverage_data[it.first].first = it.second.first; coverage_data[it.first].second += it.second.second; } diff --git a/kernel/register.cc b/kernel/register.cc index fe67cc35c..9436b540a 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -972,7 +972,7 @@ struct HelpPass : public Pass { } for (auto &it : cell_help_messages.cell_help) { if (cells.count(it.first) == 0) { - log_warning("Found cell model '%s' without matching cell type.\n", it.first.c_str()); + log_warning("Found cell model '%s' without matching cell type.\n", it.first); } } diff --git a/kernel/tclapi.cc b/kernel/tclapi.cc index 729d06ca0..a2ebaffa2 100644 --- a/kernel/tclapi.cc +++ b/kernel/tclapi.cc @@ -137,7 +137,7 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a if (err.empty()) { Tcl_SetObjResult(interp, json_to_tcl(interp, json)); } else - log_warning("Ignoring result.json scratchpad value due to parse error: %s\n", err.c_str()); + log_warning("Ignoring result.json scratchpad value due to parse error: %s\n", err); } else if ((result = scratchpad.find("result.string")) != scratchpad.end()) { Tcl_SetObjResult(interp, Tcl_NewStringObj(result->second.data(), result->second.size())); } diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index b532b4527..9f72d90f7 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -323,7 +323,7 @@ struct CheckPass : public Pass { string message = stringf("Drivers conflicting with a constant %s driver:\n", log_signal(state)); for (auto str : wire_drivers[state]) message += stringf(" %s\n", str); - log_warning("%s", message.c_str()); + log_warning("%s", message); counter++; } @@ -332,7 +332,7 @@ struct CheckPass : public Pass { string message = stringf("multiple conflicting drivers for %s.%s:\n", log_id(module), log_signal(it.first)); for (auto str : it.second) message += stringf(" %s\n", str); - log_warning("%s", message.c_str()); + log_warning("%s", message); counter++; } @@ -418,7 +418,7 @@ struct CheckPass : public Pass { prev = bit; } - log_warning("%s", message.c_str()); + log_warning("%s", message); counter++; } diff --git a/passes/cmds/select.cc b/passes/cmds/select.cc index 469e36ef1..6da15c19a 100644 --- a/passes/cmds/select.cc +++ b/passes/cmds/select.cc @@ -658,7 +658,7 @@ static void select_op_expand(RTLIL::Design *design, const std::string &arg, char } if (rem_objects == 0) - log_warning("reached configured limit at `%s'.\n", arg.c_str()); + log_warning("reached configured limit at `%s'.\n", arg); } static void select_filter_active_mod(RTLIL::Design *design, RTLIL::Selection &sel) @@ -1002,14 +1002,14 @@ static void select_stmt(RTLIL::Design *design, std::string arg, bool disable_emp if (it.second == false && !disable_empty_warning) { std::string selection_str = select_blackboxes ? "=" : ""; selection_str += it.first; - log_warning("Selection \"%s\" did not match any module.\n", selection_str.c_str()); + log_warning("Selection \"%s\" did not match any module.\n", selection_str); } } for (auto &it : arg_memb_found) { if (it.second == false && !disable_empty_warning) { std::string selection_str = select_blackboxes ? "=" : ""; selection_str += it.first; - log_warning("Selection \"%s\" did not match any object.\n", selection_str.c_str()); + log_warning("Selection \"%s\" did not match any object.\n", selection_str); } } } @@ -1451,7 +1451,7 @@ struct SelectPass : public Pass { while (std::getline(f, line)) { size_t slash_pos = line.find('/'); if (slash_pos == string::npos) { - log_warning("Ignoring line without slash in 'select -read': %s\n", line.c_str()); + log_warning("Ignoring line without slash in 'select -read': %s\n", line); continue; } IdString mod_name = RTLIL::escape_id(line.substr(0, slash_pos)); diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 6e46ab5e2..61135e066 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -228,7 +228,7 @@ struct statdata_t { cell_area.at(cell_type).is_sequential = cell_data.is_sequential; } else { - log_warning("too small single_parameter_area %s width: %d size: %d\n", cell_type.c_str(), max_width, + log_warning("too small single_parameter_area %s width: %d size: %d\n", cell_type, max_width, (int)cell_data.single_parameter_area.size()); cell_area.at(cell_type).area = cell_data.single_parameter_area.back(); cell_area.at(cell_type).is_sequential = cell_data.is_sequential; @@ -274,7 +274,7 @@ struct statdata_t { cell_data.double_parameter_area.at(width_a - 1).at(width_b - 1); cell_area.at(cell_type).is_sequential = cell_data.is_sequential; } else { - log_warning("too small double_parameter_area %s, width_a: %d, width_b: %d, size_a: %d, size_b: %d\n", cell_type.c_str(), + log_warning("too small double_parameter_area %s, width_a: %d, width_b: %d, size_a: %d, size_b: %d\n", cell_type, width_a, width_b, (int)cell_data.double_parameter_area.size(), (int)cell_data.double_parameter_area.at(width_a - 1).size()); cell_area.at(cell_type).area = cell_data.double_parameter_area.back().back(); diff --git a/passes/cmds/timeest.cc b/passes/cmds/timeest.cc index 86a529520..b878050da 100644 --- a/passes/cmds/timeest.cc +++ b/passes/cmds/timeest.cc @@ -403,7 +403,7 @@ struct TimeestPass : Pass { for (auto m : d->selected_modules()) { if (!m->wire(RTLIL::escape_id(clk))) { - log_warning("No domain '%s' in module %s\n", clk.c_str(), log_id(m)); + log_warning("No domain '%s' in module %s\n", clk, log_id(m)); continue; } diff --git a/passes/equiv/equiv_add.cc b/passes/equiv/equiv_add.cc index 4deef6e32..b3c97fa80 100644 --- a/passes/equiv/equiv_add.cc +++ b/passes/equiv/equiv_add.cc @@ -61,7 +61,7 @@ struct EquivAddPass : public Pass { if (gold_cell == nullptr) { if (try_mode) { - log_warning("Can't find gold cell '%s'.\n", args[2].c_str()); + log_warning("Can't find gold cell '%s'.\n", args[2]); return; } log_cmd_error("Can't find gold cell '%s'.\n", args[2]); @@ -69,7 +69,7 @@ struct EquivAddPass : public Pass { if (gate_cell == nullptr) { if (try_mode) { - log_warning("Can't find gate cell '%s'.\n", args[3].c_str()); + log_warning("Can't find gate cell '%s'.\n", args[3]); return; } log_cmd_error("Can't find gate cell '%s'.\n", args[3]); @@ -126,7 +126,7 @@ struct EquivAddPass : public Pass { if (!SigSpec::parse(gate_signal, module, args[2])) { if (try_mode) { - log_warning("Error in gate signal: %s\n", args[2].c_str()); + log_warning("Error in gate signal: %s\n", args[2]); return; } log_cmd_error("Error in gate signal: %s\n", args[2]); @@ -134,7 +134,7 @@ struct EquivAddPass : public Pass { if (!SigSpec::parse_rhs(gate_signal, gold_signal, module, args[1])) { if (try_mode) { - log_warning("Error in gold signal: %s\n", args[1].c_str()); + log_warning("Error in gold signal: %s\n", args[1]); return; } log_cmd_error("Error in gold signal: %s\n", args[1]); diff --git a/passes/fsm/fsm_detect.cc b/passes/fsm/fsm_detect.cc index 86d654cc4..9cffbf95a 100644 --- a/passes/fsm/fsm_detect.cc +++ b/passes/fsm/fsm_detect.cc @@ -225,7 +225,7 @@ static void detect_fsm(RTLIL::Wire *wire, bool ignore_self_reset=false) if (!warnings.empty()) { string warnmsg = stringf("Regarding the user-specified fsm_encoding attribute on %s.%s:\n", log_id(wire->module), log_id(wire)); for (auto w : warnings) warnmsg += " " + w; - log_warning("%s", warnmsg.c_str()); + log_warning("%s", warnmsg); } else { log("FSM state register %s.%s already has fsm_encoding attribute.\n", log_id(wire->module), log_id(wire)); } diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index f670d1fd2..a7f86c3f0 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -937,7 +937,7 @@ struct HierarchyPass : public Pass { const std::string &value = args[++argidx]; auto r = parameters.emplace(key, value); if (!r.second) { - log_warning("-chparam %s already specified: overwriting.\n", key.c_str()); + log_warning("-chparam %s already specified: overwriting.\n", key); r.first->second = value; } continue; diff --git a/passes/hierarchy/submod.cc b/passes/hierarchy/submod.cc index f979e7acc..bf135386c 100644 --- a/passes/hierarchy/submod.cc +++ b/passes/hierarchy/submod.cc @@ -95,7 +95,7 @@ struct SubmodWorker for (auto &conn : cell->connections()) flag_signal(conn.second, true, ct.cell_output(cell->type, conn.first), ct.cell_input(cell->type, conn.first), false, false); } else { - log_warning("Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name.c_str(), cell->type.c_str()); + log_warning("Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name, cell->type); for (auto &conn : cell->connections()) flag_signal(conn.second, true, true, true, false, false); } @@ -111,7 +111,7 @@ struct SubmodWorker for (auto &conn : cell->connections()) flag_signal(conn.second, false, false, false, true, true); if (flag_found_something) - log_warning("Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name.c_str(), cell->type.c_str()); + log_warning("Port directions for cell %s (%s) are unknown. Assuming inout for all ports.\n", cell->name, cell->type); } } diff --git a/passes/memory/memlib.cc b/passes/memory/memlib.cc index 216b750fd..11c9f9074 100644 --- a/passes/memory/memlib.cc +++ b/passes/memory/memlib.cc @@ -1097,7 +1097,7 @@ Library MemLibrary::parse_library(const std::vector &filenames, con Parser(file, res, defines, defines_unused); } for (auto def: defines_unused) { - log_warning("define %s not used in the library.\n", def.c_str()); + log_warning("define %s not used in the library.\n", def); } return res; } diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index cef2c0dc3..b9df09ea6 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -233,7 +233,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto it : driver_driver_logs) { if (used_raw_bits.count(it.first)) for (auto msg : it.second) - log_warning("%s\n", msg.c_str()); + log_warning("%s\n", msg); } } diff --git a/passes/sat/qbfsat.cc b/passes/sat/qbfsat.cc index ad28884f7..b011227e2 100644 --- a/passes/sat/qbfsat.cc +++ b/passes/sat/qbfsat.cc @@ -233,7 +233,7 @@ QbfSolutionType call_qbf_solver(RTLIL::Module *mod, const QbfSolveOptions &opt, ret.stdout_lines.push_back(line.substr(0, line.size()-1)); //don't include trailing newline auto warning_pos = line.find(smtbmc_warning); if (warning_pos != std::string::npos) - log_warning("%s", line.substr(warning_pos + smtbmc_warning.size() + 1).c_str()); + log_warning("%s", line.substr(warning_pos + smtbmc_warning.size() + 1)); else if (opt.show_smtbmc && !quiet) log("smtbmc output: %s", line); diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 56b207a58..1b653a218 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -256,7 +256,7 @@ struct SimInstance if ((shared->fst) && !(shared->hide_internal && wire->name[0] == '$')) { fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); if (id==0 && wire->name.isPublic()) - log_warning("Unable to find wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(wire->name)).c_str()); + log_warning("Unable to find wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(wire->name))); fst_handles[wire] = id; } @@ -927,7 +927,7 @@ struct SimInstance if (shared->serious_asserts) log_error("Assertion %s.%s (%s) failed.\n", hiername(), log_id(cell), label); else - log_warning("Assertion %s.%s (%s) failed.\n", hiername().c_str(), log_id(cell), label.c_str()); + log_warning("Assertion %s.%s (%s) failed.\n", hiername(), log_id(cell), label); } } } @@ -1244,7 +1244,7 @@ struct SimInstance Const fst_val = Const::from_string(shared->fst->valueOf(item.second)); Const sim_val = get_state(item.first); if (sim_val.size()!=fst_val.size()) { - log_warning("Signal '%s.%s' size is different in gold and gate.\n", scope.c_str(), log_id(item.first)); + log_warning("Signal '%s.%s' size is different in gold and gate.\n", scope, log_id(item.first)); continue; } if (shared->sim_mode == SimulationMode::sim) { @@ -1252,7 +1252,7 @@ struct SimInstance } else if (shared->sim_mode == SimulationMode::gate && !fst_val.is_fully_def()) { // FST data contains X for(int i=0;isim_mode == SimulationMode::gold && !sim_val.is_fully_def()) { // sim data contains X for(int i=0;icell(escaped_s); if (!c) - log_warning("Wire/cell %s not present in module %s\n",symbol.c_str(),log_id(topmod)); + log_warning("Wire/cell %s not present in module %s\n",symbol,log_id(topmod)); if (c->is_mem_cell()) { std::string memid = c->parameters.at(ID::MEMID).decode_string(); @@ -1873,7 +1873,7 @@ struct SimWorker : SimShared log("witness hierarchy: found wire %s\n", path.str()); bool inserted = hierarchy.paths.emplace(path, {instance, item.wire, {}, INT_MIN}).second; if (!inserted) - log_warning("Yosys witness path `%s` is ambiguous in this design\n", path.str().c_str()); + log_warning("Yosys witness path `%s` is ambiguous in this design\n", path.str()); } } else if (item.mem) { auto it = mem_paths.find(path); @@ -1890,7 +1890,7 @@ struct SimWorker : SimShared continue; bool inserted = hierarchy.paths.emplace(word_path, {instance, nullptr, item.mem->memid, addr}).second; if (!inserted) - log_warning("Yosys witness path `%s` is ambiguous in this design\n", path.str().c_str()); + log_warning("Yosys witness path `%s` is ambiguous in this design\n", path.str()); } } } @@ -1899,7 +1899,7 @@ struct SimWorker : SimShared for (auto &path : paths) if (!hierarchy.paths.count(path)) - log_warning("Yosys witness path `%s` was not found in this design, ignoring\n", path.str().c_str()); + log_warning("Yosys witness path `%s` was not found in this design, ignoring\n", path.str()); dict> clock_inputs; @@ -1922,7 +1922,7 @@ struct SimWorker : SimShared for (int t = 0; t < GetSize(yw.steps); t++) { if (yw.get_bits(t, clock_bits_offset, 1) != expected) - log_warning("Yosys witness trace has an unexpected value for the clock input `%s` in step %d.\n", signal.path.str().c_str(), t); + log_warning("Yosys witness trace has an unexpected value for the clock input `%s` in step %d.\n", signal.path.str(), t); } } } @@ -2000,7 +2000,7 @@ struct SimWorker : SimShared YwHierarchy hierarchy = prepare_yw_hierarchy(yw); if (yw.steps.empty()) { - log_warning("Yosys witness file `%s` contains no time steps\n", yw.filename.c_str()); + log_warning("Yosys witness file `%s` contains no time steps\n", yw.filename); } else { top->set_initstate_outputs(initstate ? State::S1 : State::S0); set_yw_state(yw, hierarchy, 0); diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index d7a7e3d4a..ac723fdbb 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -329,7 +329,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe #endif if (ret != 0) { if (check_file_exists(stringf("%s/output.aig", tempdir_name))) - log_warning("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret); + log_warning("ABC: execution of command \"%s\" failed: return code %d.\n", buffer, ret); else log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer, ret); } diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index c89495c62..7d4fd77ad 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -191,7 +191,7 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) { s.next(); lhs = parse(s); if (s.peek() != ')') { - log_warning("expected ')' instead of '%c' while parsing Liberty expression '%s'\n", s.peek(), s.full_expr().c_str()); + log_warning("expected ')' instead of '%c' while parsing Liberty expression '%s'\n", s.peek(), s.full_expr()); return lhs; } s.next(); @@ -200,7 +200,7 @@ LibertyExpression LibertyExpression::parse(Lexer &s, int min_prio) { lhs.kind = Kind::NOT; lhs.children.push_back(parse(s, 7)); } else { - log_warning("unrecognised character '%c' while parsing Liberty expression '%s'\n", c, s.full_expr().c_str()); + log_warning("unrecognised character '%c' while parsing Liberty expression '%s'\n", c, s.full_expr()); return lhs; } diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index f882aa356..9603956a8 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -1192,7 +1192,7 @@ struct TestCellPass : public Pass { worst_abs = num_cells - num_cells_estimate; worst_rel = (float)(num_cells - num_cells_estimate) / (float)num_cells_estimate; } - log_warning("Upper bound violated for %s: %d > %d\n", cell_type.c_str(), num_cells, num_cells_estimate); + log_warning("Upper bound violated for %s: %d > %d\n", cell_type, num_cells, num_cells_estimate); } } } diff --git a/techlibs/intel/synth_intel.cc b/techlibs/intel/synth_intel.cc index d3202d5cb..e02885cd0 100644 --- a/techlibs/intel/synth_intel.cc +++ b/techlibs/intel/synth_intel.cc @@ -242,7 +242,7 @@ struct SynthIntelPass : public ScriptPass { run("memory_bram -rules +/intel/common/brams_m9k.txt", "(if applicable for family)"); run("techmap -map +/intel/common/brams_map_m9k.v", "(if applicable for family)"); } else { - log_warning("BRAM mapping is not currently supported for %s.\n", family_opt.c_str()); + log_warning("BRAM mapping is not currently supported for %s.\n", family_opt); } } diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc index 20b8c98c3..46b30573c 100644 --- a/techlibs/xilinx/synth_xilinx.cc +++ b/techlibs/xilinx/synth_xilinx.cc @@ -316,7 +316,7 @@ struct SynthXilinxPass : public ScriptPass log_cmd_error("-widemux is not currently supported for LUT4-based architectures.\n"); if (lut_size != 6) { - log_warning("Shift register inference not yet supported for family %s.\n", family.c_str()); + log_warning("Shift register inference not yet supported for family %s.\n", family); nosrl = true; } From 548deba259e8f58ed2704ee237347a965b0b8b26 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 16 Sep 2025 23:03:45 +0000 Subject: [PATCH 37/60] Remove .c_str() calls from parameters to log_file_warning() --- frontends/ast/genrtlil.cc | 4 ++-- frontends/ast/simplify.cc | 4 ++-- frontends/verilog/const2ast.cc | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 5fd478ff3..84f2f9d73 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1539,7 +1539,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (dynamic_cast(current_module)) { /* nothing to do here */ } else if (flag_autowire) - log_file_warning(*location.begin.filename, location.begin.line, "Identifier `%s' is implicitly declared.\n", str.c_str()); + log_file_warning(*location.begin.filename, location.begin.line, "Identifier `%s' is implicitly declared.\n", str); else input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str); } @@ -2200,7 +2200,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) log_file_info(*location.begin.filename, location.begin.line, "\n"); } else if (str == "$warning") { if (sz > 0) - log_file_warning(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str.c_str()); + log_file_warning(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str); else log_file_warning(*location.begin.filename, location.begin.line, "\n"); } else if (str == "$error") { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 9b679d0aa..d4e78b730 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1032,7 +1032,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // note that $display, $finish, and $stop are used for synthesis-time DRC so they're not in this list if ((type == AST_FCALL || type == AST_TCALL) && (str == "$strobe" || str == "$monitor" || str == "$time" || str == "$dumpfile" || str == "$dumpvars" || str == "$dumpon" || str == "$dumpoff" || str == "$dumpall")) { - log_file_warning(*location.begin.filename, location.begin.line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str.c_str()); + log_file_warning(*location.begin.filename, location.begin.line, "Ignoring call to system %s %s.\n", type == AST_FCALL ? "function" : "task", str); delete_children(); str = std::string(); } @@ -1042,7 +1042,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin str == "$write" || str == "$writeb" || str == "$writeh" || str == "$writeo")) { if (!current_always) { - log_file_warning(*location.begin.filename, location.begin.line, "System task `%s' outside initial or always block is unsupported.\n", str.c_str()); + log_file_warning(*location.begin.filename, location.begin.line, "System task `%s' outside initial or always block is unsupported.\n", str); delete_children(); str = std::string(); } else { diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 661b4ef96..573af336b 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -49,7 +49,7 @@ void ConstParser::log_maybe_loc_error(std::string msg) { } void ConstParser::log_maybe_loc_warn(std::string msg) { - log_file_warning(*loc.begin.filename, loc.begin.line, "%s", msg.c_str()); + log_file_warning(*loc.begin.filename, loc.begin.line, "%s", msg); } // divide an arbitrary length decimal number by two and return the rest From d276529d46c747b1ba8c4b5f038067f6264c5ee2 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 16 Sep 2025 23:06:28 +0000 Subject: [PATCH 38/60] Remove .c_str() calls from parameters to log_file_info() --- frontends/ast/genrtlil.cc | 2 +- frontends/ast/simplify.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 84f2f9d73..7518e4a3e 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -2195,7 +2195,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) int sz = children.size(); if (str == "$info") { if (sz > 0) - log_file_info(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str.c_str()); + log_file_info(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str); else log_file_info(*location.begin.filename, location.begin.line, "\n"); } else if (str == "$warning") { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index d4e78b730..d249bc8ad 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -161,7 +161,7 @@ Fmt AstNode::processFormat(int stage, bool sformat_like, int default_base, size_ arg.sig = node_arg->bitsAsConst(); arg.signed_ = node_arg->is_signed; } else if (may_fail) { - log_file_info(*location.begin.filename, location.begin.line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str.c_str(), index + 1); + log_file_info(*location.begin.filename, location.begin.line, "Skipping system task `%s' with non-constant argument at position %zu.\n", str, index + 1); return Fmt(); } else { log_file_error(*location.begin.filename, location.begin.line, "Failed to evaluate system task `%s' with non-constant argument at position %zu.\n", str, index + 1); From a1141f1a4c68a2d70829aedc412c2b257734f944 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 16 Sep 2025 23:12:14 +0000 Subject: [PATCH 39/60] Remove some unnecessary .c_str() calls to the result of unescape_id() --- backends/aiger2/aiger.cc | 2 +- frontends/ast/genrtlil.cc | 8 ++++---- frontends/ast/simplify.cc | 30 +++++++++++++++--------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index bf7497bb5..6aea97fda 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -1012,7 +1012,7 @@ struct XAigerWriter : AigerWriter { for (auto box : minfo.found_blackboxes) { log_debug(" - %s.%s (type %s): ", cursor.path().c_str(), - RTLIL::unescape_id(box->name).c_str(), + RTLIL::unescape_id(box->name), log_id(box->type)); Module *box_module = design->module(box->type), *box_derived; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 7518e4a3e..c26750c98 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1241,7 +1241,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (children[0]->simplify(true, 1, -1, false) == true) { } if (children[0]->type != AST_CONSTANT) input_error("System function %s called with non-const argument!\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str)); width_hint = max(width_hint, int(children[0]->asInt(true))); } break; @@ -1291,7 +1291,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun while (right->simplify(true, 1, -1, false)) { } if (left->type != AST_CONSTANT || right->type != AST_CONSTANT) input_error("Function %s has non-constant width!", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str)); result_width = abs(int(left->asInt(true) - right->asInt(true))); } width_hint = max(width_hint, result_width); @@ -2237,12 +2237,12 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) if (GetSize(children) > 1) input_error("System function %s got %d arguments, expected 1 or 0.\n", - RTLIL::unescape_id(str).c_str(), GetSize(children)); + RTLIL::unescape_id(str), GetSize(children)); if (GetSize(children) == 1) { if (children[0]->type != AST_CONSTANT) input_error("System function %s called with non-const argument!\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str)); width = children[0]->asInt(true); } diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index d249bc8ad..cf9d7443e 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1915,7 +1915,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin if (current_scope.at(modname)->type != AST_CELL) input_error("Defparam argument `%s . %s` does not match a cell!\n", - RTLIL::unescape_id(modname).c_str(), RTLIL::unescape_id(paramname).c_str()); + RTLIL::unescape_id(modname), RTLIL::unescape_id(paramname)); auto paraset = std::make_unique(location, AST_PARASET, children[1]->clone(), GetSize(children) > 2 ? children[2]->clone() : nullptr); paraset->str = paramname; @@ -3394,11 +3394,11 @@ skip_dynamic_range_lvalue_expansion:; if (GetSize(children) != 1 && GetSize(children) != 2) input_error("System function %s got %d arguments, expected 1 or 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); if (!current_always_clocked) input_error("System function %s is only allowed in clocked blocks.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str)); if (GetSize(children) == 2) { @@ -3469,11 +3469,11 @@ skip_dynamic_range_lvalue_expansion:; { if (GetSize(children) != 1) input_error("System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); if (!current_always_clocked) input_error("System function %s is only allowed in clocked blocks.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str)); auto present = children.at(0)->clone(); auto past = clone(); @@ -3511,7 +3511,7 @@ skip_dynamic_range_lvalue_expansion:; { if (children.size() != 1) input_error("System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); auto buf = children[0]->clone(); while (buf->simplify(true, stage, width_hint, sign_hint)) { } @@ -3538,11 +3538,11 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$dimensions" || str == "\\$unpacked_dimensions" || str == "\\$bits") { if (children.size() != 1) input_error("System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); } else { if (children.size() != 1 && children.size() != 2) input_error("System function %s got %d arguments, expected 1 or 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); if (children.size() == 2) { auto buf = children[1]->clone(); // Evaluate constant expression @@ -3634,18 +3634,18 @@ skip_dynamic_range_lvalue_expansion:; if (func_with_two_arguments) { if (children.size() != 2) input_error("System function %s got %d arguments, expected 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); } else { if (children.size() != 1) input_error("System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); } if (children.size() >= 1) { while (children[0]->simplify(true, stage, width_hint, sign_hint)) { } if (!children[0]->isConst()) input_error("Failed to evaluate system function `%s' with non-constant argument.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str)); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[0]->detectSignWidth(child_width_hint, child_sign_hint); @@ -3656,7 +3656,7 @@ skip_dynamic_range_lvalue_expansion:; while (children[1]->simplify(true, stage, width_hint, sign_hint)) { } if (!children[1]->isConst()) input_error("Failed to evaluate system function `%s' with non-constant argument.\n", - RTLIL::unescape_id(str).c_str()); + RTLIL::unescape_id(str)); int child_width_hint = width_hint; bool child_sign_hint = sign_hint; children[1]->detectSignWidth(child_width_hint, child_sign_hint); @@ -3703,7 +3703,7 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$countbits") { if (children.size() < 2) input_error("System function %s got %d arguments, expected at least 2.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); std::vector control_bits; @@ -3760,7 +3760,7 @@ skip_dynamic_range_lvalue_expansion:; if (str == "\\$countones" || str == "\\$isunknown" || str == "\\$onehot" || str == "\\$onehot0") { if (children.size() != 1) input_error("System function %s got %d arguments, expected 1.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); auto countbits = clone(); countbits->str = "\\$countbits"; @@ -3834,7 +3834,7 @@ skip_dynamic_range_lvalue_expansion:; { if (GetSize(children) < 2 || GetSize(children) > 4) input_error("System function %s got %d arguments, expected 2-4.\n", - RTLIL::unescape_id(str).c_str(), int(children.size())); + RTLIL::unescape_id(str), int(children.size())); auto node_filename = children[0]->clone(); while (node_filename->simplify(true, stage, width_hint, sign_hint)) { } From f80be49fa16dc331039f0148a8282f6bfc08e170 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Tue, 16 Sep 2025 23:14:11 +0000 Subject: [PATCH 40/60] Remove unnecessary .c_str() in EDIF_ macros --- backends/edif/edif.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index d1be0b37f..61d6ee254 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -30,9 +30,9 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true).c_str() -#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br).c_str() -#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false).c_str() +#define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true) +#define EDIF_DEFR(_id, _ren, _bl, _br) edif_names(RTLIL::unescape_id(_id), true, _ren, _bl, _br) +#define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false) struct EdifNames { From 5e550ddc3085c1bf524517e45f30b6c4f3ee248f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Sep 2025 00:22:59 +0000 Subject: [PATCH 41/60] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 281f5a868..ef63f23ad 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+88 +YOSYS_VER := 0.57+125 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 d24488d3a5539895a652a44ba7f1863c2dc2ef3e Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Wed, 17 Sep 2025 03:23:52 +0000 Subject: [PATCH 42/60] Instead of using builtin_ff_cell_types() directly, go through a method Cell::is_builtin_ff() --- backends/verilog/verilog_backend.cc | 8 ++++---- kernel/celledges.cc | 2 +- kernel/cost.cc | 2 +- kernel/ffmerge.cc | 2 +- kernel/functional.cc | 2 +- kernel/rtlil.cc | 10 +++++++++- kernel/rtlil.h | 2 ++ kernel/satgen.cc | 2 +- passes/cmds/check.cc | 4 ++-- passes/cmds/clean_zerowidth.cc | 2 +- passes/cmds/dft_tag.cc | 4 ++-- passes/cmds/future.cc | 2 +- passes/cmds/setundef.cc | 2 +- passes/cmds/timeest.cc | 2 +- passes/cmds/xprop.cc | 4 ++-- passes/equiv/equiv_induct.cc | 2 +- passes/equiv/equiv_simple.cc | 4 ++-- passes/opt/opt_clean.cc | 2 +- passes/opt/opt_dff.cc | 4 ++-- passes/opt/opt_ffinv.cc | 2 +- passes/opt/opt_merge.cc | 6 +++--- passes/sat/async2sync.cc | 2 +- passes/sat/clk2fflogic.cc | 2 +- passes/sat/fmcombine.cc | 2 +- passes/sat/formalff.cc | 16 ++++++++-------- passes/sat/sim.cc | 4 ++-- passes/techmap/abc.cc | 4 ++-- passes/techmap/abc9_ops.cc | 2 +- passes/techmap/clockgate.cc | 2 +- passes/techmap/dfflegalize.cc | 4 ++-- passes/techmap/dffunmap.cc | 2 +- passes/techmap/zinit.cc | 2 +- 32 files changed, 61 insertions(+), 51 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index b03639b8d..aea29f710 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -970,7 +970,7 @@ void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, b std::string cellname(RTLIL::Cell *cell) { - if (!norename && cell->name[0] == '$' && RTLIL::builtin_ff_cell_types().count(cell->type) && cell->hasPort(ID::Q) && !cell->type.in(ID($ff), ID($_FF_))) + if (!norename && cell->name[0] == '$' && cell->is_builtin_ff() && cell->hasPort(ID::Q) && !cell->type.in(ID($ff), ID($_FF_))) { RTLIL::SigSpec sig = cell->getPort(ID::Q); if (GetSize(sig) != 1 || sig.is_fully_const()) @@ -1498,7 +1498,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) { FfData ff(nullptr, cell); @@ -1976,7 +1976,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) } } - if (siminit && RTLIL::builtin_ff_cell_types().count(cell->type) && cell->hasPort(ID::Q) && !cell->type.in(ID($ff), ID($_FF_))) { + if (siminit && cell->is_builtin_ff() && cell->hasPort(ID::Q) && !cell->type.in(ID($ff), ID($_FF_))) { std::stringstream ss; dump_reg_init(ss, cell->getPort(ID::Q)); if (!ss.str().empty()) { @@ -2334,7 +2334,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) continue; } - if (!RTLIL::builtin_ff_cell_types().count(cell->type) || !cell->hasPort(ID::Q) || cell->type.in(ID($ff), ID($_FF_))) + if (!cell->is_builtin_ff() || !cell->hasPort(ID::Q) || cell->type.in(ID($ff), ID($_FF_))) continue; RTLIL::SigSpec sig = cell->getPort(ID::Q); diff --git a/kernel/celledges.cc b/kernel/celledges.cc index 8e52d0380..c39ced95a 100644 --- a/kernel/celledges.cc +++ b/kernel/celledges.cc @@ -447,7 +447,7 @@ bool YOSYS_NAMESPACE_PREFIX AbstractCellEdgesDatabase::add_edges_from_cell(RTLIL return true; } - if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (cell->is_builtin_ff()) { ff_op(this, cell); return true; } diff --git a/kernel/cost.cc b/kernel/cost.cc index 985220f14..29787fa52 100644 --- a/kernel/cost.cc +++ b/kernel/cost.cc @@ -145,7 +145,7 @@ unsigned int CellCosts::get(RTLIL::Cell *cell) if (design_ && design_->module(cell->type) && cell->parameters.empty()) { log_debug("%s is a module, recurse\n", cell->name.c_str()); return get(design_->module(cell->type)); - } else if (RTLIL::builtin_ff_cell_types().count(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()); return cell->getParam(ID::WIDTH).as_int(); diff --git a/kernel/ffmerge.cc b/kernel/ffmerge.cc index 632cba05c..709549e4d 100644 --- a/kernel/ffmerge.cc +++ b/kernel/ffmerge.cc @@ -335,7 +335,7 @@ void FfMergeHelper::set(FfInitVals *initvals_, RTLIL::Module *module_) } for (auto cell : module->cells()) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (cell->is_builtin_ff()) { if (cell->hasPort(ID::D)) { SigSpec d = (*sigmap)(cell->getPort(ID::D)); for (int i = 0; i < GetSize(d); i++) diff --git a/kernel/functional.cc b/kernel/functional.cc index 75c9b580b..2a1bf598a 100644 --- a/kernel/functional.cc +++ b/kernel/functional.cc @@ -605,7 +605,7 @@ private: } Node node = handle_memory(mem); factory.update_pending(cell_outputs.at({cell, ID(RD_DATA)}), node); - } else if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + } else if (cell->is_builtin_ff()) { FfData ff(&ff_initvals, cell); if (!ff.has_gclk) log_error("The design contains a %s flip-flop at %s. This is not supported by the functional backend. " diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 586262f97..2d29dab9f 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -87,7 +87,7 @@ static_assert(check_well_known_id_order()); dict RTLIL::constpad; -const pool &RTLIL::builtin_ff_cell_types() { +static const pool &builtin_ff_cell_types_internal() { static const pool res = { ID($sr), ID($ff), @@ -238,6 +238,10 @@ const pool &RTLIL::builtin_ff_cell_types() { return res; } +const pool &RTLIL::builtin_ff_cell_types() { + return builtin_ff_cell_types_internal(); +} + #define check(condition) log_assert(condition && "malformed Const union") const Const::bitvectype& Const::get_bits() const { @@ -4497,6 +4501,10 @@ bool RTLIL::Cell::is_mem_cell() const return type.in(ID($mem), ID($mem_v2)) || has_memid(); } +bool RTLIL::Cell::is_builtin_ff() const { + return builtin_ff_cell_types_internal().count(type) > 0; +} + RTLIL::SigChunk::SigChunk(const RTLIL::SigBit &bit) { wire = bit.wire; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 6b4bc0c7d..2d7bf9a9c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -556,6 +556,7 @@ template <> struct IDMacroHelper<-1> { namespace RTLIL { extern dict constpad; + [[deprecated("Call cell->is_builtin_ff() instead")]] const pool &builtin_ff_cell_types(); static inline std::string escape_id(const std::string &str) { @@ -2147,6 +2148,7 @@ public: bool has_memid() const; bool is_mem_cell() const; + bool is_builtin_ff() const; }; struct RTLIL::CaseRule : public RTLIL::AttrObject diff --git a/kernel/satgen.cc b/kernel/satgen.cc index 7885eccf8..f2c1e00c2 100644 --- a/kernel/satgen.cc +++ b/kernel/satgen.cc @@ -1202,7 +1202,7 @@ bool SatGen::importCell(RTLIL::Cell *cell, int timestep) return true; } - if (timestep > 0 && (RTLIL::builtin_ff_cell_types().count(cell->type) || cell->type == ID($anyinit))) + if (timestep > 0 && (cell->is_builtin_ff() || cell->type == ID($anyinit))) { FfData ff(nullptr, cell); diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index b532b4527..44dbdf28e 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -285,7 +285,7 @@ struct CheckPass : public Pass { } if (yosys_celltypes.cell_evaluable(cell->type) || cell->type.in(ID($mem_v2), ID($memrd), ID($memrd_v2)) \ - || RTLIL::builtin_ff_cell_types().count(cell->type)) { + || cell->is_builtin_ff()) { if (!edges_db.add_edges_from_cell(cell)) coarsened_cells.insert(cell); } @@ -426,7 +426,7 @@ struct CheckPass : public Pass { { for (auto cell : module->cells()) { - if (RTLIL::builtin_ff_cell_types().count(cell->type) == 0) + if (cell->is_builtin_ff() == 0) continue; for (auto bit : sigmap(cell->getPort(ID::Q))) diff --git a/passes/cmds/clean_zerowidth.cc b/passes/cmds/clean_zerowidth.cc index 021726450..d48d3a958 100644 --- a/passes/cmds/clean_zerowidth.cc +++ b/passes/cmds/clean_zerowidth.cc @@ -73,7 +73,7 @@ struct CleanZeroWidthPass : public Pass { cell->unsetPort(it.first); } } - } else if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + } else if (cell->is_builtin_ff()) { // Coarse FF cells: remove if WIDTH == 0 (no outputs). // This will also trigger on fine cells, so use the Q port // width instead of actual WIDTH parameter. diff --git a/passes/cmds/dft_tag.cc b/passes/cmds/dft_tag.cc index 5d9756ca0..0a306d113 100644 --- a/passes/cmds/dft_tag.cc +++ b/passes/cmds/dft_tag.cc @@ -430,7 +430,7 @@ struct DftTagWorker { return; } - if (RTLIL::builtin_ff_cell_types().count(cell->type) || cell->type == ID($anyinit)) { + if (cell->is_builtin_ff() || cell->type == ID($anyinit)) { FfData ff(&initvals, cell); if (ff.has_clk || ff.has_gclk) @@ -686,7 +686,7 @@ struct DftTagWorker { return; } - if (RTLIL::builtin_ff_cell_types().count(cell->type) || cell->type == ID($anyinit)) { + if (cell->is_builtin_ff() || cell->type == ID($anyinit)) { FfData ff(&initvals, cell); // TODO handle some more variants if ((ff.has_clk || ff.has_gclk) && !ff.has_ce && !ff.has_aload && !ff.has_srst && !ff.has_arst && !ff.has_sr) { diff --git a/passes/cmds/future.cc b/passes/cmds/future.cc index 5dcf46bcf..81cc86bff 100644 --- a/passes/cmds/future.cc +++ b/passes/cmds/future.cc @@ -85,7 +85,7 @@ struct FutureWorker { if (found_driver->second.size() > 1) log_error("Found multiple drivers for future_ff target signal %s\n", log_signal(bit)); auto driver = *found_driver->second.begin(); - if (!RTLIL::builtin_ff_cell_types().count(driver.cell->type) && driver.cell->type != ID($anyinit)) + if (!driver.cell->is_builtin_ff() && driver.cell->type != ID($anyinit)) log_error("Driver for future_ff target signal %s has non-FF cell type %s\n", log_signal(bit), log_id(driver.cell->type)); FfData ff(&initvals, driver.cell); diff --git a/passes/cmds/setundef.cc b/passes/cmds/setundef.cc index 6d3e30561..5d2ccfcc8 100644 --- a/passes/cmds/setundef.cc +++ b/passes/cmds/setundef.cc @@ -364,7 +364,7 @@ struct SetundefPass : public Pass { for (auto cell : module->cells()) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; for (auto bit : sigmap(cell->getPort(ID::Q))) diff --git a/passes/cmds/timeest.cc b/passes/cmds/timeest.cc index 86a529520..75356610c 100644 --- a/passes/cmds/timeest.cc +++ b/passes/cmds/timeest.cc @@ -88,7 +88,7 @@ struct EstimateSta { for (auto cell : m->cells()) { SigSpec launch, sample; - if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (cell->is_builtin_ff()) { // collect launch and sample points for FF cell FfData ff(nullptr, cell); if (!ff.has_clk) { diff --git a/passes/cmds/xprop.cc b/passes/cmds/xprop.cc index 8b2e7ae08..7291bb859 100644 --- a/passes/cmds/xprop.cc +++ b/passes/cmds/xprop.cc @@ -302,7 +302,7 @@ struct XpropWorker return; } - if (RTLIL::builtin_ff_cell_types().count(cell->type) || cell->type == ID($anyinit)) { + if (cell->is_builtin_ff() || cell->type == ID($anyinit)) { FfData ff(&initvals, cell); if (cell->type != ID($anyinit)) @@ -853,7 +853,7 @@ struct XpropWorker return; } - if (RTLIL::builtin_ff_cell_types().count(cell->type) || cell->type == ID($anyinit)) { + if (cell->is_builtin_ff() || cell->type == ID($anyinit)) { FfData ff(&initvals, cell); if ((ff.has_clk || ff.has_gclk) && !ff.has_ce && !ff.has_aload && !ff.has_srst && !ff.has_arst && !ff.has_sr) { diff --git a/passes/equiv/equiv_induct.cc b/passes/equiv/equiv_induct.cc index 1995be3cd..e1a3a7990 100644 --- a/passes/equiv/equiv_induct.cc +++ b/passes/equiv/equiv_induct.cc @@ -56,7 +56,7 @@ struct EquivInductWorker for (auto cell : cells) { if (!satgen.importCell(cell, step) && !cell_warn_cache.count(cell)) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) log_warning("No SAT model available for async FF cell %s (%s). Consider running `async2sync` or `clk2fflogic` first.\n", log_id(cell), log_id(cell->type)); else log_warning("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type)); diff --git a/passes/equiv/equiv_simple.cc b/passes/equiv/equiv_simple.cc index 9e3076077..97f95ac63 100644 --- a/passes/equiv/equiv_simple.cc +++ b/passes/equiv/equiv_simple.cc @@ -93,7 +93,7 @@ struct EquivSimpleWorker for (auto &conn : cell->connections()) if (yosys_celltypes.cell_input(cell->type, conn.first)) for (auto bit : model.sigmap(conn.second)) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (cell->is_builtin_ff()) { if (!conn.first.in(ID::CLK, ID::C)) next_seed.insert(bit); } else @@ -231,7 +231,7 @@ struct EquivSimpleWorker static void report_missing_model(Cell* cell) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) log_cmd_error("No SAT model available for async FF cell %s (%s). Consider running `async2sync` or `clk2fflogic` first.\n", log_id(cell), log_id(cell->type)); else log_cmd_error("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type)); diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index cef2c0dc3..68a2156fb 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -206,7 +206,7 @@ void rmunused_module_cells(Module *module, bool verbose) if (verbose) log_debug(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str()); module->design->scratchpad_set_bool("opt.did_something", true); - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) ffinit.remove_init(cell->getPort(ID::Q)); module->remove(cell); count_rm_cells++; diff --git a/passes/opt/opt_dff.cc b/passes/opt/opt_dff.cc index a364539e4..04bcec835 100644 --- a/passes/opt/opt_dff.cc +++ b/passes/opt/opt_dff.cc @@ -89,7 +89,7 @@ struct OptDffWorker } } - if (module->design->selected(module, cell) && RTLIL::builtin_ff_cell_types().count(cell->type)) + if (module->design->selected(module, cell) && cell->is_builtin_ff()) dff_cells.push_back(cell); } @@ -802,7 +802,7 @@ struct OptDffWorker bool did_something = false; for (auto cell : module->selected_cells()) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); diff --git a/passes/opt/opt_ffinv.cc b/passes/opt/opt_ffinv.cc index 882221e56..42d6da49b 100644 --- a/passes/opt/opt_ffinv.cc +++ b/passes/opt/opt_ffinv.cc @@ -209,7 +209,7 @@ struct OptFfInvWorker std::vector ffs; for (Cell *cell : module->selected_cells()) - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) ffs.push_back(cell); for (Cell *cell : ffs) { diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index fbfdb9b63..1cb499740 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -110,7 +110,7 @@ struct OptMergeWorker comm.eat(hash_ops>::hash(port, assign_map(sig))); } h = comm.hash_into(h); - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) h = initvals(cell->getPort(ID::Q)).hash_into(h); } return h; @@ -153,7 +153,7 @@ struct OptMergeWorker for (const auto &it : cell1->connections_) { if (cell1->output(it.first)) { - if (it.first == ID::Q && RTLIL::builtin_ff_cell_types().count(cell1->type)) { + if (it.first == ID::Q && cell1->is_builtin_ff()) { // For the 'Q' output of state elements, // use the (* init *) attribute value conn1[it.first] = initvals(it.second); @@ -201,7 +201,7 @@ struct OptMergeWorker bool has_dont_care_initval(const RTLIL::Cell *cell) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) return false; return !initvals(cell->getPort(ID::Q)).is_fully_def(); diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index e86a78d81..eb3b154b2 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -129,7 +129,7 @@ struct Async2syncPass : public Pass { continue; } - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc index db1eaad4b..dd94dd0d7 100644 --- a/passes/sat/clk2fflogic.cc +++ b/passes/sat/clk2fflogic.cc @@ -275,7 +275,7 @@ struct Clk2fflogicPass : public Pass { continue; } - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); diff --git a/passes/sat/fmcombine.cc b/passes/sat/fmcombine.cc index 2d31822c4..505526c14 100644 --- a/passes/sat/fmcombine.cc +++ b/passes/sat/fmcombine.cc @@ -118,7 +118,7 @@ struct FmcombineWorker Cell *gold = import_prim_cell(cell, "_gold"); Cell *gate = import_prim_cell(cell, "_gate"); if (opts.initeq) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (cell->is_builtin_ff()) { SigSpec gold_q = gold->getPort(ID::Q); SigSpec gate_q = gate->getPort(ID::Q); SigSpec en = module->Initstate(NEW_ID); diff --git a/passes/sat/formalff.cc b/passes/sat/formalff.cc index c0b0cfc15..452e0e59b 100644 --- a/passes/sat/formalff.cc +++ b/passes/sat/formalff.cc @@ -92,7 +92,7 @@ struct InitValWorker ModWalker::PortBit portbit = *portbits.begin(); RTLIL::Cell *cell = portbit.cell; - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) { FfData ff(&initvals, cell); @@ -224,7 +224,7 @@ struct InitValWorker for (auto portbit : portbits) { RTLIL::Cell *cell = portbit.cell; - if (!cell->type.in(ID($mux), ID($and), ID($or), ID($mem_v2)) && !RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (!cell->type.in(ID($mux), ID($and), ID($or), ID($mem_v2)) && !cell->is_builtin_ff()) { return true; } } @@ -232,7 +232,7 @@ struct InitValWorker for (auto portbit : portbits) { RTLIL::Cell *cell = portbit.cell; - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) { FfData ff(&initvals, cell); if (ff.has_aload || ff.has_sr || ff.has_arst || ff.has_gclk || !ff.has_clk) @@ -641,7 +641,7 @@ struct FormalFfPass : public Pass { pool input_bits; pool> input_clk_bits; for (auto cell : module->selected_cells()) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (cell->is_builtin_ff()) { FfData ff(&initvals, cell); if (!ff.has_clk) continue; @@ -743,7 +743,7 @@ struct FormalFfPass : public Pass { auto gate_driver = *found->second.begin(); - if (!RTLIL::builtin_ff_cell_types().count(gate_driver.cell->type)) { + if (!gate_driver.cell->is_builtin_ff()) { log_debug("non FF driver for gate enable %s.%s of gated clk bit %s.%s\n", log_id(module), log_signal(SigSpec(gate_enable)), log_id(module), log_signal(SigSpec(clk))); continue; @@ -784,7 +784,7 @@ struct FormalFfPass : public Pass { log_debug("rewriting cell %s.%s (%s)\n", log_id(module), log_id(clocked_cell), log_id(clocked_cell->type)); - if (RTLIL::builtin_ff_cell_types().count(clocked_cell->type)) { + if (clocked_cell->is_builtin_ff()) { FfData ff(&initvals, clocked_cell); log_assert(ff.has_clk); @@ -836,7 +836,7 @@ struct FormalFfPass : public Pass { for (auto cell : module->selected_cells()) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) + if (cell->is_builtin_ff()) { FfData ff(&worker.initvals, cell); if (ff.has_aload || ff.has_sr || ff.has_arst || ff.val_init.is_fully_def()) @@ -883,7 +883,7 @@ struct FormalFfPass : public Pass { continue; } - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index aadea328f..69c8367c2 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -308,7 +308,7 @@ struct SimInstance } } - if (RTLIL::builtin_ff_cell_types().count(cell->type) || cell->type == ID($anyinit)) { + if (cell->is_builtin_ff() || cell->type == ID($anyinit)) { FfData ff_data(nullptr, cell); ff_state_t ff; ff.past_d = Const(State::Sx, ff_data.width); @@ -1017,7 +1017,7 @@ struct SimInstance dict registers; for (auto cell : module->cells()) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (cell->is_builtin_ff()) { FfData ff_data(nullptr, cell); SigSpec q = sigmap(ff_data.sig_q); if (q.is_wire() && signal_database.count(q.as_wire()) != 0) { diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index c5bdd6ecf..9ec5e7aae 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -373,7 +373,7 @@ void AbcModuleState::mark_port(const AbcSigMap &assign_map, RTLIL::SigSpec sig) bool AbcModuleState::extract_cell(const AbcSigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool keepff) { - if (RTLIL::builtin_ff_cell_types().count(cell->type)) { + if (cell->is_builtin_ff()) { FfData ff(&initvals, cell); gate_type_t type = G(FF); if (!ff.has_clk) @@ -2427,7 +2427,7 @@ struct AbcPass : public Pass { } } - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 069b94204..9a9f7dcb5 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -224,7 +224,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) } else if (derived_module->get_bool_attribute(ID::abc9_box)) { for (auto derived_cell : derived_module->cells()) - if (derived_cell->is_mem_cell() || RTLIL::builtin_ff_cell_types().count(derived_cell->type)) { + if (derived_cell->is_mem_cell() || derived_cell->is_builtin_ff()) { derived_module->set_bool_attribute(ID::abc9_box, false); derived_module->set_bool_attribute(ID::abc9_bypass); break; diff --git a/passes/techmap/clockgate.cc b/passes/techmap/clockgate.cc index b834b8f35..f4e0b0f03 100644 --- a/passes/techmap/clockgate.cc +++ b/passes/techmap/clockgate.cc @@ -333,7 +333,7 @@ struct ClockgatePass : public Pass { int gated_flop_count = 0; for (auto module : design->selected_unboxed_whole_modules()) { for (auto cell : module->cells()) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(nullptr, cell); diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc index 5a622c611..dc29750c8 100644 --- a/passes/techmap/dfflegalize.cc +++ b/passes/techmap/dfflegalize.cc @@ -1196,7 +1196,7 @@ unrecognized: srst_used.clear(); for (auto cell : module->cells()) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); @@ -1208,7 +1208,7 @@ unrecognized: } for (auto cell : module->selected_cells()) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); legalize_ff(ff); diff --git a/passes/techmap/dffunmap.cc b/passes/techmap/dffunmap.cc index 8703bf1a0..020597c4b 100644 --- a/passes/techmap/dffunmap.cc +++ b/passes/techmap/dffunmap.cc @@ -74,7 +74,7 @@ struct DffunmapPass : public Pass { for (auto cell : mod->selected_cells()) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc index 38936e64d..809651ebd 100644 --- a/passes/techmap/zinit.cc +++ b/passes/techmap/zinit.cc @@ -63,7 +63,7 @@ struct ZinitPass : public Pass { for (auto cell : module->selected_cells()) { - if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + if (!cell->is_builtin_ff()) continue; FfData ff(&initvals, cell); From 2d81726459ed15d360d30c75bab8e552b38568a9 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 16 Sep 2025 13:59:15 +0200 Subject: [PATCH 43/60] write_xaiger2: Fix output port mapping when opaque boxes are present --- backends/aiger2/aiger.cc | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index c7ed3b81f..36365927c 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -903,6 +903,16 @@ struct XAigerWriter : AigerWriter { typedef std::pair HierBit; std::vector pos; std::vector pis; + + // * The aiger output port sequence is COs (inputs to modeled boxes), + // inputs to opaque boxes, then module outputs. COs going first is + // required by abc. + // * proper_pos_counter counts ports which follow after COs + // * The mapping file `pseudopo` and `po` statements use indexing relative + // to the first port following COs. + // * If a module output is directly driven by an opaque box, the emission + // of the po statement in the mapping file is skipped. This is done to + // aid re-integration of the mapped result. int proper_pos_counter = 0; pool driven_by_opaque_box; @@ -937,7 +947,7 @@ struct XAigerWriter : AigerWriter { lit_counter += 2; } - void append_box_ports(Cell *box, HierCursor &cursor, bool inputs) + void append_opaque_box_ports(Cell *box, HierCursor &cursor, bool inputs) { for (auto &conn : box->connections_) { bool is_input = box->input(conn.first); @@ -955,13 +965,14 @@ struct XAigerWriter : AigerWriter { continue; } + // Inputs to opaque boxes are proper POs as far as abc is concerned if (map_file.is_open()) { log_assert(cursor.is_top()); - map_file << "pseudopo " << proper_pos_counter++ << " " << bitp + map_file << "pseudopo " << proper_pos_counter << " " << bitp << " " << box->name.c_str() << " " << conn.first.c_str() << "\n"; } - + proper_pos_counter++; pos.push_back(std::make_pair(bit, cursor)); if (mapping_prep) @@ -1038,7 +1049,7 @@ struct XAigerWriter : AigerWriter { }); for (auto [cursor, box, def] : opaque_boxes) - append_box_ports(box, cursor, false); + append_opaque_box_ports(box, cursor, false); holes_module = design->addModule(NEW_ID); std::vector holes_pis; @@ -1086,6 +1097,8 @@ struct XAigerWriter : AigerWriter { bit = RTLIL::Sx; } + // Nonopaque box inputs come first and are not part of + // the PO numbering used by the mapping file. pos.push_back(std::make_pair(bit, cursor)); } boxes_co_num += port->width; @@ -1138,7 +1151,7 @@ struct XAigerWriter : AigerWriter { } for (auto [cursor, box, def] : opaque_boxes) - append_box_ports(box, cursor, true); + append_opaque_box_ports(box, cursor, true); write_be32(h_buffer, 1); write_be32(h_buffer, pis.size()); @@ -1195,10 +1208,14 @@ struct XAigerWriter : AigerWriter { for (auto w : top->wires()) if (w->port_output) for (int i = 0; i < w->width; i++) { + // When a module output is directly driven by an opaque box, we + // don't emit it to the mapping file to aid re-integration, but we + // do emit a proper PO. if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) { - map_file << "po " << proper_pos_counter++ << " " << i + map_file << "po " << proper_pos_counter << " " << i << " " << w->name.c_str() << "\n"; } + proper_pos_counter++; pos.push_back(std::make_pair(SigBit(w, i), HierCursor{})); } From 22423b97c10ebae511867b07262cb837f385870c Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Thu, 14 Aug 2025 16:13:43 +0200 Subject: [PATCH 44/60] kernel: Add RTLIL::PortDir for a combined input and output flag --- kernel/celltypes.h | 10 ++++++++++ kernel/rtlil.cc | 16 ++++++++++++++++ kernel/rtlil.h | 8 ++++++++ 3 files changed, 34 insertions(+) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 469017029..34592192f 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -320,6 +320,16 @@ struct CellTypes return it != cell_types.end() && it->second.inputs.count(port) != 0; } + RTLIL::PortDir cell_port_dir(RTLIL::IdString type, RTLIL::IdString port) const + { + auto it = cell_types.find(type); + if (it == cell_types.end()) + return RTLIL::PD_UNKNOWN; + bool is_input = it->second.inputs.count(port); + bool is_output = it->second.outputs.count(port); + return RTLIL::PortDir(is_input + is_output * 2); + } + bool cell_evaluable(const RTLIL::IdString &type) const { auto it = cell_types.find(type); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 2d29dab9f..4e94b8cc1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -4376,6 +4376,22 @@ bool RTLIL::Cell::output(const RTLIL::IdString& portname) const return false; } +RTLIL::PortDir RTLIL::Cell::port_dir(const RTLIL::IdString& portname) const +{ + if (yosys_celltypes.cell_known(type)) + return yosys_celltypes.cell_port_dir(type, portname); + if (module && module->design) { + RTLIL::Module *m = module->design->module(type); + if (m == nullptr) + return PortDir::PD_UNKNOWN; + RTLIL::Wire *w = m->wire(portname); + if (w == nullptr) + return PortDir::PD_UNKNOWN; + return PortDir(w->port_input + w->port_output * 2); + } + return PortDir::PD_UNKNOWN; +} + bool RTLIL::Cell::hasParam(const RTLIL::IdString& paramname) const { return parameters.count(paramname) != 0; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 2d7bf9a9c..4c3e2182e 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -91,6 +91,13 @@ namespace RTLIL STATIC_ID_END, }; + enum PortDir : unsigned char { + PD_UNKNOWN = 0, + PD_INPUT = 1, + PD_OUTPUT = 2, + PD_INOUT = 3 + }; + struct Const; struct AttrObject; struct NamedObject; @@ -2123,6 +2130,7 @@ public: bool known() const; bool input(const RTLIL::IdString &portname) const; bool output(const RTLIL::IdString &portname) const; + PortDir port_dir(const RTLIL::IdString &portname) const; // access cell parameters bool hasParam(const RTLIL::IdString ¶mname) const; From c4f435569f6c8d3649ed82d5d2e2588f94b0b6c5 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Wed, 3 Sep 2025 15:29:08 +0200 Subject: [PATCH 45/60] kernel: Add known_driver method to Wire/SigSpec --- kernel/rtlil.cc | 9 +++++++++ kernel/rtlil.h | 4 ++++ 2 files changed, 13 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 4e94b8cc1..5f8e6ad66 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -5534,6 +5534,15 @@ bool RTLIL::SigSpec::is_chunk() const return GetSize(chunks_) == 1; } +bool RTLIL::SigSpec::known_driver() const +{ + pack(); + for (auto &chunk : chunks_) + if (chunk.is_wire() && !chunk.wire->known_driver()) + return false; + return true; +} + bool RTLIL::SigSpec::is_fully_const() const { cover("kernel.rtlil.sigspec.is_fully_const"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 4c3e2182e..15154eb64 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1329,6 +1329,8 @@ public: bool is_chunk() const; inline bool is_bit() const { return width_ == 1; } + bool known_driver() const; + bool is_fully_const() const; bool is_fully_zero() const; bool is_fully_ones() const; @@ -2059,6 +2061,8 @@ public: int width, start_offset, port_id; bool port_input, port_output, upto, is_signed; + bool known_driver() const { return driverCell_ != nullptr; } + RTLIL::Cell *driverCell() const { log_assert(driverCell_); return driverCell_; }; RTLIL::IdString driverPort() const { log_assert(driverCell_); return driverPort_; }; From 1251e92e3a988b33f2075118071f4454247041d6 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Wed, 3 Sep 2025 15:26:33 +0200 Subject: [PATCH 46/60] Add `$input_port` and `$connect` cell types --- kernel/celltypes.h | 2 ++ kernel/rtlil.cc | 13 +++++++++++++ techlibs/common/simlib.v | 23 +++++++++++++++++++++++ techlibs/common/techmap.v | 25 +++++++++++++++++++++++++ 4 files changed, 63 insertions(+) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 34592192f..2c3535eac 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -111,6 +111,8 @@ struct CellTypes setup_type(ID($original_tag), {ID::A}, {ID::Y}); setup_type(ID($future_ff), {ID::A}, {ID::Y}); setup_type(ID($scopeinfo), {}, {}); + setup_type(ID($input_port), {}, {ID::Y}); + setup_type(ID($connect), {ID::A, ID::B}, {}); } void setup_internals_eval() diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 5f8e6ad66..3858a3372 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2451,6 +2451,19 @@ namespace { check_expected(); return; } + if (cell->type.in(ID($input_port))) { + param(ID::WIDTH); + port(ID::Y, param(ID::WIDTH)); + check_expected(); + return; + } + if (cell->type.in(ID($connect))) { + param(ID::WIDTH); + port(ID::A, param(ID::WIDTH)); + port(ID::B, param(ID::WIDTH)); + check_expected(); + return; + } /* * Checklist for adding internal cell types * ======================================== diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 6e39aa60a..096df07b9 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -3216,3 +3216,26 @@ module \$scopeinfo (); parameter TYPE = ""; endmodule + +// -------------------------------------------------------- +//* group wire +module \$connect (A, B); + +parameter WIDTH = 0; + +inout [WIDTH-1:0] A; +inout [WIDTH-1:0] B; + +tran connect[WIDTH-1:0] (A, B); + +endmodule + +// -------------------------------------------------------- +//* group wire +module \$input_port (Y); + +parameter WIDTH = 0; + +inout [WIDTH-1:0] Y; + +endmodule diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index fdf11904b..7a9ad7693 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -647,3 +647,28 @@ module _90_lut; endmodule `endif + +// -------------------------------------------------------- +// Bufnorm helpers +// -------------------------------------------------------- + +(* techmap_celltype = "$connect" *) +module \$connect (A, B); + +parameter WIDTH = 0; + +inout [WIDTH-1:0] A; +inout [WIDTH-1:0] B; + +assign A = B; // RTLIL assignments are not inherently directed + +endmodule + +(* techmap_celltype = "$input_port" *) +module \$input_port (Y); + +parameter WIDTH = 0; + +inout [WIDTH-1:0] Y; // This cell is just a maker, so we leave Y undriven + +endmodule From d88d6fce87442dc3a020fd770a1952f6cedbb192 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Wed, 3 Sep 2025 15:34:51 +0200 Subject: [PATCH 47/60] kernel: Rewrite bufNormalize This is a complete rewrite of the RTLIL-kernel-side bufnorm code. This is done to support inout ports and undirected connections as well as to allow removal of cells while in bufnorm mode. This doesn't yet update the (experimental) `bufnorm` pass, so to manually test the new kernel functionality, it is important to only use `bufnorm -update` and `bufnorm -reset` which rely entirely on the kernel functionality. Other modes of the `bufnorm` pass may still fail in the presence of inout ports or undirected connections. --- Makefile | 1 + kernel/rtlil.cc | 211 ++----------- kernel/rtlil.h | 7 +- kernel/rtlil_bufnorm.cc | 679 ++++++++++++++++++++++++++++++++++++++++ tests/various/aiger2.ys | 2 + 5 files changed, 716 insertions(+), 184 deletions(-) create mode 100644 kernel/rtlil_bufnorm.cc diff --git a/Makefile b/Makefile index ef63f23ad..3e0849c09 100644 --- a/Makefile +++ b/Makefile @@ -644,6 +644,7 @@ $(eval $(call add_include_file,frontends/blif/blifparse.h)) $(eval $(call add_include_file,backends/rtlil/rtlil_backend.h)) OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o kernel/io.o kernel/gzip.o +OBJS += kernel/rtlil_bufnorm.o OBJS += kernel/log_help.o ifeq ($(ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS),1) OBJS += kernel/log_compat.o diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 3858a3372..4f34d6f7b 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2844,7 +2844,13 @@ void RTLIL::Module::remove(RTLIL::Cell *cell) log_assert(cells_.count(cell->name) != 0); log_assert(refcount_cells_ == 0); cells_.erase(cell->name); - delete cell; + if (design && design->flagBufferedNormalized && buf_norm_cell_queue.count(cell)) { + cell->type.clear(); + cell->name.clear(); + pending_deleted_cells.insert(cell); + } else { + delete cell; + } } void RTLIL::Module::remove(RTLIL::Process *process) @@ -3019,6 +3025,14 @@ void RTLIL::Module::fixup_ports() std::sort(all_ports.begin(), all_ports.end(), fixup_ports_compare); + if (design && design->flagBufferedNormalized) { + for (auto &w : wires_) + if (w.second->driverCell_ && w.second->driverCell_->type == ID($input_port)) + buf_norm_wire_queue.insert(w.second); + + buf_norm_wire_queue.insert(all_ports.begin(), all_ports.end()); + } + ports.clear(); for (size_t i = 0; i < all_ports.size(); i++) { ports.push_back(all_ports[i]->name); @@ -4163,188 +4177,7 @@ bool RTLIL::Cell::hasPort(const RTLIL::IdString& portname) const return connections_.count(portname) != 0; } -void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname) -{ - RTLIL::SigSpec signal; - auto conn_it = connections_.find(portname); - - if (conn_it != connections_.end()) - { - for (auto mon : module->monitors) - mon->notify_connect(this, conn_it->first, conn_it->second, signal); - - if (module->design) - for (auto mon : module->design->monitors) - mon->notify_connect(this, conn_it->first, conn_it->second, signal); - - if (yosys_xtrace) { - log("#X# Unconnect %s.%s.%s\n", log_id(this->module), log_id(this), log_id(portname)); - log_backtrace("-X- ", yosys_xtrace-1); - } - - connections_.erase(conn_it); - } -} - -void RTLIL::Design::bufNormalize(bool enable) -{ - if (!enable) - { - if (!flagBufferedNormalized) - return; - - for (auto module : modules()) { - module->bufNormQueue.clear(); - for (auto wire : module->wires()) { - wire->driverCell_ = nullptr; - wire->driverPort_ = IdString(); - } - } - - flagBufferedNormalized = false; - return; - } - - if (!flagBufferedNormalized) - { - for (auto module : modules()) - { - for (auto cell : module->cells()) - for (auto &conn : cell->connections()) { - if (!cell->output(conn.first) || GetSize(conn.second) == 0) - continue; - if (conn.second.is_wire()) { - Wire *wire = conn.second.as_wire(); - log_assert(wire->driverCell_ == nullptr); - wire->driverCell_ = cell; - wire->driverPort_ = conn.first; - } else { - pair key(cell, conn.first); - module->bufNormQueue.insert(key); - } - } - } - - flagBufferedNormalized = true; - } - - for (auto module : modules()) - module->bufNormalize(); -} - -void RTLIL::Module::bufNormalize() -{ - if (!design->flagBufferedNormalized) - return; - - while (GetSize(bufNormQueue) || !connections_.empty()) - { - pool> queue; - bufNormQueue.swap(queue); - - pool outWires; - for (auto &conn : connections()) - for (auto &chunk : conn.first.chunks()) - if (chunk.wire) outWires.insert(chunk.wire); - - SigMap sigmap(this); - new_connections({}); - - for (auto &key : queue) - { - Cell *cell = key.first; - const IdString &portname = key.second; - const SigSpec &sig = cell->getPort(portname); - if (GetSize(sig) == 0) continue; - - if (sig.is_wire()) { - Wire *wire = sig.as_wire(); - if (wire->driverCell_) { - log_error("Conflict between %s %s in module %s\n", - log_id(cell), log_id(wire->driverCell_), log_id(this)); - } - log_assert(wire->driverCell_ == nullptr); - wire->driverCell_ = cell; - wire->driverPort_ = portname; - continue; - } - - for (auto &chunk : sig.chunks()) - if (chunk.wire) outWires.insert(chunk.wire); - - Wire *wire = addWire(NEW_ID, GetSize(sig)); - sigmap.add(sig, wire); - cell->setPort(portname, wire); - - // FIXME: Move init attributes from old 'sig' to new 'wire' - } - - for (auto wire : outWires) - { - SigSpec outsig = wire, insig = sigmap(wire); - for (int i = 0; i < GetSize(wire); i++) - if (insig[i] == outsig[i]) - insig[i] = State::Sx; - addBuf(NEW_ID, insig, outsig); - } - } -} - -void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal) -{ - auto r = connections_.insert(portname); - auto conn_it = r.first; - if (!r.second && conn_it->second == signal) - return; - - for (auto mon : module->monitors) - mon->notify_connect(this, conn_it->first, conn_it->second, signal); - - if (module->design) - for (auto mon : module->design->monitors) - mon->notify_connect(this, conn_it->first, conn_it->second, signal); - - if (yosys_xtrace) { - log("#X# Connect %s.%s.%s = %s (%d)\n", log_id(this->module), log_id(this), log_id(portname), log_signal(signal), GetSize(signal)); - log_backtrace("-X- ", yosys_xtrace-1); - } - - while (module->design && module->design->flagBufferedNormalized && output(portname)) - { - pair key(this, portname); - - if (conn_it->second.is_wire()) { - Wire *w = conn_it->second.as_wire(); - if (w->driverCell_ == this && w->driverPort_ == portname) { - w->driverCell_ = nullptr; - w->driverPort_ = IdString(); - } - } - - if (GetSize(signal) == 0) { - module->bufNormQueue.erase(key); - break; - } - - if (!signal.is_wire()) { - module->bufNormQueue.insert(key); - break; - } - - Wire *w = signal.as_wire(); - if (w->driverCell_ != nullptr) { - pair other_key(w->driverCell_, w->driverPort_); - module->bufNormQueue.insert(other_key); - } - w->driverCell_ = this; - w->driverPort_ = portname; - - module->bufNormQueue.erase(key); - break; - } - - conn_it->second = std::move(signal); -} +// bufnorm const RTLIL::SigSpec &RTLIL::Cell::getPort(const RTLIL::IdString& portname) const { @@ -5638,6 +5471,18 @@ bool RTLIL::SigSpec::has_const() const return false; } +bool RTLIL::SigSpec::has_const(State state) const +{ + cover("kernel.rtlil.sigspec.has_const"); + + pack(); + for (auto it = chunks_.begin(); it != chunks_.end(); it++) + if (it->width > 0 && it->wire == NULL && std::find(it->data.begin(), it->data.end(), state) != it->data.end()) + return true; + return false; +} + + bool RTLIL::SigSpec::has_marked_bits() const { cover("kernel.rtlil.sigspec.has_marked_bits"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 15154eb64..096d1dfcf 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1337,6 +1337,7 @@ public: bool is_fully_def() const; bool is_fully_undef() const; bool has_const() const; + bool has_const(State state) const; bool has_marked_bits() const; bool is_onehot(int *pos = nullptr) const; @@ -1728,7 +1729,11 @@ public: std::vector ports; void fixup_ports(); - pool> bufNormQueue; + pool buf_norm_cell_queue; + pool> buf_norm_cell_port_queue; + pool buf_norm_wire_queue; + pool pending_deleted_cells; + dict> buf_norm_connect_index; void bufNormalize(); template void rewrite_sigspecs(T &functor); diff --git a/kernel/rtlil_bufnorm.cc b/kernel/rtlil_bufnorm.cc new file mode 100644 index 000000000..6d619d9e6 --- /dev/null +++ b/kernel/rtlil_bufnorm.cc @@ -0,0 +1,679 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" +#include "kernel/modtools.h" + +#include +#include +#include + +YOSYS_NAMESPACE_BEGIN + + +void RTLIL::Design::bufNormalize(bool enable) +{ + if (!enable) + { + if (!flagBufferedNormalized) + return; + + for (auto module : modules()) { + module->buf_norm_cell_queue.clear(); + module->buf_norm_wire_queue.clear(); + module->buf_norm_cell_port_queue.clear(); + for (auto wire : module->wires()) { + wire->driverCell_ = nullptr; + wire->driverPort_ = IdString(); + } + } + + flagBufferedNormalized = false; + return; + } + + if (!flagBufferedNormalized) + { + for (auto module : modules()) + { + // When entering buf normalized mode, we need the first module-level bufNormalize + // call to know about all drivers, about all module ports (whether represented by + // a cell or not) and about all used but undriven wires (whether represented by a + // cell or not). We ensure this by enqueing all cell output ports and all wires. + + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) { + if (GetSize(conn.second) == 0 || (cell->port_dir(conn.first) != RTLIL::PD_OUTPUT && cell->port_dir(conn.first) != RTLIL::PD_INOUT)) + continue; + module->buf_norm_cell_queue.insert(cell); + module->buf_norm_cell_port_queue.emplace(cell, conn.first); + } + for (auto wire : module->wires()) + module->buf_norm_wire_queue.insert(wire); + + } + + flagBufferedNormalized = true; + } + + for (auto module : modules()) + module->bufNormalize(); +} + +struct bit_drive_data_t { + int drivers = 0; + int inout = 0; + int users = 0; +}; + +typedef ModWalker::PortBit PortBit; + +void RTLIL::Module::bufNormalize() +{ + // Since this is kernel code, we only log with yosys_xtrace set to not get + // in the way when using `debug` to debug specific passes.q +#define xlog(...) do { if (yosys_xtrace) log("#X [bufnorm] " __VA_ARGS__); } while (0) + + if (!design->flagBufferedNormalized) + return; + + if (!buf_norm_cell_queue.empty() || !buf_norm_wire_queue.empty() || !connections_.empty()) + { + // Ensure that every enqueued input port is represented by a cell + for (auto wire : buf_norm_wire_queue) { + if (wire->port_input && !wire->port_output) { + if (wire->driverCell_ != nullptr && wire->driverCell_->type != ID($input_port)) { + wire->driverCell_ = nullptr; + wire->driverPort_.clear(); + } + if (wire->driverCell_ == nullptr) { + Cell *input_port_cell = addCell(NEW_ID, ID($input_port)); + input_port_cell->setParam(ID::WIDTH, GetSize(wire)); + input_port_cell->setPort(ID::Y, wire); // this hits the fast path that doesn't mutate the queues + } + } + } + + // Next we will temporarily undo buf normalization locally for + // everything enqueued. This means we will turn $buf and $connect back + // into connections. When doing this we also need to enqueue the other + // end of $buf and $connect cells, so we use a queue and do this until + // reaching a fixed point. + + // While doing this, we will also discover all drivers fully connected + // to enqueued wires. We keep track of which wires are driven by a + // unique and full cell ports (in which case the wire can stay + // connected to the port) and which cell ports will need to be + // reconnected to a fresh intermediate wire to re-normalize the module. + + idict wire_queue_entries; // Ordered queue of wires to process + int wire_queue_pos = 0; // Index up to which we processed the wires + + // Wires with their unique driving cell port. If we know a wire is + // driven by multiple (potential) drivers, this is indicated by a + // nullptr as cell. + dict> direct_driven_wires; + + // Set of non-unique or driving cell ports for each processed wire. + dict>> direct_driven_wires_conflicts; + + // Set of cell ports that need a fresh intermediate wire. + pool> pending_ports; + + // This helper will be called for every output/inout cell port that is + // already enqueued or becomes reachable when denormalizing $buf or + // $connect cells. + auto enqueue_cell_port = [&](Cell *cell, IdString port) { + xlog("processing cell port %s.%s\n", log_id(cell), log_id(port)); + + // An empty cell type means the cell got removed + if (cell->type.empty()) + return; + + + SigSpec const &sig = cell->getPort(port); + if (cell->type == ID($input_port)) { + // If an `$input_port` cell isn't fully connected to a full + // input port wire, we remove it since the wires are still the + // canonical source of module ports and the `$input_port` cells + // are just helpers to simplfiy the bufnorm invariant. + log_assert(port == ID::Y); + if (!sig.is_wire()) { + buf_norm_cell_queue.insert(cell); + remove(cell); + return; + } + + Wire *w = sig.as_wire(); + if (!w->port_input || w->port_output) { + buf_norm_cell_queue.insert(cell); + remove(cell); + return; + } + w->driverCell_ = cell; + w->driverPort_ = ID::Y; + } else if (cell->type == ID($buf) && cell->attributes.empty() && !cell->name.isPublic()) { + // For a plain `$buf` cell, we enqueue all wires on its input + // side, bypass it using module level connections (skipping 'z + // bits) and then remove the cell. Eventually the module level + // connections will turn back into `$buf` and `$connect` cells, + // but since we also need to handle externally added module + // level connections, turning everything into connections first + // simplifies the logic for doing so. + + // TODO: We could defer removing the $buf cells here, and + // re-use them in case we would create a new identical cell + // later. + log_assert(port == ID::Y); + SigSpec sig_a = cell->getPort(ID::A); + SigSpec sig_y = sig; + + for (auto const &s : {sig_a, sig}) + for (auto const &chunk : s.chunks()) + if (chunk.wire) + wire_queue_entries(chunk.wire); + + if (sig_a.has_const(State::Sz)) { + SigSpec new_a; + SigSpec new_y; + for (int i = 0; i < GetSize(sig_a); ++i) { + SigBit b = sig_a[i]; + if (b == State::Sz) + continue; + new_a.append(b); + new_y.append(sig_y[i]); + } + sig_a = std::move(new_a); + sig_y = std::move(new_y); + } + + if (!sig_y.empty()) + connect(sig_y, sig_a); + buf_norm_cell_queue.insert(cell); + remove(cell); + return; + } + + // Make sure all wires of the cell port are enqueued, ensuring we + // detect other connected drivers (output and inout). + for (auto const &chunk : sig.chunks()) + if (chunk.wire) + wire_queue_entries(chunk.wire); + + if (sig.is_wire()) { + // If the full cell port is connected to a full wire, we might be + // able to keep that connection if this is a unique output port driving that wire + Wire *w = sig.as_wire(); + + // We try to store the current port as unique driver, if this + // succeeds we're done with the port. + auto [found, inserted] = direct_driven_wires.emplace(w, {cell, port}); + if (inserted || (found->second.first == cell && found->second.second == port)) + return; + + // When this failed, we store this port as a conflict. If we + // had already stored a candidate for a unique driver, we also + // move it to the conflicts, leaving a nullptr marker. + + auto &conflicts = direct_driven_wires_conflicts[w]; + if (Cell *other_cell = found->second.first) { + if (other_cell->type == ID($input_port)) { + // Multiple input port cells + log_assert(cell->type != ID($input_port)); + } else { + pending_ports.insert(found->second); + conflicts.emplace(found->second); + found->second = {nullptr, {}}; + } + } + if (cell->type == ID($input_port)) { + found->second = {cell, port}; + } else { + conflicts.emplace(cell, port); + } + } + + // Adds this port to the ports that need a fresh intermediate wire. + // For full wires uniquely driven by a full output port, this isn't + // reached due to the `return` above. + pending_ports.emplace(cell, port); + }; + + // We process all explicitly enqueued cell ports (clearing the module level queue). + for (auto const &[cell, port_name] : buf_norm_cell_port_queue) + enqueue_cell_port(cell, port_name); + buf_norm_cell_port_queue.clear(); + + // And enqueue all wires for `$buf`/`$connect` processing (clearing the module level queue). + for (auto wire : buf_norm_wire_queue) + wire_queue_entries(wire); + buf_norm_wire_queue.clear(); + + // We also enqueue all wires that saw newly added module level connections. + for (auto &[a, b] : connections_) + for (auto &sig : {a, b}) + for (auto const &chunk : sig.chunks()) + if (chunk.wire) + wire_queue_entries(chunk.wire); + + // We then process all wires by processing known driving cell ports + // (previously buf normalized) and following all `$connect` cells (that + // have a dedicated module level index while the design is in buf + // normalized mode). + while (wire_queue_pos < GetSize(wire_queue_entries)) { + auto wire = wire_queue_entries[wire_queue_pos++]; + xlog("processing wire %s\n", log_id(wire)); + + if (wire->driverCell_) { + Cell *cell = wire->driverCell_; + IdString port = wire->driverPort_; + enqueue_cell_port(cell, port); + } + + while (true) { + auto found = buf_norm_connect_index.find(wire); + if (found == buf_norm_connect_index.end()) + break; + while (!found->second.empty()) { + Cell *connect_cell = *found->second.begin(); + log_assert(connect_cell->type == ID($connect)); + SigSpec const &sig_a = connect_cell->getPort(ID::A); + SigSpec const &sig_b = connect_cell->getPort(ID::B); + xlog("found $connect cell %s: %s <-> %s\n", log_id(connect_cell), log_signal(sig_a), log_signal(sig_b)); + for (auto &side : {sig_a, sig_b}) + for (auto chunk : side.chunks()) + if (chunk.wire) + wire_queue_entries(chunk.wire); + connect(sig_a, sig_b); + buf_norm_cell_queue.insert(connect_cell); + remove(connect_cell); + } + } + } + + // At this point we know all cell ports and wires that need to be + // re-normalized and know their connectivity is represented by module + // level connections. + + // As a first step for re-normalization we add all require intermediate + // wires for cell output and inout ports. + for (auto &[cell, port] : pending_ports) { + SigSpec const &sig = cell->getPort(port); + Wire *w = addWire(NEW_ID, GetSize(sig)); + + // We update the module level connections, `direct_driven_wires` + // and `direct_driven_wires_conflicts` in such a way that they + // correspond to what you would get if the intermediate wires had + // been in place from the beginning. + connect(sig, w); + auto port_dir = cell->port_dir(port); + if (port_dir == RTLIL::PD_INOUT || port_dir == RTLIL::PD_UNKNOWN) { + direct_driven_wires.emplace(w, {nullptr, {}}); + direct_driven_wires_conflicts[w].emplace(cell, port); + } else { + direct_driven_wires.emplace(w, {cell, port}); + } + + cell->setPort(port, w); + wire_queue_entries(w); + } + + // At this point we're done with creating wires and know which ones are + // fully driven by full output ports of existing cells. + + // First we clear the bufnorm data for all processed wires, all of + // these will be reassigned later, but we use `driverCell_ == nullptr` + // to keep track of the wires that we still have to update. + for (auto wire : wire_queue_entries) { + wire->driverCell_ = nullptr; + wire->driverPort_.clear(); + } + + // For the unique output cell ports fully connected to a full wire, we + // can update the bufnorm data right away. For all other wires we will + // have to create new `$buf` cells. + for (auto const &[wire, cellport] : direct_driven_wires) { + wire->driverCell_ = cellport.first; + wire->driverPort_ = cellport.second; + } + + + // To create fresh `$buf` cells for all remaining wires, we need to + // process the module level connectivity to figure out what the input + // of those `$buf` cells should be and to figure out whether we need + // any `$connect` cells to represent bidirectional inout connections + // (or driver conflicts). + + if (yosys_xtrace) + for (auto const &[lhs, rhs] : connections_) + xlog("connection %s <-> %s\n", log_signal(lhs), log_signal(rhs)); + + + // We transfer the connectivity into a sigmap and then clear the module + // level connections. This forgets about the structure of module level + // connections, but bufnorm only guarantees that the connectivity as + // maintained by a `SigMap` is preserved. + SigMap sigmap(this); + new_connections({}); + + pool conflicted; + pool driven; + + // We iterate over all direct driven wires and try to make that wire's + // sigbits the representative sigbit for the net. We do a second pass + // to detect conflicts to then remove the conflicts from `driven`. + for (bool check : {false, true}) { + for (auto const &[wire, cellport] : direct_driven_wires) { + if (cellport.first == nullptr) + continue; + auto const &[cell, port] = cellport; + + SigSpec z_mask; + if (cell->type == ID($buf)) + z_mask = cell->getPort(ID::A); + + for (int i = 0; i != GetSize(wire); ++i) { + SigBit driver = SigBit(wire, i); + if (!z_mask.empty() && z_mask[i] == State::Sz) + continue; + if (check) { + SigBit repr = sigmap(driver); + if (repr != driver) + conflicted.insert(repr); + else + driven.insert(repr); + } else { + sigmap.database.promote(driver); + } + } + } + } + + // Ensure that module level inout ports are directly driven or + // connected using `$connect` cells and never `$buf`fered. + for (auto wire : wire_queue_entries) { + if (!wire->port_input || !wire->port_output) + continue; + for (int i = 0; i != GetSize(wire); ++i) { + SigBit driver = SigBit(wire, i); + SigBit repr = sigmap(driver); + if (driver != repr) + driven.erase(repr); + } + } + + for (auto &bit : conflicted) + driven.erase(bit); + + // Module level bitwise connections not representable by `$buf` cells + pool> undirected_connections; + + // Starts out empty but is updated with the connectivity realized by freshly added `$buf` cells + SigMap buf_connected; + + // For every enqueued wire, we compute a SigSpec of representative + // drivers. If there are any bits without a unique driver we represent + // that with `Sz`. If there are multiple drivers for a net, they become + // connected via `$connect` cells but every wire of the net has the + // corresponding bit still driven by a buffered `Sz`. + for (auto wire : wire_queue_entries) { + SigSpec wire_drivers; + for (int i = 0; i < GetSize(wire); ++i) { + SigBit bit(wire, i); + SigBit mapped = sigmap(bit); + xlog("bit %s -> mapped %s\n", log_signal(bit), log_signal(mapped)); + + + buf_connected.apply(bit); + buf_connected.add(bit, mapped); + buf_connected.database.promote(mapped); + + if (wire->driverCell_ == nullptr) { + if (!mapped.is_wire() || driven.count(mapped)) { + wire_drivers.append(mapped); + continue; + } else { + wire_drivers.append(State::Sz); + } + } + + if (bit < mapped) + undirected_connections.emplace(bit, mapped); + else if (mapped < bit) + undirected_connections.emplace(mapped, bit); + } + + if (wire->driverCell_ == nullptr) { + xlog("wire %s drivers %s\n", log_id(wire), log_signal(wire_drivers)); + addBuf(NEW_ID, wire_drivers, wire); + } + } + + // Finally we group the bitwise connections to emit word-level $connect cells + + static auto sort_key = [](std::pair const &p) { + int first_offset = p.first.is_wire() ? p.first.offset : 0; + int second_offset = p.second.is_wire() ? p.second.offset : 0; + return std::make_tuple(p.first.wire, p.second.wire, first_offset - second_offset, p); + }; + + undirected_connections.sort([](std::pair const &p, std::pair const &q) { + return sort_key(p) < sort_key(q); + }); + + SigSpec tmp_a, tmp_b; + + for (auto &[bit_a, bit_b] : undirected_connections) { + tmp_a.append(bit_a); + tmp_b.append(bit_b); + } + + xlog("LHS: %s\n", log_signal(tmp_a)); + xlog("RHS: %s\n", log_signal(tmp_b)); + + + SigSpec sig_a, sig_b; + SigBit next_a, next_b; + + auto emit_connect_cell = [&]() { + if (sig_a.empty()) + return; + xlog("connect %s <-> %s\n", log_signal(sig_a), log_signal(sig_b)); + Cell *connect_cell = addCell(NEW_ID, ID($connect)); + connect_cell->setParam(ID::WIDTH, GetSize(sig_a)); + connect_cell->setPort(ID::A, sig_a); + connect_cell->setPort(ID::B, sig_b); + sig_a = SigSpec(); + sig_b = SigSpec(); + }; + + for (auto &[bit_a, bit_b] : undirected_connections) { + if (bit_a == bit_b) + continue; + if (bit_a != next_a || bit_b != next_b) + emit_connect_cell(); + + sig_a.append(bit_a); + sig_b.append(bit_b); + next_a = bit_a; + next_b = bit_b; + if (next_a.is_wire()) + next_a.offset++; + if (next_b.is_wire()) + next_b.offset++; + + } + emit_connect_cell(); + + buf_norm_cell_queue.clear(); + + log_assert(buf_norm_cell_port_queue.empty()); + log_assert(buf_norm_wire_queue.empty()); + log_assert(connections_.empty()); + } + + for (auto cell : pending_deleted_cells) { + delete cell; + } + pending_deleted_cells.clear(); +} + +void RTLIL::Cell::unsetPort(const RTLIL::IdString& portname) +{ + RTLIL::SigSpec signal; + auto conn_it = connections_.find(portname); + + if (conn_it != connections_.end()) + { + for (auto mon : module->monitors) + mon->notify_connect(this, conn_it->first, conn_it->second, signal); + + if (module->design) + for (auto mon : module->design->monitors) + mon->notify_connect(this, conn_it->first, conn_it->second, signal); + + if (yosys_xtrace) { + log("#X# Unconnect %s.%s.%s\n", log_id(this->module), log_id(this), log_id(portname)); + log_backtrace("-X- ", yosys_xtrace-1); + } + + if (module->design && module->design->flagBufferedNormalized) { + if (conn_it->second.is_wire()) { + Wire *w = conn_it->second.as_wire(); + if (w->driverCell_ == this && w->driverPort_ == portname) { + w->driverCell_ = nullptr; + w->driverPort_ = IdString(); + module->buf_norm_wire_queue.insert(w); + } + } + + if (type == ID($connect)) { + for (auto &[port, sig] : connections_) { + for (auto &chunk : sig.chunks()) { + if (!chunk.wire) + continue; + auto it = module->buf_norm_connect_index.find(chunk.wire); + if (it == module->buf_norm_connect_index.end()) + continue; + it->second.erase(this); + if (it->second.empty()) + module->buf_norm_connect_index.erase(it); + } + } + connections_.erase(conn_it); + for (auto &[port, sig] : connections_) { + for (auto &chunk : sig.chunks()) { + if (!chunk.wire) + continue; + module->buf_norm_connect_index[chunk.wire].insert(this); + } + } + return; + } + } + + connections_.erase(conn_it); + } +} + +void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal) +{ + auto r = connections_.insert(portname); + auto conn_it = r.first; + if (!r.second && conn_it->second == signal) + return; + + for (auto mon : module->monitors) + mon->notify_connect(this, conn_it->first, conn_it->second, signal); + + if (module->design) + for (auto mon : module->design->monitors) + mon->notify_connect(this, conn_it->first, conn_it->second, signal); + + if (yosys_xtrace) { + log("#X# Connect %s.%s.%s = %s (%d)\n", log_id(this->module), log_id(this), log_id(portname), log_signal(signal), GetSize(signal)); + log_backtrace("-X- ", yosys_xtrace-1); + } + + if (module->design && module->design->flagBufferedNormalized) + { + // We eagerly clear a driver that got disconnected by changing this port connection + if (conn_it->second.is_wire()) { + Wire *w = conn_it->second.as_wire(); + if (w->driverCell_ == this && w->driverPort_ == portname) { + w->driverCell_ = nullptr; + w->driverPort_ = IdString(); + module->buf_norm_wire_queue.insert(w); + } + } + + auto dir = port_dir(portname); + // This is a fast path that handles connecting a full driverless wire to an output port, + // everything else is goes through the bufnorm queues and is handled during the next + // bufNormalize call + if ((dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) && signal.is_wire()) { + Wire *w = signal.as_wire(); + if (w->driverCell_ == nullptr) { + w->driverCell_ = this; + w->driverPort_ = portname; + + conn_it->second = std::move(signal); + return; + } + } + + if (dir == RTLIL::PD_OUTPUT || dir == RTLIL::PD_INOUT) { + module->buf_norm_cell_queue.insert(this); + module->buf_norm_cell_port_queue.emplace(this, portname); + } else { + for (auto &chunk : signal.chunks()) + if (chunk.wire != nullptr && chunk.wire->driverCell_ == nullptr) + module->buf_norm_wire_queue.insert(chunk.wire); + } + + if (type == ID($connect)) { + for (auto &[port, sig] : connections_) { + for (auto &chunk : sig.chunks()) { + if (!chunk.wire) + continue; + auto it = module->buf_norm_connect_index.find(chunk.wire); + if (it == module->buf_norm_connect_index.end()) + continue; + it->second.erase(this); + if (it->second.empty()) + module->buf_norm_connect_index.erase(it); + } + } + conn_it->second = std::move(signal); + for (auto &[port, sig] : connections_) { + for (auto &chunk : sig.chunks()) { + if (!chunk.wire) + continue; + module->buf_norm_connect_index[chunk.wire].insert(this); + } + } + return; + } + } + conn_it->second = std::move(signal); + +} + +YOSYS_NAMESPACE_END diff --git a/tests/various/aiger2.ys b/tests/various/aiger2.ys index d2b024d2f..6f6958141 100644 --- a/tests/various/aiger2.ys +++ b/tests/various/aiger2.ys @@ -157,6 +157,7 @@ splitnets -ports copy test gold flatten gold techmap submodule1 +opt_clean select test write_aiger2 -flatten aiger2_ops.aig select -clear @@ -216,6 +217,7 @@ prep -top top techmap t:$add splitnets -ports top +opt_clean write_aiger2 -flatten aiger2_flatten.aig flatten rename top gold From 5f79a6e868118bb9f91a3d72f23621a5b1f40f90 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Wed, 3 Sep 2025 15:36:42 +0200 Subject: [PATCH 48/60] Clean up $buf with 'z inputs, $input_port and $connect cells This ensures that entering and leaving bufnorm followed by `opt_clean` is equivalent to just running `opt_clean`. Also make sure that 'z-$buf cells get techmapped in a compatible way. --- passes/opt/opt_clean.cc | 29 +++++++++++++++++++++++++++-- passes/techmap/simplemap.cc | 17 ++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index d9bd4c027..a254dc915 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -600,15 +600,40 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool log("Finding unused cells or wires in module %s..\n", module->name); std::vector delcells; - for (auto cell : module->cells()) + for (auto cell : module->cells()) { if (cell->type.in(ID($pos), ID($_BUF_), ID($buf)) && !cell->has_keep_attr()) { bool is_signed = cell->type == ID($pos) && cell->getParam(ID::A_SIGNED).as_bool(); RTLIL::SigSpec a = cell->getPort(ID::A); RTLIL::SigSpec y = cell->getPort(ID::Y); a.extend_u0(GetSize(y), is_signed); - module->connect(y, a); + + if (a.has_const(State::Sz)) { + SigSpec new_a; + SigSpec new_y; + for (int i = 0; i < GetSize(a); ++i) { + SigBit b = a[i]; + if (b == State::Sz) + continue; + new_a.append(b); + new_y.append(y[i]); + } + a = std::move(new_a); + y = std::move(new_y); + } + if (!y.empty()) + module->connect(y, a); + delcells.push_back(cell); + } else if (cell->type.in(ID($connect)) && !cell->has_keep_attr()) { + RTLIL::SigSpec a = cell->getPort(ID::A); + RTLIL::SigSpec b = cell->getPort(ID::B); + if (a.has_const() && !b.has_const()) + std::swap(a, b); + module->connect(a, b); + delcells.push_back(cell); + } else if (cell->type.in(ID($input_port)) && !cell->has_keep_attr()) { delcells.push_back(cell); } + } for (auto cell : delcells) { if (verbose) log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(), diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index b23985770..ddfd7e03e 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -47,7 +47,22 @@ void simplemap_buf(RTLIL::Module *module, RTLIL::Cell *cell) RTLIL::SigSpec sig_a = cell->getPort(ID::A); RTLIL::SigSpec sig_y = cell->getPort(ID::Y); - module->connect(RTLIL::SigSig(sig_y, sig_a)); + if (sig_a.has_const(State::Sz)) { + SigSpec new_a; + SigSpec new_y; + for (int i = 0; i < GetSize(sig_a); ++i) { + SigBit b = sig_a[i]; + if (b == State::Sz) + continue; + new_a.append(b); + new_y.append(sig_y[i]); + } + sig_a = std::move(new_a); + sig_y = std::move(new_y); + } + + if (!sig_y.empty()) + module->connect(RTLIL::SigSig(sig_y, sig_a)); } void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell) From 4918f37be3787045709ce9bd68bcaf25417632e1 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 16 Sep 2025 14:01:15 +0200 Subject: [PATCH 49/60] write_aiger2: Treat inout ports as output ports With the previous bufnorm implementation inout ports were not supported at all, so this didn't matter, but with the new bufnorm implementation they need to be treated as output ports. --- backends/aiger2/aiger.cc | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 956e9c43a..fad73ba9b 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -566,7 +566,7 @@ struct Index { } Lit ret; - if (!bit.wire->port_input) { + if (!bit.wire->port_input || bit.wire->port_output) { // an output of a cell Cell *driver = bit.wire->driverCell(); @@ -618,7 +618,7 @@ struct Index { if (!cursor) { log_assert(bit.wire->module == top); - log_assert(bit.wire->port_input); + log_assert(bit.wire->port_input && !bit.wire->port_output); return lits[top_minfo->windices[bit.wire] + bit.offset]; } else { log_assert(bit.wire->module == cursor->leaf_module(*this)); @@ -723,7 +723,7 @@ struct AigerWriter : Index { for (auto id : top->ports) { Wire *w = top->wire(id); log_assert(w); - if (w->port_input) + if (w->port_input && !w->port_output) for (int i = 0; i < w->width; i++) { pi_literal(SigBit(w, i)) = lit_counter; inputs.push_back(SigBit(w, i)); @@ -828,7 +828,7 @@ struct XAigerAnalysis : Index { { log_assert(cursor.is_top()); // TOOD: fix analyzer to work with hierarchy - if (bit.wire->port_input) + if (bit.wire->port_input && !bit.wire->port_output) return false; Cell *driver = bit.wire->driverCell(); @@ -838,7 +838,7 @@ struct XAigerAnalysis : Index { int max = 1; for (auto wire : mod->wires()) - if (wire->port_input) + if (wire->port_input && !wire->port_output) for (int i = 0; i < wire->width; i++) { int ilevel = visit(cursor, driver->getPort(wire->name)[i]); max = std::max(max, ilevel + 1); @@ -858,7 +858,7 @@ struct XAigerAnalysis : Index { for (auto id : top->ports) { Wire *w = top->wire(id); log_assert(w); - if (w->port_input) + if (w->port_input && !w->port_output) for (int i = 0; i < w->width; i++) pi_literal(SigBit(w, i)) = 0; } @@ -868,7 +868,7 @@ struct XAigerAnalysis : Index { Module *def = design->module(box->type); if (!(def && def->has_attribute(ID::abc9_box_id))) for (auto &conn : box->connections_) - if (box->output(conn.first)) + if (box->port_dir(conn.first) != RTLIL::PD_INPUT) for (auto bit : conn.second) pi_literal(bit, &cursor) = 0; } @@ -883,7 +883,7 @@ struct XAigerAnalysis : Index { Module *def = design->module(box->type); if (!(def && def->has_attribute(ID::abc9_box_id))) for (auto &conn : box->connections_) - if (box->input(conn.first)) + if (box->port_dir(conn.first) == RTLIL::PD_INPUT) for (auto bit : conn.second) (void) eval_po(bit); } @@ -950,12 +950,7 @@ struct XAigerWriter : AigerWriter { void append_opaque_box_ports(Cell *box, HierCursor &cursor, bool inputs) { for (auto &conn : box->connections_) { - bool is_input = box->input(conn.first); - bool is_output = box->output(conn.first); - - if (!(is_input || is_output) || (is_input && is_output)) - log_error("Ambiguous port direction on %s/%s\n", - log_id(box->type), log_id(conn.first)); + bool is_input = box->port_dir(conn.first) == RTLIL::PD_INPUT; if (is_input && inputs) { int bitp = 0; @@ -980,10 +975,10 @@ struct XAigerWriter : AigerWriter { bitp++; } - } else if (is_output && !inputs) { + } else if (!is_input && !inputs) { for (auto &bit : conn.second) { - if (!bit.wire || bit.wire->port_input) - log_error("Bad connection"); + if (!bit.wire || (bit.wire->port_input && !bit.wire->port_output)) + log_error("Bad connection %s/%s ~ %s\n", log_id(box), log_id(conn.first), log_signal(conn.second)); ensure_pi(bit, cursor); @@ -1119,7 +1114,7 @@ struct XAigerWriter : AigerWriter { holes_pi_idx++; } holes_wb->setPort(port_id, in_conn); - } else if (port->port_output && !port->port_input) { + } else if (port->port_output) { // primary for (int i = 0; i < port->width; i++) { SigBit bit; @@ -1172,7 +1167,7 @@ struct XAigerWriter : AigerWriter { log_assert(port); if (port->port_input && !port->port_output) { box_co_num += port->width; - } else if (port->port_output && !port->port_input) { + } else if (port->port_output) { box_ci_num += port->width; } else { log_abort(); @@ -1195,7 +1190,7 @@ struct XAigerWriter : AigerWriter { reset_counters(); for (auto w : top->wires()) - if (w->port_input) + if (w->port_input && !w->port_output) for (int i = 0; i < w->width; i++) ensure_pi(SigBit(w, i)); From 47b3ee8c8bafb5e1fc8f884b28eaf474e0a8ae8b Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 16 Sep 2025 14:02:32 +0200 Subject: [PATCH 50/60] write_aiger2: Ignore the $input_port cell during indexing. The $input_port cell is added by the bufnorm code to simplify handling of input ports for new code that uses bufnorm, but the aiger2 backend does already handle input ports separately, so we just ignore those. --- backends/aiger2/aiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index fad73ba9b..05714bc2e 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -91,7 +91,7 @@ struct Index { int pos = index_wires(info, m); for (auto cell : m->cells()) { - if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3))) + if (cell->type.in(KNOWN_OPS) || cell->type.in(ID($scopeinfo), ID($specify2), ID($specify3), ID($input_port))) continue; Module *submodule = m->design->module(cell->type); From 4f239b536bafd8f358c9b08600f1146bcb6f6120 Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 16 Sep 2025 13:40:12 +0200 Subject: [PATCH 51/60] abc_new: Hide buffered 'z drivers from read/write_xaiger2 With the updated bufnorm code, buffered 'z drivers are used as anchor points for undirected connections. These are currently not supported by read/write_xaiger2, so we temporarily replace those by roughly equivalent $tribuf cells which will be handled as blackboxes that properly roundtrip through the xaiger2 front and backend. --- passes/techmap/abc9_ops.cc | 82 +++++++++++++++++++++++++++++++++++++- passes/techmap/abc_new.cc | 2 + 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 9a9f7dcb5..ecba519bf 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -1566,6 +1566,70 @@ clone_lut: design->remove(mapped_mod); } + +static void replace_zbufs(Design *design) +{ + design->bufNormalize(true); + std::vector zbufs; + + for (auto mod : design->modules()) { + zbufs.clear(); + for (auto cell : mod->cells()) { + if (cell->type != ID($buf)) + continue; + auto &sig = cell->getPort(ID::A); + for (int i = 0; i < GetSize(sig); ++i) { + if (sig[i] == State::Sz) { + zbufs.push_back(cell); + break; + } + } + } + + for (auto cell : zbufs) { + auto sig = cell->getPort(ID::A); + for (int i = 0; i < GetSize(sig); ++i) { + if (sig[i] == State::Sz) { + Wire *w = mod->addWire(NEW_ID); + Cell *ud = mod->addCell(NEW_ID, ID($tribuf)); + ud->set_bool_attribute(ID(aiger2_zbuf)); + ud->setParam(ID::WIDTH, 1); + ud->setPort(ID::Y, w); + ud->setPort(ID::EN, State::S0); + ud->setPort(ID::A, State::S0); + sig[i] = w; + } + } + log("XXX %s -> %s\n", log_signal(cell->getPort(ID::A)), log_signal(sig)); + cell->setPort(ID::A, sig); + } + + mod->bufNormalize(); + } +} + + + +static void restore_zbufs(Design *design) +{ + std::vector to_remove; + + for (auto mod : design->modules()) { + to_remove.clear(); + for (auto cell : mod->cells()) + if (cell->type == ID($tribuf) && cell->has_attribute(ID(aiger2_zbuf))) + to_remove.push_back(cell); + + for (auto cell : to_remove) { + SigSpec sig_y = cell->getPort(ID::Y); + mod->addBuf(NEW_ID, Const(State::Sz, GetSize(sig_y)), sig_y); + mod->remove(cell); + } + mod->bufNormalize(); + } +} + + struct Abc9OpsPass : public Pass { Abc9OpsPass() : Pass("abc9_ops", "helper functions for ABC9") { } void help() override @@ -1668,6 +1732,8 @@ struct Abc9OpsPass : public Pass { bool prep_lut_mode = false; bool prep_box_mode = false; bool reintegrate_mode = false; + bool replace_zbufs_mode = false; + bool restore_zbufs_mode = false; bool dff_mode = false; std::string write_lut_dst; int maxlut = 0; @@ -1754,16 +1820,30 @@ struct Abc9OpsPass : public Pass { dff_mode = true; continue; } + if (arg == "-replace_zbufs") { + replace_zbufs_mode = true; + valid = true; + continue; + } + if (arg == "-restore_zbufs") { + restore_zbufs_mode = true; + valid = true; + continue; + } break; } extra_args(args, argidx, design); if (!valid) - log_cmd_error("At least one of -check, -break_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate must be specified.\n"); + log_cmd_error("At least one of -check, -break_scc, -prep_{delays,xaiger,dff[123],lut,box}, -write_{lut,box}, -reintegrate, -{replace,restore}_zbufs must be specified.\n"); if (dff_mode && !check_mode && !prep_hier_mode && !prep_delays_mode && !prep_xaiger_mode && !reintegrate_mode) log_cmd_error("'-dff' option is only relevant for -prep_{hier,delay,xaiger} or -reintegrate.\n"); + if (replace_zbufs_mode) + replace_zbufs(design); + if (restore_zbufs_mode) + restore_zbufs(design); if (check_mode) check(design, dff_mode); if (prep_hier_mode) diff --git a/passes/techmap/abc_new.cc b/passes/techmap/abc_new.cc index 286ab4d5b..c48295916 100644 --- a/passes/techmap/abc_new.cc +++ b/passes/techmap/abc_new.cc @@ -169,10 +169,12 @@ struct AbcNewPass : public ScriptPass { } run(stringf(" abc9_ops -write_box %s/input.box", tmpdir)); + run(" abc9_ops -replace_zbufs"); run(stringf(" write_xaiger2 -mapping_prep -map2 %s/input.map2 %s/input.xaig", tmpdir, tmpdir)); run(stringf(" abc9_exe %s -cwd %s -box %s/input.box", exe_options, tmpdir, tmpdir)); run(stringf(" read_xaiger2 -sc_mapping -module_name %s -map2 %s/input.map2 %s/output.aig", modname.c_str(), tmpdir.c_str(), tmpdir.c_str())); + run(" abc9_ops -restore_zbufs"); if (!help_mode && mod->has_attribute(ID(abc9_script))) { if (script_save.empty()) From 79e05a195db710f52778ee38f45ed338d14f691e Mon Sep 17 00:00:00 2001 From: Jannis Harder Date: Tue, 16 Sep 2025 15:49:36 +0200 Subject: [PATCH 52/60] verilog: Bufnorm cell backend and frontend support This makes the Verilog backend handle the $connect and $input_port cells. This represents the undirected $connect cell using the `tran` primitive, so we also extend the frontend to support this. --- backends/verilog/verilog_backend.cc | 50 +++++++++++++++++++++++++++++ frontends/ast/simplify.cc | 26 ++++++++++----- frontends/verilog/verilog_lexer.l | 2 +- 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index aea29f710..c747aa901 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -1099,6 +1099,33 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) } if (cell->type.in(ID($_BUF_), ID($buf))) { + if (cell->type == ID($buf) && cell->getPort(ID::A).has_const(State::Sz)) { + RTLIL::SigSpec a = cell->getPort(ID::A); + RTLIL::SigSpec y = cell->getPort(ID::Y); + a.extend_u0(GetSize(y)); + + if (a.has_const(State::Sz)) { + SigSpec new_a; + SigSpec new_y; + for (int i = 0; i < GetSize(a); ++i) { + SigBit b = a[i]; + if (b == State::Sz) + continue; + new_a.append(b); + new_y.append(y[i]); + } + a = std::move(new_a); + y = std::move(new_y); + } + if (!y.empty()) { + f << stringf("%s" "assign ", indent); + dump_sigspec(f, y); + f << stringf(" = "); + dump_sigspec(f, a); + f << stringf(";\n"); + } + return true; + } f << stringf("%s" "assign ", indent); dump_sigspec(f, cell->getPort(ID::Y)); f << stringf(" = "); @@ -1498,6 +1525,29 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell) return true; } + if (cell->type == ID($input_port)) + return true; + + if (cell->type == ID($connect)) + { + int width = cell->getParam(ID::WIDTH).as_int() ; + if (width == 1) { + f << stringf("%s" "tran(", indent); + dump_sigspec(f, cell->getPort(ID::A)); + f << stringf(", "); + dump_sigspec(f, cell->getPort(ID::B)); + f << stringf(");\n"); + } else { + auto tran_id = next_auto_id(); + f << stringf("%s" "tran %s[%d:0](", indent, tran_id, width - 1); + dump_sigspec(f, cell->getPort(ID::A)); + f << stringf(", "); + dump_sigspec(f, cell->getPort(ID::B)); + f << stringf(");\n"); + } + return true; + } + if (cell->is_builtin_ff()) { FfData ff(nullptr, cell); diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index cf9d7443e..81018e137 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2756,19 +2756,24 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin newNode = std::make_unique(location, AST_GENBLOCK); int num = max(children.at(0)->range_left, children.at(0)->range_right) - min(children.at(0)->range_left, children.at(0)->range_right) + 1; + if (this->children.at(1)->type == AST_PRIMITIVE) { + // Move the range to the AST_PRIMITIVE node and replace this with the AST_PRIMITIVE node handled below + newNode = std::move(this->children.at(1)); + newNode->range_left = this->children.at(0)->range_left; + newNode->range_right = this->children.at(0)->range_right; + newNode->range_valid = true; + goto apply_newNode; + } + for (int i = 0; i < num; i++) { int idx = children.at(0)->range_left > children.at(0)->range_right ? children.at(0)->range_right + i : children.at(0)->range_right - i; auto new_cell_owned = children.at(1)->clone(); auto* new_cell = new_cell_owned.get(); newNode->children.push_back(std::move(new_cell_owned)); new_cell->str += stringf("[%d]", idx); - if (new_cell->type == AST_PRIMITIVE) { - input_error("Cell arrays of primitives are currently not supported.\n"); - } else { - this->dumpAst(NULL, " "); - log_assert(new_cell->children.at(0)->type == AST_CELLTYPE); - new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str); - } + + log_assert(new_cell->children.at(0)->type == AST_CELLTYPE); + new_cell->children.at(0)->str = stringf("$array:%d:%d:%s", i, num, new_cell->children.at(0)->str); } goto apply_newNode; @@ -2789,6 +2794,11 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } children.clear(); + // TODO handle bit-widths of primitives and support cell arrays for more primitives + + if (range_valid && str != "tran") + input_error("Cell arrays of primitives are currently not supported.\n"); + if (str == "bufif0" || str == "bufif1" || str == "notif0" || str == "notif1") { if (children_list.size() != 3) @@ -2817,7 +2827,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin fixup_hierarchy_flags(); did_something = true; } - else if (str == "buf" || str == "not") + else if (str == "buf" || str == "not" || str == "tran") { auto& input = children_list.back(); if (str == "not") diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index c6d2ed992..62a7f7bbb 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -493,7 +493,7 @@ TIME_SCALE_SUFFIX [munpf]?s \"{3}(\"{0,2}([^\\"]|\\.|\\\n))*\"{3} { return process_str(yytext + 3, yyleng - 6, true, out_loc); } -and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 { +and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1|tran { auto val = std::make_unique(YYText()); return parser::make_TOK_PRIMITIVE(std::move(val), out_loc); } From 5b099abda4e05af0830d840ee6bd144ec6047b78 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Wed, 17 Sep 2025 16:02:04 +0100 Subject: [PATCH 53/60] help: fix memory leak for -dump-cells-json --- kernel/register.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/kernel/register.cc b/kernel/register.cc index 9436b540a..bd12dcc38 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -956,13 +956,7 @@ struct HelpPass : public Pass { auto name = it.first.str(); if (cell_help_messages.contains(name)) { auto cell_help = cell_help_messages.get(name); - if (groups.count(cell_help.group) != 0) { - auto group_cells = &groups.at(cell_help.group); - group_cells->push_back(name); - } else { - auto group_cells = new vector(1, name); - groups.emplace(cell_help.group, *group_cells); - } + groups[cell_help.group].emplace_back(name); auto cell_pair = pair(cell_help, it.second); cells.emplace(name, cell_pair); } else { From a686c5a73c71c238ce5ac25baac84af10932a997 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 00:22:24 +0000 Subject: [PATCH 54/60] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3e0849c09..1a5ecf35b 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+125 +YOSYS_VER := 0.57+148 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 042aff7c77ae9b7766e6e530e4427f07471bc287 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 19 Sep 2025 11:39:24 +1200 Subject: [PATCH 55/60] Bump test-compile to gcc-14 as newest --- .github/workflows/test-compile.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index 45d3d7b90..7c18c7ba0 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -42,7 +42,7 @@ jobs: - 'gcc-10' # newest, make sure to update maximum standard step to match - 'clang-19' - - 'gcc-13' + - 'gcc-14' include: # macOS x86 - os: macos-13 @@ -81,7 +81,7 @@ jobs: # maximum standard, only on newest compilers - name: Build C++20 - if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-13' }} + if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-14' }} shell: bash run: | make config-$CC_SHORT From 6b3a7e244037e891dc98774845516b2a1b0c1840 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:21:36 +0000 Subject: [PATCH 56/60] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1a5ecf35b..720fd6323 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+148 +YOSYS_VER := 0.57+153 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 9fa27dae3cc68205eab8d9d06302ace2bc6ddf41 Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Sat, 13 Sep 2025 17:15:24 +0300 Subject: [PATCH 57/60] hotfix: fix new log functions being incompatible with pyosys Modify python wrapper generator script with corner-case handlers such that functions that start with `log_formatted` have the format string coerced to `"%s"` and also have an alias without the `_formatted` part. --- misc/py_wrap_generator.py | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index ef0862587..e695d1ef0 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -71,7 +71,7 @@ keyword_aliases = { #These can be used without any explicit conversion primitive_types = ["void", "bool", "int", "double", "size_t", "std::string", - "string", "State", "char_p", "std::source_location", "source_location"] + "string", "string_view", "std::string_view", "State", "char_p", "std::source_location", "source_location"] from enum import Enum @@ -557,6 +557,7 @@ class Attribute: default_value = None pos = None pos_counter = 0 + coerce_arg = None def __init__(self, wtype, varname, is_const = False, default_value = None): self.wtype = wtype @@ -566,7 +567,7 @@ class Attribute: self.container = None @staticmethod - def from_string(str_def, containing_file, line_number): + def from_string(str_def, containing_file, line_number, *, owner_fn_name=""): if len(str_def) < 3: return None orig = str_def @@ -630,6 +631,14 @@ class Attribute: else: arg.wtype.attr_type = attr_types.amp arg.varname = arg.varname[1:] + + # special exception: format strings + if arg.wtype.name in ["std::string_view", "string_view"]: + if arg.varname == "format": + arg.coerce_arg = '"%s"' + elif arg.varname == "prefix" and "warning" in owner_fn_name: + arg.coerce_arg = '"Warning: "' + return arg #Generates the varname. If the attribute has no name in the header file, @@ -1391,7 +1400,7 @@ class WFunction: for i, arg in enumerate(args): if arg.strip() == "...": continue - parsed = Attribute.from_string(arg.strip(), containing_file, line_number) + parsed = Attribute.from_string(arg.strip(), containing_file, line_number, owner_fn_name=func.name) if parsed == None: return None # Only allow std::source_location as defaulted last argument, and @@ -1431,6 +1440,8 @@ class WFunction: text += "static " text += self.ret_type.gen_text() + " " + self.alias + "(" for arg in self.args: + if arg.coerce_arg: + continue text += arg.gen_listitem() text += ", " if len(self.args) > 0: @@ -1497,6 +1508,8 @@ class WFunction: text += self.member_of.name + "::" text += self.alias + "(" for arg in self.args: + if arg.coerce_arg: + continue text += arg.gen_listitem() text += ", " if len(self.args) > 0: @@ -1516,13 +1529,14 @@ class WFunction: if self.ret_type.name in classnames: text += self.ret_type.name + "::get_py_obj(" if self.member_of == None: - text += "::" + self.namespace + "::" + self.alias + "(" + text += "::" + self.namespace + "::" + self.name + "(" elif self.is_static: text += self.member_of.namespace + "::" + self.member_of.name + "::" + self.name + "(" else: text += "this->get_cpp_obj()->" + self.name + "(" for arg in self.args: - text += arg.gen_call() + ", " + text += arg.coerce_arg or arg.gen_call() + text += ", " if len(self.args) > 0: text = text[:-2] if self.ret_type.name in classnames: @@ -1639,6 +1653,8 @@ class WFunction: else: text += "(" + self.member_of.name + "::*)(" for a in self.args: + if a.coerce_arg: + continue text += a.gen_listitem_hash() + ", " if len(self.args) > 0: text = text[0:-2] + f"){self.gen_post_qualifiers(True)}>" @@ -2122,6 +2138,16 @@ def parse_header(source): if class_ == None: debug("\tFound unowned function \"" + candidate.name + "\" in namespace " + concat_namespace(namespaces),2) unowned_functions.append(candidate) + + # generate log aliases + if candidate.name.startswith("log_formatted"): + alias = candidate.name.replace("log_formatted", "log") + if alias == "log_string": + alias = "log" + copied_candidate = copy.copy(candidate) + copied_candidate.alias = alias + unowned_functions.append(copied_candidate) + else: debug("\t\tFound function \"" + candidate.name + "\" of class \"" + class_[0].name + "\" in namespace " + concat_namespace(namespaces),2) class_[0].found_funs.append(candidate) @@ -2359,6 +2385,8 @@ def gen_wrappers(filename, debug_level_ = 0): #include USING_YOSYS_NAMESPACE +using std::string_view; + namespace YOSYS_PYTHON { [[noreturn]] static void log_python_exception_as_error() { From 1fa5ceee8c57347b9a834ecd3f4a80cf343f91fa Mon Sep 17 00:00:00 2001 From: Mohamed Gaber Date: Mon, 15 Sep 2025 17:02:11 +0300 Subject: [PATCH 58/60] pyosys: restore remaining log functions Co-authored-by: George Rennie <19538554+georgerennie@users.noreply.github.com> --- kernel/log.h | 5 +++++ misc/py_wrap_generator.py | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/kernel/log.h b/kernel/log.h index 78b202159..bd5788758 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -153,6 +153,11 @@ inline void log_warning(FmtString...> fmt, const Args &... ar { log_formatted_warning("Warning: ", fmt.format(args...)); } + +inline void log_formatted_warning_noprefix(std::string str) +{ + log_formatted_warning("", str); +} template inline void log_warning_noprefix(FmtString...> fmt, const Args &... args) { diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index e695d1ef0..aa1406f9b 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -632,12 +632,17 @@ class Attribute: arg.wtype.attr_type = attr_types.amp arg.varname = arg.varname[1:] - # special exception: format strings + # handle string views if arg.wtype.name in ["std::string_view", "string_view"]: - if arg.varname == "format": + if arg.varname == "format" and owner_fn_name.startswith("log_"): + # coerce format strings to "%s" (not bridgable) arg.coerce_arg = '"%s"' elif arg.varname == "prefix" and "warning" in owner_fn_name: + # coerce warning prefix to "warning:" arg.coerce_arg = '"Warning: "' + else: + # boost::python can't bridge string views, so just copy them + arg.wtype.name = "string" return arg From d60dc93e9223e33b635194ed5efc49c4fb89fc49 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Sat, 20 Sep 2025 11:01:25 +1000 Subject: [PATCH 59/60] Gowin. Renaming inputs of the DCS primitive. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dynamic clock selection (DCS) primitive has undergone changes with the release of the GW5A series—the CLK0,1,2,3 inputs are now CLKIN0,1,2,3, but only for GW5A series chips. There are no functional changes, only renaming. Here we are transferring the description of the DCS primitive from general to specialized files for each chip series. We have also fixed a bug in the generation script that caused the loss of primitive parameters. Fortunately, this only affected the analog-to-digital converter, which has not yet been implemented. Signed-off-by: YRabbit --- techlibs/gowin/cells_sim.v | 8 --- techlibs/gowin/cells_xtra.py | 4 +- techlibs/gowin/cells_xtra_gw1n.v | 7 +++ techlibs/gowin/cells_xtra_gw2a.v | 12 +++++ techlibs/gowin/cells_xtra_gw5a.v | 84 ++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 10 deletions(-) diff --git a/techlibs/gowin/cells_sim.v b/techlibs/gowin/cells_sim.v index 58a2f52e6..5e6083426 100644 --- a/techlibs/gowin/cells_sim.v +++ b/techlibs/gowin/cells_sim.v @@ -1958,14 +1958,6 @@ parameter FREQ_DIV = 100; parameter REGULATOR_EN = 1'b0; endmodule -(* blackbox *) -module DCS (CLK0, CLK1, CLK2, CLK3, CLKSEL, SELFORCE, CLKOUT); -input CLK0, CLK1, CLK2, CLK3, SELFORCE; -input [3:0] CLKSEL; -output CLKOUT; -parameter DCS_MODE = "RISING"; -endmodule - (* blackbox *) module EMCU ( input FCLK, diff --git a/techlibs/gowin/cells_xtra.py b/techlibs/gowin/cells_xtra.py index 7a7c9ac0a..01416268a 100644 --- a/techlibs/gowin/cells_xtra.py +++ b/techlibs/gowin/cells_xtra.py @@ -25,7 +25,7 @@ _skip = { # These are already described, no need to extract them from the vendor 'OSCO', 'OSCW', 'OSCZ', 'OSER10', 'OSER16', 'OSER10', 'OSER4', 'OSER8', 'OVIDEO', 'PLLVR', 'RAM16S1', 'RAM16S2', 'RAM16S4', 'RAM16SDP1', 'RAM16SDP2', 'RAM16SDP4', 'rPLL', 'SDP', - 'SDPX9', 'SP', 'SPX9', 'TBUF', 'TLVDS_OBUF', 'VCC', 'DCS', 'EMCU', + 'SDPX9', 'SP', 'SPX9', 'TBUF', 'TLVDS_OBUF', 'VCC', 'EMCU', # These are not planned for implementation 'MUX2_MUX8', 'MUX2_MUX16', 'MUX2_MUX32', 'MUX4', 'MUX8', 'MUX16', 'MUX32', 'DL', 'DLE', 'DLC', 'DLCE', 'DLP', 'DLPE', 'DLN', 'DLNE', @@ -50,7 +50,7 @@ def xtract_cells_decl(dir, fout): fout.write('\n') if l.rstrip()[-1] != ';': state = State.IN_MODULE_MULTILINE - elif l.startswith('parameter') and state == State.IN_MODULE: + elif l.lstrip().startswith('parameter') and state == State.IN_MODULE: fout.write(l) if l.rstrip()[-1] == ',': state = State.IN_PARAMETER diff --git a/techlibs/gowin/cells_xtra_gw1n.v b/techlibs/gowin/cells_xtra_gw1n.v index abf2c0493..436fda0fa 100644 --- a/techlibs/gowin/cells_xtra_gw1n.v +++ b/techlibs/gowin/cells_xtra_gw1n.v @@ -1109,6 +1109,13 @@ parameter IDLE = 4'd0, RD_S2 = 4'd12; endmodule +module DCS (...); +input CLK0, CLK1, CLK2, CLK3, SELFORCE; +input [3:0] CLKSEL; +output CLKOUT; + parameter DCS_MODE = "RISING"; +endmodule + module DQCE (...); input CLKIN; input CE; diff --git a/techlibs/gowin/cells_xtra_gw2a.v b/techlibs/gowin/cells_xtra_gw2a.v index 5c365f8da..4df48ab64 100644 --- a/techlibs/gowin/cells_xtra_gw2a.v +++ b/techlibs/gowin/cells_xtra_gw2a.v @@ -1082,6 +1082,11 @@ input RLOADN, RMOVE, RDIR, WLOADN, WMOVE, WDIR, HOLD; output DQSR90, DQSW0, DQSW270; output [2:0] RPOINT, WPOINT; output RVALID,RBURST, RFLAG, WFLAG; + parameter FIFO_MODE_SEL = 1'b0; + parameter RD_PNTR = 3'b000; + parameter DQS_MODE = "X1"; + parameter HWL = "false"; + parameter GSREN = "false"; endmodule module DLLDLY (...); @@ -1095,6 +1100,13 @@ parameter DLY_SIGN = 1'b0; parameter DLY_ADJ = 0; endmodule +module DCS (...); +input CLK0, CLK1, CLK2, CLK3, SELFORCE; +input [3:0] CLKSEL; +output CLKOUT; + parameter DCS_MODE = "RISING"; +endmodule + module DQCE (...); input CLKIN; input CE; diff --git a/techlibs/gowin/cells_xtra_gw5a.v b/techlibs/gowin/cells_xtra_gw5a.v index c82f6af25..b4df1f33e 100644 --- a/techlibs/gowin/cells_xtra_gw5a.v +++ b/techlibs/gowin/cells_xtra_gw5a.v @@ -1143,6 +1143,13 @@ input CE; output CLKOUT; endmodule +module DCS (...); +input CLKIN0, CLKIN1, CLKIN2, CLKIN3, SELFORCE; +input [3:0] CLKSEL; +output CLKOUT; +parameter DCS_MODE = "RISING"; +endmodule + module DDRDLL (...); input CLKIN; input STOP; @@ -1714,18 +1721,94 @@ input LOAD; endmodule module ADCLRC (...); + parameter DYN_BKEN = "FALSE"; + parameter BUF_SERDES_Q1_EN = 3'b000; + parameter BUF_BK2_EN = 6'b000000; + parameter BUF_BK3_EN = 6'b000000; + parameter BUF_BK4_EN = 6'b000000; + parameter BUF_BK5_EN = 6'b000000; + parameter BUF_BK10_EN = 5'b00000; + parameter BUF_BK11_EN = 5'b00000; + parameter CLK_SEL = 1'b0; + parameter PIOCLK_SEL = 1'b0; + parameter VSEN_CTL = 3'b000; + parameter VSEN_CTL_SEL = 1'b0; + parameter ADC_MODE = 1'b0; + parameter DIV_CTL = 2'd0; + parameter SAMPLE_CNT_SEL = 3'd4; + parameter RATE_CHANGE_CTRL = 3'd4; endmodule module ADCULC (...); + parameter DYN_BKEN = "FALSE"; + parameter BUF_VCC_EN = 1'b0; + parameter BUF_VCCM_EN = 1'b0; + parameter BUF_MIPI_M0_EN = 3'b000; + parameter BUF_MIPI_M1_EN = 3'b000; + parameter BUF_SERDES_Q0_EN = 3'b000; + parameter BUF_BK6_EN = 6'b000000; + parameter BUF_BK7_EN = 6'b000000; + parameter CLK_SEL = 1'b0; + parameter PIOCLK_SEL = 1'b0; + parameter VSEN_CTL = 3'b000; + parameter VSEN_CTL_SEL = 1'b0; + parameter ADC_MODE = 1'b0; + parameter DIV_CTL = 2'd0; + parameter SAMPLE_CNT_SEL = 3'd4; + parameter RATE_CHANGE_CTRL = 3'd4; endmodule module ADC (...); + parameter CLK_SEL = 1'b0; + parameter DIV_CTL = 2'd0; + parameter BUF_EN = 12'b000000000000; + parameter BUF_BK0_VREF_EN = 1'b0; + parameter BUF_BK1_VREF_EN = 1'b0; + parameter BUF_BK2_VREF_EN = 1'b0; + parameter BUF_BK3_VREF_EN = 1'b0; + parameter BUF_BK4_VREF_EN = 1'b0; + parameter BUF_BK5_VREF_EN = 1'b0; + parameter BUF_BK6_VREF_EN = 1'b0; + parameter BUF_BK7_VREF_EN = 1'b0; + parameter CSR_ADC_MODE = 1'b1; + parameter CSR_VSEN_CTRL = 3'd0; + parameter CSR_SAMPLE_CNT_SEL = 3'd4; + parameter CSR_RATE_CHANGE_CTRL = 3'd4; + parameter CSR_FSCAL = 10'd730; + parameter CSR_OFFSET = -12'd1180; endmodule module ADC_SAR (...); + parameter BUF_EN = 29'b0; + parameter CLK_SEL = 1'b1; + parameter DIV_CTL = 2'd2; + parameter ADC_EN_SEL = 1'b0; + parameter PHASE_SEL = 1'b0; + parameter CSR_ADC_MODE = 1'b1; + parameter CSR_VSEN_CTRL = 3'd0; + parameter CSR_SAMPLE_CNT_SEL = 3'd4; + parameter CSR_RATE_CHANGE_CTRL = 3'd4; + parameter CSR_FSCAL = 10'd730; + parameter CSR_OFFSET = -12'd1180; + parameter ADC_CLK_DIV = 2'b00; + parameter ADC_CLKDIV_EN = 1'b0; + parameter CLK_SRC_SEL = 1'b1; + parameter VREF_BUF_EN = 1'b1; + parameter COUNT_LEN = 5'b10100; + parameter DAC_SAMPLE_END = 5'b10010; + parameter DAC_SAMPLE_START = 5'b01101; + parameter SH_SAMPLE_END = 5'b01011; + parameter SH_SAMPLE_START = 5'b00001; + parameter AUTO_CHOP_EN = 1'b0; + parameter CHOP_CLK_DIV = 4'b0; endmodule module LICD (...); + parameter STAGE_NUM = 2'b00; + parameter ENCDEC_NUM = 2'b00; + parameter CODE_WIDTH = 2'b00; + parameter INTERLEAVE_EN = 3'b000; + parameter INTERLEAVE_MODE = 3'b000; endmodule module MIPI_DPHY (...); @@ -2456,6 +2539,7 @@ parameter EQ_ZLD_LN2 = 4'b1000; endmodule module GTR12_QUAD (...); + parameter POSITION = "Q0"; endmodule module GTR12_UPAR (...); From b9dc5784119d5ca95847324a64f5a57d9aa66f22 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 21 Sep 2025 00:25:14 +0000 Subject: [PATCH 60/60] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 720fd6323..4d1a94bc2 100644 --- a/Makefile +++ b/Makefile @@ -164,7 +164,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.57+153 +YOSYS_VER := 0.57+157 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)