3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-06-06 14:13:23 +00:00

sigspec: decrease size with tagged union of bits and chunks

This commit is contained in:
Emil J. Tywoniak 2024-07-14 13:37:42 +02:00
parent b08688f711
commit 36fe6d4c56
2 changed files with 116 additions and 16 deletions

View file

@ -3791,6 +3791,8 @@ RTLIL::SigSpec::SigSpec(std::initializer_list<RTLIL::SigSpec> parts)
width_ = 0; width_ = 0;
hash_ = 0; hash_ = 0;
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
log_assert(parts.size() > 0); log_assert(parts.size() > 0);
auto ie = parts.begin(); auto ie = parts.begin();
auto it = ie + parts.size() - 1; auto it = ie + parts.size() - 1;
@ -3802,6 +3804,8 @@ RTLIL::SigSpec::SigSpec(const RTLIL::Const &value)
{ {
cover("kernel.rtlil.sigspec.init.const"); cover("kernel.rtlil.sigspec.init.const");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (GetSize(value) != 0) { if (GetSize(value) != 0) {
chunks_.emplace_back(value); chunks_.emplace_back(value);
width_ = chunks_.back().width; width_ = chunks_.back().width;
@ -3816,6 +3820,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::Const &&value)
{ {
cover("kernel.rtlil.sigspec.init.const.move"); cover("kernel.rtlil.sigspec.init.const.move");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (GetSize(value) != 0) { if (GetSize(value) != 0) {
chunks_.emplace_back(std::move(value)); chunks_.emplace_back(std::move(value));
width_ = chunks_.back().width; width_ = chunks_.back().width;
@ -3830,6 +3836,8 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk)
{ {
cover("kernel.rtlil.sigspec.init.chunk"); cover("kernel.rtlil.sigspec.init.chunk");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (chunk.width != 0) { if (chunk.width != 0) {
chunks_.emplace_back(chunk); chunks_.emplace_back(chunk);
width_ = chunks_.back().width; width_ = chunks_.back().width;
@ -3844,6 +3852,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::SigChunk &&chunk)
{ {
cover("kernel.rtlil.sigspec.init.chunk.move"); cover("kernel.rtlil.sigspec.init.chunk.move");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (chunk.width != 0) { if (chunk.width != 0) {
chunks_.emplace_back(std::move(chunk)); chunks_.emplace_back(std::move(chunk));
width_ = chunks_.back().width; width_ = chunks_.back().width;
@ -3858,6 +3868,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire)
{ {
cover("kernel.rtlil.sigspec.init.wire"); cover("kernel.rtlil.sigspec.init.wire");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (wire->width != 0) { if (wire->width != 0) {
chunks_.emplace_back(wire); chunks_.emplace_back(wire);
width_ = chunks_.back().width; 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"); cover("kernel.rtlil.sigspec.init.wire_part");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (width != 0) { if (width != 0) {
chunks_.emplace_back(wire, offset, width); chunks_.emplace_back(wire, offset, width);
width_ = chunks_.back().width; width_ = chunks_.back().width;
@ -3886,6 +3900,8 @@ RTLIL::SigSpec::SigSpec(const std::string &str)
{ {
cover("kernel.rtlil.sigspec.init.str"); cover("kernel.rtlil.sigspec.init.str");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (str.size() != 0) { if (str.size() != 0) {
chunks_.emplace_back(str); chunks_.emplace_back(str);
width_ = chunks_.back().width; width_ = chunks_.back().width;
@ -3900,6 +3916,8 @@ RTLIL::SigSpec::SigSpec(int val, int width)
{ {
cover("kernel.rtlil.sigspec.init.int"); cover("kernel.rtlil.sigspec.init.int");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (width != 0) if (width != 0)
chunks_.emplace_back(val, width); chunks_.emplace_back(val, width);
width_ = width; width_ = width;
@ -3911,6 +3929,8 @@ RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width)
{ {
cover("kernel.rtlil.sigspec.init.state"); cover("kernel.rtlil.sigspec.init.state");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (width != 0) if (width != 0)
chunks_.emplace_back(bit, width); chunks_.emplace_back(bit, width);
width_ = width; width_ = width;
@ -3922,6 +3942,8 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width)
{ {
cover("kernel.rtlil.sigspec.init.bit"); cover("kernel.rtlil.sigspec.init.bit");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
if (width != 0) { if (width != 0) {
if (bit.wire == NULL) if (bit.wire == NULL)
chunks_.emplace_back(bit.data, width); chunks_.emplace_back(bit.data, width);
@ -3938,6 +3960,8 @@ RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigChunk> &chunks)
{ {
cover("kernel.rtlil.sigspec.init.stdvec_chunks"); cover("kernel.rtlil.sigspec.init.stdvec_chunks");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
width_ = 0; width_ = 0;
hash_ = 0; hash_ = 0;
for (const auto &c : chunks) for (const auto &c : chunks)
@ -3949,6 +3973,8 @@ RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigBit> &bits)
{ {
cover("kernel.rtlil.sigspec.init.stdvec_bits"); cover("kernel.rtlil.sigspec.init.stdvec_bits");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0; width_ = 0;
hash_ = 0; hash_ = 0;
for (const auto &bit : bits) for (const auto &bit : bits)
@ -3960,6 +3986,8 @@ RTLIL::SigSpec::SigSpec(const pool<RTLIL::SigBit> &bits)
{ {
cover("kernel.rtlil.sigspec.init.pool_bits"); cover("kernel.rtlil.sigspec.init.pool_bits");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0; width_ = 0;
hash_ = 0; hash_ = 0;
for (const auto &bit : bits) for (const auto &bit : bits)
@ -3971,6 +3999,8 @@ RTLIL::SigSpec::SigSpec(const std::set<RTLIL::SigBit> &bits)
{ {
cover("kernel.rtlil.sigspec.init.stdset_bits"); cover("kernel.rtlil.sigspec.init.stdset_bits");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0; width_ = 0;
hash_ = 0; hash_ = 0;
for (const auto &bit : bits) for (const auto &bit : bits)
@ -3982,23 +4012,47 @@ RTLIL::SigSpec::SigSpec(bool bit)
{ {
cover("kernel.rtlil.sigspec.init.bool"); cover("kernel.rtlil.sigspec.init.bool");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0; width_ = 0;
hash_ = 0; hash_ = 0;
append(SigBit(bit)); append(SigBit(bit));
check(); 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<SigChunk>();
}
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<SigBit>();
}
void RTLIL::SigSpec::pack() const void RTLIL::SigSpec::pack() const
{ {
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
if (that->bits_.empty()) if (packed_ || that->bits_.empty())
return; return;
cover("kernel.rtlil.sigspec.convert.pack"); cover("kernel.rtlil.sigspec.convert.pack");
log_assert(that->chunks_.empty());
std::vector<RTLIL::SigBit> old_bits; std::vector<RTLIL::SigBit> old_bits;
std::vector<RTLIL::SigChunk> new_chunks;
old_bits.swap(that->bits_); old_bits.swap(that->bits_);
RTLIL::SigChunk *last = NULL; RTLIL::SigChunk *last = NULL;
@ -4016,11 +4070,14 @@ void RTLIL::SigSpec::pack() const
continue; continue;
} }
} }
that->chunks_.push_back(bit); new_chunks.push_back(bit);
last = &that->chunks_.back(); last = &new_chunks.back();
last_end_offset = bit.offset + 1; last_end_offset = bit.offset + 1;
} }
that->switch_to_packed();
that->chunks_.swap(new_chunks);
check(); check();
} }
@ -4028,19 +4085,21 @@ void RTLIL::SigSpec::unpack() const
{ {
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
if (that->chunks_.empty()) if (!packed_ || that->chunks_.empty())
return; return;
cover("kernel.rtlil.sigspec.convert.unpack"); cover("kernel.rtlil.sigspec.convert.unpack");
log_assert(that->bits_.empty());
that->bits_.reserve(that->width_); std::vector<RTLIL::SigBit> new_bits;
new_bits.reserve(that->width_);
for (auto &c : that->chunks_) for (auto &c : that->chunks_)
for (int i = 0; i < c.width; i++) for (int i = 0; i < c.width; i++)
that->bits_.emplace_back(c, i); new_bits.emplace_back(c, i);
that->chunks_.clear(); that->chunks_.clear();
that->hash_ = 0; that->hash_ = 0;
that->switch_to_unpacked();
that->bits_.swap(new_bits);
} }
void RTLIL::SigSpec::updhash() const void RTLIL::SigSpec::updhash() const
@ -4620,7 +4679,6 @@ void RTLIL::SigSpec::check(Module *mod) const
w += chunk.width; w += chunk.width;
} }
log_assert(w == width_); log_assert(w == width_);
log_assert(bits_.empty());
} }
else else
{ {
@ -4631,9 +4689,7 @@ void RTLIL::SigSpec::check(Module *mod) const
if (bits_[i].wire != nullptr) if (bits_[i].wire != nullptr)
log_assert(bits_[i].wire->module == mod); log_assert(bits_[i].wire->module == mod);
} }
log_assert(width_ == GetSize(bits_)); log_assert(width_ == GetSize(bits_));
log_assert(chunks_.empty());
} }
} }
#endif #endif

View file

@ -842,20 +842,25 @@ struct RTLIL::SigSpec
{ {
private: private:
int width_; int width_;
bool packed_;
unsigned long hash_; unsigned long hash_;
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0 union {
std::vector<RTLIL::SigBit> bits_; // LSB at index 0 std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
};
void pack() const; void pack() const;
void unpack() const; void unpack() const;
void switch_to_packed() const;
void switch_to_unpacked() const;
void updhash() const; void updhash() const;
inline bool packed() const { inline bool packed() const {
return bits_.empty(); return packed_;
} }
inline void inline_unpack() const { inline void inline_unpack() const {
if (!chunks_.empty()) if (packed_ && !chunks_.empty())
unpack(); unpack();
} }
@ -864,8 +869,47 @@ private:
friend struct RTLIL::Module; friend struct RTLIL::Module;
public: 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<RTLIL::SigSpec> parts); SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
SigSpec(const Yosys::RTLIL::SigSpec &other)
{
packed_ = other.packed_;
width_ = other.width_;
hash_ = other.hash_;
if (packed_) {
(void)new (&this->chunks_) std::vector<SigChunk>();
chunks_ = other.chunks_;
} else {
(void)new (&this->bits_) std::vector<SigBit>();
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(const RTLIL::Const &value);
SigSpec(RTLIL::Const &&value); SigSpec(RTLIL::Const &&value);