3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-08-03 09:50:24 +00:00
This commit is contained in:
Robert O'Callahan 2025-08-01 05:32:00 +00:00 committed by GitHub
commit 47ec9833af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 728 additions and 517 deletions

View file

@ -27,10 +27,10 @@ YOSYS_NAMESPACE_BEGIN
struct FfInitVals
{
const SigMap *sigmap;
const SigMapView *sigmap;
dict<SigBit, std::pair<State,SigBit>> initbits;
void set(const SigMap *sigmap_, RTLIL::Module *module)
void set(const SigMapView *sigmap_, RTLIL::Module *module)
{
sigmap = sigmap_;
initbits.clear();
@ -126,7 +126,7 @@ struct FfInitVals
initbits.clear();
}
FfInitVals (const SigMap *sigmap, RTLIL::Module *module)
FfInitVals (const SigMapView *sigmap, RTLIL::Module *module)
{
set(sigmap, module);
}

View file

@ -58,7 +58,7 @@ YOSYS_NAMESPACE_BEGIN
struct FfMergeHelper
{
const SigMap *sigmap;
const SigMapView *sigmap;
RTLIL::Module *module;
FfInitVals *initvals;

View file

@ -1327,7 +1327,8 @@ public:
return p;
}
// Merge sets if the given indices belong to different sets
// Merge sets if the given indices belong to different sets.
// Makes ifind(j) the root of the merged set.
void imerge(int i, int j)
{
i = ifind(i);

View file

@ -237,6 +237,42 @@ using sort_by_name_id_guard = typename std::enable_if<std::is_same<T,RTLIL::Cell
template<typename T>
class SigSet<T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name_id<typename std::remove_pointer<T>::type>> {};
struct SigMapView
{
mfp<SigBit> database;
// Modify bit to its representative
void apply(RTLIL::SigBit &bit) const
{
bit = database.find(bit);
}
void apply(RTLIL::SigSpec &sig) const
{
for (auto &bit : sig)
apply(bit);
}
RTLIL::SigBit operator()(RTLIL::SigBit bit) const
{
apply(bit);
return bit;
}
RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
{
apply(sig);
return sig;
}
RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
{
SigSpec sig(wire);
apply(sig);
return sig;
}
};
/**
* SigMap wraps a union-find "database"
* to map SigBits of a module to canonical representative SigBits.
@ -244,10 +280,8 @@ class SigSet<T, sort_by_name_id_guard<T>> : public SigSet<T, RTLIL::sort_by_name
* If a SigBit has a const state (impl: bit.wire is nullptr),
* it's promoted to a representative.
*/
struct SigMap
struct SigMap final : public SigMapView
{
mfp<SigBit> database;
SigMap(RTLIL::Module *module = NULL)
{
if (module != NULL)
@ -320,37 +354,6 @@ struct SigMap
inline void add(Wire *wire) { return add(RTLIL::SigSpec(wire)); }
// Modify bit to its representative
void apply(RTLIL::SigBit &bit) const
{
bit = database.find(bit);
}
void apply(RTLIL::SigSpec &sig) const
{
for (auto &bit : sig)
apply(bit);
}
RTLIL::SigBit operator()(RTLIL::SigBit bit) const
{
apply(bit);
return bit;
}
RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
{
apply(sig);
return sig;
}
RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
{
SigSpec sig(wire);
apply(sig);
return sig;
}
// All non-const bits
RTLIL::SigSpec allbits() const
{
@ -362,6 +365,107 @@ struct SigMap
}
};
/**
* SiValgMap wraps a union-find "database" to map SigBits of a module to
* canonical representative SigBits plus some optional Val value associated with the bits.
* Val has a commutative, associative, idempotent operator|=, a default constructor
* which constructs an identity element, and a copy constructor.
* SigBits that are connected share a set in the underlying database;
* the associated value is the "sum" of all the values associated with the contributing bits.
* If any of the SigBits in a set are a constant, the canonical SigBit is a constant.
*/
template <class Val>
struct SigValMap final : public SigMapView
{
dict<SigBit, Val> values;
void swap(SigValMap<Val> &other)
{
database.swap(other.database);
values.swap(other.values);
}
void clear()
{
database.clear();
values.clear();
}
// Rebuild SigMap for all connections in module
void set(RTLIL::Module *module)
{
int bitcount = 0;
for (auto &it : module->connections())
bitcount += it.first.size();
database.clear();
values.clear();
database.reserve(bitcount);
for (auto &it : module->connections())
add(it.first, it.second);
}
// Add connections from "from" to "to", bit-by-bit.
void add(const RTLIL::SigSpec& from, const RTLIL::SigSpec& to)
{
log_assert(GetSize(from) == GetSize(to));
for (int i = 0; i < GetSize(from); i++)
{
int bfi = database.lookup(from[i]);
int bti = database.lookup(to[i]);
if (bfi == bti) {
continue;
}
const RTLIL::SigBit &bf = database[bfi];
const RTLIL::SigBit &bt = database[bti];
if (bf.wire == nullptr) {
// bf is constant so make it the canonical representative.
database.imerge(bti, bfi);
merge_value(bt, bf);
} else {
// Make bt the canonical representative.
database.imerge(bfi, bti);
merge_value(bf, bt);
}
}
}
void addVal(const RTLIL::SigBit &bit, const Val &val)
{
values[database.find(bit)] |= val;
}
void addVal(const RTLIL::SigSpec &sig, const Val &val)
{
for (const auto &bit : sig)
addVal(bit, val);
}
Val apply_and_get_value(RTLIL::SigBit &bit) const
{
bit = database.find(bit);
auto it = values.find(bit);
return it == values.end() ? Val() : it->second;
}
private:
void merge_value(const RTLIL::SigBit &from, const RTLIL::SigBit &to)
{
auto it = values.find(from);
if (it == values.end()) {
return;
}
// values[to] could resize the underlying `entries` so
// finish using `it` first.
Val v = it->second;
values.erase(it);
values[to] |= v;
}
};
YOSYS_NAMESPACE_END
#endif /* SIGTOOLS_H */

File diff suppressed because it is too large Load diff