diff options
Diffstat (limited to 'kernel/modtools.h')
-rw-r--r-- | kernel/modtools.h | 194 |
1 files changed, 150 insertions, 44 deletions
diff --git a/kernel/modtools.h b/kernel/modtools.h index 58cdd5b0e..69c13bd3b 100644 --- a/kernel/modtools.h +++ b/kernel/modtools.h @@ -33,6 +33,7 @@ struct ModIndex : public RTLIL::Monitor RTLIL::IdString port; int offset; + PortInfo() : cell(), port(), offset() { } PortInfo(RTLIL::Cell* _c, RTLIL::IdString _p, int _o) : cell(_c), port(_p), offset(_o) { } bool operator<(const PortInfo &other) const { @@ -42,24 +43,44 @@ struct ModIndex : public RTLIL::Monitor return offset < other.offset; return port < other.port; } + + bool operator==(const PortInfo &other) const { + return cell == other.cell && port == other.port && offset == other.offset; + } + + unsigned int hash() const { + return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset); + } }; struct SigBitInfo { bool is_input, is_output; - std::set<PortInfo> ports; + pool<PortInfo> ports; SigBitInfo() : is_input(false), is_output(false) { } + + bool operator==(const SigBitInfo &other) const { + return is_input == other.is_input && is_output == other.is_output && ports == other.ports; + } + + void merge(const SigBitInfo &other) + { + is_input = is_input || other.is_input; + is_output = is_output || other.is_output; + ports.insert(other.ports.begin(), other.ports.end()); + } }; SigMap sigmap; RTLIL::Module *module; std::map<RTLIL::SigBit, SigBitInfo> database; + int auto_reload_counter; bool auto_reload_module; void port_add(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig) { - for (int i = 0; i < SIZE(sig); i++) { + for (int i = 0; i < GetSize(sig); i++) { RTLIL::SigBit bit = sigmap(sig[i]); if (bit.wire) database[bit].ports.insert(PortInfo(cell, port, i)); @@ -68,7 +89,7 @@ struct ModIndex : public RTLIL::Monitor void port_del(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig) { - for (int i = 0; i < SIZE(sig); i++) { + for (int i = 0; i < GetSize(sig); i++) { RTLIL::SigBit bit = sigmap(sig[i]); if (bit.wire) database[bit].ports.erase(PortInfo(cell, port, i)); @@ -80,15 +101,17 @@ struct ModIndex : public RTLIL::Monitor return database[sigmap(bit)]; } - void reload_module() + void reload_module(bool reset_sigmap = true) { - sigmap.clear(); - sigmap.set(module); + if (reset_sigmap) { + sigmap.clear(); + sigmap.set(module); + } database.clear(); for (auto wire : module->wires()) if (wire->port_input || wire->port_output) - for (int i = 0; i < SIZE(wire); i++) { + for (int i = 0; i < GetSize(wire); i++) { RTLIL::SigBit bit = sigmap(RTLIL::SigBit(wire, i)); if (bit.wire && wire->port_input) database[bit].is_input = true; @@ -99,31 +122,105 @@ struct ModIndex : public RTLIL::Monitor for (auto &conn : cell->connections()) port_add(cell, conn.first, conn.second); - auto_reload_module = false; + if (auto_reload_module) { + if (++auto_reload_counter > 2) + log_warning("Auto-reload in ModIndex -- possible performance bug!\n"); + auto_reload_module = false; + } } - virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) OVERRIDE + void check() { +#ifndef NDEBUG if (auto_reload_module) - reload_module(); + return; + + for (auto it : database) + log_assert(it.first == sigmap(it.first)); + + auto database_bak = std::move(database); + reload_module(false); + + if (!(database == database_bak)) + { + for (auto &it : database_bak) + if (!database.count(it.first)) + log("ModuleIndex::check(): Only in database_bak, not database: %s\n", log_signal(it.first)); + + for (auto &it : database) + if (!database_bak.count(it.first)) + log("ModuleIndex::check(): Only in database, not database_bak: %s\n", log_signal(it.first)); + else if (!(it.second == database_bak.at(it.first))) + log("ModuleIndex::check(): Different content for database[%s].\n", log_signal(it.first)); + + log_assert(database == database_bak); + } +#endif + } + + virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE + { + log_assert(module == cell->module); + + if (auto_reload_module) + return; port_del(cell, port, old_sig); port_add(cell, port, sig); } - virtual void notify_connect(RTLIL::Module *mod, const RTLIL::SigSig&) + virtual void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const RTLIL::SigSig &sigsig) YS_OVERRIDE { log_assert(module == mod); - auto_reload_module = true; + + if (auto_reload_module) + return; + + for (int i = 0; i < GetSize(sigsig.first); i++) + { + RTLIL::SigBit lhs = sigmap(sigsig.first[i]); + RTLIL::SigBit rhs = sigmap(sigsig.second[i]); + bool has_lhs = database.count(lhs); + bool has_rhs = database.count(rhs); + + if (!has_lhs && !has_rhs) { + sigmap.add(lhs, rhs); + } else + if (!has_rhs) { + SigBitInfo new_info = database.at(lhs); + database.erase(lhs); + sigmap.add(lhs, rhs); + lhs = sigmap(lhs); + if (lhs.wire) + database[lhs] = new_info; + } else + if (!has_lhs) { + SigBitInfo new_info = database.at(rhs); + database.erase(rhs); + sigmap.add(lhs, rhs); + rhs = sigmap(rhs); + if (rhs.wire) + database[rhs] = new_info; + } else { + SigBitInfo new_info = database.at(lhs); + new_info.merge(database.at(rhs)); + database.erase(lhs); + database.erase(rhs); + sigmap.add(lhs, rhs); + rhs = sigmap(rhs); + if (rhs.wire) + database[rhs] = new_info; + } + } } - virtual void notify_connect(RTLIL::Module *mod, const std::vector<RTLIL::SigSig>&) + virtual void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const std::vector<RTLIL::SigSig>&) YS_OVERRIDE { log_assert(module == mod); auto_reload_module = true; } - virtual void notify_blackout(RTLIL::Module *mod) + virtual void notify_blackout(RTLIL::Module *mod YS_ATTRIBUTE(unused)) YS_OVERRIDE { log_assert(module == mod); auto_reload_module = true; @@ -131,6 +228,7 @@ struct ModIndex : public RTLIL::Monitor ModIndex(RTLIL::Module *_m) : module(_m) { + auto_reload_counter = 0; auto_reload_module = true; module->monitors.insert(this); } @@ -168,9 +266,9 @@ struct ModIndex : public RTLIL::Monitor return info->is_output; } - std::set<PortInfo> &query_ports(RTLIL::SigBit bit) + pool<PortInfo> &query_ports(RTLIL::SigBit bit) { - static std::set<PortInfo> empty_result_set; + static pool<PortInfo> empty_result_set; SigBitInfo *info = query(bit); if (info == nullptr) return empty_result_set; @@ -193,6 +291,14 @@ struct ModWalker return port < other.port; return offset < other.offset; } + + bool operator==(const PortBit &other) const { + return cell == other.cell && port == other.port && offset == other.offset; + } + + unsigned int hash() const { + return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset); + } }; RTLIL::Design *design; @@ -201,11 +307,11 @@ struct ModWalker CellTypes ct; SigMap sigmap; - std::map<RTLIL::SigBit, std::set<PortBit>> signal_drivers; - std::map<RTLIL::SigBit, std::set<PortBit>> signal_consumers; - std::set<RTLIL::SigBit> signal_inputs, signal_outputs; + dict<RTLIL::SigBit, pool<PortBit>> signal_drivers; + dict<RTLIL::SigBit, pool<PortBit>> signal_consumers; + pool<RTLIL::SigBit> signal_inputs, signal_outputs; - std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_outputs, cell_inputs; + dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_outputs, cell_inputs; void add_wire(RTLIL::Wire *wire) { @@ -286,11 +392,11 @@ struct ModWalker // get_* methods -- single RTLIL::SigBit template<typename T> - inline bool get_drivers(std::set<PortBit> &result, RTLIL::SigBit bit) const + inline bool get_drivers(pool<PortBit> &result, RTLIL::SigBit bit) const { bool found = false; if (signal_drivers.count(bit)) { - const std::set<PortBit> &r = signal_drivers.at(bit); + const pool<PortBit> &r = signal_drivers.at(bit); result.insert(r.begin(), r.end()); found = true; } @@ -298,11 +404,11 @@ struct ModWalker } template<typename T> - inline bool get_consumers(std::set<PortBit> &result, RTLIL::SigBit bit) const + inline bool get_consumers(pool<PortBit> &result, RTLIL::SigBit bit) const { bool found = false; if (signal_consumers.count(bit)) { - const std::set<PortBit> &r = signal_consumers.at(bit); + const pool<PortBit> &r = signal_consumers.at(bit); result.insert(r.begin(), r.end()); found = true; } @@ -310,7 +416,7 @@ struct ModWalker } template<typename T> - inline bool get_inputs(std::set<RTLIL::SigBit> &result, RTLIL::SigBit bit) const + inline bool get_inputs(pool<RTLIL::SigBit> &result, RTLIL::SigBit bit) const { bool found = false; if (signal_inputs.count(bit)) @@ -319,7 +425,7 @@ struct ModWalker } template<typename T> - inline bool get_outputs(std::set<RTLIL::SigBit> &result, RTLIL::SigBit bit) const + inline bool get_outputs(pool<RTLIL::SigBit> &result, RTLIL::SigBit bit) const { bool found = false; if (signal_outputs.count(bit)) @@ -330,12 +436,12 @@ struct ModWalker // get_* methods -- container of RTLIL::SigBit's (always by reference) template<typename T> - inline bool get_drivers(std::set<PortBit> &result, const T &bits) const + inline bool get_drivers(pool<PortBit> &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) if (signal_drivers.count(bit)) { - const std::set<PortBit> &r = signal_drivers.at(bit); + const pool<PortBit> &r = signal_drivers.at(bit); result.insert(r.begin(), r.end()); found = true; } @@ -343,12 +449,12 @@ struct ModWalker } template<typename T> - inline bool get_consumers(std::set<PortBit> &result, const T &bits) const + inline bool get_consumers(pool<PortBit> &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) if (signal_consumers.count(bit)) { - const std::set<PortBit> &r = signal_consumers.at(bit); + const pool<PortBit> &r = signal_consumers.at(bit); result.insert(r.begin(), r.end()); found = true; } @@ -356,7 +462,7 @@ struct ModWalker } template<typename T> - inline bool get_inputs(std::set<RTLIL::SigBit> &result, const T &bits) const + inline bool get_inputs(pool<RTLIL::SigBit> &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) @@ -366,7 +472,7 @@ struct ModWalker } template<typename T> - inline bool get_outputs(std::set<RTLIL::SigBit> &result, const T &bits) const + inline bool get_outputs(pool<RTLIL::SigBit> &result, const T &bits) const { bool found = false; for (RTLIL::SigBit bit : bits) @@ -377,25 +483,25 @@ struct ModWalker // get_* methods -- call by RTLIL::SigSpec (always by value) - bool get_drivers(std::set<PortBit> &result, RTLIL::SigSpec signal) const + bool get_drivers(pool<PortBit> &result, RTLIL::SigSpec signal) const { std::vector<RTLIL::SigBit> bits = sigmap(signal); return get_drivers(result, bits); } - bool get_consumers(std::set<PortBit> &result, RTLIL::SigSpec signal) const + bool get_consumers(pool<PortBit> &result, RTLIL::SigSpec signal) const { std::vector<RTLIL::SigBit> bits = sigmap(signal); return get_consumers(result, bits); } - bool get_inputs(std::set<RTLIL::SigBit> &result, RTLIL::SigSpec signal) const + bool get_inputs(pool<RTLIL::SigBit> &result, RTLIL::SigSpec signal) const { std::vector<RTLIL::SigBit> bits = sigmap(signal); return get_inputs(result, bits); } - bool get_outputs(std::set<RTLIL::SigBit> &result, RTLIL::SigSpec signal) const + bool get_outputs(pool<RTLIL::SigBit> &result, RTLIL::SigSpec signal) const { std::vector<RTLIL::SigBit> bits = sigmap(signal); return get_outputs(result, bits); @@ -405,47 +511,47 @@ struct ModWalker template<typename T> inline bool has_drivers(const T &sig) const { - std::set<PortBit> result; + pool<PortBit> result; return get_drivers(result, sig); } template<typename T> inline bool has_consumers(const T &sig) const { - std::set<PortBit> result; + pool<PortBit> result; return get_consumers(result, sig); } template<typename T> inline bool has_inputs(const T &sig) const { - std::set<RTLIL::SigBit> result; + pool<RTLIL::SigBit> result; return get_inputs(result, sig); } template<typename T> inline bool has_outputs(const T &sig) const { - std::set<RTLIL::SigBit> result; + pool<RTLIL::SigBit> result; return get_outputs(result, sig); } // has_* methods -- call by value inline bool has_drivers(RTLIL::SigSpec sig) const { - std::set<PortBit> result; + pool<PortBit> result; return get_drivers(result, sig); } inline bool has_consumers(RTLIL::SigSpec sig) const { - std::set<PortBit> result; + pool<PortBit> result; return get_consumers(result, sig); } inline bool has_inputs(RTLIL::SigSpec sig) const { - std::set<RTLIL::SigBit> result; + pool<RTLIL::SigBit> result; return get_inputs(result, sig); } inline bool has_outputs(RTLIL::SigSpec sig) const { - std::set<RTLIL::SigBit> result; + pool<RTLIL::SigBit> result; return get_outputs(result, sig); } }; |