diff --git a/kernel/hashlib.h b/kernel/hashlib.h index aa9f43ff4..3b33748d3 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -56,11 +56,25 @@ const int hashtable_size_factor = 3; #define DJB2_32 +namespace legacy { + inline uint32_t mkhash_add(uint32_t a, uint32_t b) { + return ((a << 5) + a) + b; + } +}; - +/** + * Hash a type with an accumulator in a record or array context + */ template struct hash_ops; +/** + * Hash a single instance in isolation. + * Can have explicit specialization, but the default redirects to hash_ops + */ +template +struct hash_top_ops; + inline unsigned int mkhash_xorshift(unsigned int a) { if (sizeof(a) == 4) { a ^= a << 13; @@ -141,6 +155,16 @@ class Hasher { } }; +template +struct hash_top_ops { + static inline bool cmp(const T &a, const T &b) { + return hash_ops::cmp(a, b); + } + static inline Hasher hash(const T &a) { + return hash_ops::hash_acc(a, Hasher()); + } +}; + template struct hash_ops { static inline bool cmp(const T &a, const T &b) { @@ -339,12 +363,12 @@ inline int hashtable_size(int min_size) throw std::length_error("hash table exceeded maximum size."); } -template class dict; -template class idict; -template class pool; -template class mfp; +template> class dict; +template> class idict; +template> class pool; +template> class mfp; -template +template class dict { struct entry_t { @@ -359,7 +383,7 @@ class dict { std::vector hashtable; std::vector entries; - hash_ops ops; + OPS ops; #ifdef NDEBUG static inline void do_assert(bool) { } @@ -373,7 +397,7 @@ class dict { { Hasher::hash_t hash = 0; if (!hashtable.empty()) - hash = run_hash(key) % (unsigned int)(hashtable.size()); + hash = ops.hash(key).yield() % (unsigned int)(hashtable.size()); return hash; } @@ -800,10 +824,10 @@ public: const_iterator end() const { return const_iterator(nullptr, -1); } }; -template +template class pool { - template friend class idict; + template friend class idict; protected: struct entry_t @@ -818,7 +842,7 @@ protected: std::vector hashtable; std::vector entries; - hash_ops ops; + OPS ops; #ifdef NDEBUG static inline void do_assert(bool) { } @@ -832,7 +856,7 @@ protected: { Hasher::hash_t hash = 0; if (!hashtable.empty()) - hash = run_hash(key) % (unsigned int)(hashtable.size()); + hash = ops.hash(key).yield() % (unsigned int)(hashtable.size()); return hash; } @@ -1148,7 +1172,7 @@ public: Hasher hash_acc(Hasher h) const { h.acc(entries.size()); for (auto &it : entries) { - h.commutative_acc(run_hash(it.udata)); + h.commutative_acc(ops.hash(it.udata).yield()); } return h; } @@ -1167,10 +1191,10 @@ public: const_iterator end() const { return const_iterator(nullptr, -1); } }; -template +template class idict { - pool database; + pool database; public: class const_iterator @@ -1264,10 +1288,10 @@ public: * mfp stands for "merge, find, promote" * i-prefixed methods operate on indices in parents */ -template +template class mfp { - mutable idict database; + mutable idict database; mutable std::vector parents; public: diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 4f9550478..afa538540 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -896,6 +896,19 @@ struct RTLIL::SigBit bool operator ==(const RTLIL::SigBit &other) const; bool operator !=(const RTLIL::SigBit &other) const; Hasher hash_acc(Hasher h) const; + Hasher hash_top() const; +}; + +namespace hashlib { + template <> + struct hash_top_ops { + static inline bool cmp(const RTLIL::SigBit &a, const RTLIL::SigBit &b) { + return a == b; + } + static inline Hasher hash(const RTLIL::SigBit sb) { + return sb.hash_top(); + } + }; }; struct RTLIL::SigSpecIterator @@ -1825,15 +1838,24 @@ inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const { inline Hasher RTLIL::SigBit::hash_acc(Hasher h) const { if (wire) { h.acc(offset); - // hash_acc isn't allowed to come first, or it might hash trivially - // and possibly ruin things - h = wire->name.hash_acc(h); + h.acc(wire->name); return h; } h.acc(data); return h; } + +inline Hasher RTLIL::SigBit::hash_top() const { + Hasher h; + if (wire) { + h.force(hashlib::legacy::mkhash_add(wire->name.index_, offset)); + return h; + } + h.force(data); + return h; +} + inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { return (*sig_p)[index]; }