aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/modtools.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/modtools.h')
-rw-r--r--kernel/modtools.h194
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);
}
};