From 1d526b7f061fb7e7961fa4d0b318b27cfda469d4 Mon Sep 17 00:00:00 2001
From: Eddie Hung <eddieh@ece.ubc.ca>
Date: Fri, 5 Apr 2019 17:35:49 -0700
Subject: [PATCH] Call shregmap twice -- once for variable, another for fixed

---
 passes/techmap/shregmap.cc      | 46 ++++++++++++---------------------
 techlibs/xilinx/cells_map.v     |  3 +++
 techlibs/xilinx/synth_xilinx.cc | 19 ++++++++------
 3 files changed, 31 insertions(+), 37 deletions(-)

diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc
index 408e3f8c7..a805ac5a6 100644
--- a/passes/techmap/shregmap.cc
+++ b/passes/techmap/shregmap.cc
@@ -138,11 +138,8 @@ struct ShregmapTechXilinx7 : ShregmapTech
 
 	virtual bool analyze(vector<int> &taps, const vector<SigBit> &qbits) override
 	{
-		log("analyze() with %zu taps", taps.size());
-		for (auto t : taps) log(" %d", t);
-		log("\n");
 		if (GetSize(taps) == 1)
-			return taps[0] >= opts.minlen-1;
+			return taps[0] >= opts.minlen-1 && sigbit_to_shiftx_offset.count(qbits[0]);
 
 		if (taps.back() < opts.minlen-1)
 			return false;
@@ -150,38 +147,31 @@ struct ShregmapTechXilinx7 : ShregmapTech
 		Cell *shiftx = nullptr;
 		int group = 0;
 		for (int i = 0; i < GetSize(taps); ++i) {
+			auto it = sigbit_to_shiftx_offset.find(qbits[i]);
+			if (it == sigbit_to_shiftx_offset.end())
+				return false;
+
 			// Check taps are sequential
 			if (i != taps[i])
 				return false;
 			// Check taps are not connected to a shift register,
 			// or sequential to the same shift register
-			auto it = sigbit_to_shiftx_offset.find(qbits[i]);
 			if (i == 0) {
-				if (it == sigbit_to_shiftx_offset.end()) {
+				int offset;
+				std::tie(shiftx,offset,group) = it->second;
+				if (offset != i)
 					return false;
-				}
-				else {
-					int offset;
-					std::tie(shiftx,offset,group) = it->second;
-					if (offset != i)
-						return false;
-				}
 			}
 			else {
-				if (it == sigbit_to_shiftx_offset.end()) {
+				Cell *shiftx_ = std::get<0>(it->second);
+				if (shiftx_ != shiftx)
+					return false;
+				int offset = std::get<1>(it->second);
+				if (offset != i)
+					return false;
+				int group_ = std::get<2>(it->second);
+				if (group_ != group)
 					return false;
-				}
-				else {
-					Cell *shiftx_ = std::get<0>(it->second);
-					if (shiftx_ != shiftx)
-						return false;
-					int offset = std::get<1>(it->second);
-					if (offset != i)
-						return false;
-					int group_ = std::get<2>(it->second);
-					if (group_ != group)
-						return false;
-				}
 			}
 		}
 		log_assert(shiftx);
@@ -206,9 +196,7 @@ struct ShregmapTechXilinx7 : ShregmapTech
 		auto bit = tap.second;
 
 		auto it = sigbit_to_shiftx_offset.find(bit);
-		// If fixed-length, no fixup necessary
-		if (it == sigbit_to_shiftx_offset.end())
-			return true;
+		log_assert(it != sigbit_to_shiftx_offset.end());
 
 		auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_");
 		newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH"));
diff --git a/techlibs/xilinx/cells_map.v b/techlibs/xilinx/cells_map.v
index c80e51bd0..704ab21b1 100644
--- a/techlibs/xilinx/cells_map.v
+++ b/techlibs/xilinx/cells_map.v
@@ -141,3 +141,6 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
     end
   endgenerate
 endmodule
+
+`ifndef SRL_ONLY
+`endif
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index 2676f5915..57bde998f 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -113,22 +113,23 @@ struct SynthXilinxPass : public Pass
 		log("        dffsr2dff\n");
 		log("        dff2dffe\n");
 		log("        opt -full\n");
-		log("        simplemap t:$dff t:$dffe (without -nosrl and without -retime only)\n");
-		log("        shregmap -tech xilinx -minlen 3 (without -nosrl and without -retime only)\n");
+		log("        simplemap t:$dff t:$dffe (without '-nosrl' only)\n");
+		log("        shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n");
 		log("        techmap -map +/techmap.v -map +/xilinx/arith_map.v\n");
 		log("        opt -fast\n");
 		log("\n");
 		log("    map_cells:\n");
-		log("        techmap -map +/xilinx/cells_map.v\n");
-		log("        dffinit -ff FDRE   Q INIT -ff FDCE   Q INIT -ff FDPE   Q INIT -ff FDSE   Q INIT \\\n");
-		log("                -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n");
+		log("        techmap -map +/techmap.v -map +/xilinx/cells_map.v\n");
 		log("        clean\n");
 		log("\n");
 		log("    map_luts:\n");
 		log("        techmap -map +/techmap.v -map +/xilinx/ff_map.v t:$_DFF_?N?\n");
 		log("        abc -luts 2:2,3,6:5,10,20 [-dff]\n");
 		log("        clean\n");
-		log("        techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v");
+		log("        shregmap -minlen 3 -init -params -enpol any_or_none (without '-nosrl' only)\n");
+		log("        techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
+		log("        dffinit -ff FDRE   Q INIT -ff FDCE   Q INIT -ff FDPE   Q INIT -ff FDSE   Q INIT \\\n");
+		log("                -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n");
 		log("\n");
 		log("    check:\n");
 		log("        hierarchy -check\n");
@@ -266,7 +267,7 @@ struct SynthXilinxPass : public Pass
 			Pass::call(design, "dff2dffe");
 			Pass::call(design, "opt -full");
 
-			if (!nosrl && !retime) {
+			if (!nosrl) {
 				Pass::call(design, "simplemap t:$dff t:$dffe");
 				Pass::call(design, "shregmap -tech xilinx -minlen 3");
 			}
@@ -292,7 +293,9 @@ struct SynthXilinxPass : public Pass
 			Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/ff_map.v t:$_DFF_?N?");
 			Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
 			Pass::call(design, "clean");
-			Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v");
+			if (!nosrl)
+				Pass::call(design, "shregmap -minlen 3 -init -params -enpol any_or_none");
+			Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
 			Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
 					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
 		}