hashlib: remove is_new from HasherDJB32, implement hash_top for IdString

This commit is contained in:
Emil J. Tywoniak 2024-11-06 12:58:04 +01:00
parent 8513021e0b
commit 60c1e41557
2 changed files with 314 additions and 313 deletions

View File

@ -48,14 +48,9 @@ namespace hashlib {
* instead of pointers. * instead of pointers.
*/ */
// TODO describe how comparison hashes are special
// TODO draw the line between generic and hash function specific code
const int hashtable_size_trigger = 2; const int hashtable_size_trigger = 2;
const int hashtable_size_factor = 3; const int hashtable_size_factor = 3;
#define DJB2_32
namespace legacy { namespace legacy {
inline uint32_t mkhash_add(uint32_t a, uint32_t b) { inline uint32_t mkhash_add(uint32_t a, uint32_t b) {
return ((a << 5) + a) + b; return ((a << 5) + a) + b;
@ -89,16 +84,11 @@ inline unsigned int mkhash_xorshift(unsigned int a) {
return a; return a;
} }
class Hasher { class HasherDJB32 {
public: public:
#ifdef DJB2_32
using hash_t = uint32_t; using hash_t = uint32_t;
#endif
#ifdef DJB2_64
using hash_t = uint64_t;
#endif
Hasher() { HasherDJB32() {
// traditionally 5381 is used as starting value for the djb2 hash // traditionally 5381 is used as starting value for the djb2 hash
state = 5381; state = 5381;
} }
@ -106,7 +96,7 @@ class Hasher {
fudge = f; fudge = f;
} }
private: private:
uint32_t state; uint32_t state;
static uint32_t fudge; static uint32_t fudge;
// The XOR version of DJB2 // The XOR version of DJB2
@ -142,19 +132,17 @@ class Hasher {
*this = hash_ops<T>::hash_acc(t, *this); *this = hash_ops<T>::hash_acc(t, *this);
} }
void commutative_acc(uint32_t t) { void commutative_acc(hash_t t) {
state ^= t; state ^= t;
} }
void force(hash_t new_state) { void force(hash_t new_state) {
state = new_state; state = new_state;
} }
bool is_new() const {
return state == Hasher().state;
}
}; };
using Hasher = HasherDJB32;
template<typename T> template<typename T>
struct hash_top_ops { struct hash_top_ops {
static inline bool cmp(const T &a, const T &b) { static inline bool cmp(const T &a, const T &b) {

View File

@ -76,11 +76,13 @@ namespace RTLIL
struct SyncRule; struct SyncRule;
struct Process; struct Process;
struct Binding; struct Binding;
struct IdString;
typedef std::pair<SigSpec, SigSpec> SigSig; typedef std::pair<SigSpec, SigSpec> SigSig;
};
struct IdString struct RTLIL::IdString
{ {
#undef YOSYS_XTRACE_GET_PUT #undef YOSYS_XTRACE_GET_PUT
#undef YOSYS_SORT_ID_FREE_LIST #undef YOSYS_SORT_ID_FREE_LIST
#undef YOSYS_USE_STICKY_IDS #undef YOSYS_USE_STICKY_IDS
@ -96,15 +98,15 @@ namespace RTLIL
static std::vector<char*> global_id_storage_; static std::vector<char*> global_id_storage_;
static dict<char*, int> global_id_index_; static dict<char*, int> global_id_index_;
#ifndef YOSYS_NO_IDS_REFCNT #ifndef YOSYS_NO_IDS_REFCNT
static std::vector<int> global_refcount_storage_; static std::vector<int> global_refcount_storage_;
static std::vector<int> global_free_idx_list_; static std::vector<int> global_free_idx_list_;
#endif #endif
#ifdef YOSYS_USE_STICKY_IDS #ifdef YOSYS_USE_STICKY_IDS
static int last_created_idx_ptr_; static int last_created_idx_ptr_;
static int last_created_idx_[8]; static int last_created_idx_[8];
#endif #endif
static inline void xtrace_db_dump() static inline void xtrace_db_dump()
{ {
@ -223,7 +225,7 @@ namespace RTLIL
return idx; return idx;
} }
#ifndef YOSYS_NO_IDS_REFCNT #ifndef YOSYS_NO_IDS_REFCNT
static inline void put_reference(int idx) static inline void put_reference(int idx)
{ {
// put_reference() may be called from destructors after the destructor of // put_reference() may be called from destructors after the destructor of
@ -257,9 +259,9 @@ namespace RTLIL
global_id_storage_.at(idx) = nullptr; global_id_storage_.at(idx) = nullptr;
global_free_idx_list_.push_back(idx); global_free_idx_list_.push_back(idx);
} }
#else #else
static inline void put_reference(int) { } static inline void put_reference(int) { }
#endif #endif
// the actual IdString object is just is a single int // the actual IdString object is just is a single int
@ -360,16 +362,14 @@ namespace RTLIL
*this = IdString(); *this = IdString();
} }
Hasher hash_acc(Hasher h) const { Hasher hash_acc(Hasher h) const { return hash_ops<int>::hash_acc(index_, h); }
// If we're starting a hashing sequence, simply start with unhashed ID
if (h.is_new()) { Hasher hash_top() const {
Hasher h;
h.force((Hasher::hash_t) index_); h.force((Hasher::hash_t) index_);
return h; return h;
} }
return hash_ops<int>::hash_acc(index_, h);
}
// The following is a helper key_compare class. Instead of for example std::set<Cell*> // The following is a helper key_compare class. Instead of for example std::set<Cell*>
// use std::set<Cell*, IdString::compare_ptr_by_name<Cell>> if the order of cells in the // use std::set<Cell*, IdString::compare_ptr_by_name<Cell>> if the order of cells in the
// set has an influence on the algorithm. // set has an influence on the algorithm.
@ -382,29 +382,42 @@ namespace RTLIL
// often one needs to check if a given IdString is part of a list (for example a list // often one needs to check if a given IdString is part of a list (for example a list
// of cell types). the following functions helps with that. // of cell types). the following functions helps with that.
template<typename... Args> template<typename... Args>
bool in(Args... args) const { bool in(Args... args) const {
// Credit: https://articles.emptycrate.com/2016/05/14/folds_in_cpp11_ish.html return (... || in(args));
bool result = false;
(void) std::initializer_list<int>{ (result = result || in(args), 0)... };
return result;
} }
bool in(const IdString &rhs) const { return *this == rhs; } bool in(const IdString &rhs) const { return *this == rhs; }
bool in(const char *rhs) const { return *this == rhs; } bool in(const char *rhs) const { return *this == rhs; }
bool in(const std::string &rhs) const { return *this == rhs; } bool in(const std::string &rhs) const { return *this == rhs; }
bool in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; } inline bool in(const pool<IdString> &rhs) const;
inline bool in(const pool<IdString> &&rhs) const;
bool isPublic() const { return begins_with("\\"); } bool isPublic() const { return begins_with("\\"); }
}; };
namespace hashlib {
template <>
struct hash_top_ops<RTLIL::IdString> {
static inline bool cmp(const RTLIL::IdString &a, const RTLIL::IdString &b) {
return a == b;
}
static inline Hasher hash(const RTLIL::IdString id) {
return id.hash_top();
}
};
};
// TODO deprecate this
inline bool RTLIL::IdString::in(const pool<IdString> &rhs) const { return rhs.count(*this) != 0; }
inline bool RTLIL::IdString::in(const pool<IdString> &&rhs) const { return rhs.count(*this) != 0; }
namespace RTLIL {
namespace ID { namespace ID {
#define X(_id) extern IdString _id; #define X(_id) extern IdString _id;
#include "kernel/constids.inc" #include "kernel/constids.inc"
#undef X #undef X
}; };
extern dict<std::string, std::string> constpad; extern dict<std::string, std::string> constpad;
const pool<IdString> &builtin_ff_cell_types(); const pool<IdString> &builtin_ff_cell_types();