3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-11-05 13:56:04 +00:00

Switch the SigSpec packed representation to allow just a single chunk that's inline in the SigSpec.

Single-chunk SigSpecs are very common and this avoids a heap allocation. It also simplifies
some algorithms.
This commit is contained in:
Robert O'Callahan 2025-10-30 15:02:39 +00:00
parent 1af5d4f2db
commit 9a2fd4c31b
2 changed files with 208 additions and 243 deletions

View file

@ -4448,9 +4448,7 @@ RTLIL::SigSpec::SigSpec(std::initializer_list<RTLIL::SigSpec> parts)
{ {
cover("kernel.rtlil.sigspec.init.list"); cover("kernel.rtlil.sigspec.init.list");
width_ = 0; init_empty_bits();
hash_ = 0;
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;
@ -4463,12 +4461,11 @@ RTLIL::SigSpec::SigSpec(const RTLIL::Const &value)
cover("kernel.rtlil.sigspec.init.const"); cover("kernel.rtlil.sigspec.init.const");
if (GetSize(value) != 0) { if (GetSize(value) != 0) {
chunks_.emplace_back(value); rep_ = CHUNK;
width_ = chunks_.back().width; new (&chunk_) RTLIL::SigChunk(value);
} else { } else {
width_ = 0; init_empty_bits();
} }
hash_ = 0;
check(); check();
} }
@ -4477,12 +4474,11 @@ RTLIL::SigSpec::SigSpec(RTLIL::Const &&value)
cover("kernel.rtlil.sigspec.init.const.move"); cover("kernel.rtlil.sigspec.init.const.move");
if (GetSize(value) != 0) { if (GetSize(value) != 0) {
chunks_.emplace_back(std::move(value)); rep_ = CHUNK;
width_ = chunks_.back().width; new (&chunk_) RTLIL::SigChunk(value);
} else { } else {
width_ = 0; init_empty_bits();
} }
hash_ = 0;
check(); check();
} }
@ -4491,12 +4487,11 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigChunk &chunk)
cover("kernel.rtlil.sigspec.init.chunk"); cover("kernel.rtlil.sigspec.init.chunk");
if (chunk.width != 0) { if (chunk.width != 0) {
chunks_.emplace_back(chunk); rep_ = CHUNK;
width_ = chunks_.back().width; new (&chunk_) RTLIL::SigChunk(chunk);
} else { } else {
width_ = 0; init_empty_bits();
} }
hash_ = 0;
check(); check();
} }
@ -4505,12 +4500,11 @@ RTLIL::SigSpec::SigSpec(RTLIL::SigChunk &&chunk)
cover("kernel.rtlil.sigspec.init.chunk.move"); cover("kernel.rtlil.sigspec.init.chunk.move");
if (chunk.width != 0) { if (chunk.width != 0) {
chunks_.emplace_back(std::move(chunk)); rep_ = CHUNK;
width_ = chunks_.back().width; new (&chunk_) RTLIL::SigChunk(chunk);
} else { } else {
width_ = 0; init_empty_bits();
} }
hash_ = 0;
check(); check();
} }
@ -4519,12 +4513,11 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire)
cover("kernel.rtlil.sigspec.init.wire"); cover("kernel.rtlil.sigspec.init.wire");
if (wire->width != 0) { if (wire->width != 0) {
chunks_.emplace_back(wire); rep_ = CHUNK;
width_ = chunks_.back().width; new (&chunk_) RTLIL::SigChunk(wire);
} else { } else {
width_ = 0; init_empty_bits();
} }
hash_ = 0;
check(); check();
} }
@ -4533,12 +4526,11 @@ RTLIL::SigSpec::SigSpec(RTLIL::Wire *wire, int offset, int width)
cover("kernel.rtlil.sigspec.init.wire_part"); cover("kernel.rtlil.sigspec.init.wire_part");
if (width != 0) { if (width != 0) {
chunks_.emplace_back(wire, offset, width); rep_ = CHUNK;
width_ = chunks_.back().width; new (&chunk_) RTLIL::SigChunk(wire, offset, width);
} else { } else {
width_ = 0; init_empty_bits();
} }
hash_ = 0;
check(); check();
} }
@ -4547,12 +4539,11 @@ RTLIL::SigSpec::SigSpec(const std::string &str)
cover("kernel.rtlil.sigspec.init.str"); cover("kernel.rtlil.sigspec.init.str");
if (str.size() != 0) { if (str.size() != 0) {
chunks_.emplace_back(str); rep_ = CHUNK;
width_ = chunks_.back().width; new (&chunk_) RTLIL::SigChunk(str);
} else { } else {
width_ = 0; init_empty_bits();
} }
hash_ = 0;
check(); check();
} }
@ -4560,10 +4551,11 @@ RTLIL::SigSpec::SigSpec(int val, int width)
{ {
cover("kernel.rtlil.sigspec.init.int"); cover("kernel.rtlil.sigspec.init.int");
if (width != 0) if (width != 0) {
chunks_.emplace_back(val, width); rep_ = CHUNK;
width_ = width; new (&chunk_) RTLIL::SigChunk(val, width);
hash_ = 0; } else
init_empty_bits();
check(); check();
} }
@ -4571,10 +4563,11 @@ RTLIL::SigSpec::SigSpec(RTLIL::State bit, int width)
{ {
cover("kernel.rtlil.sigspec.init.state"); cover("kernel.rtlil.sigspec.init.state");
if (width != 0) if (width != 0) {
chunks_.emplace_back(bit, width); rep_ = CHUNK;
width_ = width; new (&chunk_) RTLIL::SigChunk(bit, width);
hash_ = 0; } else
init_empty_bits();
check(); check();
} }
@ -4583,14 +4576,20 @@ RTLIL::SigSpec::SigSpec(const RTLIL::SigBit &bit, int width)
cover("kernel.rtlil.sigspec.init.bit"); cover("kernel.rtlil.sigspec.init.bit");
if (width != 0) { if (width != 0) {
if (bit.wire == NULL) if (bit.wire == NULL) {
chunks_.emplace_back(bit.data, width); rep_ = CHUNK;
else new (&chunk_) RTLIL::SigChunk(bit.data, width);
} else if (width == 1) {
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(bit);
} else {
init_empty_bits();
bits_.reserve(width);
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
chunks_.push_back(bit); bits_.push_back(bit);
} }
width_ = width; } else
hash_ = 0; init_empty_bits();
check(); check();
} }
@ -4598,8 +4597,7 @@ RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigChunk> &chunks)
{ {
cover("kernel.rtlil.sigspec.init.stdvec_chunks"); cover("kernel.rtlil.sigspec.init.stdvec_chunks");
width_ = 0; init_empty_bits();
hash_ = 0;
for (const auto &c : chunks) for (const auto &c : chunks)
append(c); append(c);
check(); check();
@ -4609,8 +4607,7 @@ RTLIL::SigSpec::SigSpec(const std::vector<RTLIL::SigBit> &bits)
{ {
cover("kernel.rtlil.sigspec.init.stdvec_bits"); cover("kernel.rtlil.sigspec.init.stdvec_bits");
width_ = 0; init_empty_bits();
hash_ = 0;
for (const auto &bit : bits) for (const auto &bit : bits)
append(bit); append(bit);
check(); check();
@ -4620,8 +4617,7 @@ RTLIL::SigSpec::SigSpec(const pool<RTLIL::SigBit> &bits)
{ {
cover("kernel.rtlil.sigspec.init.pool_bits"); cover("kernel.rtlil.sigspec.init.pool_bits");
width_ = 0; init_empty_bits();
hash_ = 0;
for (const auto &bit : bits) for (const auto &bit : bits)
append(bit); append(bit);
check(); check();
@ -4631,8 +4627,7 @@ RTLIL::SigSpec::SigSpec(const std::set<RTLIL::SigBit> &bits)
{ {
cover("kernel.rtlil.sigspec.init.stdset_bits"); cover("kernel.rtlil.sigspec.init.stdset_bits");
width_ = 0; init_empty_bits();
hash_ = 0;
for (const auto &bit : bits) for (const auto &bit : bits)
append(bit); append(bit);
check(); check();
@ -4642,9 +4637,8 @@ RTLIL::SigSpec::SigSpec(bool bit)
{ {
cover("kernel.rtlil.sigspec.init.bool"); cover("kernel.rtlil.sigspec.init.bool");
width_ = 0; rep_ = CHUNK;
hash_ = 0; new (&chunk_) RTLIL::SigChunk(bit ? RTLIL::S1 : RTLIL::S0);
append(SigBit(bit));
check(); check();
} }
@ -4673,58 +4667,23 @@ void RTLIL::SigSpec::Chunks::const_iterator::next_chunk_bits()
chunk.width = i - bit_index; chunk.width = i - bit_index;
} }
void RTLIL::SigSpec::pack() const
{
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
if (that->bits_.empty())
return;
cover("kernel.rtlil.sigspec.convert.pack");
log_assert(that->chunks_.empty());
std::vector<RTLIL::SigBit> old_bits;
old_bits.swap(that->bits_);
RTLIL::SigChunk *last = NULL;
int last_end_offset = 0;
for (auto &bit : old_bits) {
if (last && bit.wire == last->wire) {
if (bit.wire == NULL) {
last->data.push_back(bit.data);
last->width++;
continue;
} else if (last_end_offset == bit.offset) {
last_end_offset++;
last->width++;
continue;
}
}
that->chunks_.push_back(bit);
last = &that->chunks_.back();
last_end_offset = bit.offset + 1;
}
check();
}
void RTLIL::SigSpec::unpack() const void RTLIL::SigSpec::unpack() const
{ {
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; if (rep_ == BITS)
if (that->chunks_.empty())
return; return;
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
cover("kernel.rtlil.sigspec.convert.unpack"); cover("kernel.rtlil.sigspec.convert.unpack");
log_assert(that->bits_.empty());
that->bits_.reserve(that->size()); std::vector<RTLIL::SigBit> bits;
for (auto &c : that->chunks_) bits.reserve(that->chunk_.width);
for (int i = 0; i < c.width; i++) for (int i = 0; i < that->chunk_.width; i++)
that->bits_.emplace_back(c, i); bits.emplace_back(that->chunk_, i);
that->chunks_.clear(); that->chunk_.~SigChunk();
that->rep_ = BITS;
new (&that->bits_) std::vector<RTLIL::SigBit>(std::move(bits));
} }
void RTLIL::SigSpec::updhash() const void RTLIL::SigSpec::updhash() const
@ -4896,11 +4855,8 @@ void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *othe
bits_[i].offset >= pattern_chunk.offset && bits_[i].offset >= pattern_chunk.offset &&
bits_[i].offset < pattern_chunk.offset + pattern_chunk.width) { bits_[i].offset < pattern_chunk.offset + pattern_chunk.width) {
bits_.erase(bits_.begin() + i); bits_.erase(bits_.begin() + i);
width_--; if (other != NULL)
if (other != NULL) {
other->bits_.erase(other->bits_.begin() + i); other->bits_.erase(other->bits_.begin() + i);
other->width_--;
}
break; break;
} }
} }
@ -4938,11 +4894,8 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec
for (int i = GetSize(bits_) - 1; i >= 0; i--) { for (int i = GetSize(bits_) - 1; i >= 0; i--) {
if (bits_[i].wire != NULL && pattern.count(bits_[i])) { if (bits_[i].wire != NULL && pattern.count(bits_[i])) {
bits_.erase(bits_.begin() + i); bits_.erase(bits_.begin() + i);
width_--; if (other != NULL)
if (other != NULL) {
other->bits_.erase(other->bits_.begin() + i); other->bits_.erase(other->bits_.begin() + i);
other->width_--;
}
} }
} }
hash_ = 0; hash_ = 0;
@ -4968,11 +4921,8 @@ void RTLIL::SigSpec::remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigS
for (int i = GetSize(bits_) - 1; i >= 0; i--) { for (int i = GetSize(bits_) - 1; i >= 0; i--) {
if (bits_[i].wire != NULL && pattern.count(bits_[i])) { if (bits_[i].wire != NULL && pattern.count(bits_[i])) {
bits_.erase(bits_.begin() + i); bits_.erase(bits_.begin() + i);
width_--; if (other != NULL)
if (other != NULL) {
other->bits_.erase(other->bits_.begin() + i); other->bits_.erase(other->bits_.begin() + i);
other->width_--;
}
} }
} }
hash_ = 0; hash_ = 0;
@ -4998,11 +4948,8 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::Wire*> &pattern, RTLIL::SigSpec *
for (int i = GetSize(bits_) - 1; i >= 0; i--) { for (int i = GetSize(bits_) - 1; i >= 0; i--) {
if (bits_[i].wire != NULL && pattern.count(bits_[i].wire)) { if (bits_[i].wire != NULL && pattern.count(bits_[i].wire)) {
bits_.erase(bits_.begin() + i); bits_.erase(bits_.begin() + i);
width_--; if (other != NULL)
if (other != NULL) {
other->bits_.erase(other->bits_.begin() + i); other->bits_.erase(other->bits_.begin() + i);
other->width_--;
}
} }
} }
hash_ = 0; hash_ = 0;
@ -5100,41 +5047,27 @@ void RTLIL::SigSpec::replace(int offset, const RTLIL::SigSpec &with)
void RTLIL::SigSpec::remove_const() void RTLIL::SigSpec::remove_const()
{ {
if (packed()) if (rep_ == CHUNK)
{ {
cover("kernel.rtlil.sigspec.remove_const.packed"); cover("kernel.rtlil.sigspec.remove_const.packed");
std::vector<RTLIL::SigChunk> new_chunks; if (chunk_.wire == NULL) {
new_chunks.reserve(GetSize(chunks_)); chunk_.~SigChunk();
init_empty_bits();
width_ = 0; }
for (auto &chunk : chunks_)
if (chunk.wire != NULL) {
if (!new_chunks.empty() &&
new_chunks.back().wire == chunk.wire &&
new_chunks.back().offset + new_chunks.back().width == chunk.offset) {
new_chunks.back().width += chunk.width;
} else {
new_chunks.push_back(chunk);
}
width_ += chunk.width;
}
chunks_.swap(new_chunks);
} }
else else
{ {
cover("kernel.rtlil.sigspec.remove_const.unpacked"); cover("kernel.rtlil.sigspec.remove_const.unpacked");
std::vector<RTLIL::SigBit> new_bits; std::vector<RTLIL::SigBit> new_bits;
new_bits.reserve(width_); new_bits.reserve(bits_.size());
for (auto &bit : bits_) for (auto &bit : bits_)
if (bit.wire != NULL) if (bit.wire != NULL)
new_bits.push_back(bit); new_bits.push_back(bit);
bits_.swap(new_bits); bits_.swap(new_bits);
width_ = bits_.size();
} }
hash_ = 0; hash_ = 0;
@ -5152,7 +5085,6 @@ void RTLIL::SigSpec::remove(int offset, int length)
log_assert(offset + length <= size()); log_assert(offset + length <= size());
bits_.erase(bits_.begin() + offset, bits_.begin() + offset + length); bits_.erase(bits_.begin() + offset, bits_.begin() + offset + length);
width_ = bits_.size();
hash_ = 0; hash_ = 0;
check(); check();
@ -5191,10 +5123,21 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const
void RTLIL::SigSpec::rewrite_wires(std::function<void(RTLIL::Wire*& wire)> rewrite) void RTLIL::SigSpec::rewrite_wires(std::function<void(RTLIL::Wire*& wire)> rewrite)
{ {
pack(); if (rep_ == CHUNK) {
for (RTLIL::SigChunk &chunk : chunks_) if (chunk_.wire != nullptr)
if (chunk.wire != nullptr) rewrite(chunk_.wire);
rewrite(chunk.wire); return;
}
std::vector<RTLIL::SigBit> new_bits;
for (const RTLIL::SigChunk &chunk : chunks()) {
RTLIL::SigChunk c = chunk;
if (c.wire != nullptr)
rewrite(c.wire);
for (int i = 0; i < c.width; i++)
new_bits.emplace_back(c, i);
}
bits_ = std::move(new_bits);
hash_ = 0; hash_ = 0;
} }
@ -5210,60 +5153,54 @@ void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal)
cover("kernel.rtlil.sigspec.append"); cover("kernel.rtlil.sigspec.append");
if (packed()) hash_ = 0;
for (auto &other_c : signal.chunks()) if (rep_ == CHUNK && signal.rep_ == CHUNK && chunk_.wire == signal.chunk_.wire) {
{ if (chunk_.wire == NULL) {
auto &my_last_c = chunks_.back(); chunk_.data.insert(chunk_.data.end(), signal.chunk_.data.begin(), signal.chunk_.data.end());
if (my_last_c.wire == NULL && other_c.wire == NULL) { chunk_.width = GetSize(chunk_.data);
auto &this_data = my_last_c.data; return;
auto &other_data = other_c.data; }
this_data.insert(this_data.end(), other_data.begin(), other_data.end()); if (chunk_.offset + chunk_.width == signal.chunk_.offset) {
my_last_c.width += other_c.width; chunk_.width += signal.chunk_.width;
} else return;
if (my_last_c.wire == other_c.wire && my_last_c.offset + my_last_c.width == other_c.offset) {
my_last_c.width += other_c.width;
} else
chunks_.push_back(other_c);
} }
else {
signal.unpack();
bits_.insert(bits_.end(), signal.bits_.begin(), signal.bits_.end());
} }
width_ += signal.size(); unpack();
hash_ = 0; for (const SigBit &bit : signal.bits())
bits_.push_back(bit);
check(); check();
} }
void RTLIL::SigSpec::append(const RTLIL::SigBit &bit) void RTLIL::SigSpec::append(const RTLIL::SigBit &bit)
{ {
if (packed()) hash_ = 0;
{
if (size() == 0) {
destroy();
rep_ = CHUNK;
new (&chunk_) RTLIL::SigChunk(bit);
return;
}
if (rep_ == CHUNK && chunk_.wire == bit.wire) {
cover("kernel.rtlil.sigspec.append_bit.packed"); cover("kernel.rtlil.sigspec.append_bit.packed");
if (chunks_.size() == 0) if (chunk_.wire == NULL) {
chunks_.push_back(bit); chunk_.data.push_back(bit.data);
else chunk_.width++;
if (bit.wire == NULL) return;
if (chunks_.back().wire == NULL) { }
chunks_.back().data.push_back(bit.data); if (chunk_.offset + chunk_.width == bit.offset) {
chunks_.back().width++; chunk_.width++;
} else return;
chunks_.push_back(bit); }
else
if (chunks_.back().wire == bit.wire && chunks_.back().offset + chunks_.back().width == bit.offset)
chunks_.back().width++;
else
chunks_.push_back(bit);
}
else
{
cover("kernel.rtlil.sigspec.append_bit.unpacked");
bits_.push_back(bit);
} }
width_++; unpack();
hash_ = 0;
cover("kernel.rtlil.sigspec.append_bit.unpacked");
bits_.push_back(bit);
check(); check();
} }
@ -5296,50 +5233,36 @@ RTLIL::SigSpec RTLIL::SigSpec::repeat(int num) const
#ifndef NDEBUG #ifndef NDEBUG
void RTLIL::SigSpec::check(Module *mod) const void RTLIL::SigSpec::check(Module *mod) const
{ {
if (size() > 64) if (rep_ == CHUNK)
{
cover("kernel.rtlil.sigspec.check.skip");
}
else if (packed())
{ {
cover("kernel.rtlil.sigspec.check.packed"); cover("kernel.rtlil.sigspec.check.packed");
int w = 0; log_assert(chunk_.width != 0);
for (size_t i = 0; i < chunks_.size(); i++) { if (chunk_.wire == NULL) {
const RTLIL::SigChunk &chunk = chunks_[i]; log_assert(chunk_.offset == 0);
log_assert(chunk.width != 0); log_assert(chunk_.data.size() == (size_t)chunk_.width);
if (chunk.wire == NULL) { } else {
if (i > 0) log_assert(chunk_.offset >= 0);
log_assert(chunks_[i-1].wire != NULL); log_assert(chunk_.width >= 0);
log_assert(chunk.offset == 0); log_assert(chunk_.offset + chunk_.width <= chunk_.wire->width);
log_assert(chunk.data.size() == (size_t)chunk.width); log_assert(chunk_.data.size() == 0);
} else { if (mod != nullptr)
if (i > 0 && chunks_[i-1].wire == chunk.wire) log_assert(chunk_.wire->module == mod);
log_assert(chunk.offset != chunks_[i-1].offset + chunks_[i-1].width);
log_assert(chunk.offset >= 0);
log_assert(chunk.width >= 0);
log_assert(chunk.offset + chunk.width <= chunk.wire->width);
log_assert(chunk.data.size() == 0);
if (mod != nullptr)
log_assert(chunk.wire->module == mod);
}
w += chunk.width;
} }
log_assert(w == size()); }
log_assert(bits_.empty()); else if (size() > 64)
{
cover("kernel.rtlil.sigspec.check.skip");
} }
else else
{ {
cover("kernel.rtlil.sigspec.check.unpacked"); cover("kernel.rtlil.sigspec.check.unpacked");
if (mod != nullptr) { if (mod != nullptr) {
for (size_t i = 0; i < bits_.size(); i++) for (const RTLIL::SigBit &bit : bits_)
if (bits_[i].wire != nullptr) if (bit.wire != nullptr)
log_assert(bits_[i].wire->module == mod); log_assert(bit.wire->module == mod);
} }
log_assert(size() == GetSize(bits_));
log_assert(chunks_.empty());
} }
} }
#endif #endif
@ -5713,7 +5636,7 @@ std::map<RTLIL::SigBit, RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_map(const RTLIL
log_assert(size() == other.size()); log_assert(size() == other.size());
std::map<RTLIL::SigBit, RTLIL::SigBit> new_map; std::map<RTLIL::SigBit, RTLIL::SigBit> new_map;
for (int i = 0; i < width_; i++) for (int i = 0; i < GetSize(bits_); i++)
new_map[bits_[i]] = other.bits_[i]; new_map[bits_[i]] = other.bits_[i];
return new_map; return new_map;
@ -5730,7 +5653,7 @@ dict<RTLIL::SigBit, RTLIL::SigBit> RTLIL::SigSpec::to_sigbit_dict(const RTLIL::S
dict<RTLIL::SigBit, RTLIL::SigBit> new_map; dict<RTLIL::SigBit, RTLIL::SigBit> new_map;
new_map.reserve(size()); new_map.reserve(size());
for (int i = 0; i < width_; i++) for (int i = 0; i < GetSize(bits_); i++)
new_map[bits_[i]] = other.bits_[i]; new_map[bits_[i]] = other.bits_[i];
return new_map; return new_map;

View file

@ -1233,29 +1233,53 @@ struct RTLIL::SigSpecConstIterator
struct RTLIL::SigSpec struct RTLIL::SigSpec
{ {
private: private:
int width_; enum Representation : char {
Hasher::hash_t hash_; CHUNK,
std::vector<RTLIL::SigChunk> chunks_; // LSB at index 0 BITS,
std::vector<RTLIL::SigBit> bits_; // LSB at index 0 };
void pack() const; Representation rep_;
void unpack() const; Hasher::hash_t hash_ = 0;
void updhash() const; union {
RTLIL::SigChunk chunk_;
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
};
inline bool packed() const { void init_empty_bits() {
return bits_.empty(); rep_ = BITS;
new (&bits_) std::vector<RTLIL::SigBit>;
} }
void unpack() const;
inline void inline_unpack() const { inline void inline_unpack() const {
if (!chunks_.empty()) if (rep_ == CHUNK)
unpack(); unpack();
} }
void updhash() const;
void destroy() {
if (rep_ == CHUNK)
chunk_.~SigChunk();
else
bits_.~vector();
}
friend struct Chunks;
public: public:
SigSpec() : width_(0), hash_(0) {} SigSpec() { init_empty_bits(); }
SigSpec(std::initializer_list<RTLIL::SigSpec> parts); SigSpec(std::initializer_list<RTLIL::SigSpec> parts);
SigSpec(const SigSpec &value) = default; SigSpec(const SigSpec &value) : rep_(value.rep_), hash_(value.hash_) {
SigSpec(SigSpec &&value) = default; if (value.rep_ == CHUNK)
new (&chunk_) RTLIL::SigChunk(value.chunk_);
else
new (&bits_) std::vector<RTLIL::SigBit>(value.bits_);
}
SigSpec(SigSpec &&value) : rep_(value.rep_), hash_(value.hash_) {
if (value.rep_ == CHUNK)
new (&chunk_) RTLIL::SigChunk(std::move(value.chunk_));
else
new (&bits_) std::vector<RTLIL::SigBit>(std::move(value.bits_));
}
SigSpec(const RTLIL::Const &value); SigSpec(const RTLIL::Const &value);
SigSpec(RTLIL::Const &&value); SigSpec(RTLIL::Const &&value);
SigSpec(const RTLIL::SigChunk &chunk); SigSpec(const RTLIL::SigChunk &chunk);
@ -1271,9 +1295,30 @@ public:
SigSpec(const pool<RTLIL::SigBit> &bits); SigSpec(const pool<RTLIL::SigBit> &bits);
SigSpec(const std::set<RTLIL::SigBit> &bits); SigSpec(const std::set<RTLIL::SigBit> &bits);
explicit SigSpec(bool bit); explicit SigSpec(bool bit);
~SigSpec() {
destroy();
}
SigSpec &operator=(const SigSpec &rhs) = default; SigSpec &operator=(const SigSpec &rhs) {
SigSpec &operator=(SigSpec &&rhs) = default; destroy();
rep_ = rhs.rep_;
hash_ = rhs.hash_;
if (rep_ == CHUNK)
new (&chunk_) RTLIL::SigChunk(rhs.chunk_);
else
new (&bits_) std::vector<RTLIL::SigBit>(rhs.bits_);
return *this;
}
SigSpec &operator=(SigSpec &&rhs) {
destroy();
rep_ = rhs.rep_;
hash_ = rhs.hash_;
if (rep_ == CHUNK)
new (&chunk_) RTLIL::SigChunk(std::move(rhs.chunk_));
else
new (&bits_) std::vector<RTLIL::SigBit>(std::move(rhs.bits_));
return *this;
}
struct Chunks { struct Chunks {
Chunks(const SigSpec &spec) : spec(spec) {} Chunks(const SigSpec &spec) : spec(spec) {}
@ -1285,28 +1330,25 @@ public:
using reference = const SigChunk &; using reference = const SigChunk &;
const SigSpec &spec; const SigSpec &spec;
int chunk_index;
int bit_index; int bit_index;
SigChunk chunk; SigChunk chunk;
const_iterator(const SigSpec &spec) : spec(spec) { const_iterator(const SigSpec &spec) : spec(spec) {
chunk_index = 0;
bit_index = 0; bit_index = 0;
if (!spec.packed()) if (spec.rep_ == BITS)
next_chunk_bits(); next_chunk_bits();
} }
void next_chunk_bits(); void next_chunk_bits();
const SigChunk &operator*() { const SigChunk &operator*() {
if (spec.packed()) if (spec.rep_ == CHUNK)
return spec.chunks_[chunk_index]; return spec.chunk_;
return chunk; return chunk;
}; };
const SigChunk *operator->() { return &**this; } const SigChunk *operator->() { return &**this; }
const_iterator &operator++() { const_iterator &operator++() {
bit_index += (**this).width; bit_index += (**this).width;
++chunk_index; if (spec.rep_ == BITS)
if (!spec.packed())
next_chunk_bits(); next_chunk_bits();
return *this; return *this;
} }
@ -1362,7 +1404,7 @@ public:
inline Chunks chunks() const { return {*this}; } inline Chunks chunks() const { return {*this}; }
inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; } inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; }
inline int size() const { return width_; } inline int size() const { return rep_ == CHUNK ? chunk_.width : GetSize(bits_); }
inline bool empty() const { return size() == 0; } inline bool empty() const { return size() == 0; }
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); hash_ = 0; return bits_.at(index); } inline RTLIL::SigBit &operator[](int index) { inline_unpack(); hash_ = 0; return bits_.at(index); }