Compare commits

..

32 Commits

Author SHA1 Message Date
Robert O'Callahan d5027f9a1f
Merge 1cf3497d15 into 5d0847f6fb 2025-11-08 04:58:17 +13:00
Robert O'Callahan 1cf3497d15 Repack SigSpecs when possible 2025-11-07 15:54:56 +00:00
Robert O'Callahan 38d1d071a5 Implement SigSpec::updhash() using a relaxed atomic for thread-safety 2025-11-07 15:54:56 +00:00
Robert O'Callahan 745222fa3b Make SigSpec::unpack() non-const 2025-11-07 15:54:56 +00:00
Robert O'Callahan 870ae18a2d 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.
2025-11-07 15:54:56 +00:00
Robert O'Callahan e1169d03fe Use chunks iterator for SigSpec::extract() 2025-11-07 15:54:56 +00:00
Robert O'Callahan 4939484840 Don't reset the hash when unpacking, instead clear the hash whenever bits are modified 2025-11-07 15:54:56 +00:00
Robert O'Callahan aa4a0fe815 Use size() instead of direct access to width_ in many places 2025-11-07 15:54:56 +00:00
Robert O'Callahan 619f49eabe Remove unnecessary pack() from SigSpec::extend_u0() 2025-11-07 15:54:55 +00:00
Robert O'Callahan b612c1bb39 Simplify SigSpec::as_bit() 2025-11-07 15:54:55 +00:00
Robert O'Callahan a69d48dd19 Instead of using packing and hashing to compute SigSpec ordering and equality, just use the width and chunkwise comparisons
This avoids having to pack and compute hashes, and generally results in a
simpler ordering.
2025-11-07 15:54:55 +00:00
Robert O'Callahan 92ea557979 Build a temporary SigChunk list in the iterator in the cases where that's needed 2025-11-07 15:54:55 +00:00
Robert O'Callahan 7394a2c597 Make SigSpec conversion to vector of SigChunk use chunks iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan 974b4dbe25 Make SigSpec::parse_rhs use is_chunk to avoid direct access to chunks_ 2025-11-07 15:54:55 +00:00
Robert O'Callahan 62cd3ddfb8 Make SigSpec::to_sigbit_pool use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan 4ed25c0538 Make SigSpec::to_sigbit_set use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan 39b89aae88 Use SigSpec::try_as_const in some places 2025-11-07 15:54:55 +00:00
Robert O'Callahan dd3940c8bb Make SigSpec::is_one_hot use try_as_const 2025-11-07 15:54:55 +00:00
Robert O'Callahan ce597dc38c Fix try_as_const/as_wire/as_chunk 2025-11-07 15:54:55 +00:00
Robert O'Callahan 0281ed1458 Add try_as_const and use the const iterator a bit more 2025-11-07 15:54:55 +00:00
Robert O'Callahan 0091d14e6d Make SigSpec::has_marked_bits use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan 80b3efb3da Make SigSpec::has_const(State) use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan ed8022f53f Make SigSpec::has_const use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan 1893c61fe2 Make SigSpec::is_fully_undef use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan e2defe7898 Make SigSpec::is_fully_def use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan 152a487cc8 Make SigSpec::is_fully_ones use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan ddd04e13e0 Make SigSpec::is_fully_zero use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan a7ac396fd9 Make is_fully_const use chunk iterator 2025-11-07 15:54:55 +00:00
Robert O'Callahan b0ee67a355 Make SigSpec::is_wire/is_chunk/is_fully_const use chunk iterator 2025-11-07 15:54:54 +00:00
Robert O'Callahan fc7d61132d Make SigSpec::updhash() use chunk iterator 2025-11-07 15:54:54 +00:00
Robert O'Callahan 3f7af10eda Make SigSpec::chunks() return an object that can be iterated over without packing the SigSpec 2025-11-07 15:54:54 +00:00
Robert O'Callahan 8d4f790951 Make Module stop accessing internals of SigSpec 2025-11-07 13:25:38 +00:00
2 changed files with 127 additions and 20 deletions

View File

@ -4692,6 +4692,39 @@ void RTLIL::SigSpec::unpack()
new (&bits_) std::vector<RTLIL::SigBit>(std::move(bits));
}
void RTLIL::SigSpec::try_repack()
{
if (rep_ != BITS)
return;
cover("kernel.rtlil.sigspec.convert.try_repack");
int bits_size = GetSize(bits_);
if (bits_size == 0)
return;
if (bits_[0].is_wire()) {
for (int i = 1; i < bits_size; i++)
if (bits_[0].wire != bits_[i].wire || bits_[0].offset + i != bits_[i].offset)
return;
SigChunk chunk(bits_[0].wire, bits_[0].offset, bits_size);
bits_.~vector();
rep_ = CHUNK;
new (&chunk_) SigChunk(std::move(chunk));
return;
}
std::vector<RTLIL::State> bits;
bits.reserve(bits_size);
bits.push_back(bits_[0].data);
for (int i = 1; i < bits_size; i++) {
if (bits_[i].is_wire())
return;
bits.push_back(bits_[i].data);
}
bits_.~vector();
rep_ = CHUNK;
new (&chunk_) SigChunk(std::move(bits));
}
Hasher::hash_t RTLIL::SigSpec::updhash() const
{
cover("kernel.rtlil.sigspec.hash");
@ -4719,6 +4752,7 @@ void RTLIL::SigSpec::sort()
cover("kernel.rtlil.sigspec.sort");
std::sort(bits_.begin(), bits_.end());
hash_.clear();
try_repack();
}
void RTLIL::SigSpec::sort_and_unify()
@ -4736,6 +4770,7 @@ void RTLIL::SigSpec::sort_and_unify()
*this = unique_bits;
hash_.clear();
try_repack();
}
void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec &with)
@ -4759,13 +4794,17 @@ void RTLIL::SigSpec::replace(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec
}
int this_size = size();
bool other_modified = false;
for (int j = 0; j < this_size; j++) {
auto it = pattern_to_with.find((*this)[j]);
if (it != pattern_to_with.end()) {
other_modified = true;
(*other)[j] = with[it->second];
}
}
if (other_modified)
other->try_repack();
other->check();
}
@ -4784,12 +4823,17 @@ void RTLIL::SigSpec::replace(const dict<RTLIL::SigBit, RTLIL::SigBit> &rules, RT
if (rules.empty()) return;
int this_size = size();
bool other_modified = false;
for (int i = 0; i < this_size; i++) {
auto it = rules.find((*this)[i]);
if (it != rules.end())
if (it != rules.end()) {
other_modified = true;
(*other)[i] = it->second;
}
}
if (other_modified)
other->try_repack();
other->check();
}
@ -4808,12 +4852,17 @@ void RTLIL::SigSpec::replace(const std::map<RTLIL::SigBit, RTLIL::SigBit> &rules
if (rules.empty()) return;
int this_size = size();
bool other_modified = false;
for (int i = 0; i < this_size; i++) {
auto it = rules.find((*this)[i]);
if (it != rules.end())
if (it != rules.end()) {
other_modified = true;
(*other)[i] = it->second;
}
}
if (other_modified)
other->try_repack();
other->check();
}
@ -4839,9 +4888,10 @@ void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *othe
if (other != NULL) {
log_assert(size() == other->size());
other->unpack();
other->hash_.clear();
}
bool modified = false;
bool other_modified = false;
for (int i = GetSize(bits_) - 1; i >= 0; i--)
{
if (bits_[i].wire == NULL) continue;
@ -4850,14 +4900,24 @@ void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *othe
if (bits_[i].wire == pattern_chunk.wire &&
bits_[i].offset >= pattern_chunk.offset &&
bits_[i].offset < pattern_chunk.offset + pattern_chunk.width) {
modified = true;
bits_.erase(bits_.begin() + i);
if (other != NULL)
if (other != NULL) {
other_modified = true;
other->bits_.erase(other->bits_.begin() + i);
}
break;
}
}
hash_.clear();
if (modified) {
hash_.clear();
try_repack();
}
if (other_modified) {
other->hash_.clear();
other->try_repack();
}
check();
}
@ -4884,18 +4944,29 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::SigBit> &pattern, RTLIL::SigSpec
if (other != NULL) {
log_assert(size() == other->size());
other->unpack();
other->hash_.clear();
}
bool modified = false;
bool other_modified = false;
for (int i = GetSize(bits_) - 1; i >= 0; i--) {
if (bits_[i].wire != NULL && pattern.count(bits_[i])) {
modified = true;
bits_.erase(bits_.begin() + i);
if (other != NULL)
if (other != NULL) {
other_modified = true;
other->bits_.erase(other->bits_.begin() + i);
}
}
}
hash_.clear();
if (modified) {
hash_.clear();
try_repack();
}
if (other_modified) {
other->hash_.clear();
other->try_repack();
}
check();
}
@ -4911,18 +4982,29 @@ void RTLIL::SigSpec::remove2(const std::set<RTLIL::SigBit> &pattern, RTLIL::SigS
if (other != NULL) {
log_assert(size() == other->size());
other->unpack();
other->hash_.clear();
}
bool modified = false;
bool other_modified = false;
for (int i = GetSize(bits_) - 1; i >= 0; i--) {
if (bits_[i].wire != NULL && pattern.count(bits_[i])) {
modified = true;
bits_.erase(bits_.begin() + i);
if (other != NULL)
if (other != NULL) {
other_modified = true;
other->bits_.erase(other->bits_.begin() + i);
}
}
}
hash_.clear();
if (modified) {
hash_.clear();
try_repack();
}
if (other_modified) {
other->hash_.clear();
other->try_repack();
}
check();
}
@ -4938,18 +5020,29 @@ void RTLIL::SigSpec::remove2(const pool<RTLIL::Wire*> &pattern, RTLIL::SigSpec *
if (other != NULL) {
log_assert(size() == other->size());
other->unpack();
other->hash_.clear();
}
bool modified = false;
bool other_modified = false;
for (int i = GetSize(bits_) - 1; i >= 0; i--) {
if (bits_[i].wire != NULL && pattern.count(bits_[i].wire)) {
modified = true;
bits_.erase(bits_.begin() + i);
if (other != NULL)
if (other != NULL) {
other_modified = true;
other->bits_.erase(other->bits_.begin() + i);
}
}
}
hash_.clear();
if (modified) {
hash_.clear();
try_repack();
}
if (other_modified) {
other->hash_.clear();
other->try_repack();
}
check();
}
@ -5025,6 +5118,9 @@ void RTLIL::SigSpec::replace(int offset, const RTLIL::SigSpec &with)
{
cover("kernel.rtlil.sigspec.replace_pos");
if (with.size() == 0)
return;
unpack();
log_assert(offset >= 0);
@ -5037,6 +5133,7 @@ void RTLIL::SigSpec::replace(int offset, const RTLIL::SigSpec &with)
++i;
}
hash_.clear();
try_repack();
check();
}
@ -5050,6 +5147,7 @@ void RTLIL::SigSpec::remove_const()
if (chunk_.wire == NULL) {
chunk_.~SigChunk();
init_empty_bits();
hash_.clear();
}
}
else
@ -5058,15 +5156,16 @@ void RTLIL::SigSpec::remove_const()
std::vector<RTLIL::SigBit> new_bits;
new_bits.reserve(bits_.size());
for (auto &bit : bits_)
if (bit.wire != NULL)
new_bits.push_back(bit);
bits_.swap(new_bits);
if (GetSize(new_bits) != GetSize(bits_)) {
bits_.swap(new_bits);
hash_.clear();
try_repack();
}
}
hash_.clear();
check();
}
@ -5074,6 +5173,9 @@ void RTLIL::SigSpec::remove(int offset, int length)
{
cover("kernel.rtlil.sigspec.remove_pos");
if (length == 0)
return;
unpack();
log_assert(offset >= 0);
@ -5083,6 +5185,7 @@ void RTLIL::SigSpec::remove(int offset, int length)
bits_.erase(bits_.begin() + offset, bits_.begin() + offset + length);
hash_.clear();
try_repack();
check();
}

View File

@ -1287,6 +1287,7 @@ private:
if (rep_ == CHUNK)
unpack();
}
void try_repack();
Hasher::hash_t updhash() const;
void destroy() {
@ -1370,6 +1371,10 @@ public:
if (spec.rep_ == BITS)
next_chunk_bits();
}
enum End { END };
const_iterator(const SigSpec &spec, End) : spec(spec) {
bit_index = spec.size();
}
void next_chunk_bits();
const SigChunk &operator*() {
@ -1389,8 +1394,7 @@ public:
};
const_iterator begin() const { return const_iterator(spec); }
const_iterator end() const {
const_iterator it(spec);
it.bit_index = spec.size();
const_iterator it(spec, const_iterator::END);
return it;
}
// Later we should deprecate these and remove their in-tree calls,