summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/log.h5
-rw-r--r--kernel/modtools.h111
-rw-r--r--kernel/rtlil.cc36
-rw-r--r--kernel/rtlil.h10
-rw-r--r--kernel/sigtools.h13
-rw-r--r--kernel/yosys.cc5
-rw-r--r--kernel/yosys.h9
7 files changed, 165 insertions, 24 deletions
diff --git a/kernel/log.h b/kernel/log.h
index 0109faf6..9fc83800 100644
--- a/kernel/log.h
+++ b/kernel/log.h
@@ -57,11 +57,6 @@ void log_pop();
void log_reset_stack();
void log_flush();
-namespace RTLIL {
- struct SigSpec;
- struct Cell;
-}
-
const char *log_signal(const RTLIL::SigSpec &sig, bool autoint = true);
const char *log_id(std::string id);
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
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 79ddd2e0..13705852 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -1092,11 +1092,11 @@ void RTLIL::Module::connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs
void RTLIL::Module::new_connections(const std::vector<RTLIL::SigSig> &new_conn)
{
for (auto mon : monitors)
- mon->notify_new_connections(this, new_conn);
+ mon->notify_connect(this, new_conn);
if (design)
for (auto mon : design->monitors)
- mon->notify_new_connections(this, new_conn);
+ mon->notify_connect(this, new_conn);
connections_ = new_conn;
}
@@ -1516,30 +1516,40 @@ bool RTLIL::Cell::hasPort(RTLIL::IdString portname) const
void RTLIL::Cell::unsetPort(RTLIL::IdString portname)
{
- std::pair<RTLIL::IdString, RTLIL::SigSpec> new_conn(portname, RTLIL::SigSpec());
+ RTLIL::SigSpec signal;
+ auto conn_it = connections_.find(portname);
- for (auto mon : module->monitors)
- mon->notify_cell_connect(this, new_conn);
+ if (conn_it != connections_.end())
+ {
+ for (auto mon : module->monitors)
+ mon->notify_connect(this, conn_it->first, conn_it->second, signal);
- if (module->design)
- for (auto mon : module->design->monitors)
- mon->notify_cell_connect(this, new_conn);
+ if (module->design)
+ for (auto mon : module->design->monitors)
+ mon->notify_connect(this, conn_it->first, conn_it->second, signal);
- connections_.erase(portname);
+ connections_.erase(conn_it);
+ }
}
void RTLIL::Cell::setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
{
- std::pair<RTLIL::IdString, RTLIL::SigSpec> new_conn(portname, signal);
+ auto conn_it = connections_.find(portname);
+
+ if (conn_it == connections_.end()) {
+ connections_[portname] = RTLIL::SigSpec();
+ conn_it = connections_.find(portname);
+ log_assert(conn_it != connections_.end());
+ }
for (auto mon : module->monitors)
- mon->notify_cell_connect(this, new_conn);
+ mon->notify_connect(this, conn_it->first, conn_it->second, signal);
if (module->design)
for (auto mon : module->design->monitors)
- mon->notify_cell_connect(this, new_conn);
+ mon->notify_connect(this, conn_it->first, conn_it->second, signal);
- connections_[portname] = signal;
+ conn_it->second = signal;
}
const RTLIL::SigSpec &RTLIL::Cell::getPort(RTLIL::IdString portname) const
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 43c7e105..0685f1ea 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -334,9 +334,9 @@ struct RTLIL::Monitor
virtual ~Monitor() { }
virtual void notify_module_add(RTLIL::Module*) { }
virtual void notify_module_del(RTLIL::Module*) { }
- virtual void notify_cell_connect(RTLIL::Cell*, const std::pair<RTLIL::IdString, RTLIL::SigSpec>&) { }
+ virtual void notify_connect(RTLIL::Cell*, const RTLIL::IdString&, const RTLIL::SigSpec&, RTLIL::SigSpec&) { }
virtual void notify_connect(RTLIL::Module*, const RTLIL::SigSig&) { }
- virtual void notify_new_connections(RTLIL::Module*, const std::vector<RTLIL::SigSig>&) { }
+ virtual void notify_connect(RTLIL::Module*, const std::vector<RTLIL::SigSig>&) { }
virtual void notify_blackout(RTLIL::Module*) { }
};
@@ -708,15 +708,15 @@ struct RTLIL::SigBit
{
RTLIL::Wire *wire;
union {
- RTLIL::State data;
- int offset;
+ RTLIL::State data; // used if wire == NULL
+ int offset; // used if wire != NULL
};
SigBit() : wire(NULL), data(RTLIL::State::S0) { }
SigBit(RTLIL::State bit) : wire(NULL), data(bit) { }
SigBit(RTLIL::Wire *wire) : wire(wire), data(RTLIL::State::S0) { log_assert(wire && wire->width == 1); }
SigBit(RTLIL::Wire *wire, int offset) : wire(wire), offset(offset) { log_assert(wire); }
- SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { if (wire) offset = chunk.offset; else data = chunk.data.bits[0]; log_assert(chunk.width == 1); }
+ SigBit(const RTLIL::SigChunk &chunk) : wire(chunk.wire) { log_assert(chunk.width == 1); if (wire) offset = chunk.offset; else data = chunk.data.bits[0]; }
SigBit(const RTLIL::SigChunk &chunk, int index) : wire(chunk.wire) { if (wire) offset = chunk.offset + index; else data = chunk.data.bits[index]; }
SigBit(const RTLIL::SigSpec &sig);
diff --git a/kernel/sigtools.h b/kernel/sigtools.h
index b691749a..32ef444a 100644
--- a/kernel/sigtools.h
+++ b/kernel/sigtools.h
@@ -391,11 +391,24 @@ struct SigMap
map_bit(bit);
}
+ RTLIL::SigBit operator()(RTLIL::SigBit bit) const
+ {
+ apply(bit);
+ return bit;
+ }
+
RTLIL::SigSpec operator()(RTLIL::SigSpec sig) const
{
apply(sig);
return sig;
}
+
+ RTLIL::SigSpec operator()(RTLIL::Wire *wire) const
+ {
+ RTLIL::SigSpec sig(wire);
+ apply(sig);
+ return sig;
+ }
};
YOSYS_NAMESPACE_END
diff --git a/kernel/yosys.cc b/kernel/yosys.cc
index 34800ce8..67194563 100644
--- a/kernel/yosys.cc
+++ b/kernel/yosys.cc
@@ -53,6 +53,11 @@ std::string stringf(const char *fmt, ...)
return string;
}
+int SIZE(RTLIL::Wire *wire)
+{
+ return wire->width;
+}
+
void yosys_setup()
{
Pass::init_register();
diff --git a/kernel/yosys.h b/kernel/yosys.h
index 119e7e8a..d9db57c5 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -61,8 +61,15 @@
YOSYS_NAMESPACE_BEGIN
+namespace RTLIL {
+ struct SigSpec;
+ struct Wire;
+ struct Cell;
+}
+
std::string stringf(const char *fmt, ...);
-#define SIZE(__obj) int(__obj.size())
+template<typename T> int SIZE(const T &obj) { return obj.size(); }
+int SIZE(RTLIL::Wire *wire);
YOSYS_NAMESPACE_END