3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-11-04 21:39:14 +00:00
This commit is contained in:
Robert O'Callahan 2025-11-03 10:04:15 +01:00 committed by GitHub
commit f8b7ad0ac9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 668 additions and 550 deletions

View file

@ -121,7 +121,8 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
dump_sigchunk(f, sig.as_chunk(), autoint); dump_sigchunk(f, sig.as_chunk(), autoint);
} else { } else {
f << stringf("{ "); f << stringf("{ ");
for (const auto& chunk : reversed(sig.chunks())) { auto chunks = sig.chunks();
for (const auto& chunk : reversed(chunks)) {
dump_sigchunk(f, chunk, false); dump_sigchunk(f, chunk, false);
f << stringf(" "); f << stringf(" ");
} }

View file

@ -382,8 +382,9 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig)
dump_sigchunk(f, sig.as_chunk()); dump_sigchunk(f, sig.as_chunk());
} else { } else {
f << stringf("{ "); f << stringf("{ ");
for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) { auto chunks = sig.chunks();
if (it != sig.chunks().rbegin()) for (auto it = chunks.rbegin(); it != chunks.rend(); ++it) {
if (it != chunks.rbegin())
f << stringf(", "); f << stringf(", ");
dump_sigchunk(f, *it, true); dump_sigchunk(f, *it, true);
} }

File diff suppressed because it is too large Load diff

View file

@ -1222,9 +1222,10 @@ struct RTLIL::SigSpecConstIterator
typedef RTLIL::SigBit& reference; typedef RTLIL::SigBit& reference;
const RTLIL::SigSpec *sig_p; const RTLIL::SigSpec *sig_p;
RTLIL::SigBit bit;
int index; int index;
inline const RTLIL::SigBit &operator*() const; inline const RTLIL::SigBit &operator*();
inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; } inline bool operator!=(const RTLIL::SigSpecConstIterator &other) const { return index != other.index; }
inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; } inline bool operator==(const RTLIL::SigSpecIterator &other) const { return index == other.index; }
inline void operator++() { index++; } inline void operator++() { index++; }
@ -1233,33 +1234,83 @@ 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 };
// An AtomicHash is either clear or a nonzero integer.
struct AtomicHash {
// Create an initially clear value.
AtomicHash() : atomic_(0) {}
AtomicHash(const AtomicHash &rhs) : atomic_(rhs.load()) {}
AtomicHash &operator=(const AtomicHash &rhs) { store(rhs.load()); return *this; }
// Read the hash. Returns nullopt if the hash is clear.
std::optional<Hasher::hash_t> read() const {
Hasher::hash_t value = load();
if (value == 0)
return std::nullopt;
return value;
}
// Set the hash. If the value is already set, then the new value must
// equal the current value.
void set(Hasher::hash_t value) const {
log_assert(value != 0);
Hasher::hash_t old = const_cast<std::atomic<Hasher::hash_t>&>(atomic_)
.exchange(value, std::memory_order_relaxed);
log_assert(old == 0 || old == value);
}
void clear() { store(0); }
private:
int load() const { return atomic_.load(std::memory_order_relaxed); }
void store(Hasher::hash_t value) const {
const_cast<std::atomic<Hasher::hash_t>&>(atomic_).store(value, std::memory_order_relaxed);
}
void pack() const; std::atomic<Hasher::hash_t> atomic_;
void unpack() const; };
void updhash() const;
inline bool packed() const { Representation rep_;
return bits_.empty(); AtomicHash hash_;
union {
RTLIL::SigChunk chunk_;
std::vector<RTLIL::SigBit> bits_; // LSB at index 0
};
void init_empty_bits() {
rep_ = BITS;
new (&bits_) std::vector<RTLIL::SigBit>;
} }
inline void inline_unpack() const { void unpack();
if (!chunks_.empty()) inline void inline_unpack() {
if (rep_ == CHUNK)
unpack(); unpack();
} }
// Only used by Module::remove(const pool<Wire*> &wires) Hasher::hash_t updhash() const;
// but cannot be more specific as it isn't yet declared void destroy() {
friend struct RTLIL::Module; 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);
@ -1275,24 +1326,135 @@ 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;
}
inline const std::vector<RTLIL::SigChunk> &chunks() const { pack(); return chunks_; } struct Chunks {
inline const std::vector<RTLIL::SigBit> &bits() const { inline_unpack(); return bits_; } Chunks(const SigSpec &spec) : spec(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 &;
inline int size() const { return width_; } const SigSpec &spec;
inline bool empty() const { return width_ == 0; } int bit_index;
SigChunk chunk;
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); return bits_.at(index); } const_iterator(const SigSpec &spec) : spec(spec) {
inline const RTLIL::SigBit &operator[](int index) const { inline_unpack(); return bits_.at(index); } bit_index = 0;
if (spec.rep_ == BITS)
next_chunk_bits();
}
void next_chunk_bits();
const SigChunk &operator*() {
if (spec.rep_ == CHUNK)
return spec.chunk_;
return chunk;
};
const SigChunk *operator->() { return &**this; }
const_iterator &operator++() {
bit_index += (**this).width;
if (spec.rep_ == BITS)
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;
}
// Later we should deprecate these and remove their in-tree calls,
// so we can eventually remove chunk_vector.
std::vector<RTLIL::SigChunk>::const_reverse_iterator rbegin() {
ensure_chunk_vector();
return chunk_vector.rbegin();
}
std::vector<RTLIL::SigChunk>::const_reverse_iterator rend() {
ensure_chunk_vector();
return chunk_vector.rend();
}
int size() {
ensure_chunk_vector();
return chunk_vector.size();
}
int size() const {
int result = 0;
for (const SigChunk &_: *this)
++result;
return result;
}
const SigChunk &at(int index) {
ensure_chunk_vector();
return chunk_vector.at(index);
}
operator const std::vector<RTLIL::SigChunk>&() {
ensure_chunk_vector();
return chunk_vector;
}
private:
void ensure_chunk_vector() {
if (spec.size() > 0 && chunk_vector.empty()) {
for (const RTLIL::SigChunk &c : *this)
chunk_vector.push_back(c);
}
}
const SigSpec &spec;
std::vector<RTLIL::SigChunk> chunk_vector;
};
friend struct Chunks::const_iterator;
inline Chunks chunks() const { return {*this}; }
inline const SigSpec &bits() const { return *this; }
inline int size() const { return rep_ == CHUNK ? chunk_.width : GetSize(bits_); }
inline bool empty() const { return size() == 0; };
inline RTLIL::SigBit &operator[](int index) { inline_unpack(); hash_.clear(); return bits_.at(index); }
inline RTLIL::SigBit operator[](int index) const {
if (rep_ == CHUNK) {
if (index < 0 || index >= chunk_.width)
throw std::out_of_range("SigSpec::operator[]");
if (chunk_.wire)
return RTLIL::SigBit(chunk_.wire, chunk_.offset + index);
return RTLIL::SigBit(chunk_.data[index]);
}
return bits_.at(index);
}
inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; } inline RTLIL::SigSpecIterator begin() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = 0; return it; }
inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = width_; return it; } inline RTLIL::SigSpecIterator end() { RTLIL::SigSpecIterator it; it.sig_p = this; it.index = size(); return it; }
inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; } inline RTLIL::SigSpecConstIterator begin() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = 0; return it; }
inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = width_; return it; } inline RTLIL::SigSpecConstIterator end() const { RTLIL::SigSpecConstIterator it; it.sig_p = this; it.index = size(); return it; }
void sort(); void sort();
void sort_and_unify(); void sort_and_unify();
@ -1324,10 +1486,14 @@ public:
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const;
RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(const pool<RTLIL::SigBit> &pattern, const RTLIL::SigSpec *other = NULL) const;
RTLIL::SigSpec extract(int offset, int length = 1) const; RTLIL::SigSpec extract(int offset, int length = 1) const;
RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); } RTLIL::SigSpec extract_end(int offset) const { return extract(offset, size() - offset); }
RTLIL::SigBit lsb() const { log_assert(width_); return (*this)[0]; }; void rewrite_wires(std::function<void(RTLIL::Wire*& wire)> rewrite);
RTLIL::SigBit msb() const { log_assert(width_); return (*this)[width_ - 1]; };
RTLIL::SigBit lsb() const { log_assert(size()); return (*this)[0]; };
RTLIL::SigBit msb() const { log_assert(size()); return (*this)[size() - 1]; };
RTLIL::SigBit front() const { return (*this)[0]; }
RTLIL::SigBit back() const { return (*this)[size() - 1]; }
void append(const RTLIL::SigSpec &signal); void append(const RTLIL::SigSpec &signal);
inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); } inline void append(Wire *wire) { append(RTLIL::SigSpec(wire)); }
@ -1350,7 +1516,7 @@ public:
bool is_wire() const; bool is_wire() const;
bool is_chunk() const; bool is_chunk() const;
inline bool is_bit() const { return width_ == 1; } inline bool is_bit() const { return size() == 1; }
bool known_driver() const; bool known_driver() const;
@ -1387,6 +1553,9 @@ public:
int as_int_saturating(bool is_signed = false) const; int as_int_saturating(bool is_signed = false) const;
std::string as_string() const; std::string as_string() const;
// Returns std::nullopt if there are any non-constant bits. Returns an empty
// Const if this has zero width.
std::optional<RTLIL::Const> try_as_const() const;
RTLIL::Const as_const() const; RTLIL::Const as_const() const;
RTLIL::Wire *as_wire() const; RTLIL::Wire *as_wire() const;
RTLIL::SigChunk as_chunk() const; RTLIL::SigChunk as_chunk() const;
@ -1404,11 +1573,19 @@ public:
static bool parse_sel(RTLIL::SigSpec &sig, RTLIL::Design *design, RTLIL::Module *module, std::string str); 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); 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;
operator std::vector<RTLIL::SigBit>() const { return bits(); } operator std::vector<RTLIL::SigBit>() const { return to_sigbit_vector(); }
const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; } const RTLIL::SigBit &at(int offset, const RTLIL::SigBit &defval) { return offset < size() ? (*this)[offset] : defval; }
[[nodiscard]] Hasher hash_into(Hasher h) const { if (!hash_) updhash(); h.eat(hash_); return h; } [[nodiscard]] Hasher hash_into(Hasher h) const {
Hasher::hash_t val;
if (std::optional<Hasher::hash_t> current = hash_.read())
val = *current;
else
val = updhash();
h.eat(val);
return h;
}
#ifndef NDEBUG #ifndef NDEBUG
void check(Module *mod = nullptr) const; void check(Module *mod = nullptr) const;
@ -2312,13 +2489,15 @@ inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const {
return (*sig_p)[index]; return (*sig_p)[index];
} }
inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() const { inline const RTLIL::SigBit &RTLIL::SigSpecConstIterator::operator*() {
return (*sig_p)[index]; bit = (*sig_p)[index];
return bit;
} }
inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) { inline RTLIL::SigBit::SigBit(const RTLIL::SigSpec &sig) {
log_assert(sig.size() == 1 && sig.chunks().size() == 1); log_assert(sig.size() == 1);
*this = SigBit(sig.chunks().front()); auto it = sig.chunks().begin();
*this = SigBit(*it);
} }
template<typename T> template<typename T>

View file

@ -277,14 +277,26 @@ inline int ceil_log2(int x)
#endif #endif
} }
template <typename T>
auto reversed(T& container) {
struct reverse_view {
reverse_view(T& container) : container(container) {}
auto begin() const { return container.rbegin(); }
auto end() const { return container.rend(); }
T& container;
};
return reverse_view{container};
}
template <typename T> template <typename T>
auto reversed(const T& container) { auto reversed(const T& container) {
struct reverse_view { struct reverse_view {
const T& cont; reverse_view(const T& container) : container(container) {}
auto begin() const { return cont.rbegin(); } auto begin() const { return container.rbegin(); }
auto end() const { return cont.rend(); } auto end() const { return container.rend(); }
}; const T& container;
return reverse_view{container}; };
return reverse_view{container};
} }
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END

View file

@ -278,11 +278,12 @@ struct ShowWorker
std::vector<std::string> label_pieces; std::vector<std::string> label_pieces;
int bitpos = sig.size()-1; int bitpos = sig.size()-1;
for (int rep, chunk_idx = ((int) sig.chunks().size()) - 1; chunk_idx >= 0; chunk_idx -= rep) { RTLIL::SigSpec::Chunks sig_chunks = sig.chunks();
const RTLIL::SigChunk &c = sig.chunks().at(chunk_idx); for (int rep, chunk_idx = ((int) sig_chunks.size()) - 1; chunk_idx >= 0; chunk_idx -= rep) {
const RTLIL::SigChunk &c = sig_chunks.at(chunk_idx);
// Find the number of times this chunk is repeating // Find the number of times this chunk is repeating
for (rep = 1; chunk_idx - rep >= 0 && c == sig.chunks().at(chunk_idx - rep); rep++); for (rep = 1; chunk_idx - rep >= 0 && c == sig_chunks.at(chunk_idx - rep); rep++);
int cl, cr; int cl, cr;
cl = c.offset + c.width - 1; cl = c.offset + c.width - 1;

View file

@ -1428,13 +1428,13 @@ void reintegrate(RTLIL::Module *module, bool dff_mode)
// Copy connections (and rename) from mapped_mod to module // Copy connections (and rename) from mapped_mod to module
for (auto conn : mapped_mod->connections()) { for (auto conn : mapped_mod->connections()) {
if (!conn.first.is_fully_const()) { if (!conn.first.is_fully_const()) {
auto chunks = conn.first.chunks(); std::vector<RTLIL::SigChunk> chunks = conn.first.chunks();
for (auto &c : chunks) for (auto &c : chunks)
c.wire = module->wires_.at(remap_name(c.wire->name)); c.wire = module->wires_.at(remap_name(c.wire->name));
conn.first = std::move(chunks); conn.first = std::move(chunks);
} }
if (!conn.second.is_fully_const()) { if (!conn.second.is_fully_const()) {
auto chunks = conn.second.chunks(); std::vector<RTLIL::SigChunk> chunks = conn.second.chunks();
for (auto &c : chunks) for (auto &c : chunks)
if (c.wire) if (c.wire)
c.wire = module->wires_.at(remap_name(c.wire->name)); c.wire = module->wires_.at(remap_name(c.wire->name));