From beb5cb55a537086dd066aca4e29248cbac44a417 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Povi=C5=A1er?= <povik@cutebit.org>
Date: Wed, 22 Nov 2023 14:57:13 +0100
Subject: [PATCH] booth: Expose `-lowpower` option

---
 passes/techmap/booth.cc | 34 ++++++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/passes/techmap/booth.cc b/passes/techmap/booth.cc
index 0830f9766..581400236 100644
--- a/passes/techmap/booth.cc
+++ b/passes/techmap/booth.cc
@@ -66,6 +66,7 @@ struct BoothPassWorker {
 	RTLIL::Module *module;
 	SigMap sigmap;
 	int booth_counter;
+	bool lowpower = false;
 
 	BoothPassWorker(RTLIL::Module *module) : module(module), sigmap(module) { booth_counter = 0; }
 
@@ -276,12 +277,20 @@ struct BoothPassWorker {
 			}
 			log_assert(GetSize(Y) == required_op_size);
 
-			CreateBoothMult(module,
-				A, // multiplicand
-				B, // multiplier(scanned)
-				Y, // result
-				is_signed
-			);
+			if (!lowpower)
+				CreateBoothMult(module,
+					A, // multiplicand
+					B, // multiplier(scanned)
+					Y, // result
+					is_signed
+				);
+			else
+				CreateBoothLowpowerMult(module,
+					A, // multiplicand
+					B, // multiplier(scanned)
+					Y, // result
+					is_signed
+				);
 
 			module->remove(cell);
 			booth_counter++;
@@ -904,12 +913,15 @@ struct BoothPassWorker {
 	}
 
 	/*
-	  Signed Multiplier
+	  Low-power Multiplier
 	*/
-	void CreateBoothSMult(RTLIL::Module *module, SigSpec X, SigSpec Y, SigSpec Z)
+	void CreateBoothLowpowerMult(RTLIL::Module *module, SigSpec X, SigSpec Y, SigSpec Z, bool is_signed)
 	{ // product
 		int x_sz = X.size(), y_sz = Y.size(), z_sz = Z.size();
 
+		if (!is_signed)
+			log_error("Low-power Booth architecture is only supported on signed multipliers.\n");
+
 		unsigned enc_count = (y_sz / 2) + (((y_sz % 2) != 0) ? 1 : 0);
 		int dec_count = x_sz + 1;
 
@@ -1118,8 +1130,13 @@ struct BoothPass : public Pass {
 		log_header(design, "Executing BOOTH pass (map to Booth multipliers).\n");
 
 		size_t argidx;
+		bool lowpower = false;
 		for (argidx = 1; argidx < args.size(); argidx++) {
 			break;
+			if (args[argidx] == "-lowpower")
+				lowpower = true;
+			else
+				break;
 		}
 		extra_args(args, argidx, design);
 
@@ -1128,6 +1145,7 @@ struct BoothPass : public Pass {
 		for (auto mod : design->selected_modules()) {
 			if (!mod->has_processes_warn()) {
 				BoothPassWorker worker(mod);
+				worker.lowpower = lowpower;
 				worker.run();
 				total += worker.booth_counter;
 			}