diff --git a/kernel/log.h b/kernel/log.h
index 0109faf62..9fc83800c 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 06e96246f..09f2ae65e 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 79ddd2e02..137058522 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 43c7e1050..0685f1ea2 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 b691749a8..32ef444aa 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 34800ce8e..671945631 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 119e7e8a6..d9db57c51 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
 
diff --git a/passes/cmds/trace.cc b/passes/cmds/trace.cc
index b4bc45c20..6a5ea346e 100644
--- a/passes/cmds/trace.cc
+++ b/passes/cmds/trace.cc
@@ -34,9 +34,9 @@ struct TraceMonitor : public RTLIL::Monitor
 		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
@@ -44,7 +44,7 @@ struct TraceMonitor : public RTLIL::Monitor
 		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)
diff --git a/passes/memory/memory_share.cc b/passes/memory/memory_share.cc
index fde6ea007..ace6eeaf1 100644
--- a/passes/memory/memory_share.cc
+++ b/passes/memory/memory_share.cc
@@ -735,9 +735,8 @@ struct MemorySharePass : public Pass {
 	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;