From 45017e19ec8498285835a83d0c55eac38506e5a1 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Fri, 31 Oct 2025 10:06:13 +0000 Subject: [PATCH] Make SigSpec::unpack() non-const --- kernel/rtlil.cc | 108 ++++++++++++++++++++++-------------------------- kernel/rtlil.h | 29 +++++++++---- 2 files changed, 71 insertions(+), 66 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 9dadf7ccb..5f36ab4e5 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -4667,23 +4667,21 @@ void RTLIL::SigSpec::Chunks::const_iterator::next_chunk_bits() chunk.width = i - bit_index; } -void RTLIL::SigSpec::unpack() const +void RTLIL::SigSpec::unpack() { if (rep_ == BITS) return; - RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; - cover("kernel.rtlil.sigspec.convert.unpack"); std::vector bits; - bits.reserve(that->chunk_.width); - for (int i = 0; i < that->chunk_.width; i++) - bits.emplace_back(that->chunk_, i); + bits.reserve(chunk_.width); + for (int i = 0; i < chunk_.width; i++) + bits.emplace_back(chunk_, i); - that->chunk_.~SigChunk(); - that->rep_ = BITS; - new (&that->bits_) std::vector(std::move(bits)); + chunk_.~SigChunk(); + rep_ = BITS; + new (&bits_) std::vector(std::move(bits)); } void RTLIL::SigSpec::updhash() const @@ -4746,25 +4744,22 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec log_assert(size() == other->size()); log_assert(pattern.size() == with.size()); - pattern.unpack(); - with.unpack(); - unpack(); - other->unpack(); - dict pattern_to_with; - for (int i = 0; i < GetSize(pattern.bits_); i++) { - if (pattern.bits_[i].wire != NULL) { - pattern_to_with.emplace(pattern.bits_[i], i); + int pattern_size = pattern.size(); + for (int i = 0; i < pattern_size; i++) { + SigBit pattern_bit = pattern[i]; + if (pattern_bit.wire != NULL) { + pattern_to_with.emplace(pattern_bit, i); } } - for (int j = 0; j < GetSize(bits_); j++) { - auto it = pattern_to_with.find(bits_[j]); + int this_size = size(); + for (int j = 0; j < this_size; j++) { + auto it = pattern_to_with.find((*this)[j]); if (it != pattern_to_with.end()) { - other->bits_[j] = with.bits_[it->second]; + (*other)[j] = with[it->second]; } } - other->hash_ = 0; other->check(); } @@ -4782,15 +4777,13 @@ void RTLIL::SigSpec::replace(const dict &rules, RT log_assert(size() == other->size()); if (rules.empty()) return; - unpack(); - other->unpack(); - for (int i = 0; i < GetSize(bits_); i++) { - auto it = rules.find(bits_[i]); + int this_size = size(); + for (int i = 0; i < this_size; i++) { + auto it = rules.find((*this)[i]); if (it != rules.end()) - other->bits_[i] = it->second; + (*other)[i] = it->second; } - other->hash_ = 0; other->check(); } @@ -4808,15 +4801,13 @@ void RTLIL::SigSpec::replace(const std::map &rules log_assert(size() == other->size()); if (rules.empty()) return; - unpack(); - other->unpack(); - for (int i = 0; i < GetSize(bits_); i++) { - auto it = rules.find(bits_[i]); + int this_size = size(); + for (int i = 0; i < this_size; i++) { + auto it = rules.find((*this)[i]); if (it != rules.end()) - other->bits_[i] = it->second; + (*other)[i] = it->second; } - other->hash_ = 0; other->check(); } @@ -5570,23 +5561,25 @@ bool RTLIL::SigSpec::match(const char* pattern) const { cover("kernel.rtlil.sigspec.match"); - unpack(); - log_assert(int(strlen(pattern)) == GetSize(bits_)); + int pattern_len = strlen(pattern); + log_assert(pattern_len == size()); - for (auto it = bits_.rbegin(); it != bits_.rend(); it++, pattern++) { - if (*pattern == ' ') + for (int i = 0; i < pattern_len; ++i) { + char ch = pattern[i]; + if (ch == ' ') continue; - if (*pattern == '*') { - if (*it != State::Sz && *it != State::Sx) + RTLIL::SigBit bit = (*this)[pattern_len - 1 - i]; + if (ch == '*') { + if (bit != State::Sz && bit != State::Sx) return false; continue; } - if (*pattern == '0') { - if (*it != State::S0) + if (ch == '0') { + if (bit != State::S0) return false; } else - if (*pattern == '1') { - if (*it != State::S1) + if (ch == '1') { + if (bit != State::S1) return false; } else log_abort(); @@ -5622,22 +5615,23 @@ std::vector RTLIL::SigSpec::to_sigbit_vector() const { cover("kernel.rtlil.sigspec.to_sigbit_vector"); - unpack(); - return bits_; + std::vector result; + result.reserve(size()); + for (SigBit bit : *this) + result.push_back(bit); + return result; } std::map RTLIL::SigSpec::to_sigbit_map(const RTLIL::SigSpec &other) const { cover("kernel.rtlil.sigspec.to_sigbit_map"); - unpack(); - other.unpack(); - - log_assert(size() == other.size()); + int this_size = size(); + log_assert(this_size == other.size()); std::map new_map; - for (int i = 0; i < GetSize(bits_); i++) - new_map[bits_[i]] = other.bits_[i]; + for (int i = 0; i < this_size; i++) + new_map[(*this)[i]] = other[i]; return new_map; } @@ -5646,15 +5640,13 @@ dict RTLIL::SigSpec::to_sigbit_dict(const RTLIL::S { cover("kernel.rtlil.sigspec.to_sigbit_dict"); - unpack(); - other.unpack(); - - log_assert(size() == other.size()); + int this_size = size(); + log_assert(this_size == other.size()); dict new_map; - new_map.reserve(size()); - for (int i = 0; i < GetSize(bits_); i++) - new_map[bits_[i]] = other.bits_[i]; + new_map.reserve(this_size); + for (int i = 0; i < this_size; i++) + new_map[(*this)[i]] = other[i]; return new_map; } diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 1265875e3..4e21cbe1e 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1222,9 +1222,10 @@ struct RTLIL::SigSpecConstIterator typedef RTLIL::SigBit& reference; const RTLIL::SigSpec *sig_p; + RTLIL::SigBit bit; int index; - inline const RTLIL::SigBit &operator*() const; + inline const RTLIL::SigBit &operator*(); inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; } inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; } inline void operator++() { index++; } @@ -1250,8 +1251,8 @@ private: new (&bits_) std::vector; } - void unpack() const; - inline void inline_unpack() const { + void unpack(); + inline void inline_unpack() { if (rep_ == CHUNK) unpack(); } @@ -1402,13 +1403,22 @@ public: friend struct Chunks::const_iterator; inline Chunks chunks() const { return {*this}; } - inline const std::vector &bits() const { inline_unpack(); return bits_; } + inline const SigSpec &bits() const { return *this; } inline int size() const { return rep_ == CHUNK ? chunk_.width : GetSize(bits_); } inline bool empty() const { return size() == 0; } inline RTLIL::SigBit &operator[](int index) { inline_unpack(); hash_ = 0; return bits_.at(index); } - inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); } + inline RTLIL::SigBit operator[](int index) const { + if (rep_ == CHUNK) { + if (index < 0 || index >= chunk_.width) + throw std::out_of_range("SigSpec::operator[]"); + if (chunk_.wire) + return RTLIL::SigBit(chunk_.wire, chunk_.offset + index); + return RTLIL::SigBit(chunk_.data[index]); + } + return bits_.at(index); + } inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; } inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = size(); return it; } @@ -1452,6 +1462,8 @@ public: RTLIL::SigBit lsb() const { log_assert(size()); return (*this)[0]; }; RTLIL::SigBit msb() const { log_assert(size()); return (*this)[size() - 1]; }; + RTLIL::SigBit front() const { return (*this)[0]; } + RTLIL::SigBit back() const { return (*this)[size() - 1]; } void append(const RTLIL::SigSpec &signal); inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); } @@ -1532,7 +1544,7 @@ public: static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str); operator std::vector() const; - operator std::vector() const { return bits(); } + operator std::vector() const { return to_sigbit_vector(); } const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < size() ? (*this)[offset] : defval; } [[nodiscard]] Hasher hash_into(Hasher h) const { if (!hash_) updhash(); h.eat(hash_); return h; } @@ -2439,8 +2451,9 @@ inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { return (*sig_p)[index]; } -inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() const { - return (*sig_p)[index]; +inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() { + bit = (*sig_p)[index]; + return bit; } inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {