diff --git a/include/verilated_unordered_set_map.h b/include/verilated_unordered_set_map.h index 59b13c4ac..ec71a099d 100644 --- a/include/verilated_unordered_set_map.h +++ b/include/verilated_unordered_set_map.h @@ -43,6 +43,7 @@ #include "verilatedos.h" #include +#include #include // Abstract 'vl_hash' and 'vl_equal_to' templates. @@ -112,6 +113,7 @@ public: // TYPES typedef std::list Bucket; typedef vluint64_t size_type; + enum RehashType {GROW, SHRINK}; template friend class vl_unordered_map; @@ -192,12 +194,16 @@ public: vl_unordered_set() : m_numElements(0) , m_log2Buckets(4) - , m_bucketsp(NULL) { } + , m_bucketsp(NULL) + , m_hash() + , m_equal() { } vl_unordered_set(const vl_unordered_set& other) : m_numElements(other.m_numElements) , m_log2Buckets(other.m_log2Buckets) - , m_bucketsp(NULL) { + , m_bucketsp(NULL) + , m_hash() + , m_equal() { if (other.m_bucketsp) { m_bucketsp = new Bucket[numBuckets()]; for (size_type i = 0; i < numBuckets(); i++) { @@ -308,10 +314,9 @@ public: // if we don't rehash: iterator result_it(bucketIdx, m_bucketsp[bucketIdx].begin(), this); - if (needToRehash()) { - rehash(); - // ... since we rehashed, do a lookup to get the - // result iterator. + if (needToRehash(GROW)) { + rehash(GROW); + // ... since we rehashed, do a lookup to get the result iterator. result_it = find(val); } @@ -331,6 +336,13 @@ public: if (it != end()) { m_bucketsp[bucketIdx].erase(it.bit()); m_numElements--; + // Rehashing to handle a shrinking data set is important + // for the Scoreboard in V3Partition, which begins tracking + // a huge number of vertices and then tracks a successively + // smaller number over time. + if (needToRehash(SHRINK)) { + rehash(SHRINK); + } return 1; } return 0; @@ -338,9 +350,8 @@ public: void clear() { if (m_bucketsp) { - for (size_type i = 0; i < numBuckets(); i++) { - m_bucketsp[i].clear(); - } + delete [] m_bucketsp; + m_bucketsp = NULL; } m_numElements = 0; } @@ -357,10 +368,28 @@ private: if (!m_bucketsp) m_bucketsp = new Bucket[numBuckets()]; } - bool needToRehash() const { return ((4 * numBuckets()) < m_numElements); } + bool needToRehash(RehashType rt) const { + if (rt == GROW) { + return ((4 * numBuckets()) < m_numElements); + } else { + return (numBuckets() > (4 * m_numElements)); + } + } + + void rehash(RehashType rt) { + size_type new_log2Buckets; + if (rt == GROW) { + new_log2Buckets = m_log2Buckets + 2; + } else { + if (m_log2Buckets <= 4) { + // On shrink, saturate m_log2Buckets at its + // initial size of 2^4 == 16 buckets. Don't risk + // underflowing! + return; + } + new_log2Buckets = m_log2Buckets - 2; + } - void rehash() { - size_type new_log2Buckets = m_log2Buckets + 2; size_type new_num_buckets = VL_ULL(1) << new_log2Buckets; Bucket* new_bucketsp = new Bucket[new_num_buckets]; @@ -475,7 +504,12 @@ template (it->second); + return it->second; + } + Value& at(const Key& k) { + iterator it = find(k); + if (it == end()) { throw std::out_of_range("sorry"); } + return it->second; } void clear() { m_set.clear(); } size_type size() const { return m_set.size(); } diff --git a/include/verilatedos.h b/include/verilatedos.h index fe3903b19..f58b74d75 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -158,10 +158,17 @@ #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) # define VL_EQ_DELETE = delete # define vl_unique_ptr std::unique_ptr -# define vl_unordered_map std::unordered_map -# define vl_unordered_set std::unordered_set -# define VL_INCLUDE_UNORDERED_MAP -# define VL_INCLUDE_UNORDERED_SET +// By default we use std:: types in C++11. +// Define VL_USE_UNORDERED_TYPES to test these pre-C++11 classes +# ifdef VL_USE_UNORDERED_TYPES +# define VL_INCLUDE_UNORDERED_MAP "verilated_unordered_set_map.h" +# define VL_INCLUDE_UNORDERED_SET "verilated_unordered_set_map.h" +# else +# define vl_unordered_map std::unordered_map +# define vl_unordered_set std::unordered_set +# define VL_INCLUDE_UNORDERED_MAP +# define VL_INCLUDE_UNORDERED_SET +# endif #else # define VL_EQ_DELETE # define vl_unique_ptr std::auto_ptr