From 3121d19d95ae916b96baa000197f3ec2aa5c5ad7 Mon Sep 17 00:00:00 2001
From: Clifford Wolf <clifford@clifford.at>
Date: Fri, 14 Feb 2014 11:28:42 +0100
Subject: [PATCH] Added abc -keepff option

---
 passes/abc/abc.cc | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/passes/abc/abc.cc b/passes/abc/abc.cc
index 4add6452d..bd0d983ac 100644
--- a/passes/abc/abc.cc
+++ b/passes/abc/abc.cc
@@ -109,7 +109,7 @@ static void mark_port(RTLIL::SigSpec sig)
 	}
 }
 
-static void extract_cell(RTLIL::Cell *cell)
+static void extract_cell(RTLIL::Cell *cell, bool keepff)
 {
 	if (cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
 	{
@@ -121,6 +121,11 @@ static void extract_cell(RTLIL::Cell *cell)
 		RTLIL::SigSpec sig_d = cell->connections["\\D"];
 		RTLIL::SigSpec sig_q = cell->connections["\\Q"];
 
+		if (keepff)
+			for (auto &c : sig_q.chunks)
+				if (c.wire != NULL)
+					c.wire->attributes["\\keep"] = 1;
+
 		assign_map.apply(sig_d);
 		assign_map.apply(sig_q);
 
@@ -403,7 +408,7 @@ static std::string fold_abc_cmd(std::string str)
 }
 
 static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
-		std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, bool dff_mode, std::string clk_str)
+		std::string liberty_file, std::string constr_file, bool cleanup, int lut_mode, bool dff_mode, std::string clk_str, bool keepff)
 {
 	module = current_module;
 	map_autoidx = RTLIL::autoidx++;
@@ -498,7 +503,7 @@ static void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std
 		if (design->selected(current_module, it.second))
 			cells.push_back(it.second);
 	for (auto c : cells)
-		extract_cell(c);
+		extract_cell(c, keepff);
 
 	for (auto &wire_it : module->wires) {
 		if (wire_it.second->port_id > 0 || wire_it.second->get_bool_attribute("\\keep"))
@@ -940,6 +945,10 @@ struct AbcPass : public Pass {
 		log("        with -dff, then it falls back to the automatic dection of clock domain\n");
 		log("        if the specified clock is not found in a module.)\n");
 		log("\n");
+		log("    -keepff\n");
+		log("        set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n");
+		log("        them, for example for equivialence checking.)\n");
+		log("\n");
 		log("    -nocleanup\n");
 		log("        when this option is used, the temporary files created by this pass\n");
 		log("        are not removed. this is useful for debugging.\n");
@@ -960,7 +969,7 @@ struct AbcPass : public Pass {
 
 		std::string exe_file = rewrite_yosys_exe("yosys-abc");
 		std::string script_file, liberty_file, constr_file, clk_str;
-		bool dff_mode = false, cleanup = true;
+		bool dff_mode = false, keepff = false, cleanup = true;
 		int lut_mode = 0;
 
 		size_t argidx;
@@ -1001,6 +1010,10 @@ struct AbcPass : public Pass {
 				clk_str = args[++argidx];
 				continue;
 			}
+			if (arg == "-keepff") {
+				keepff = true;
+				continue;
+			}
 			if (arg == "-nocleanup") {
 				cleanup = false;
 				continue;
@@ -1020,7 +1033,7 @@ struct AbcPass : public Pass {
 				if (mod_it.second->processes.size() > 0)
 					log("Skipping module %s as it contains processes.\n", mod_it.second->name.c_str());
 				else
-					abc_module(design, mod_it.second, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str);
+					abc_module(design, mod_it.second, script_file, exe_file, liberty_file, constr_file, cleanup, lut_mode, dff_mode, clk_str, keepff);
 			}
 
 		assign_map.clear();