From 7b6c93f475b0e0ef885e557d7f702e60480811fd Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 2 Aug 2024 18:25:58 +0200 Subject: [PATCH] hashlib: buildable --- kernel/bitpattern.h | 4 +- kernel/hashlib.h | 142 ++++++++++++++++++++++++-------------------- 2 files changed, 80 insertions(+), 66 deletions(-) diff --git a/kernel/bitpattern.h b/kernel/bitpattern.h index ed570450ecf..4da7466c6d5 100644 --- a/kernel/bitpattern.h +++ b/kernel/bitpattern.h @@ -25,10 +25,10 @@ YOSYS_NAMESPACE_BEGIN -struct BitPatternPool : public Hashable +struct BitPatternPool { int width; - struct bits_t { + struct bits_t : public Hashable { std::vector bitdata; mutable hash_t cached_hash; bits_t(int width = 0) : bitdata(width), cached_hash(0) { } diff --git a/kernel/hashlib.h b/kernel/hashlib.h index f5e03b5b187..3cbe6f79d16 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -37,7 +37,7 @@ typedef uint64_t hash_t; // typedef hash_t acc_t; struct Hashable { - virtual ~Hashable() = 0; + ~Hashable() {} // Empty implementation public: [[nodiscard]] virtual hash_t hash_acc(hash_t acc) const = 0; @@ -67,9 +67,31 @@ inline unsigned int mkhash_xorshift(unsigned int a) { } +template +struct has_hash_method : std::false_type {}; -template -struct hash_ops: std::false_type {}; +template +struct has_hash_method().hash())>> : std::true_type {}; + +template +inline constexpr bool has_hash_method_v = has_hash_method::value; + +template struct hash_ops { + static inline bool cmp(const T &a, const T &b) { return a == b; } + + /** + * This function exists because dict, which has a hash method, that hashes + * keys as well as values, is used in Yosys with types that don't have + * a hash method. + */ + template static inline typename std::enable_if, hash_t>::type hash(const U &) + { + throw std::logic_error("Unimplemented hash method"); + return 0; + } + + template static inline typename std::enable_if, hash_t>::type hash(const U &a) { return a.hash(); } +}; template struct hash_ops>> { @@ -94,29 +116,21 @@ template<> struct hash_ops : hash_int_ops return a ? 1 : 0; } }; -template<> struct hash_ops : hash_int_ops -{ - static inline hash_t hash(int32_t a) { - return a; - } -}; -template<> struct hash_ops : hash_int_ops -{ - static inline hash_t hash(int64_t a) { - return mkhash((unsigned int)(a), (unsigned int)(a >> 32)); - } -}; -template<> struct hash_ops : hash_int_ops + +template +struct hash_ops>> : hash_int_ops { - static inline hash_t hash(uint32_t a) { - return a; - } + static inline hash_t hash(T a) { + return static_cast(a); + } }; -template<> struct hash_ops : hash_int_ops + +template +struct hash_ops>> : hash_int_ops { - static inline hash_t hash(uint64_t a) { - return mkhash((unsigned int)(a), (unsigned int)(a >> 32)); - } + static inline hash_t hash(T a) { + return (hash_t)(a); + } }; template<> struct hash_ops { @@ -203,47 +217,47 @@ struct hash_obj_ops { } }; -// Primary template -template -struct is_hashable : std::false_type {}; - -// Helper to check if hash_ops exists for a type U -template -struct has_hash_ops : std::false_type {}; - -template -struct has_hash_ops::hash(std::declval())), - decltype(hash_ops::cmp(std::declval(), std::declval())) ->> : std::true_type {}; - -// Helper to check if T is convertible to U and U has hash_ops -template -struct is_convertible_and_hashable : - std::conjunction< - std::is_convertible, - has_hash_ops - > {}; - -// Helper to check convertibility to a list of types -template -struct is_convertible_to_any_hashable : - std::disjunction< - is_convertible_and_hashable... - > {}; - -// Specialization that checks for direct hash_ops or convertibility to hashable types -template -struct is_hashable::value || - is_convertible_to_any_hashable::value - > -> : std::true_type {}; +// // Primary template +// template +// struct is_hashable : std::false_type {}; + +// // Helper to check if hash_ops exists for a type U +// template +// struct has_hash_ops : std::false_type {}; + +// template +// struct has_hash_ops::hash(std::declval())), +// decltype(hash_ops::cmp(std::declval(), std::declval())) +// >> : std::true_type {}; + +// // Helper to check if T is convertible to U and U has hash_ops +// template +// struct is_convertible_and_hashable : +// std::conjunction< +// std::is_convertible, +// has_hash_ops +// > {}; + +// // Helper to check convertibility to a list of types +// template +// struct is_convertible_to_any_hashable : +// std::disjunction< +// is_convertible_and_hashable... +// > {}; + +// // Specialization that checks for direct hash_ops or convertibility to hashable types +// template +// struct is_hashable::value || +// is_convertible_to_any_hashable::value +// > +// > : std::true_type {}; template inline unsigned int mkhash(const T &v) {