From 3404934c9cf1be141542e4d23f2b0c5a80ad5ea7 Mon Sep 17 00:00:00 2001
From: Andrew Zonenberg <azonenberg@drawersteak.com>
Date: Fri, 15 Sep 2017 10:52:09 -0700
Subject: extract_reduce now only removes the head of the chain, relying on
 "clean" to delete upstream cells. Added "-allow-off-chain" flag, but it's
 currently ignored.

---
 passes/techmap/extract_reduce.cc | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

(limited to 'passes')

diff --git a/passes/techmap/extract_reduce.cc b/passes/techmap/extract_reduce.cc
index 54e45f836..3da6cc40d 100644
--- a/passes/techmap/extract_reduce.cc
+++ b/passes/techmap/extract_reduce.cc
@@ -37,7 +37,7 @@ struct ExtractReducePass : public Pass
 	{
 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 		log("\n");
-		log("    extract_reduce [selection]\n");
+		log("    extract_reduce [options] [selection]\n");
 		log("\n");
 		log("converts gate chains into $reduce_* cells\n");
 		log("\n");
@@ -48,6 +48,11 @@ struct ExtractReducePass : public Pass
 		log("to map the design to only $_AND_ cells, run extract_reduce, map the remaining\n");
 		log("parts of the design to AND/OR/XOR cells, and run extract_reduce a second time.\n");
 		log("\n");
+		log("    -allow-off-chain\n");
+		log("        Allows matching of cells that have loads outside the chain. These cells\n");
+		log("        will be replicated and folded into the $reduce_* cell, but the original\n");
+		log("        cell will remain, driving its original loads.\n");
+		log("\n");
 	}
 
 	virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
@@ -56,12 +61,14 @@ struct ExtractReducePass : public Pass
 		log_push();
 
 		size_t argidx;
+		bool allow_off_chain = false;
 		for (argidx = 1; argidx < args.size(); argidx++)
 		{
-			// if (args[argidx] == "-v") {
-			// 	verbose = true;
-			// 	continue;
-			// }
+			if (args[argidx] == "-allow-off-chain")
+			{
+				allow_off_chain = true;
+				continue;
+			}
 			break;
 		}
 		extra_args(args, argidx, design);
@@ -102,6 +109,7 @@ struct ExtractReducePass : public Pass
 
 			// Actual logic starts here
 			pool<Cell*> consumed_cells;
+			pool<Cell*> head_cells;
 			for (auto cell : module->selected_cells())
 			{
 				if (consumed_cells.count(cell))
@@ -212,7 +220,7 @@ struct ExtractReducePass : public Pass
 
 					SigBit output = sigmap(head_cell->getPort("\\Y")[0]);
 
-					auto new_reduce_cell = module->addCell(NEW_ID, 
+					auto new_reduce_cell = module->addCell(NEW_ID,
 						gt == GateType::And ? "$reduce_and" :
 						gt == GateType::Or ? "$reduce_or" :
 						gt == GateType::Xor ? "$reduce_xor" : "");
@@ -224,11 +232,13 @@ struct ExtractReducePass : public Pass
 
 					for (auto x : cur_supercell)
 						consumed_cells.insert(x);
-					}
+					head_cells.insert(head_cell);
 				}
+			}
 
-			// Remove every cell that we've used up
-			for (auto cell : consumed_cells)
+			// Remove all of the head cells, since we supplant them.
+			// Do not remove the upstream cells since some might still be in use ("clean" will get rid of unused ones)
+			for (auto cell : head_cells)
 				module->remove(cell);
 		}
 
-- 
cgit v1.2.3