From 7dc0439de426483013a445122643e930b0bd0fa2 Mon Sep 17 00:00:00 2001
From: Dan Ravensloft <dan.ravensloft@gmail.com>
Date: Sat, 4 Jul 2020 21:20:26 +0100
Subject: [PATCH] sf2: replace sf2_iobs with {clkbuf,iopad}map

---
 techlibs/sf2/Makefile.inc |   1 -
 techlibs/sf2/cells_sim.v  | 141 ++++++++++++++++++++++++---
 techlibs/sf2/sf2_iobs.cc  | 197 --------------------------------------
 techlibs/sf2/synth_sf2.cc |  10 +-
 4 files changed, 135 insertions(+), 214 deletions(-)
 delete mode 100644 techlibs/sf2/sf2_iobs.cc

diff --git a/techlibs/sf2/Makefile.inc b/techlibs/sf2/Makefile.inc
index cc3054ace..cade49f37 100644
--- a/techlibs/sf2/Makefile.inc
+++ b/techlibs/sf2/Makefile.inc
@@ -1,6 +1,5 @@
 
 OBJS += techlibs/sf2/synth_sf2.o
-OBJS += techlibs/sf2/sf2_iobs.o
 
 $(eval $(call add_share_file,share/sf2,techlibs/sf2/arith_map.v))
 $(eval $(call add_share_file,share/sf2,techlibs/sf2/cells_map.v))
diff --git a/techlibs/sf2/cells_sim.v b/techlibs/sf2/cells_sim.v
index c62748b11..eff57a655 100644
--- a/techlibs/sf2/cells_sim.v
+++ b/techlibs/sf2/cells_sim.v
@@ -1,7 +1,6 @@
 // https://coredocs.s3.amazonaws.com/Libero/12_0_0/Tool/sf2_mlg.pdf
 
 module ADD2 (
-
 	input A, B,
 	output Y
 );
@@ -76,6 +75,7 @@ endmodule
 
 module CLKINT (
 	input A,
+	(* clkbuf_driver *)
 	output Y
 );
 	assign Y = A;
@@ -83,6 +83,7 @@ endmodule
 
 module CLKINT_PRESERVE (
 	input A,
+	(* clkbuf_driver *)
 	output Y
 );
 	assign Y = A;
@@ -90,6 +91,7 @@ endmodule
 
 module GCLKINT (
 	input A, EN,
+	(* clkbuf_driver *)
 	output Y
 );
 	assign Y = A & EN;
@@ -97,6 +99,7 @@ endmodule
 
 module RCLKINT (
 	input A,
+	(* clkbuf_driver *)
 	output Y
 );
 	assign Y = A;
@@ -104,6 +107,7 @@ endmodule
 
 module RGCLKINT (
 	input A, EN,
+	(* clkbuf_driver *)
 	output Y
 );
 	assign Y = A & EN;
@@ -113,6 +117,7 @@ module SLE (
 	output Q,
 	input ADn,
 	input ALn,
+	(* clkbuf_sink *)
 	input CLK,
 	input D,
 	input LAT,
@@ -155,9 +160,41 @@ endmodule
 // module SYSRESET
 // module SYSCTRL_RESET_STATUS
 // module LIVE_PROBE_FB
-// module GCLKBUF
-// module GCLKBUF_DIFF
-// module GCLKBIBUF
+
+(* blackbox *)
+module GCLKBUF (
+	(* iopad_external_pin *)
+	input PAD,
+	input EN,
+	(* clkbuf_driver *)
+	output Y
+);
+endmodule
+
+(* blackbox *)
+module GCLKBUF_DIFF (
+	(* iopad_external_pin *)
+	input PADP,
+	(* iopad_external_pin *)
+	input PADN,
+	input EN,
+	(* clkbuf_driver *)
+	output Y
+);
+endmodule
+
+(* blackbox *)
+module GCLKBIBUF (
+	input D,
+	input E,
+	input EN,
+	(* iopad_external_pin *)
+	inout PAD,
+	(* clkbuf_driver *)
+	output Y
+);
+endmodule
+
 // module DFN1
 // module DFN1C0
 // module DFN1E1
@@ -288,38 +325,118 @@ module XOR8 (
 endmodule
 
 // module UJTAG
-// module BIBUF
-// module BIBUF_DIFF
-// module CLKBIBUF
+
+module BIBUF (
+	input D,
+	input E,
+	(* iopad_external_pin *)
+	inout PAD,
+	output Y
+);
+	assign PAD = E ? D : 1'bz;
+	assign Y = PAD;
+endmodule
+
+(* blackbox *)
+module BIBUF_DIFF (
+	input D,
+	input E,
+	(* iopad_external_pin *)
+	inout PADP,
+	(* iopad_external_pin *)
+	inout PADN,
+	output Y
+);
+endmodule
+
+module CLKBIBUF (
+	input D,
+	input E,
+	(* iopad_external_pin *)
+	inout PAD,
+	(* clkbuf_driver *)
+	output Y
+);
+	assign PAD = E ? D : 1'bz;
+	assign Y = PAD;
+endmodule
 
 module CLKBUF (
+	(* iopad_external_pin *)
 	input PAD,
+	(* clkbuf_driver *)
 	output Y
 );
 	assign Y = PAD;
 endmodule
 
-// module CLKBUF_DIFF
+(* blackbox *)
+module CLKBUF_DIFF (
+	(* iopad_external_pin *)
+	input PADP,
+	(* iopad_external_pin *)
+	input PADN,
+	(* clkbuf_driver *)
+	output Y
+);
+endmodule
 
 module INBUF (
+	(* iopad_external_pin *)
 	input PAD,
 	output Y
 );
 	assign Y = PAD;
 endmodule
 
-// module INBUF_DIFF
+(* blackbox *)
+module INBUF_DIFF (
+	(* iopad_external_pin *)
+	input PADP,
+	(* iopad_external_pin *)
+	input PADN,
+	output Y
+);
+endmodule
 
 module OUTBUF (
 	input D,
+	(* iopad_external_pin *)
 	output PAD
 );
 	assign PAD = D;
 endmodule
 
-// module OUTBUF_DIFF
-// module TRIBUFF
-// module TRIBUFF_DIFF
+(* blackbox *)
+module OUTBUF_DIFF (
+	input D,
+	(* iopad_external_pin *)
+	output PADP,
+	(* iopad_external_pin *)
+	output PADN
+);
+endmodule
+
+module TRIBUFF (
+	input D,
+	input E,
+	(* iopad_external_pin *)
+	output PAD
+);
+	assign PAD = E ? D : 1'bz;
+endmodule
+
+(* blackbox *)
+module TRIBUFF_DIFF (
+	input D,
+	input E,
+	(* iopad_external_pin *)
+	output PADP,
+	(* iopad_external_pin *)
+	output PADN
+);
+endmodule
+
 // module DDR_IN
 // module DDR_OUT
 // module RAM1K18
diff --git a/techlibs/sf2/sf2_iobs.cc b/techlibs/sf2/sf2_iobs.cc
deleted file mode 100644
index 5fd719ce5..000000000
--- a/techlibs/sf2/sf2_iobs.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- *  yosys -- Yosys Open SYnthesis Suite
- *
- *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *
- *  Permission to use, copy, modify, and/or distribute this software for any
- *  purpose with or without fee is hereby granted, provided that the above
- *  copyright notice and this permission notice appear in all copies.
- *
- *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-#include "kernel/yosys.h"
-#include "kernel/sigtools.h"
-
-USING_YOSYS_NAMESPACE
-PRIVATE_NAMESPACE_BEGIN
-
-static void handle_iobufs(Module *module, bool clkbuf_mode)
-{
-	SigMap sigmap(module);
-
-	pool<SigBit> clk_bits;
-	pool<SigBit> handled_io_bits;
-	dict<SigBit, SigBit> rewrite_bits;
-	vector<pair<Cell*, SigBit>> pad_bits;
-
-	for (auto cell : module->cells())
-	{
-		if (clkbuf_mode && cell->type == ID(SLE)) {
-			for (auto bit : sigmap(cell->getPort(ID::CLK)))
-				clk_bits.insert(bit);
-		}
-		if (cell->type.in(ID(INBUF), ID(OUTBUF), ID(TRIBUFF), ID(BIBUF), ID(CLKBUF), ID(CLKBIBUF),
-				ID(INBUF_DIFF), ID(OUTBUF_DIFF), ID(BIBUFF_DIFF), ID(TRIBUFF_DIFF), ID(CLKBUF_DIFF),
-				ID(GCLKBUF), ID(GCLKBUF_DIFF), ID(GCLKBIBUF))) {
-			for (auto bit : sigmap(cell->getPort(ID(PAD))))
-				handled_io_bits.insert(bit);
-		}
-	}
-
-	for (auto wire : vector<Wire*>(module->wires()))
-	{
-		if (!wire->port_input && !wire->port_output)
-			continue;
-
-		for (int index = 0; index < GetSize(wire); index++)
-		{
-			SigBit bit(wire, index);
-			SigBit canonical_bit = sigmap(bit);
-
-			if (handled_io_bits.count(canonical_bit))
-				continue;
-
-			if (wire->port_input && wire->port_output)
-				log_error("Failed to add buffer for inout port bit %s.\n", log_signal(bit));
-
-			IdString buf_type, buf_port;
-
-			if (wire->port_output) {
-				buf_type = ID(OUTBUF);
-				buf_port = ID::D;
-			} else if (clkbuf_mode && clk_bits.count(canonical_bit)) {
-				buf_type = ID(CLKBUF);
-				buf_port = ID::Y;
-			} else {
-				buf_type = ID(INBUF);
-				buf_port = ID::Y;
-			}
-
-			Cell *c = module->addCell(NEW_ID, buf_type);
-			SigBit new_bit = module->addWire(NEW_ID);
-			c->setPort(buf_port, new_bit);
-			pad_bits.push_back(make_pair(c, bit));
-			rewrite_bits[canonical_bit] = new_bit;
-
-			log("Added %s cell %s for port bit %s.\n", log_id(c->type), log_id(c), log_signal(bit));
-		}
-	}
-
-	auto rewrite_function = [&](SigSpec &s) {
-		for (auto &bit : s) {
-			SigBit canonical_bit = sigmap(bit);
-			if (rewrite_bits.count(canonical_bit))
-				bit = rewrite_bits.at(canonical_bit);
-		}
-	};
-
-	module->rewrite_sigspecs(rewrite_function);
-
-	for (auto &it : pad_bits)
-		it.first->setPort(ID(PAD), it.second);
-}
-
-static void handle_clkint(Module *module)
-{
-	SigMap sigmap(module);
-
-	pool<SigBit> clk_bits;
-	vector<SigBit> handled_clk_bits;
-
-	for (auto cell : module->cells())
-	{
-		if (cell->type == ID(SLE)) {
-			for (auto bit : sigmap(cell->getPort(ID::CLK)))
-				clk_bits.insert(bit);
-		}
-		if (cell->type.in(ID(CLKBUF), ID(CLKBIBUF), ID(CLKBUF_DIFF), ID(GCLKBUF), ID(GCLKBUF_DIFF), ID(GCLKBIBUF),
-				ID(CLKINT), ID(CLKINT_PRESERVE), ID(GCLKINT), ID(RCLKINT), ID(RGCLKINT))) {
-			for (auto bit : sigmap(cell->getPort(ID::Y)))
-				handled_clk_bits.push_back(bit);
-		}
-	}
-
-	for (auto bit : handled_clk_bits)
-		clk_bits.erase(bit);
-
-	for (auto cell : vector<Cell*>(module->cells()))
-	for (auto &conn : cell->connections())
-	{
-		if (!cell->output(conn.first))
-			continue;
-
-		SigSpec sig = conn.second;
-		bool did_something = false;
-
-		for (auto &bit : sig) {
-			SigBit canonical_bit = sigmap(bit);
-			if (clk_bits.count(canonical_bit)) {
-				Cell *c = module->addCell(NEW_ID, ID(CLKINT));
-				SigBit new_bit = module->addWire(NEW_ID);
-				c->setPort(ID::A, new_bit);
-				c->setPort(ID::Y, bit);
-				log("Added %s cell %s for clock signal %s.\n", log_id(c->type), log_id(c), log_signal(bit));
-				clk_bits.erase(canonical_bit);
-				did_something = true;
-				bit = new_bit;
-			}
-		}
-
-		if (did_something)
-			cell->setPort(conn.first, sig);
-	}
-
-	for (auto bit : clk_bits)
-		log_error("Failed to insert CLKINT for clock signal %s.\n", log_signal(bit));
-}
-
-struct Sf2IobsPass : public Pass {
-	Sf2IobsPass() : Pass("sf2_iobs", "SF2: insert IO buffers") { }
-	void help() override
-	{
-		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
-		log("\n");
-		log("    sf2_iobs [options] [selection]\n");
-		log("\n");
-		log("Add SF2 I/O buffers and global buffers to top module as needed.\n");
-		log("\n");
-		log("    -clkbuf\n");
-		log("        Insert PAD->global_net clock buffers\n");
-		log("\n");
-	}
-	void execute(std::vector<std::string> args, RTLIL::Design *design) override
-	{
-		bool clkbuf_mode = false;
-
-		log_header(design, "Executing sf2_iobs pass (insert IO buffers).\n");
-
-		size_t argidx;
-		for (argidx = 1; argidx < args.size(); argidx++)
-		{
-			if (args[argidx] == "-clkbuf") {
-				clkbuf_mode = true;
-				continue;
-			}
-			break;
-		}
-		extra_args(args, argidx, design);
-
-		Module *module = design->top_module();
-
-		if (module == nullptr)
-			log_cmd_error("No top module found.\n");
-
-		handle_iobufs(module, clkbuf_mode);
-		handle_clkint(module);
-	}
-} Sf2IobsPass;
-
-PRIVATE_NAMESPACE_END
diff --git a/techlibs/sf2/synth_sf2.cc b/techlibs/sf2/synth_sf2.cc
index 6b2a3f9b8..096450ad3 100644
--- a/techlibs/sf2/synth_sf2.cc
+++ b/techlibs/sf2/synth_sf2.cc
@@ -209,10 +209,12 @@ struct SynthSf2Pass : public ScriptPass
 
 		if (check_label("map_iobs"))
 		{
-			if (help_mode)
-				run("sf2_iobs [-clkbuf]", "(unless -noiobs)");
-			else if (iobs)
-				run(clkbuf ? "sf2_iobs -clkbuf" : "sf2_iobs");
+			if (help_mode || iobs) {
+				if (help_mode || clkbuf) {
+					run("clkbufmap -buf CLKINT Y:A -inpad CLKBUF Y:PAD", "(if -clkbuf, unless -noiobs)");
+				}
+				run("iopadmap -bits -inpad INBUF Y:PAD -outpad OUTBUF D:PAD -toutpad TRIBUFF E:D:PAD -tinoutpad BIBUF E:Y:D:PAD", "(unless -noiobs");
+			}
 			run("clean");
 		}