3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-17 04:35:44 +00:00

Merge branch 'YosysHQ:main' into main

This commit is contained in:
Akash Levy 2025-08-27 11:10:13 -07:00 committed by GitHub
commit dc52f6ca1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 394 additions and 180 deletions

View file

@ -25,6 +25,18 @@
YOSYS_NAMESPACE_BEGIN
/**
* This file implements BitPatternPool for efficiently storing and querying
* sets of fixed-width 2-valued logic constants compressed as "bit patterns".
* A bit pattern can have don't cares on one or more bit positions (State::Sa).
*
* In terms of logic synthesis:
* A BitPatternPool is a sum of products (SOP).
* BitPatternPool::bits_t is a cube.
*
* BitPatternPool does not permit adding new patterns, only removing.
* Its intended use case is in analysing cases in case/match constructs in HDL.
*/
struct BitPatternPool
{
int width;
@ -67,6 +79,9 @@ struct BitPatternPool
}
}
/**
* Constructs a pool of all possible patterns (all don't-care bits)
*/
BitPatternPool(int width)
{
this->width = width;
@ -78,6 +93,10 @@ struct BitPatternPool
}
}
/**
* Convert a constant SigSpec to a pattern. Normalize Yosys many-valued
* to three-valued logic.
*/
bits_t sig2bits(RTLIL::SigSpec sig)
{
bits_t bits;
@ -88,6 +107,9 @@ struct BitPatternPool
return bits;
}
/**
* Two cubes match if their intersection is non-empty.
*/
bool match(bits_t a, bits_t b)
{
log_assert(int(a.bitdata.size()) == width);
@ -98,6 +120,15 @@ struct BitPatternPool
return true;
}
/**
* Does cube sig overlap any cube in the pool?
* For example:
* pool({aaa}).has_any(01a) == true
* pool({01a}).has_any(01a) == true
* pool({011}).has_any(01a) == true
* pool({01a}).has_any(011) == true
* pool({111}).has_any(01a) == false
*/
bool has_any(RTLIL::SigSpec sig)
{
bits_t bits = sig2bits(sig);
@ -107,6 +138,15 @@ struct BitPatternPool
return false;
}
/**
* Is cube sig covered by a cube in the pool?
* For example:
* pool({aaa}).has_all(01a) == true
* pool({01a}).has_any(01a) == true
* pool({01a}).has_any(011) == true
* pool({011}).has_all(01a) == false
* pool({111}).has_all(01a) == false
*/
bool has_all(RTLIL::SigSpec sig)
{
bits_t bits = sig2bits(sig);
@ -121,6 +161,12 @@ struct BitPatternPool
return false;
}
/**
* Remove cube sig from the pool, splitting the remaining cubes. True if success.
* For example:
* Taking 011 out of pool({01a}) -> pool({010}), returns true.
* Taking 011 out of pool({010}) does nothing, returns false.
*/
bool take(RTLIL::SigSpec sig)
{
bool status = false;
@ -143,6 +189,9 @@ struct BitPatternPool
return status;
}
/**
* Remove all patterns. Returns false if already empty.
*/
bool take_all()
{
if (database.empty())

View file

@ -180,58 +180,58 @@ struct hash_ops {
};
template<typename P, typename Q> struct hash_ops<std::pair<P, Q>> {
static inline bool cmp(std::pair<P, Q> a, std::pair<P, Q> b) {
static inline bool cmp(const std::pair<P, Q> &a, const std::pair<P, Q> &b) {
return a == b;
}
[[nodiscard]] static inline Hasher hash_into(std::pair<P, Q> a, Hasher h) {
[[nodiscard]] static inline Hasher hash_into(const std::pair<P, Q> &a, Hasher h) {
h = hash_ops<P>::hash_into(a.first, h);
h = hash_ops<Q>::hash_into(a.second, h);
return h;
}
HASH_TOP_LOOP_FST (std::pair<P, Q> a) HASH_TOP_LOOP_SND
HASH_TOP_LOOP_FST (const std::pair<P, Q> &a) HASH_TOP_LOOP_SND
};
template<typename... T> struct hash_ops<std::tuple<T...>> {
static inline bool cmp(std::tuple<T...> a, std::tuple<T...> b) {
static inline bool cmp(const std::tuple<T...> &a, const std::tuple<T...> &b) {
return a == b;
}
template<size_t I = 0>
static inline typename std::enable_if<I == sizeof...(T), Hasher>::type hash_into(std::tuple<T...>, Hasher h) {
static inline typename std::enable_if<I == sizeof...(T), Hasher>::type hash_into(const std::tuple<T...> &, Hasher h) {
return h;
}
template<size_t I = 0>
static inline typename std::enable_if<I != sizeof...(T), Hasher>::type hash_into(std::tuple<T...> a, Hasher h) {
static inline typename std::enable_if<I != sizeof...(T), Hasher>::type hash_into(const std::tuple<T...> &a, Hasher h) {
typedef hash_ops<typename std::tuple_element<I, std::tuple<T...>>::type> element_ops_t;
h = hash_into<I+1>(a, h);
h = element_ops_t::hash_into(std::get<I>(a), h);
return h;
}
HASH_TOP_LOOP_FST (std::tuple<T...> a) HASH_TOP_LOOP_SND
HASH_TOP_LOOP_FST (const std::tuple<T...> &a) HASH_TOP_LOOP_SND
};
template<typename T> struct hash_ops<std::vector<T>> {
static inline bool cmp(std::vector<T> a, std::vector<T> b) {
static inline bool cmp(const std::vector<T> &a, const std::vector<T> &b) {
return a == b;
}
[[nodiscard]] static inline Hasher hash_into(std::vector<T> a, Hasher h) {
[[nodiscard]] static inline Hasher hash_into(const std::vector<T> &a, Hasher h) {
h.eat((uint32_t)a.size());
for (auto k : a)
h.eat(k);
return h;
}
HASH_TOP_LOOP_FST (std::vector<T> a) HASH_TOP_LOOP_SND
HASH_TOP_LOOP_FST (const std::vector<T> &a) HASH_TOP_LOOP_SND
};
template<typename T, size_t N> struct hash_ops<std::array<T, N>> {
static inline bool cmp(std::array<T, N> a, std::array<T, N> b) {
static inline bool cmp(const std::array<T, N> &a, const std::array<T, N> &b) {
return a == b;
}
[[nodiscard]] static inline Hasher hash_into(std::array<T, N> a, Hasher h) {
[[nodiscard]] static inline Hasher hash_into(const std::array<T, N> &a, Hasher h) {
for (const auto& k : a)
h = hash_ops<T>::hash_into(k, h);
return h;
}
HASH_TOP_LOOP_FST (std::array<T, N> a) HASH_TOP_LOOP_SND
HASH_TOP_LOOP_FST (const std::array<T, N> &a) HASH_TOP_LOOP_SND
};
struct hash_cstr_ops {
@ -303,10 +303,10 @@ template<> struct hash_ops<std::monostate> {
};
template<typename... T> struct hash_ops<std::variant<T...>> {
static inline bool cmp(std::variant<T...> a, std::variant<T...> b) {
static inline bool cmp(const std::variant<T...> &a, const std::variant<T...> &b) {
return a == b;
}
[[nodiscard]] static inline Hasher hash_into(std::variant<T...> a, Hasher h) {
[[nodiscard]] static inline Hasher hash_into(const std::variant<T...> &a, Hasher h) {
std::visit([& h](const auto &v) { h.eat(v); }, a);
h.eat(a.index());
return h;
@ -314,10 +314,10 @@ template<typename... T> struct hash_ops<std::variant<T...>> {
};
template<typename T> struct hash_ops<std::optional<T>> {
static inline bool cmp(std::optional<T> a, std::optional<T> b) {
static inline bool cmp(const std::optional<T> &a, const std::optional<T> &b) {
return a == b;
}
[[nodiscard]] static inline Hasher hash_into(std::optional<T> a, Hasher h) {
[[nodiscard]] static inline Hasher hash_into(const std::optional<T> &a, Hasher h) {
if(a.has_value())
h.eat(*a);
else