From: Clifford Wolf Date: Fri, 26 Dec 2014 20:35:22 +0000 (+0100) Subject: Replaced std::unordered_map as implementation for Yosys::dict X-Git-Tag: yosys-0.5~215 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9e6fb0b02ccf209528ead026de8eef0a8a0d7740;p=yosys.git Replaced std::unordered_map as implementation for Yosys::dict --- diff --git a/backends/ilang/ilang_backend.cc b/backends/ilang/ilang_backend.cc index 19c2805ca..dd5b6f3ce 100644 --- a/backends/ilang/ilang_backend.cc +++ b/backends/ilang/ilang_backend.cc @@ -103,7 +103,7 @@ void ILANG_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo dump_sigchunk(f, sig.as_chunk(), autoint); } else { f << stringf("{ "); - for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) { + for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) { dump_sigchunk(f, *it, false); f << stringf(" "); } @@ -115,7 +115,7 @@ void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL:: { std::map sorted_attributes(wire->attributes.begin(), wire->attributes.end()); - for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); @@ -140,7 +140,7 @@ void ILANG_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL { std::map sorted_attributes(memory->attributes.begin(), memory->attributes.end()); - for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); @@ -159,18 +159,18 @@ void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: std::map sorted_parameters(cell->parameters.begin(), cell->parameters.end()); std::map sorted_connections(cell->connections().begin(), cell->connections().end()); - for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { + for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); } f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); - for (auto it = sorted_parameters.begin(); it != sorted_parameters.end(); it++) { + for (auto it = sorted_parameters.begin(); it != sorted_parameters.end(); ++it) { f << stringf("%s parameter%s %s ", indent.c_str(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); } - for (auto it = sorted_connections.begin(); it != sorted_connections.end(); it++) { + for (auto it = sorted_connections.begin(); it != sorted_connections.end(); ++it) { f << stringf("%s connect %s ", indent.c_str(), it->first.c_str()); dump_sigspec(f, it->second); f << stringf("\n"); @@ -180,7 +180,7 @@ void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs) { - for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) + for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) { f << stringf("%s" "assign ", indent.c_str()); dump_sigspec(f, it->first); @@ -189,13 +189,13 @@ void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, con f << stringf("\n"); } - for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) + for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it) dump_proc_switch(f, indent, *it); } void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw) { - for (auto it = sw->attributes.begin(); it != sw->attributes.end(); it++) { + for (auto it = sw->attributes.begin(); it != sw->attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); @@ -205,7 +205,7 @@ void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const dump_sigspec(f, sw->signal); f << stringf("\n"); - for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) + for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { f << stringf("%s case ", indent.c_str()); for (size_t i = 0; i < (*it)->compare.size(); i++) { @@ -237,7 +237,7 @@ void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT case RTLIL::STi: f << stringf("init\n"); break; } - for (auto it = sy->actions.begin(); it != sy->actions.end(); it++) { + for (auto it = sy->actions.begin(); it != sy->actions.end(); ++it) { f << stringf("%s update ", indent.c_str()); dump_sigspec(f, it->first); f << stringf(" "); @@ -248,14 +248,14 @@ void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RT void ILANG_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc) { - for (auto it = proc->attributes.begin(); it != proc->attributes.end(); it++) { + for (auto it = proc->attributes.begin(); it != proc->attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); } f << stringf("%s" "process %s\n", indent.c_str(), proc->name.c_str()); dump_proc_case_body(f, indent + " ", &proc->root_case); - for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++) + for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it) dump_proc_sync(f, indent + " ", *it); f << stringf("%s" "end\n", indent.c_str()); } @@ -276,7 +276,7 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu if (print_header) { - for (auto it = module->attributes.begin(); it != module->attributes.end(); it++) { + for (auto it = module->attributes.begin(); it != module->attributes.end(); ++it) { f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); dump_const(f, it->second); f << stringf("\n"); @@ -336,7 +336,7 @@ void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu } bool first_conn_line = true; - for (auto it = module->connections().begin(); it != module->connections().end(); it++) { + for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { bool show_conn = !only_selected; if (only_selected) { RTLIL::SigSpec sigs = it->first; @@ -366,7 +366,7 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl if (!flag_m) { int count_selected_mods = 0; - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { if (design->selected_whole_module(it->first)) flag_m = true; if (design->selected(it->second)) @@ -382,7 +382,7 @@ void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl f << stringf("autoidx %d\n", autoidx); } - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { if (!only_selected || design->selected(it->second)) { if (only_selected) f << stringf("\n"); diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index ffaf9ec07..be9479301 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -74,22 +74,22 @@ void reset_auto_counter(RTLIL::Module *module) reset_auto_counter_id(module->name, false); - for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) reset_auto_counter_id(it->second->name, true); - for (auto it = module->cells_.begin(); it != module->cells_.end(); it++) { + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) { reset_auto_counter_id(it->second->name, true); reset_auto_counter_id(it->second->type, false); } - for (auto it = module->processes.begin(); it != module->processes.end(); it++) + for (auto it = module->processes.begin(); it != module->processes.end(); ++it) reset_auto_counter_id(it->second->name, false); auto_name_digits = 1; for (size_t i = 10; i < auto_name_offset + auto_name_map.size(); i = i*10) auto_name_digits++; - for (auto it = auto_name_map.begin(); it != auto_name_map.end(); it++) + for (auto it = auto_name_map.begin(); it != auto_name_map.end(); ++it) log(" renaming `%s' to `_%0*d_'.\n", it->first.c_str(), auto_name_digits, auto_name_offset + it->second); } @@ -237,7 +237,7 @@ void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig) dump_sigchunk(f, sig.as_chunk()); } else { f << stringf("{ "); - for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) { + for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); ++it) { if (it != sig.chunks().rbegin()) f << stringf(", "); dump_sigchunk(f, *it, true); @@ -250,7 +250,7 @@ void dump_attributes(std::ostream &f, std::string indent, dictfirst).c_str()); f << stringf(" = "); dump_const(f, it->second); @@ -744,7 +744,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) if (cell->parameters.size() > 0) { f << stringf(" #("); - for (auto it = cell->parameters.begin(); it != cell->parameters.end(); it++) { + for (auto it = cell->parameters.begin(); it != cell->parameters.end(); ++it) { if (it != cell->parameters.begin()) f << stringf(","); f << stringf("\n%s .%s(", indent.c_str(), id(it->first).c_str()); @@ -766,7 +766,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) for (int i = 1; true; i++) { char str[16]; snprintf(str, 16, "$%d", i); - for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) { + for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { if (it->first != str) continue; if (!first_arg) @@ -780,7 +780,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell) break; found_numbered_port:; } - for (auto it = cell->connections().begin(); it != cell->connections().end(); it++) { + for (auto it = cell->connections().begin(); it != cell->connections().end(); ++it) { if (numbered_ports.count(it->first)) continue; if (!first_arg) @@ -812,7 +812,7 @@ void dump_case_body(std::ostream &f, std::string indent, RTLIL::CaseRule *cs, bo if (!omit_trailing_begin && number_of_stmts >= 2) f << stringf("%s" "begin\n", indent.c_str()); - for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) { + for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) { if (it->first.size() == 0) continue; f << stringf("%s ", indent.c_str()); @@ -822,7 +822,7 @@ void dump_case_body(std::ostream &f, std::string indent, RTLIL::CaseRule *cs, bo f << stringf(";\n"); } - for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) + for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it) dump_proc_switch(f, indent + " ", *it); if (!omit_trailing_begin && number_of_stmts == 0) @@ -836,7 +836,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw { if (sw->signal.size() == 0) { f << stringf("%s" "begin\n", indent.c_str()); - for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) { + for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { if ((*it)->compare.size() == 0) dump_case_body(f, indent + " ", *it); } @@ -848,7 +848,7 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw dump_sigspec(f, sw->signal); f << stringf(")\n"); - for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) { + for (auto it = sw->cases.begin(); it != sw->cases.end(); ++it) { f << stringf("%s ", indent.c_str()); if ((*it)->compare.size() == 0) f << stringf("default"); @@ -868,11 +868,11 @@ void dump_proc_switch(std::ostream &f, std::string indent, RTLIL::SwitchRule *sw void case_body_find_regs(RTLIL::CaseRule *cs) { - for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) + for (auto it = cs->switches.begin(); it != cs->switches.end(); ++it) for (auto it2 = (*it)->cases.begin(); it2 != (*it)->cases.end(); it2++) case_body_find_regs(*it2); - for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) { + for (auto it = cs->actions.begin(); it != cs->actions.end(); ++it) { for (auto &c : it->first.chunks()) if (c.wire != NULL) reg_wires.insert(c.wire->name); @@ -883,7 +883,7 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo { if (find_regs) { case_body_find_regs(&proc->root_case); - for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++) + for (auto it = proc->syncs.begin(); it != proc->syncs.end(); ++it) for (auto it2 = (*it)->actions.begin(); it2 != (*it)->actions.end(); it2++) { for (auto &c : it2->first.chunks()) if (c.wire != NULL) @@ -937,7 +937,7 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo } } - for (auto it = sync->actions.begin(); it != sync->actions.end(); it++) { + for (auto it = sync->actions.begin(); it != sync->actions.end(); ++it) { if (it->first.size() == 0) continue; f << stringf("%s ", indent.c_str()); @@ -958,7 +958,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) active_module = module; f << stringf("\n"); - for (auto it = module->processes.begin(); it != module->processes.end(); it++) + for (auto it = module->processes.begin(); it != module->processes.end(); ++it) dump_process(f, indent + " ", it->second, true); if (!noexpr) @@ -996,7 +996,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) bool keep_running = true; for (int port_id = 1; keep_running; port_id++) { keep_running = false; - for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) { + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) { RTLIL::Wire *wire = it->second; if (wire->port_id == port_id) { if (port_id != 1) @@ -1009,19 +1009,19 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module) } f << stringf(");\n"); - for (auto it = module->wires_.begin(); it != module->wires_.end(); it++) + for (auto it = module->wires_.begin(); it != module->wires_.end(); ++it) dump_wire(f, indent + " ", it->second); - for (auto it = module->memories.begin(); it != module->memories.end(); it++) + for (auto it = module->memories.begin(); it != module->memories.end(); ++it) dump_memory(f, indent + " ", it->second); - for (auto it = module->cells_.begin(); it != module->cells_.end(); it++) + for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) dump_cell(f, indent + " ", it->second); - for (auto it = module->processes.begin(); it != module->processes.end(); it++) + for (auto it = module->processes.begin(); it != module->processes.end(); ++it) dump_process(f, indent + " ", it->second); - for (auto it = module->connections().begin(); it != module->connections().end(); it++) + for (auto it = module->connections().begin(); it != module->connections().end(); ++it) dump_conn(f, indent + " ", it->first, it->second); f << stringf("%s" "endmodule\n", indent.c_str()); @@ -1133,7 +1133,7 @@ struct VerilogBackend : public Backend { extra_args(f, filename, args, argidx); *f << stringf("/* Generated by %s */\n", yosys_version_str); - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { if (it->second->get_bool_attribute("\\blackbox") != blackboxes) continue; if (selected && !design->selected_whole_module(it->first)) { diff --git a/kernel/cost.h b/kernel/cost.h index 1b4166e00..c6c631e0a 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -24,10 +24,10 @@ YOSYS_NAMESPACE_BEGIN -int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache = nullptr); +int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache = nullptr); int get_cell_cost(RTLIL::IdString type, const dict ¶meters = dict(), - RTLIL::Design *design = nullptr, dict *mod_cost_cache = nullptr) + RTLIL::Design *design = nullptr, dict *mod_cost_cache = nullptr) { static dict gate_cost = { { "$_BUF_", 1 }, @@ -55,18 +55,18 @@ int get_cell_cost(RTLIL::IdString type, const dictattributes.count("\\cost")) return mod->attributes.at("\\cost").as_int(); - dict local_mod_cost_cache; + dict local_mod_cost_cache; if (mod_cost_cache == nullptr) mod_cost_cache = &local_mod_cost_cache; - if (mod_cost_cache->count(mod)) - return mod_cost_cache->at(mod); + if (mod_cost_cache->count(mod->name)) + return mod_cost_cache->at(mod->name); int module_cost = 1; for (auto c : mod->cells()) module_cost += get_cell_cost(c, mod_cost_cache); - (*mod_cost_cache)[mod] = module_cost; + (*mod_cost_cache)[mod->name] = module_cost; return module_cost; } @@ -74,7 +74,7 @@ int get_cell_cost(RTLIL::IdString type, const dict *mod_cost_cache) +int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache) { return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache); } diff --git a/kernel/hashmap.h b/kernel/hashmap.h index bd4fc4d22..d5f8c4e98 100644 --- a/kernel/hashmap.h +++ b/kernel/hashmap.h @@ -19,6 +19,7 @@ #ifndef YOSYS_HASHMAP_H +#include #include #include @@ -27,28 +28,28 @@ inline unsigned int mkhash(unsigned int a, unsigned int b) { } template struct hash_ops { - bool cmp(const T &a, const T &b) { + bool cmp(const T &a, const T &b) const { return a == b; } - unsigned int hash(const T &a) { + unsigned int hash(const T &a) const { return a.hash(); } }; template<> struct hash_ops { - bool cmp(int a, int b) { + bool cmp(int a, int b) const { return a == b; } - unsigned int hash(int a) { + unsigned int hash(int a) const { return a; } }; template<> struct hash_ops { - bool cmp(const std::string &a, const std::string &b) { + bool cmp(const std::string &a, const std::string &b) const { return a == b; } - unsigned int hash(const std::string &a) { + unsigned int hash(const std::string &a) const { unsigned int v = 0; for (auto c : a) v = mkhash(v, c); @@ -56,14 +57,25 @@ template<> struct hash_ops { } }; +struct hash_ptr_ops { + bool cmp(const void *a, const void *b) const { + return a == b; + } + unsigned int hash(const void *a) const { + return (unsigned long)a; + } +}; + template> -class new_dict +class dict { struct entry_t { int link; std::pair udata; + entry_t() : link(-1) { } + entry_t(const std::pair &udata) : link(1), udata(udata) { } bool is_free() const { return link < 0; } int get_next() const { return (link > 0 ? link : -link) - 2; } @@ -79,17 +91,61 @@ class new_dict void init() { + free_list = -1; counter = 0; - entries.resize(61); + } + + void init_from(const dict &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(); } - int mkhash(const K &key) + size_t grow_size(size_t old_size) { - return ops.hash(key) % int(hashtable.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 dict reached"); + } + + int mkhash(const K &key) const + { + unsigned int hash = 0; + if (!hashtable.empty()) + hash = ops.hash(key) % (unsigned int)(hashtable.size()); + return hash; } -public: void rehash() { free_list = -1; @@ -112,7 +168,7 @@ public: void do_erase(const K &key, int hash) { int last_index = -1; - int index = hashtable[hash]; + int index = hashtable.empty() ? -1 : hashtable[hash]; while (1) { if (index < 0) return; @@ -124,7 +180,8 @@ public: entries[index].udata = std::pair(); entries[index].set_next_free(free_list); free_list = index; - counter--; + if (--counter == 0) + init(); return; } last_index = index; @@ -132,9 +189,9 @@ public: } } - int lookup_index(const K &key, int hash) + int lookup_index(const K &key, int hash) const { - int index = hashtable[hash]; + int index = hashtable.empty() ? -1 : hashtable[hash]; while (1) { if (index < 0) return -1; @@ -149,7 +206,7 @@ public: if (free_list < 0) { int i = entries.size(); - entries.resize(2*entries.size()); + entries.resize(grow_size(i)); entries[i].udata = value; entries[i].set_next_used(0); counter++; @@ -169,24 +226,74 @@ public: public: class iterator { - new_dict *ptr; + dict *ptr; int index; public: - iterator(new_dict *ptr, int index) : ptr(ptr), index(index) { } + iterator() { } + iterator(dict *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; } std::pair &operator*() { return ptr->entries[index].udata; } + std::pair *operator->() { return &ptr->entries[index].udata; } + const std::pair &operator*() const { return ptr->entries[index].udata; } + const std::pair *operator->() const { return &ptr->entries[index].udata; } }; - new_dict() + class const_iterator + { + const dict *ptr; + int index; + public: + const_iterator() { } + const_iterator(const dict *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 std::pair &operator*() const { return ptr->entries[index].udata; } + const std::pair *operator->() const { return &ptr->entries[index].udata; } + }; + + dict() { init(); } + dict(const dict &other) + { + init_from(other); + } + + dict(dict &&other) + { + free_list = -1; + counter = 0; + swap(other); + } + + dict &operator=(const dict &other) { + clear(); + init_from(other); + return *this; + } + + dict &operator=(dict &&other) { + clear(); + swap(other); + return *this; + } + + dict(const std::initializer_list> &list) + { + init(); + for (auto &it : list) + insert(it); + } + template - new_dict(InputIterator first, InputIterator last) + dict(InputIterator first, InputIterator last) { init(); insert(first, last); @@ -215,13 +322,55 @@ public: do_erase(key, hash); } - int count(const K &key) + 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); + } + + T& at(const K &key) + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + throw std::out_of_range("dict::at()"); + return entries[i].udata.second; + } + + const T& at(const K &key) const + { + int hash = mkhash(key); + int i = lookup_index(key, hash); + if (i < 0) + throw std::out_of_range("dict::at()"); + return entries[i].udata.second; + } + T& operator[](const K &key) { int hash = mkhash(key); @@ -231,8 +380,47 @@ public: return entries[i].udata.second; } + void swap(dict &other) + { + hashtable.swap(other.hashtable); + entries.swap(other.entries); + std::swap(free_list, other.free_list); + std::swap(counter, other.counter); + } + + bool operator==(const dict &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 dict &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/log.cc b/kernel/log.cc index 677884c97..5b18e3d6c 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -301,7 +301,7 @@ void log_cell(RTLIL::Cell *cell, std::string indent) // --------------------------------------------------- #ifdef YOSYS_ENABLE_COVER -new_dict> extra_coverage_data; +dict> extra_coverage_data; void cover_extra(std::string parent, std::string id, bool increment) { if (extra_coverage_data.count(id) == 0) { @@ -314,9 +314,9 @@ void cover_extra(std::string parent, std::string id, bool increment) { extra_coverage_data[id].second++; } -new_dict> get_coverage_data() +dict> get_coverage_data() { - new_dict> coverage_data; + dict> coverage_data; for (auto &it : pass_register) { std::string key = stringf("passes.%s", it.first.c_str()); diff --git a/kernel/log.h b/kernel/log.h index eec071991..9bb2b3621 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -106,10 +106,10 @@ struct CoverData { extern "C" struct CoverData __start_yosys_cover_list[]; extern "C" struct CoverData __stop_yosys_cover_list[]; -extern new_dict> extra_coverage_data; +extern dict> extra_coverage_data; void cover_extra(std::string parent, std::string id, bool increment = true); -new_dict> get_coverage_data(); +dict> get_coverage_data(); #define cover_list(_id, ...) do { cover(_id); \ std::string r = cover_list_worker(_id, __VA_ARGS__); \ diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 28fdeecdd..05160b869 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() @@ -242,7 +242,7 @@ RTLIL::Design::Design() RTLIL::Design::~Design() { - for (auto it = modules_.begin(); it != modules_.end(); it++) + for (auto it = modules_.begin(); it != modules_.end(); ++it) delete it->second; } @@ -454,13 +454,13 @@ RTLIL::Module::Module() RTLIL::Module::~Module() { - for (auto it = wires_.begin(); it != wires_.end(); it++) + for (auto it = wires_.begin(); it != wires_.end(); ++it) delete it->second; - for (auto it = memories.begin(); it != memories.end(); it++) + for (auto it = memories.begin(); it != memories.end(); ++it) delete it->second; - for (auto it = cells_.begin(); it != cells_.end(); it++) + for (auto it = cells_.begin(); it != cells_.end(); ++it) delete it->second; - for (auto it = processes.begin(); it != processes.end(); it++) + for (auto it = processes.begin(); it != processes.end(); ++it) delete it->second; } @@ -2258,7 +2258,7 @@ void RTLIL::SigSpec::unpack() const #define DJB2(_hash, _value) (_hash) = (((_hash) << 5) + (_hash)) + (_value) -void RTLIL::SigSpec::hash() const +void RTLIL::SigSpec::updhash() const { RTLIL::SigSpec *that = (RTLIL::SigSpec*)this; @@ -2721,8 +2721,8 @@ bool RTLIL::SigSpec::operator <(const RTLIL::SigSpec &other) const if (chunks_.size() != other.chunks_.size()) return chunks_.size() < other.chunks_.size(); - hash(); - other.hash(); + updhash(); + other.updhash(); if (hash_ != other.hash_) return hash_ < other.hash_; @@ -2753,8 +2753,8 @@ bool RTLIL::SigSpec::operator ==(const RTLIL::SigSpec &other) const if (chunks_.size() != chunks_.size()) return false; - hash(); - other.hash(); + updhash(); + other.updhash(); if (hash_ != other.hash_) return false; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index e684ba4ae..756cca71c 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -124,6 +124,21 @@ namespace RTLIL } }; + 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; } @@ -132,7 +147,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) @@ -263,6 +278,10 @@ namespace RTLIL *this = IdString(); } + unsigned int hash() const { + return index_; + } + // The following is a helper key_compare class. Instead of for example nodict // use nodict> if the order of cells in the // set has an influence on the algorithm. @@ -538,6 +557,7 @@ struct RTLIL::SigBit bool operator <(const RTLIL::SigBit &other) const; bool operator ==(const RTLIL::SigBit &other) const; bool operator !=(const RTLIL::SigBit &other) const; + unsigned int hash() const; }; struct RTLIL::SigSpecIterator : public std::iterator @@ -572,7 +592,7 @@ private: void pack() const; void unpack() const; - void hash() const; + void updhash() const; inline bool packed() const { return bits_.empty(); @@ -710,6 +730,8 @@ public: operator std::vector() const { return chunks(); } operator std::vector() const { return bits(); } + unsigned int hash() const { if (!hash_) updhash(); return hash_; }; + #ifndef NDEBUG void check() const; #else @@ -1213,6 +1235,12 @@ inline bool RTLIL::SigBit::operator!=(const RTLIL::SigBit &other) const { return (wire != other.wire) || (wire ? (offset != other.offset) : (data != other.data)); } +inline unsigned int RTLIL::SigBit::hash() const { + if (wire) + return wire->name.hash() * 33 + offset; + return data; +} + inline RTLIL::SigBit &RTLIL::SigSpecIterator::operator*() const { return (*sig_p)[index]; } diff --git a/kernel/yosys.h b/kernel/yosys.h index b14852eaf..9b76d28c6 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -124,7 +124,6 @@ YOSYS_NAMESPACE_BEGIN -#define dict std::unordered_map #define nodict std::unordered_set #include "kernel/hashmap.h" using std::vector; diff --git a/passes/opt/opt_const.cc b/passes/opt/opt_const.cc index 7f800bde9..9c1a18782 100644 --- a/passes/opt/opt_const.cc +++ b/passes/opt/opt_const.cc @@ -199,7 +199,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons dict invert_map; TopoSort> cells; - dict> cell_to_inbit; + dict, hash_ptr_ops> cell_to_inbit; dict> outbit_to_cell; for (auto cell : module->cells()) diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index c581b749e..9bc308873 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -41,7 +41,7 @@ struct OptShareWorker CellTypes ct; int total_count; #ifdef USE_CELL_HASH_CACHE - dict cell_hash_cache; + dict cell_hash_cache; #endif #ifdef USE_CELL_HASH_CACHE diff --git a/passes/tests/test_autotb.cc b/passes/tests/test_autotb.cc index 9713ea061..74ee0f5a9 100644 --- a/passes/tests/test_autotb.cc +++ b/passes/tests/test_autotb.cc @@ -92,7 +92,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) f << stringf("end\n"); f << stringf("endtask\n\n"); - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { std::map signal_in; std::map signal_const; @@ -106,7 +106,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) int count_ports = 0; log("Generating test bench for module `%s'.\n", it->first.c_str()); - for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); it2++) { + for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) { RTLIL::Wire *wire = it2->second; if (wire->port_output) { count_ports++; @@ -115,8 +115,8 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) } else if (wire->port_input) { count_ports++; bool is_clksignal = wire->get_bool_attribute("\\gentb_clock"); - for (auto it3 = mod->processes.begin(); it3 != mod->processes.end(); it3++) - for (auto it4 = it3->second->syncs.begin(); it4 != it3->second->syncs.end(); it4++) { + for (auto it3 = mod->processes.begin(); it3 != mod->processes.end(); ++it3) + for (auto it4 = it3->second->syncs.begin(); it4 != it3->second->syncs.end(); ++it4) { if ((*it4)->type == RTLIL::ST0 || (*it4)->type == RTLIL::ST1) continue; RTLIL::SigSpec &signal = (*it4)->signal; @@ -135,7 +135,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) } } f << stringf("%s %s(\n", id(mod->name.str()).c_str(), idy("uut", mod->name.str()).c_str()); - for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); it2++) { + for (auto it2 = mod->wires_.begin(); it2 != mod->wires_.end(); ++it2) { RTLIL::Wire *wire = it2->second; if (wire->port_output || wire->port_input) f << stringf("\t.%s(%s)%s\n", id(wire->name.str()).c_str(), @@ -146,23 +146,23 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) f << stringf("task %s;\n", idy(mod->name.str(), "reset").c_str()); f << stringf("begin\n"); int delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) + for (auto it = signal_in.begin(); it != signal_in.end(); ++it) f << stringf("\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) + for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it) f << stringf("\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { + for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it) { f << stringf("\t#100; %s <= 1;\n", it->first.c_str()); f << stringf("\t#100; %s <= 0;\n", it->first.c_str()); } delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) + for (auto it = signal_in.begin(); it != signal_in.end(); ++it) f << stringf("\t%s <= #%d ~0;\n", it->first.c_str(), ++delay_counter*2); - for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { + for (auto it = signal_clk.begin(); it != signal_clk.end(); ++it) { f << stringf("\t#100; %s <= 1;\n", it->first.c_str()); f << stringf("\t#100; %s <= 0;\n", it->first.c_str()); } delay_counter = 0; - for (auto it = signal_in.begin(); it != signal_in.end(); it++) { + for (auto it = signal_in.begin(); it != signal_in.end(); ++it) { if (signal_const.count(it->first) == 0) continue; f << stringf("\t%s <= #%d 'b%s;\n", it->first.c_str(), ++delay_counter*2, signal_const[it->first].c_str()); @@ -293,7 +293,7 @@ static void autotest(std::ostream &f, RTLIL::Design *design, int num_iter) f << stringf("initial begin\n"); f << stringf("\t// $dumpfile(\"testbench.vcd\");\n"); f << stringf("\t// $dumpvars(0, testbench);\n"); - for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) + for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) if (!it->second->get_bool_attribute("\\gentb_skip")) f << stringf("\t%s;\n", idy(it->first.str(), "test").c_str()); f << stringf("\t$finish;\n");