From 36fe6d4c5692bf5383b36d690cd6b91bd0a2f7f0 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Sun, 14 Jul 2024 13:37:42 +0200 Subject: [PATCH 1/3] sigspec: decrease size with tagged union of bits and chunks --- kernel/rtlil.cc | 78 ++++++++++++++++++++++++++++++++++++++++++------- kernel/rtlil.h | 54 ++++++++++++++++++++++++++++++---- 2 files changed, 116 insertions(+), 16 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d3946a620de..a4061491305 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3791,6 +3791,8 @@ RTLIL::SigSpec::SigSpec(std::initializer_list parts) width_ = 0; hash_ = 0; + packed_ = true; + (void)new (&this->chunks_) std::vector(); log_assert(parts.size() > 0); auto ie = parts.begin(); auto it = ie + parts.size() - 1; @@ -3802,6 +3804,8 @@ RTLIL::SigSpec::SigSpec(const RTLIL::Const &value) { cover("kernel.rtlil.sigspec.init.const"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (GetSize(value) != 0) { chunks_.emplace_back(value); width_ = chunks_.back().width; @@ -3816,6 +3820,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::Const &&value) { cover("kernel.rtlil.sigspec.init.const.move"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (GetSize(value) != 0) { chunks_.emplace_back(std::move(value)); width_ = chunks_.back().width; @@ -3830,6 +3836,8 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk) { cover("kernel.rtlil.sigspec.init.chunk"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (chunk.width != 0) { chunks_.emplace_back(chunk); width_ = chunks_.back().width; @@ -3844,6 +3852,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::SigChunk &&chunk) { cover("kernel.rtlil.sigspec.init.chunk.move"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (chunk.width != 0) { chunks_.emplace_back(std::move(chunk)); width_ = chunks_.back().width; @@ -3858,6 +3868,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire) { cover("kernel.rtlil.sigspec.init.wire"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (wire->width != 0) { chunks_.emplace_back(wire); width_ = chunks_.back().width; @@ -3872,6 +3884,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire, int offset, int width) { cover("kernel.rtlil.sigspec.init.wire_part"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (width != 0) { chunks_.emplace_back(wire, offset, width); width_ = chunks_.back().width; @@ -3886,6 +3900,8 @@ RTLIL::SigSpec::SigSpec(const std::string &str) { cover("kernel.rtlil.sigspec.init.str"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (str.size() != 0) { chunks_.emplace_back(str); width_ = chunks_.back().width; @@ -3900,6 +3916,8 @@ RTLIL::SigSpec::SigSpec(int val, int width) { cover("kernel.rtlil.sigspec.init.int"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (width != 0) chunks_.emplace_back(val, width); width_ = width; @@ -3911,6 +3929,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width) { cover("kernel.rtlil.sigspec.init.state"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (width != 0) chunks_.emplace_back(bit, width); width_ = width; @@ -3922,6 +3942,8 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width) { cover("kernel.rtlil.sigspec.init.bit"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); if (width != 0) { if (bit.wire == NULL) chunks_.emplace_back(bit.data, width); @@ -3938,6 +3960,8 @@ RTLIL::SigSpec::SigSpec(const std::vector &chunks) { cover("kernel.rtlil.sigspec.init.stdvec_chunks"); + packed_ = true; + (void)new (&this->chunks_) std::vector(); width_ = 0; hash_ = 0; for (const auto &c : chunks) @@ -3949,6 +3973,8 @@ RTLIL::SigSpec::SigSpec(const std::vector &bits) { cover("kernel.rtlil.sigspec.init.stdvec_bits"); + packed_ = false; + (void)new (&this->bits_) std::vector(); width_ = 0; hash_ = 0; for (const auto &bit : bits) @@ -3960,6 +3986,8 @@ RTLIL::SigSpec::SigSpec(const pool &bits) { cover("kernel.rtlil.sigspec.init.pool_bits"); + packed_ = false; + (void)new (&this->bits_) std::vector(); width_ = 0; hash_ = 0; for (const auto &bit : bits) @@ -3971,6 +3999,8 @@ RTLIL::SigSpec::SigSpec(const std::set &bits) { cover("kernel.rtlil.sigspec.init.stdset_bits"); + packed_ = false; + (void)new (&this->bits_) std::vector(); width_ = 0; hash_ = 0; for (const auto &bit : bits) @@ -3982,23 +4012,47 @@ RTLIL::SigSpec::SigSpec(bool bit) { cover("kernel.rtlil.sigspec.init.bool"); + packed_ = false; + (void)new (&this->bits_) std::vector(); width_ = 0; hash_ = 0; append(SigBit(bit)); check(); } +void RTLIL::SigSpec::switch_to_packed() const +{ + // TODO change to debug asserts + log_assert(!this->packed_); + log_assert(bits_.size() == 0); + RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; + that->bits_.~vector(); + that->packed_ = true; + (void)new (&that->chunks_) std::vector(); +} + +void RTLIL::SigSpec::switch_to_unpacked() const +{ + // TODO change to debug asserts + log_assert(this->packed_); + log_assert(chunks_.size() == 0); + RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; + that->chunks_.~vector(); + that->packed_ = false; + (void)new (&that->bits_) std::vector(); +} + void RTLIL::SigSpec::pack() const { RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; - if (that->bits_.empty()) + if (packed_ || that->bits_.empty()) return; cover("kernel.rtlil.sigspec.convert.pack"); - log_assert(that->chunks_.empty()); std::vector old_bits; + std::vector new_chunks; old_bits.swap(that->bits_); RTLIL::SigChunk *last = NULL; @@ -4016,11 +4070,14 @@ void RTLIL::SigSpec::pack() const continue; } } - that->chunks_.push_back(bit); - last = &that->chunks_.back(); + new_chunks.push_back(bit); + last = &new_chunks.back(); last_end_offset = bit.offset + 1; } + that->switch_to_packed(); + that->chunks_.swap(new_chunks); + check(); } @@ -4028,19 +4085,21 @@ void RTLIL::SigSpec::unpack() const { RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; - if (that->chunks_.empty()) + if (!packed_ || that->chunks_.empty()) return; cover("kernel.rtlil.sigspec.convert.unpack"); - log_assert(that->bits_.empty()); - that->bits_.reserve(that->width_); + std::vector new_bits; + new_bits.reserve(that->width_); for (auto &c : that->chunks_) for (int i = 0; i < c.width; i++) - that->bits_.emplace_back(c, i); + new_bits.emplace_back(c, i); that->chunks_.clear(); that->hash_ = 0; + that->switch_to_unpacked(); + that->bits_.swap(new_bits); } void RTLIL::SigSpec::updhash() const @@ -4620,7 +4679,6 @@ void RTLIL::SigSpec::check(Module *mod) const w += chunk.width; } log_assert(w == width_); - log_assert(bits_.empty()); } else { @@ -4631,9 +4689,7 @@ void RTLIL::SigSpec::check(Module *mod) const if (bits_[i].wire != nullptr) log_assert(bits_[i].wire->module == mod); } - log_assert(width_ == GetSize(bits_)); - log_assert(chunks_.empty()); } } #endif diff --git a/kernel/rtlil.h b/kernel/rtlil.h index f9da2949508..179e892ec8f 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -842,20 +842,25 @@ struct RTLIL::SigSpec { private: int width_; + bool packed_; unsigned long hash_; - std::vector chunks_; // LSB at index 0 - std::vector bits_; // LSB at index 0 + union { + std::vector chunks_; // LSB at index 0 + std::vector bits_; // LSB at index 0 + }; void pack() const; void unpack() const; + void switch_to_packed() const; + void switch_to_unpacked() const; void updhash() const; inline bool packed() const { - return bits_.empty(); + return packed_; } inline void inline_unpack() const { - if (!chunks_.empty()) + if (packed_ && !chunks_.empty()) unpack(); } @@ -864,8 +869,47 @@ struct RTLIL::SigSpec friend struct RTLIL::Module; public: - SigSpec() : width_(0), hash_(0) {} + SigSpec() : width_(0), packed_(true), hash_(0), chunks_() {} + ~SigSpec() { if (packed_) chunks_.~vector(); else bits_.~vector(); } SigSpec(std::initializer_list parts); + SigSpec(const Yosys::RTLIL::SigSpec &other) + { + packed_ = other.packed_; + width_ = other.width_; + hash_ = other.hash_; + if (packed_) { + (void)new (&this->chunks_) std::vector(); + chunks_ = other.chunks_; + } else { + (void)new (&this->bits_) std::vector(); + bits_ = other.bits_; + } + check(); + } + SigSpec& operator=(const Yosys::RTLIL::SigSpec & other) + { + if (packed_ != other.packed_) { + if (packed_) { + chunks_.clear(); + switch_to_unpacked(); + bits_ = other.bits_; + } else { + bits_.clear(); + switch_to_packed(); + chunks_ = other.chunks_; + } + } else { + if (packed_) + chunks_ = other.chunks_; + else + bits_ = other.bits_; + } + + width_ = other.width_; + hash_ = other.hash_; + check(); + return *this; + } SigSpec(const RTLIL::Const &value); SigSpec(RTLIL::Const &&value); From 6e3bf76ea49a03503e1bb8a26d5a36f3866ec1b8 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Sun, 14 Jul 2024 23:25:15 +0200 Subject: [PATCH 2/3] sigspec: remove asserts --- kernel/rtlil.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a4061491305..a76e0d7136a 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -4023,8 +4023,8 @@ RTLIL::SigSpec::SigSpec(bool bit) void RTLIL::SigSpec::switch_to_packed() const { // TODO change to debug asserts - log_assert(!this->packed_); - log_assert(bits_.size() == 0); + // log_assert(!this->packed_); + // log_assert(bits_.size() == 0); RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; that->bits_.~vector(); that->packed_ = true; @@ -4034,8 +4034,8 @@ void RTLIL::SigSpec::switch_to_packed() const void RTLIL::SigSpec::switch_to_unpacked() const { // TODO change to debug asserts - log_assert(this->packed_); - log_assert(chunks_.size() == 0); + // log_assert(this->packed_); + // log_assert(chunks_.size() == 0); RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; that->chunks_.~vector(); that->packed_ = false; From 7325863db26ab2eb9d129493315f08e1f503ec96 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 17 Jul 2024 18:57:47 +0200 Subject: [PATCH 3/3] sigspec: move construct --- kernel/rtlil.cc | 33 ++++++--------------------------- kernel/rtlil.h | 16 +++++++--------- 2 files changed, 13 insertions(+), 36 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a76e0d7136a..411ae31ef75 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -4020,28 +4020,6 @@ RTLIL::SigSpec::SigSpec(bool bit) check(); } -void RTLIL::SigSpec::switch_to_packed() const -{ - // TODO change to debug asserts - // log_assert(!this->packed_); - // log_assert(bits_.size() == 0); - RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; - that->bits_.~vector(); - that->packed_ = true; - (void)new (&that->chunks_) std::vector(); -} - -void RTLIL::SigSpec::switch_to_unpacked() const -{ - // TODO change to debug asserts - // log_assert(this->packed_); - // log_assert(chunks_.size() == 0); - RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; - that->chunks_.~vector(); - that->packed_ = false; - (void)new (&that->bits_) std::vector(); -} - void RTLIL::SigSpec::pack() const { RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; @@ -4075,8 +4053,9 @@ void RTLIL::SigSpec::pack() const last_end_offset = bit.offset + 1; } - that->switch_to_packed(); - that->chunks_.swap(new_chunks); + that->bits_.~vector(); + that->packed_ = true; + (void)new (&that->chunks_) std::vector(std::move(new_chunks)); check(); } @@ -4096,10 +4075,10 @@ void RTLIL::SigSpec::unpack() const for (int i = 0; i < c.width; i++) new_bits.emplace_back(c, i); - that->chunks_.clear(); that->hash_ = 0; - that->switch_to_unpacked(); - that->bits_.swap(new_bits); + that->chunks_.~vector(); + that->packed_ = false; + (void)new (&that->bits_) std::vector(std::move(new_bits)); } void RTLIL::SigSpec::updhash() const diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 179e892ec8f..5bd69a43ff5 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -838,7 +838,7 @@ struct RTLIL::SigSpecConstIterator inline void operator++() { index++; } }; -struct RTLIL::SigSpec +struct alignas(64) RTLIL::SigSpec { private: int width_; @@ -851,8 +851,6 @@ struct RTLIL::SigSpec void pack() const; void unpack() const; - void switch_to_packed() const; - void switch_to_unpacked() const; void updhash() const; inline bool packed() const { @@ -890,13 +888,13 @@ struct RTLIL::SigSpec { if (packed_ != other.packed_) { if (packed_) { - chunks_.clear(); - switch_to_unpacked(); - bits_ = other.bits_; + chunks_.~vector(); + packed_ = false; + (void)new (&bits_) std::vector(other.bits_); } else { - bits_.clear(); - switch_to_packed(); - chunks_ = other.chunks_; + bits_.~vector(); + packed_ = true; + (void)new (&chunks_) std::vector(other.chunks_); } } else { if (packed_)