diff --git a/kernel/hashlib.h b/kernel/hashlib.h index e8ddddd33..44ba893cf 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -1129,6 +1129,11 @@ public: const_iterator end() const { return const_iterator(*this, offset + size()); } }; +/** + * Union-find data structure with a promotion method + * mfp stands for "merge, find, promote" + * i-prefixed methods operate on indices in parents +*/ template class mfp { @@ -1142,13 +1147,18 @@ public: { } + // Finds a given element's index. If it isn't in the data structure, + // it is added as its own set int operator()(const K &key) const { int i = database(key); + // If the lookup caused the database to grow, + // also add a corresponding entry in parents initialized to -1 (no parent) parents.resize(database.size(), -1); return i; } + // Finds an element at given index const K &operator[](int index) const { return database[index]; @@ -1161,6 +1171,11 @@ public: while (parents[p] != -1) p = parents[p]; + // p is now the representative of i + // Now we traverse from i up to the representative again + // and make p the parent of all the nodes along the way. + // This is a side effect and doesn't affect the return value. + // It speeds up future find operations while (k != p) { int next_k = parents[k]; parents[k] = p; @@ -1170,6 +1185,7 @@ public: return p; } + // Merge sets if the given indices belong to different sets void imerge(int i, int j) { i = ifind(i); diff --git a/kernel/sigtools.h b/kernel/sigtools.h index 4ea43d743..63f1b51ec 100644 --- a/kernel/sigtools.h +++ b/kernel/sigtools.h @@ -229,6 +229,13 @@ using sort_by_name_id_guard = typename std::enable_if class SigSet> : public SigSet::type>> {}; +/** + * SigMap wraps a union-find "database" + * to map SigBits of a module to canonical representative SigBits. + * SigBits that are connected share a set in the underlying database. + * If a SigBit has a const state (impl: bit.wire is nullptr), + * it's promoted to a representative. + */ struct SigMap { mfp database; @@ -249,6 +256,7 @@ struct SigMap database.clear(); } + // Rebuild SigMap for all connections in module void set(RTLIL::Module *module) { int bitcount = 0; @@ -262,6 +270,7 @@ struct SigMap 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)); @@ -287,6 +296,7 @@ struct SigMap } } + // Add sig as disconnected from anything void add(const RTLIL::SigBit &bit) { const auto &b = database.find(bit); @@ -302,6 +312,7 @@ 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); @@ -332,6 +343,7 @@ struct SigMap return sig; } + // All non-const bits RTLIL::SigSpec allbits() const { RTLIL::SigSpec sig;