From 82aaf6d9086176c746bb157f33fd085a2e03e461 Mon Sep 17 00:00:00 2001
From: Clifford Wolf <clifford@clifford.at>
Date: Mon, 12 Nov 2018 09:27:33 +0100
Subject: [PATCH] Add "write_aiger -I -O -B"

Signed-off-by: Clifford Wolf <clifford@clifford.at>
---
 backends/aiger/aiger.cc | 38 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc
index c323691a3..dfe506c66 100644
--- a/backends/aiger/aiger.cc
+++ b/backends/aiger/aiger.cc
@@ -100,7 +100,7 @@ struct AigerWriter
 		return aig_map.at(bit);
 	}
 
-	AigerWriter(Module *module, bool zinit_mode) : module(module), zinit_mode(zinit_mode), sigmap(module)
+	AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode) : module(module), zinit_mode(zinit_mode), sigmap(module)
 	{
 		pool<SigBit> undriven_bits;
 		pool<SigBit> unused_bits;
@@ -293,6 +293,10 @@ struct AigerWriter
 			aig_map[bit] = 2*aig_m;
 		}
 
+		if (imode && input_bits.empty()) {
+			aig_m++, aig_i++;
+		}
+
 		if (zinit_mode)
 		{
 			for (auto it : ff_map) {
@@ -371,6 +375,11 @@ struct AigerWriter
 			aig_outputs.push_back(bit2aig(bit));
 		}
 
+		if (omode && output_bits.empty()) {
+			aig_o++;
+			aig_outputs.push_back(0);
+		}
+
 		for (auto it : asserts) {
 			aig_b++;
 			int bit_a = bit2aig(it.first);
@@ -378,6 +387,11 @@ struct AigerWriter
 			aig_outputs.push_back(mkgate(bit_a^1, bit_en));
 		}
 
+		if (bmode && asserts.empty()) {
+			aig_b++;
+			aig_outputs.push_back(0);
+		}
+
 		for (auto it : assumes) {
 			aig_c++;
 			int bit_a = bit2aig(it.first);
@@ -689,6 +703,11 @@ struct AigerBackend : public Backend {
 		log("    -vmap <filename>\n");
 		log("        like -map, but more verbose\n");
 		log("\n");
+		log("    -I, -O, -B\n");
+		log("        If the design contains no input/output/assert then create one\n");
+		log("        dummy input/output/bad_state pin to make the tools reading the\n");
+		log("        AIGER file happy.\n");
+		log("\n");
 	}
 	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 	{
@@ -697,6 +716,9 @@ struct AigerBackend : public Backend {
 		bool miter_mode = false;
 		bool symbols_mode = false;
 		bool verbose_map = false;
+		bool imode = false;
+		bool omode = false;
+		bool bmode = false;
 		std::string map_filename;
 
 		log_header(design, "Executing AIGER backend.\n");
@@ -729,6 +751,18 @@ struct AigerBackend : public Backend {
 				verbose_map = true;
 				continue;
 			}
+			if (args[argidx] == "-I") {
+				imode = true;
+				continue;
+			}
+			if (args[argidx] == "-O") {
+				omode = true;
+				continue;
+			}
+			if (args[argidx] == "-B") {
+				bmode = true;
+				continue;
+			}
 			break;
 		}
 		extra_args(f, filename, args, argidx);
@@ -738,7 +772,7 @@ struct AigerBackend : public Backend {
 		if (top_module == nullptr)
 			log_error("Can't find top module in current design!\n");
 
-		AigerWriter writer(top_module, zinit_mode);
+		AigerWriter writer(top_module, zinit_mode, imode, omode, bmode);
 		writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode);
 
 		if (!map_filename.empty()) {