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);
#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
}
};
+YOSYS_NAMESPACE_END
+
#endif
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;
}
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
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*) { }
};
{
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);
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
return string;
}
+int SIZE(RTLIL::Wire *wire)
+{
+ return wire->width;
+}
+
void yosys_setup()
{
Pass::init_register();
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
log("#TRACE# Module delete: %s\n", log_id(module));
}
- virtual void notify_cell_connect(RTLIL::Cell *cell, const std::pair<RTLIL::IdString, RTLIL::SigSpec> &conn) override
+ virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) override
{
- log("#TRACE# Cell connect: %s.%s.%s = %s\n", log_id(cell->module), log_id(cell), log_id(conn.first), log_signal(conn.second));
+ log("#TRACE# Cell connect: %s.%s.%s = %s (was: %s)\n", log_id(cell->module), log_id(cell), log_id(port), log_signal(sig), log_signal(old_sig));
}
virtual void notify_connect(RTLIL::Module *module, const RTLIL::SigSig &sigsig) override
log("#TRACE# Connection in module %s: %s = %s\n", log_id(module), log_signal(sigsig.first), log_signal(sigsig.second));
}
- virtual void notify_new_connections(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) override
+ virtual void notify_connect(RTLIL::Module *module, const std::vector<RTLIL::SigSig> &sigsig_vec) override
{
log("#TRACE# New connections in module %s:\n", log_id(module));
for (auto &sigsig : sigsig_vec)
virtual void execute(std::vector<std::string> args, RTLIL::Design *design) {
log_header("Executing MEMORY_SHARE pass (consolidating $memrc/$memwr cells).\n");
extra_args(args, 1, design);
- for (auto &mod_it : design->modules_)
- if (design->selected(mod_it.second))
- MemoryShareWorker(design, mod_it.second);
+ for (auto module : design->selected_modules())
+ MemoryShareWorker(design, module);
}
} MemorySharePass;