mirror of
https://github.com/verilator/verilator.git
synced 2025-04-16 01:26:54 +00:00
Improve distribution of V3Hash/V3Hasher
- Better combining, without multiplication, which means a 0 hash value is now allowed. - Do not OR in bottom bits (this was used to avoid a 0 hash but had the side effect of hashing 0 and 1 to the same value, which are actually common inputs. - Hash whole content of V3Number. This does not seem to be noticeable in runtime, but quite often the bottom word can be a special value like zero while the rest of the content varies.
This commit is contained in:
parent
5555f20bd2
commit
24b3816f5e
44
src/V3Hash.h
44
src/V3Hash.h
@ -24,40 +24,44 @@
|
||||
// V3Hash -- Generic hashing
|
||||
|
||||
class V3Hash final {
|
||||
// A 32-bit hash value. A value of 0 is illegal.
|
||||
uint32_t m_value;
|
||||
uint32_t m_value; // The 32-bit hash value.
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
V3Hash()
|
||||
: m_value{0} {}
|
||||
explicit V3Hash(uint32_t val)
|
||||
: m_value{val + 0x9e3779b9} {} // This is the same as 'V3Hash() + val'
|
||||
explicit V3Hash(int32_t val)
|
||||
: m_value{static_cast<uint32_t>(val)} {}
|
||||
explicit V3Hash(size_t val)
|
||||
: m_value{static_cast<uint32_t>(val)} {}
|
||||
explicit V3Hash(const std::string& val);
|
||||
|
||||
// METHODS
|
||||
uint32_t value() const { return m_value; }
|
||||
|
||||
// OPERATORS
|
||||
// Comparisons
|
||||
bool operator==(const V3Hash& rh) const { return m_value == rh.m_value; }
|
||||
bool operator!=(const V3Hash& rh) const { return m_value != rh.m_value; }
|
||||
bool operator<(const V3Hash& rh) const { return m_value < rh.m_value; }
|
||||
V3Hash operator+(uint32_t value) const {
|
||||
const uint64_t prod = (static_cast<uint64_t>(m_value) * 31) + value;
|
||||
return V3Hash(static_cast<uint32_t>(prod ^ (prod >> 32)));
|
||||
}
|
||||
V3Hash operator+(int32_t value) const { return *this + static_cast<uint32_t>(value); }
|
||||
V3Hash operator+(const V3Hash& that) const { return *this + that.m_value; }
|
||||
|
||||
V3Hash& operator+=(const V3Hash& that) {
|
||||
*this = *this + that.m_value;
|
||||
return *this;
|
||||
// '+' combines hashes
|
||||
V3Hash operator+(const V3Hash& that) const {
|
||||
return V3Hash(m_value ^ (that.m_value + 0x9e3779b9 + (m_value << 6) + (m_value >> 2)));
|
||||
}
|
||||
V3Hash operator+(uint32_t value) const { return *this + V3Hash(value); }
|
||||
V3Hash operator+(int32_t value) const { return *this + V3Hash(value); }
|
||||
V3Hash operator+(size_t value) const { return *this + V3Hash(value); }
|
||||
V3Hash operator+(const std::string& value) const { return *this + V3Hash(value); }
|
||||
|
||||
// '+=' combines in place
|
||||
V3Hash& operator+=(const V3Hash& that) { return *this = *this + that; }
|
||||
V3Hash& operator+=(uint32_t value) { return *this += V3Hash(value); }
|
||||
V3Hash& operator+=(int32_t value) { return *this += V3Hash(value); }
|
||||
V3Hash& operator+=(size_t value) { return *this += V3Hash(value); }
|
||||
V3Hash& operator+=(const std::string& that) { return *this += V3Hash(that); }
|
||||
|
||||
// CONSTRUCTORS
|
||||
V3Hash()
|
||||
: m_value{1} {}
|
||||
explicit V3Hash(uint32_t val)
|
||||
: m_value{val | 1} {}
|
||||
explicit V3Hash(int32_t val)
|
||||
: m_value{static_cast<uint32_t>(val)} {}
|
||||
explicit V3Hash(const std::string& val);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const V3Hash& rhs);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
|
||||
constexpr int MAX_SPRINTF_DOUBLE_SIZE
|
||||
= 1100; // Maximum characters with a sprintf %e/%f/%g (really 1079)
|
||||
@ -883,7 +884,11 @@ string V3Number::toString() const {
|
||||
return str;
|
||||
}
|
||||
|
||||
V3Hash V3Number::toHash() const { return V3Hash(m_width * (m_value[0] | 1)); }
|
||||
V3Hash V3Number::toHash() const {
|
||||
V3Hash hash(m_width);
|
||||
for (int i = 0; i < words(); ++i) { hash += m_value[i]; }
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint32_t V3Number::edataWord(int eword) const {
|
||||
UASSERT(!isFourState(), "edataWord with 4-state " << *this);
|
||||
|
Loading…
Reference in New Issue
Block a user