From bfd71e09906096c72039beebb1b3b6a79dd6b36c Mon Sep 17 00:00:00 2001
From: Eddie Hung <eddie@fpgeh.com>
Date: Tue, 23 Apr 2019 16:11:14 -0700
Subject: [PATCH] Fix abc9 with (* keep *) wires

---
 backends/aiger/xaiger.cc | 20 ++++++++++++++------
 tests/simple_abc9/abc9.v | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc
index d6438a297..504a66086 100644
--- a/backends/aiger/xaiger.cc
+++ b/backends/aiger/xaiger.cc
@@ -133,6 +133,8 @@ struct XAigerWriter
 						init_map[initsig[i]] = initval[i] == State::S1;
 			}
 
+			bool keep = wire->attributes.count("\\keep");
+
 			for (int i = 0; i < GetSize(wire); i++)
 			{
 				SigBit wirebit(wire, i);
@@ -151,8 +153,10 @@ struct XAigerWriter
 
 				if (wire->port_input)
 					input_bits.insert(bit);
+				else if (keep)
+					input_bits.insert(wirebit);
 
-				if (wire->port_output) {
+				if (wire->port_output || keep) {
 					if (bit != wirebit)
 						alias_map[wirebit] = bit;
 					output_bits.insert(wirebit);
@@ -338,10 +342,12 @@ struct XAigerWriter
 
 		for (auto bit : input_bits) {
 			RTLIL::Wire *wire = bit.wire;
-			// If encountering an inout port, then create a new wire with $inout.out
-			// suffix, make it a PO driven by the existing inout, and inherit existing
-			// inout's drivers
-			if (wire->port_input && wire->port_output && !undriven_bits.count(bit)) {
+			// If encountering an inout port, or a keep-ed wire, then create a new wire
+			// with $inout.out suffix, make it a PO driven by the existing inout, and
+			// inherit existing inout's drivers
+			if ((wire->port_input && wire->port_output && !undriven_bits.count(bit))
+					|| wire->attributes.count("\\keep")) {
+				log_assert(input_bits.count(bit) && output_bits.count(bit));
 				RTLIL::Wire *new_wire = module->wire(wire->name.str() + "$inout.out");
 				if (!new_wire)
 					new_wire = module->addWire(wire->name.str() + "$inout.out", GetSize(wire));
@@ -354,7 +360,9 @@ struct XAigerWriter
 				else if (alias_map.count(bit))
 					alias_map[new_bit] = alias_map.at(bit);
 				else
+					//log_abort();
 					alias_map[new_bit] = bit;
+				output_bits.erase(bit);
 				output_bits.insert(new_bit);
 			}
 		}
@@ -750,7 +758,7 @@ struct XAigerWriter
 			{
 				RTLIL::SigBit b(wire, i);
 				if (input_bits.count(b)) {
-					int a = aig_map.at(sig[i]);
+					int a = aig_map.at(b);
 					log_assert((a & 1) == 0);
 					input_lines[a] += stringf("input %d %d %s\n", (a >> 1)-1, i, log_id(wire));
 				}
diff --git a/tests/simple_abc9/abc9.v b/tests/simple_abc9/abc9.v
index eca340693..f37d975ff 100644
--- a/tests/simple_abc9/abc9.v
+++ b/tests/simple_abc9/abc9.v
@@ -104,3 +104,41 @@ always @(io or oe)
 assign io[3:0] = oe ? ~latch[3:0] : 4'bz;
 assign io[7:4] = !oe ? {latch[4], latch[7:3]} : 4'bz;
 endmodule
+
+module abc9_test015(input a, output b, input c);
+assign b = ~a;
+(* keep *) wire d;
+assign d = ~c;
+endmodule
+
+module abc9_test016(input a, output b);
+assign b = ~a;
+(* keep *) reg c;
+always @* c <= ~a;
+endmodule
+
+module abc9_test017(input a, output b);
+assign b = ~a;
+(* keep *) reg c;
+always @* c = b;
+endmodule
+
+module abc9_test018(input a, output b, output c);
+assign b = ~a;
+(* keep *) wire [1:0] d;
+assign c = &d;
+endmodule
+
+module abc9_test019(input a, output b);
+assign b = ~a;
+(* keep *) reg [1:0] c;
+reg d;
+always @* d <= &c;
+endmodule
+
+module abc9_test020(input a, output b);
+assign b = ~a;
+(* keep *) reg [1:0] c;
+(* keep *) reg d;
+always @* d <= &c;
+endmodule