3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-11-06 22:36:05 +00:00

Make SigSpec::chunks() return an object that can be iterated over without packing the SigSpec

This commit is contained in:
Robert O'Callahan 2025-10-27 15:46:36 +00:00
parent c4f3e61339
commit 37e4c2e8f8
4 changed files with 104 additions and 9 deletions

View file

@ -4648,6 +4648,31 @@ RTLIL::SigSpec::SigSpec(bool bit)
check();
}
void RTLIL::SigSpec::Chunks::const_iterator::next_chunk_bits()
{
int bits_size = GetSize(spec.bits_);
if (bit_index >= bits_size)
return;
int i = bit_index;
const SigBit &bit = spec.bits_[i++];
chunk.wire = bit.wire;
chunk.data.clear();
if (bit.is_wire()) {
chunk.offset = bit.offset;
while (i < bits_size && spec.bits_[i].wire == bit.wire &&
spec.bits_[i].offset == bit.offset + i - bit_index)
++i;
} else {
chunk.offset = 0;
chunk.data.push_back(bit.data);
while (i < bits_size && !spec.bits_[i].is_wire()) {
chunk.data.push_back(spec.bits_[i].data);
++i;
}
}
chunk.width = i - bit_index;
}
void RTLIL::SigSpec::pack() const
{
RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;

View file

@ -1275,7 +1275,75 @@ public:
SigSpec &operator=(const SigSpec &rhs) = default;
SigSpec &operator=(SigSpec &&rhs) = default;
inline const std::vector<RTLIL::SigChunk> &chunks() const { pack(); return chunks_; }
struct Chunks {
const SigSpec &spec;
struct const_iterator {
using iterator_category = std::forward_iterator_tag;
using value_type = const SigChunk &;
using difference_type = std::ptrdiff_t;
using pointer = const SigChunk *;
using reference = const SigChunk &;
const SigSpec &spec;
int chunk_index;
int bit_index;
SigChunk chunk;
const_iterator(const SigSpec &spec) : spec(spec) {
chunk_index = 0;
bit_index = 0;
if (!spec.packed())
next_chunk_bits();
}
void next_chunk_bits();
const SigChunk &operator*() {
if (spec.packed())
return spec.chunks_[chunk_index];
return chunk;
};
const SigChunk *operator->() { return &**this; }
const_iterator &operator++() {
bit_index += (**this).width;
++chunk_index;
if (!spec.packed())
next_chunk_bits();
return *this;
}
bool operator==(const const_iterator &rhs) const { return bit_index == rhs.bit_index; }
bool operator!=(const const_iterator &rhs) const { return !(*this == rhs); }
};
const_iterator begin() const { return const_iterator(spec); }
const_iterator end() const {
const_iterator it(spec);
it.bit_index = spec.size();
return it;
}
std::vector<RTLIL::SigChunk>::const_reverse_iterator rbegin() const {
spec.pack();
return spec.chunks_.rbegin();
}
std::vector<RTLIL::SigChunk>::const_reverse_iterator rend() const {
spec.pack();
return spec.chunks_.rend();
}
int size() const {
spec.pack();
return spec.chunks_.size();
}
const SigChunk &at(int index) const {
spec.pack();
return spec.chunks_.at(index);
}
operator const std::vector<RTLIL::SigChunk>&() const {
spec.pack();
return spec.chunks_;
}
};
friend struct Chunks::const_iterator;
inline Chunks chunks() const { return {*this}; }
inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; }
inline int size() const { return width_; }
@ -1402,7 +1470,7 @@ public:
static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str);
static bool parse_rhs(const RTLIL::SigSpec &lhs, RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str);
operator std::vector<RTLIL::SigChunk>() const { return chunks(); }
operator std::vector<RTLIL::SigChunk>() const { pack(); return chunks_; }
operator std::vector<RTLIL::SigBit>() const { return bits(); }
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; }
@ -2315,8 +2383,9 @@ inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() const {
}
inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {
log_assert(sig.size() == 1 && sig.chunks().size() == 1);
*this = SigBit(sig.chunks().front());
log_assert(sig.size() == 1);
auto it = sig.chunks().begin();
*this = SigBit(*it);
}
template<typename T>