From 865df26facfe26edc2238d1294d67277dbff7210 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik@cutebit.org>
Date: Tue, 21 May 2024 13:08:40 +0200
Subject: [PATCH] Adjust buf-normalized mode

---
 backends/rtlil/rtlil_backend.cc | 26 ++++++++++------------
 backends/rtlil/rtlil_backend.h  |  6 +++---
 kernel/celledges.cc             |  2 +-
 kernel/rtlil.cc                 | 38 +++++++++++++++++++--------------
 kernel/rtlil.h                  | 14 ++++++++++--
 5 files changed, 49 insertions(+), 37 deletions(-)

diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc
index e6f8daf96..ddc4769f6 100644
--- a/backends/rtlil/rtlil_backend.cc
+++ b/backends/rtlil/rtlil_backend.cc
@@ -118,16 +118,16 @@ void RTLIL_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, boo
 	}
 }
 
-void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, bool flag_d)
+void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire)
 {
 	for (auto &it : wire->attributes) {
 		f << stringf("%s" "attribute %s ", indent.c_str(), it.first.c_str());
 		dump_const(f, it.second);
 		f << stringf("\n");
 	}
-	if (flag_d && wire->driverCell) {
-		f << stringf("%s" "driver %s %s\n", indent.c_str(),
-				wire->driverCell->name.c_str(), wire->driverPort.c_str());
+	if (wire->driverCell_) {
+		f << stringf("%s" "# driver %s %s\n", indent.c_str(),
+				wire->driverCell()->name.c_str(), wire->driverPort().c_str());
 	}
 	f << stringf("%s" "wire ", indent.c_str());
 	if (wire->width != 1)
@@ -302,7 +302,7 @@ void RTLIL_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::
 	f << stringf("\n");
 }
 
-void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n, bool flag_d)
+void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
 {
 	bool print_header = flag_m || design->selected_whole_module(module->name);
 	bool print_body = !flag_n || !design->selected_whole_module(module->name);
@@ -339,7 +339,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
 			if (!only_selected || design->selected(module, it)) {
 				if (only_selected)
 					f << stringf("\n");
-				dump_wire(f, indent + "  ", it, flag_d);
+				dump_wire(f, indent + "  ", it);
 			}
 
 		for (auto it : module->memories)
@@ -388,7 +388,7 @@ void RTLIL_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Modu
 		f << stringf("%s" "end\n", indent.c_str());
 }
 
-void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n, bool flag_d)
+void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n)
 {
 	int init_autoidx = autoidx;
 
@@ -414,7 +414,7 @@ void RTLIL_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool onl
 		if (!only_selected || design->selected(module)) {
 			if (only_selected)
 				f << stringf("\n");
-			dump_module(f, "", module, design, only_selected, flag_m, flag_n, flag_d);
+			dump_module(f, "", module, design, only_selected, flag_m, flag_n);
 		}
 	}
 
@@ -460,7 +460,7 @@ struct RTLILBackend : public Backend {
 
 		log("Output filename: %s\n", filename.c_str());
 		*f << stringf("# Generated by %s\n", yosys_version_str);
-		RTLIL_BACKEND::dump_design(*f, design, selected, true, false, false);
+		RTLIL_BACKEND::dump_design(*f, design, selected, true, false);
 	}
 } RTLILBackend;
 
@@ -510,7 +510,7 @@ struct DumpPass : public Pass {
 	void execute(std::vector<std::string> args, RTLIL::Design *design) override
 	{
 		std::string filename;
-		bool flag_m = false, flag_n = false, flag_d = false, append = false;
+		bool flag_m = false, flag_n = false, append = false;
 
 		size_t argidx;
 		for (argidx = 1; argidx < args.size(); argidx++)
@@ -534,10 +534,6 @@ struct DumpPass : public Pass {
 				flag_n = true;
 				continue;
 			}
-			if (arg == "-d") {
-				flag_d = true;
-				continue;
-			}
 			break;
 		}
 		extra_args(args, argidx, design);
@@ -559,7 +555,7 @@ struct DumpPass : public Pass {
 			f = &buf;
 		}
 
-		RTLIL_BACKEND::dump_design(*f, design, true, flag_m, flag_n, flag_d);
+		RTLIL_BACKEND::dump_design(*f, design, true, flag_m, flag_n);
 
 		if (!empty) {
 			delete f;
diff --git a/backends/rtlil/rtlil_backend.h b/backends/rtlil/rtlil_backend.h
index 21d79d8ec..35829729c 100644
--- a/backends/rtlil/rtlil_backend.h
+++ b/backends/rtlil/rtlil_backend.h
@@ -34,7 +34,7 @@ namespace RTLIL_BACKEND {
 	void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true);
 	void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true);
 	void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true);
-	void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire, bool flag_d = false);
+	void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
 	void dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory);
 	void dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell);
 	void dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs);
@@ -42,8 +42,8 @@ namespace RTLIL_BACKEND {
 	void dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy);
 	void dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc);
 	void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right);
-	void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false, bool flag_d = false);
-	void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false, bool flag_d = false);
+	void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false);
+	void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false);
 }
 
 YOSYS_NAMESPACE_END
diff --git a/kernel/celledges.cc b/kernel/celledges.cc
index 0fbe17c56..bad7124d9 100644
--- a/kernel/celledges.cc
+++ b/kernel/celledges.cc
@@ -24,7 +24,7 @@ PRIVATE_NAMESPACE_BEGIN
 
 void bitwise_unary_op(AbstractCellEdgesDatabase *db, RTLIL::Cell *cell)
 {
-	bool is_signed = cell->getParam(ID::A_SIGNED).as_bool();
+	bool is_signed = (cell->type != ID($buf)) && cell->getParam(ID::A_SIGNED).as_bool();
 	int a_width = GetSize(cell->getPort(ID::A));
 	int y_width = GetSize(cell->getPort(ID::Y));
 
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index eaba0fe31..2d3135378 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -3575,10 +3575,12 @@ void RTLIL::Design::bufNormalize(bool enable)
 		for (auto module : modules()) {
 			module->bufNormQueue.clear();
 			for (auto wire : module->wires()) {
-				wire->driverCell = nullptr;
-				wire->driverPort = IdString();
+				wire->driverCell_ = nullptr;
+				wire->driverPort_ = IdString();
 			}
 		}
+
+		flagBufferedNormalized = false;
 		return;
 	}
 
@@ -3592,9 +3594,9 @@ void RTLIL::Design::bufNormalize(bool enable)
 					continue;
 				if (conn.second.is_wire()) {
 					Wire *wire = conn.second.as_wire();
-					log_assert(wire->driverCell == nullptr);
-					wire->driverCell = cell;
-					wire->driverPort = conn.first;
+					log_assert(wire->driverCell_ == nullptr);
+					wire->driverCell_ = cell;
+					wire->driverPort_ = conn.first;
 				} else {
 					pair<RTLIL::Cell*, RTLIL::IdString> key(cell, conn.first);
 					module->bufNormQueue.insert(key);
@@ -3614,7 +3616,7 @@ void RTLIL::Module::bufNormalize()
 	if (!design->flagBufferedNormalized)
 		return;
 
-	while (GetSize(bufNormQueue))
+	while (GetSize(bufNormQueue) || !connections_.empty())
 	{
 		pool<pair<RTLIL::Cell*, RTLIL::IdString>> queue;
 		bufNormQueue.swap(queue);
@@ -3636,9 +3638,13 @@ void RTLIL::Module::bufNormalize()
 
 			if (sig.is_wire()) {
 				Wire *wire = sig.as_wire();
-				log_assert(wire->driverCell == nullptr);
-				wire->driverCell = cell;
-				wire->driverPort = portname;
+				if (wire->driverCell_) {
+					log_error("Conflict between %s %s in module %s\n",
+										log_id(cell), log_id(wire->driverCell_), log_id(this));
+				}
+				log_assert(wire->driverCell_ == nullptr);
+				wire->driverCell_ = cell;
+				wire->driverPort_ = portname;
 				continue;
 			}
 
@@ -3688,9 +3694,9 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal
 
 		if (conn_it->second.is_wire()) {
 			Wire *w = conn_it->second.as_wire();
-			if (w->driverCell == this && w->driverPort == portname) {
-				w->driverCell = nullptr;
-				w->driverPort = IdString();
+			if (w->driverCell_ == this && w->driverPort_ == portname) {
+				w->driverCell_ = nullptr;
+				w->driverPort_ = IdString();
 			}
 		}
 
@@ -3705,12 +3711,12 @@ void RTLIL::Cell::setPort(const RTLIL::IdString& portname, RTLIL::SigSpec signal
 		}
 
 		Wire *w = signal.as_wire();
-		if (w->driverCell != nullptr) {
-			pair<RTLIL::Cell*, RTLIL::IdString> other_key(w->driverCell, w->driverPort);
+		if (w->driverCell_ != nullptr) {
+			pair<RTLIL::Cell*, RTLIL::IdString> other_key(w->driverCell_, w->driverPort_);
 			module->bufNormQueue.insert(other_key);
 		}
-		w->driverCell = this;
-		w->driverPort = portname;
+		w->driverCell_ = this;
+		w->driverPort_ = portname;
 
 		module->bufNormQueue.erase(key);
 		break;
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index 3e4c92af3..c49734cd0 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -1510,6 +1510,10 @@ public:
 #endif
 };
 
+namespace RTLIL_BACKEND {
+void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
+}
+
 struct RTLIL::Wire : public RTLIL::AttrObject
 {
 	unsigned int hashidx_;
@@ -1521,6 +1525,12 @@ protected:
 	Wire();
 	~Wire();
 
+	friend struct RTLIL::Design;
+	friend struct RTLIL::Cell;
+	friend void RTLIL_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire);
+	RTLIL::Cell *driverCell_ = nullptr;
+	RTLIL::IdString driverPort_;
+
 public:
 	// do not simply copy wires
 	Wire(RTLIL::Wire &other) = delete;
@@ -1531,8 +1541,8 @@ public:
 	int width, start_offset, port_id;
 	bool port_input, port_output, upto, is_signed;
 
-	RTLIL::Cell *driverCell = nullptr;
-	RTLIL::IdString driverPort;
+	RTLIL::Cell *driverCell() const    { log_assert(driverCell_); return driverCell_; };
+	RTLIL::IdString driverPort() const { log_assert(driverCell_); return driverPort_; };
 
 #ifdef WITH_PYTHON
 	static std::map<unsigned int, RTLIL::Wire*> *get_all_wires(void);