summaryrefslogtreecommitdiff
path: root/kernel/modtools.h
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-08-01 16:53:15 +0200
committerClifford Wolf <clifford@clifford.at>2014-08-01 17:14:32 +0200
commitd13eb7e0999def2da03eb6ddef805145f7fd9c9a (patch)
treed7634c448a42722357b474926056c10797f1546d /kernel/modtools.h
parent97a17d39e2f0088e02ed8496d905528722115674 (diff)
Added ModIndex helper class, some changes to RTLIL::Monitor
Diffstat (limited to 'kernel/modtools.h')
-rw-r--r--kernel/modtools.h111
1 files changed, 111 insertions, 0 deletions
diff --git a/kernel/modtools.h b/kernel/modtools.h
index 06e96246..09f2ae65 100644
--- a/kernel/modtools.h
+++ b/kernel/modtools.h
@@ -20,9 +20,118 @@
#ifndef MODTOOLS_H
#define MODTOOLS_H
+#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
+YOSYS_NAMESPACE_BEGIN
+
+struct ModIndex : public RTLIL::Monitor
+{
+ struct PortInfo {
+ const RTLIL::Cell* cell;
+ const RTLIL::IdString &port;
+ const int offset;
+
+ PortInfo(RTLIL::Cell* _c, const RTLIL::IdString &_p, int _o) : cell(_c), port(_p), offset(_o) { }
+
+ bool operator<(const PortInfo &other) const {
+ if (cell != other.cell)
+ return cell < other.cell;
+ if (offset != other.offset)
+ return offset < other.offset;
+ return port < other.port;
+ }
+ };
+
+ struct SigBitInfo
+ {
+ bool is_input, is_output;
+ std::set<PortInfo> ports;
+
+ SigBitInfo() : is_input(false), is_output(false) { }
+ };
+
+ SigMap sigmap;
+ RTLIL::Module *module;
+ std::map<RTLIL::SigBit, SigBitInfo> database;
+ bool auto_reload_module;
+
+ void port_add(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &sig)
+ {
+ for (int i = 0; i < SIZE(sig); i++)
+ database[sigmap(sig[i])].ports.insert(PortInfo(cell, port, i));
+ }
+
+ void port_del(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &sig)
+ {
+ for (int i = 0; i < SIZE(sig); i++)
+ database[sigmap(sig[i])].ports.erase(PortInfo(cell, port, i));
+ }
+
+ const SigBitInfo &info(RTLIL::SigBit bit)
+ {
+ return database[sigmap(bit)];
+ }
+
+ void reload_module()
+ {
+ 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++) {
+ if (wire->port_input)
+ database[sigmap(RTLIL::SigBit(wire, i))].is_input = true;
+ if (wire->port_output)
+ database[sigmap(RTLIL::SigBit(wire, i))].is_output = true;
+ }
+ for (auto cell : module->cells())
+ for (auto &conn : cell->connections())
+ port_add(cell, conn.first, conn.second);
+
+ auto_reload_module = false;
+ }
+
+ virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) override
+ {
+ if (auto_reload_module)
+ reload_module();
+
+ port_del(cell, port, old_sig);
+ port_add(cell, port, sig);
+ }
+
+ virtual void notify_connect(RTLIL::Module *mod, const RTLIL::SigSig&)
+ {
+ log_assert(module == mod);
+ auto_reload_module = true;
+ }
+
+ virtual void notify_connect(RTLIL::Module *mod, const std::vector<RTLIL::SigSig>&)
+ {
+ log_assert(module == mod);
+ auto_reload_module = true;
+ }
+
+ virtual void notify_blackout(RTLIL::Module *mod)
+ {
+ log_assert(module == mod);
+ auto_reload_module = true;
+ }
+
+ ModIndex(RTLIL::Module *_m) : module(_m) {
+ auto_reload_module = true;
+ module->monitors.insert(this);
+ }
+
+ ~ModIndex() {
+ module->monitors.erase(this);
+ }
+};
+
struct ModWalker
{
struct PortBit
@@ -295,4 +404,6 @@ struct ModWalker
}
};
+YOSYS_NAMESPACE_END
+
#endif