3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-15 21:38:45 +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;
hash_ = 0;
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
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<SigChunk>();
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<SigChunk>();
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<SigChunk>();
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<SigChunk>();
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<SigChunk>();
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<SigChunk>();
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<SigChunk>();
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<SigChunk>();
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<SigChunk>();
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<SigChunk>();
if (width != 0) {
if (bit.wire == NULL)
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");
packed_ = true;
(void)new (&this->chunks_) std::vector<SigChunk>();
width_ = 0;
hash_ = 0;
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");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0;
hash_ = 0;
for (const auto &bit : bits)
@ -3960,6 +3986,8 @@ RTLIL::SigSpec::SigSpec(const pool<RTLIL::SigBit> &bits)
{
cover("kernel.rtlil.sigspec.init.pool_bits");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
width_ = 0;
hash_ = 0;
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");
packed_ = false;
(void)new (&this->bits_) std::vector<SigBit>();
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<SigBit>();
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<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
{
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<RTLIL::SigBit> old_bits;
std::vector<RTLIL::SigChunk> 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<RTLIL::SigBit> 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

View file

@ -842,20 +842,25 @@ struct RTLIL::SigSpec
{
private:
int width_;
bool packed_;
unsigned long hash_;
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
union {
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0
std::vector<RTLIL::SigBit> 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 @@ private:
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<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(RTLIL::Const &&value);