From ec4751e55c11d7287dacd39fb61ad936995fc963 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Dec 2014 21:59:41 +0100 Subject: [PATCH] Replaced std::unordered_set (nodict) with Yosys::pool --- kernel/hashmap.h | 352 +++++++++++++++++++++++++++++++++++++++ kernel/rtlil.cc | 30 ++-- kernel/rtlil.h | 132 +++------------ kernel/yosys.h | 1 - passes/cmds/delete.cc | 8 +- passes/cmds/splitnets.cc | 2 +- passes/opt/opt_clean.cc | 2 +- passes/opt/wreduce.cc | 4 +- 8 files changed, 394 insertions(+), 137 deletions(-) diff --git a/kernel/hashmap.h b/kernel/hashmap.h index d5f8c4e98..50098ac35 100644 --- a/kernel/hashmap.h +++ b/kernel/hashmap.h @@ -57,6 +57,21 @@ template<> struct hash_ops { } }; +struct hash_cstr_ops { + bool cmp(const char *a, const char *b) const { + for (int i = 0; a[i] || b[i]; i++) + if (a[i] != b[i]) + return false; + return true; + } + unsigned int hash(const char *a) const { + size_t hash = 5381; + while (*a) + hash = mkhash(hash, *(a++)); + return hash; + } +}; + struct hash_ptr_ops { bool cmp(const void *a, const void *b) const { return a == b; @@ -423,4 +438,341 @@ public: const_iterator end() const { return const_iterator(this, entries.size()); } }; +template> +class pool +{ + struct entry_t + { + int link; + K key; + + entry_t() : link(-1) { } + entry_t(const K &key) : link(1), key(key) { } + + bool is_free() const { return link < 0; } + int get_next() const { return (link > 0 ? link : -link) - 2; } + bool get_last() const { return get_next() == -1; } + void set_next_used(int next) { link = next + 2; } + void set_next_free(int next) { link = -(next + 2); } + }; + + std::vector hashtable; + std::vector entries; + int free_list, counter; + OPS ops; + + void init() + { + free_list = -1; + counter = 0; + } + + void init_from(const pool &other) + { + hashtable.clear(); + entries.clear(); + + counter = other.size(); + int new_size = grow_size(counter); + entries.reserve(new_size); + + for (auto &it : other) + entries.push_back(entry_t(it)); + entries.resize(new_size); + rehash(); + } + + size_t grow_size(size_t old_size) + { + if (old_size < 53) return 53; + if (old_size < 113) return 113; + if (old_size < 251) return 251; + if (old_size < 503) return 503; + if (old_size < 1130) return 1130; + if (old_size < 2510) return 2510; + if (old_size < 5030) return 5030; + if (old_size < 11300) return 11300; + if (old_size < 25100) return 25100; + if (old_size < 50300) return 50300; + if (old_size < 113000) return 113000; + if (old_size < 251000) return 251000; + if (old_size < 503000) return 503000; + if (old_size < 1130000) return 1130000; + if (old_size < 2510000) return 2510000; + if (old_size < 5030000) return 5030000; + if (old_size < 11300000) return 11300000; + if (old_size < 25100000) return 25100000; + if (old_size < 50300000) return 50300000; + if (old_size < 113000000) return 113000000; + if (old_size < 251000000) return 251000000; + if (old_size < 503000000) return 503000000; + if (old_size < 1130000000) return 1130000000; + throw std::length_error("maximum size for pool reached"); + } + + int mkhash(const K &key) const + { + unsigned int hash = 0; + if (!hashtable.empty()) + hash = ops.hash(key) % (unsigned int)(hashtable.size()); + return hash; + } + + void rehash() + { + free_list = -1; + + hashtable.resize(entries.size()); + for (auto &h : hashtable) + h = -1; + + for (int i = 0; i < int(entries.size()); i++) + if (entries[i].is_free()) { + entries[i].set_next_free(free_list); + free_list = i; + } else { + int hash = mkhash(entries[i].key); + entries[i].set_next_used(hashtable[hash]); + hashtable[hash] = i; + } + } + + void do_erase(const K &key, int hash) + { + int last_index = -1; + int index = hashtable.empty() ? -1 : hashtable[hash]; + while (1) { + if (index < 0) + return; + if (ops.cmp(entries[index].key, key)) { + if (last_index < 0) + hashtable[hash] = entries[index].get_next(); + else + entries[last_index].set_next_used(entries[index].get_next()); + entries[index].key = K(); + entries[index].set_next_free(free_list); + free_list = index; + if (--counter == 0) + init(); + return; + } + last_index = index; + index = entries[index].get_next(); + } + } + + int lookup_index(const K &key, int hash) const + { + int index = hashtable.empty() ? -1 : hashtable[hash]; + while (1) { + if (index < 0) + return -1; + if (ops.cmp(entries[index].key, key)) + return index; + index = entries[index].get_next(); + } + } + + int insert_at(const K &key, int hash) + { + if (free_list < 0) + { + int i = entries.size(); + entries.resize(grow_size(i)); + entries[i].key = key; + entries[i].set_next_used(0); + counter++; + rehash(); + return i; + } + + int i = free_list; + free_list = entries[i].get_next(); + entries[i].key = key; + entries[i].set_next_used(hashtable[hash]); + hashtable[hash] = i; + counter++; + return i; + } + +public: + class iterator + { + pool *ptr; + int index; + public: + iterator() { } + iterator(pool *ptr, int index) : ptr(ptr), index(index) { } + iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } + iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + bool operator==(const iterator &other) const { return index == other.index; } + bool operator!=(const iterator &other) const { return index != other.index; } + K &operator*() { return ptr->entries[index].key; } + K *operator->() { return &ptr->entries[index].key; } + const K &operator*() const { return ptr->entries[index].key; } + const K *operator->() const { return &ptr->entries[index].key; } + }; + + class const_iterator + { + const pool *ptr; + int index; + public: + const_iterator() { } + const_iterator(const pool *ptr, int index) : ptr(ptr), index(index) { } + const_iterator operator++() { do index++; while (index != int(ptr->entries.size()) && ptr->entries[index].is_free()); return *this; } + const_iterator operator--() { do index--; while (index != 0 && ptr->entries[index].is_free()); return *this; } + bool operator==(const const_iterator &other) const { return index == other.index; } + bool operator!=(const const_iterator &other) const { return index != other.index; } + const K &operator*() const { return ptr->entries[index].key; } + const K *operator->() const { return &ptr->entries[index].key; } + }; + + pool() + { + init(); + } + + pool(const pool &other) + { + init_from(other); + } + + pool(pool &&other) + { + free_list = -1; + counter = 0; + swap(other); + } + + pool &operator=(const pool &other) { + clear(); + init_from(other); + return *this; + } + + pool &operator=(pool &&other) { + clear(); + swap(other); + return *this; + } + + pool(const std::initializer_list &list) + { + init(); + for (auto &it : list) + insert(it); + } + + template + pool(InputIterator first, InputIterator last) + { + init(); + insert(first, last); + } + + template + void insert(InputIterator first, InputIterator last) + { + for (; first != last; ++first) + insert(*first); + } + + iterator insert(const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i >= 0) + return iterator(this, i); + i = insert_at(key, hash); + return iterator(this, i); + } + + void erase(const K &key) + { + int hash = mkhash(key); + do_erase(key, hash); + } + + void erase(const iterator it) + { + int hash = mkhash(it->first); + do_erase(it->first, hash); + } + + int count(const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + return i < 0 ? 0 : 1; + } + + iterator find(const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + return end(); + return iterator(this, i); + } + + const_iterator find(const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + return end(); + return const_iterator(this, i); + } + + bool operator[](const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + return i >= 0; + } + + void swap(pool &other) + { + hashtable.swap(other.hashtable); + entries.swap(other.entries); + std::swap(free_list, other.free_list); + std::swap(counter, other.counter); + } + + bool operator==(const pool &other) const { + if (counter != other.counter) + return false; + if (counter == 0) + return true; + if (entries.size() < other.entries.size()) + for (auto &it : *this) { + auto oit = other.find(it.first); + if (oit == other.end() || oit->second != it.second) + return false; + } + else + for (auto &oit : other) { + auto it = find(oit.first); + if (it == end() || it->second != oit.second) + return false; + } + return true; + } + + bool operator!=(const pool &other) const { + return !(*this == other); + } + + size_t size() const { return counter; } + bool empty() const { return counter == 0; } + void clear() { hashtable.clear(); entries.clear(); init(); } + + iterator begin() { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return iterator(this, index); } + iterator end() { return iterator(this, entries.size()); } + + const_iterator begin() const { int index = 0; while (index != int(entries.size()) && entries[index].is_free()) index++; return const_iterator(this, index); } + const_iterator end() const { return const_iterator(this, entries.size()); } +}; + #endif diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 05160b869..8f65f5273 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -30,7 +30,7 @@ YOSYS_NAMESPACE_BEGIN RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard; std::vector RTLIL::IdString::global_refcount_storage_; std::vector RTLIL::IdString::global_id_storage_; -dict RTLIL::IdString::global_id_index_; +dict RTLIL::IdString::global_id_index_; std::vector RTLIL::IdString::global_free_idx_list_; RTLIL::Const::Const() @@ -480,7 +480,7 @@ namespace { { RTLIL::Module *module; RTLIL::Cell *cell; - nodict expected_params, expected_ports; + pool expected_params, expected_ports; InternalCellChecker(RTLIL::Module *module, RTLIL::Cell *cell) : module(module), cell(cell) { } @@ -1132,7 +1132,7 @@ namespace { struct DeleteWireWorker { RTLIL::Module *module; - const nodict *wires_p; + const pool *wires_p; void operator()(RTLIL::SigSpec &sig) { std::vector chunks = sig; @@ -1146,7 +1146,7 @@ namespace { }; } -void RTLIL::Module::remove(const nodict &wires) +void RTLIL::Module::remove(const pool &wires) { log_assert(refcount_wires_ == 0); @@ -2169,9 +2169,9 @@ RTLIL::SigSpec::SigSpec(std::vector bits) check(); } -RTLIL::SigSpec::SigSpec(nodict bits) +RTLIL::SigSpec::SigSpec(pool bits) { - cover("kernel.rtlil.sigspec.init.nodict_bits"); + cover("kernel.rtlil.sigspec.init.pool_bits"); width_ = 0; hash_ = 0; @@ -2378,22 +2378,22 @@ void RTLIL::SigSpec::remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other void RTLIL::SigSpec::remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) { - nodict pattern_bits = pattern.to_sigbit_nodict(); + pool pattern_bits = pattern.to_sigbit_nodict(); remove2(pattern_bits, other); } -void RTLIL::SigSpec::remove(const nodict &pattern) +void RTLIL::SigSpec::remove(const pool &pattern) { remove2(pattern, NULL); } -void RTLIL::SigSpec::remove(const nodict &pattern, RTLIL::SigSpec *other) const +void RTLIL::SigSpec::remove(const pool &pattern, RTLIL::SigSpec *other) const { RTLIL::SigSpec tmp = *this; tmp.remove2(pattern, other); } -void RTLIL::SigSpec::remove2(const nodict &pattern, RTLIL::SigSpec *other) +void RTLIL::SigSpec::remove2(const pool &pattern, RTLIL::SigSpec *other) { if (other) cover("kernel.rtlil.sigspec.remove_other"); @@ -2439,11 +2439,11 @@ void RTLIL::SigSpec::remove2(const nodict &pattern, RTLIL::SigSpe RTLIL::SigSpec RTLIL::SigSpec::extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other) const { - nodict pattern_bits = pattern.to_sigbit_nodict(); + pool pattern_bits = pattern.to_sigbit_nodict(); return extract(pattern_bits, other); } -RTLIL::SigSpec RTLIL::SigSpec::extract(const nodict &pattern, const RTLIL::SigSpec *other) const +RTLIL::SigSpec RTLIL::SigSpec::extract(const pool &pattern, const RTLIL::SigSpec *other) const { if (other) cover("kernel.rtlil.sigspec.extract_other"); @@ -2943,12 +2943,12 @@ std::set RTLIL::SigSpec::to_sigbit_set() const return sigbits; } -nodict RTLIL::SigSpec::to_sigbit_nodict() const +pool RTLIL::SigSpec::to_sigbit_nodict() const { - cover("kernel.rtlil.sigspec.to_sigbit_nodict"); + cover("kernel.rtlil.sigspec.to_sigbit_pool"); pack(); - nodict sigbits; + pool sigbits; for (auto &c : chunks_) for (int i = 0; i < c.width; i++) sigbits.insert(RTLIL::SigBit(c, i)); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 756cca71c..ae37c350c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -22,27 +22,6 @@ #ifndef RTLIL_H #define RTLIL_H -namespace std { - template<> struct hash { - size_t operator()(const Yosys::RTLIL::IdString &arg) const; - }; - template<> struct equal_to { - bool operator()(const Yosys::RTLIL::IdString &lhs, const Yosys::RTLIL::IdString &rhs) const; - }; - template<> struct hash { - size_t operator()(const Yosys::RTLIL::SigBit &arg) const; - }; - template<> struct equal_to { - bool operator()(const Yosys::RTLIL::SigBit &lhs, const Yosys::RTLIL::SigBit &rhs) const; - }; - template<> struct hash { - size_t operator()(const Yosys::RTLIL::SigSpec &arg) const; - }; - template<> struct equal_to { - bool operator()(const Yosys::RTLIL::SigSpec &lhs, const Yosys::RTLIL::SigSpec &rhs) const; - }; -} - YOSYS_NAMESPACE_BEGIN namespace RTLIL @@ -97,48 +76,6 @@ namespace RTLIL { // the global id string cache - struct char_ptr_cmp { - bool operator()(const char *a, const char *b) const { - for (int i = 0; a[i] || b[i]; i++) - if (a[i] != b[i]) - return a[i] < b[i]; - return false; - } - }; - - struct char_ptr_hash { - size_t operator()(const char *a) const { - size_t hash = 5381; - for (int c; (c = *a); a++) - hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ - return hash; - } - }; - - struct char_ptr_eq { - bool operator()(const char *a, const char *b) const { - for (int i = 0; a[i] || b[i]; i++) - if (a[i] != b[i]) - return false; - return true; - } - }; - - struct char_ptr_ops { - bool cmp(const char *a, const char *b) const { - for (int i = 0; a[i] || b[i]; i++) - if (a[i] != b[i]) - return false; - return true; - } - unsigned int hash(const char *a) const { - size_t hash = 5381; - while (*a) - hash = mkhash(hash, *(a++)); - return hash; - } - }; - static struct destruct_guard_t { bool ok; // POD, will be initialized to zero destruct_guard_t() { ok = true; } @@ -147,7 +84,7 @@ namespace RTLIL static std::vector global_refcount_storage_; static std::vector global_id_storage_; - static dict global_id_index_; + static dict global_id_index_; static std::vector global_free_idx_list_; static inline int get_reference(int idx) @@ -282,8 +219,8 @@ namespace RTLIL return index_; } - // The following is a helper key_compare class. Instead of for example nodict - // use nodict> if the order of cells in the + // The following is a helper key_compare class. Instead of for example pool + // use pool> if the order of cells in the // set has an influence on the algorithm. template struct compare_ptr_by_name { @@ -303,7 +240,7 @@ namespace RTLIL bool in(IdString rhs) { return *this == rhs; } bool in(const char *rhs) { return *this == rhs; } bool in(const std::string &rhs) { return *this == rhs; } - bool in(const nodict &rhs) { return rhs.count(*this) != 0; } + bool in(const pool &rhs) { return rhs.count(*this) != 0; } }; static inline std::string escape_id(std::string str) { @@ -470,8 +407,8 @@ namespace RTLIL return list_p->size(); } - operator nodict() const { - nodict result; + operator pool() const { + pool result; for (auto &it : *list_p) result.insert(it.second); return result; @@ -485,7 +422,7 @@ namespace RTLIL return result; } - nodict to_set() const { return *this; } + pool to_set() const { return *this; } std::vector to_vector() const { return *this; } }; }; @@ -619,7 +556,7 @@ public: SigSpec(RTLIL::SigBit bit, int width = 1); SigSpec(std::vector chunks); SigSpec(std::vector bits); - SigSpec(nodict bits); + SigSpec(pool bits); SigSpec(std::set bits); SigSpec(bool bit); @@ -676,15 +613,15 @@ public: void remove(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other) const; void remove2(const RTLIL::SigSpec &pattern, RTLIL::SigSpec *other); - void remove(const nodict &pattern); - void remove(const nodict &pattern, RTLIL::SigSpec *other) const; - void remove2(const nodict &pattern, RTLIL::SigSpec *other); + void remove(const pool &pattern); + void remove(const pool &pattern, RTLIL::SigSpec *other) const; + void remove2(const pool &pattern, RTLIL::SigSpec *other); void remove(int offset, int length = 1); void remove_const(); RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; - RTLIL::SigSpec extract(const nodict &pattern, const RTLIL::SigSpec *other = NULL) const; + RTLIL::SigSpec extract(const pool &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(int offset, int length = 1) const; void append(const RTLIL::SigSpec &signal); @@ -717,7 +654,7 @@ public: bool match(std::string pattern) const; std::set to_sigbit_set() const; - nodict to_sigbit_nodict() const; + pool to_sigbit_nodict() const; std::vector to_sigbit_vector() const; std::map to_sigbit_map(const RTLIL::SigSpec &other) const; dict to_sigbit_dict(const RTLIL::SigSpec &other) const; @@ -742,8 +679,8 @@ public: struct RTLIL::Selection { bool full_selection; - nodict selected_modules; - dict> selected_members; + pool selected_modules; + dict> selected_members; Selection(bool full = true) : full_selection(full) { } @@ -782,7 +719,7 @@ struct RTLIL::Monitor struct RTLIL::Design { - nodict monitors; + pool monitors; dict scratchpad; int refcount_modules_; @@ -869,7 +806,7 @@ protected: public: RTLIL::Design *design; - nodict monitors; + pool monitors; int refcount_wires_; int refcount_cells_; @@ -879,7 +816,7 @@ public: std::vector connections_; RTLIL::IdString name; - nodict avail_parameters; + pool avail_parameters; dict memories; dict processes; RTLIL_ATTRIBUTE_MEMBERS @@ -923,7 +860,7 @@ public: RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } // Removing wires is expensive. If you have to remove wires, remove them all at once. - void remove(const nodict &wires); + void remove(const pool &wires); void remove(RTLIL::Cell *cell); void rename(RTLIL::Wire *wire, RTLIL::IdString new_name); @@ -1313,35 +1250,4 @@ void RTLIL::Process::rewrite_sigspecs(T functor) YOSYS_NAMESPACE_END -inline size_t std::hash::operator()(const Yosys::RTLIL::IdString &arg) const { - return arg.index_; -} - -inline bool std::equal_to::operator()(const Yosys::RTLIL::IdString &lhs, const Yosys::RTLIL::IdString &rhs) const { - return lhs.index_ == rhs.index_; -} - -inline size_t std::hash::operator()(const Yosys::RTLIL::SigBit &arg) const { - if (arg.wire) { - size_t hash = arg.wire->name.index_; - hash = ((hash << 5) + hash) + arg.offset; - return hash; - } - return arg.data; -} - -inline bool std::equal_to::operator()(const Yosys::RTLIL::SigBit &lhs, const Yosys::RTLIL::SigBit &rhs) const { - if (lhs.wire || rhs.wire) - return lhs.wire == rhs.wire && lhs.offset == rhs.offset; - return lhs.data == rhs.data; -} - -inline size_t std::hash::operator()(const Yosys::RTLIL::SigSpec &arg) const { - return arg.get_hash(); -} - -inline bool std::equal_to::operator()(const Yosys::RTLIL::SigSpec &lhs, const Yosys::RTLIL::SigSpec &rhs) const { - return lhs == rhs; -} - #endif diff --git a/kernel/yosys.h b/kernel/yosys.h index 9b76d28c6..012b40c1f 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -124,7 +124,6 @@ YOSYS_NAMESPACE_BEGIN -#define nodict std::unordered_set #include "kernel/hashmap.h" using std::vector; diff --git a/passes/cmds/delete.cc b/passes/cmds/delete.cc index d7edcfbfc..4c8f16f48 100644 --- a/passes/cmds/delete.cc +++ b/passes/cmds/delete.cc @@ -91,10 +91,10 @@ struct DeletePass : public Pass { continue; } - nodict delete_wires; - nodict delete_cells; - nodict delete_procs; - nodict delete_mems; + pool delete_wires; + pool delete_cells; + pool delete_procs; + pool delete_mems; for (auto &it : module->wires_) if (design->selected(module, it.second)) diff --git a/passes/cmds/splitnets.cc b/passes/cmds/splitnets.cc index 6c24a8e5f..3b3fc208e 100644 --- a/passes/cmds/splitnets.cc +++ b/passes/cmds/splitnets.cc @@ -176,7 +176,7 @@ struct SplitnetsPass : public Pass { module->rewrite_sigspecs(worker); - nodict delete_wires; + pool delete_wires; for (auto &it : worker.splitmap) delete_wires.insert(it.first); module->remove(delete_wires); diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 01acb5c04..cb12b3922 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -262,7 +262,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } - nodict del_wires; + pool del_wires; int del_wires_count = 0; for (auto wire : maybe_del_wires) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index e8a38d212..1609a8be7 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -28,11 +28,11 @@ PRIVATE_NAMESPACE_BEGIN struct WreduceConfig { - nodict supported_cell_types; + pool supported_cell_types; WreduceConfig() { - supported_cell_types = nodict({ + supported_cell_types = pool({ "$not", "$pos", "$neg", "$and", "$or", "$xor", "$xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx",