From 04ef222cfb618b6ee7c43b6bef82299d5b5bc010 Mon Sep 17 00:00:00 2001
From: Clifford Wolf <clifford@clifford.at>
Date: Sat, 11 May 2019 09:24:52 +0200
Subject: Add "stat -tech xilinx"

Signed-off-by: Clifford Wolf <clifford@clifford.at>
---
 passes/cmds/stat.cc             | 76 +++++++++++++++++++++++++++++++++++++++--
 techlibs/xilinx/synth_xilinx.cc |  2 +-
 2 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc
index 54f4ea817..d22685b62 100644
--- a/passes/cmds/stat.cc
+++ b/passes/cmds/stat.cc
@@ -37,7 +37,9 @@ struct statdata_t
 	STAT_INT_MEMBERS
 	#undef X
 	double area;
+	string tech;
 
+	std::map<RTLIL::IdString, int> techinfo;
 	std::map<RTLIL::IdString, int, RTLIL::sort_by_id_str> num_cells_by_type;
 	std::set<RTLIL::IdString> unknown_cell_area;
 
@@ -70,8 +72,10 @@ struct statdata_t
 	#undef X
 	}
 
-	statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode, const dict<IdString, double> &cell_area)
+	statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode, const dict<IdString, double> &cell_area, string techname)
 	{
+		tech = techname;
+
 	#define X(_name) _name = 0;
 		STAT_NUMERIC_MEMBERS
 	#undef X
@@ -153,7 +157,8 @@ struct statdata_t
 		log("   Number of processes:         %6d\n", num_processes);
 		log("   Number of cells:             %6d\n", num_cells);
 		for (auto &it : num_cells_by_type)
-			log("     %-26s %6d\n", RTLIL::id2cstr(it.first), it.second);
+			if (it.second)
+				log("     %-26s %6d\n", RTLIL::id2cstr(it.first), it.second);
 
 		if (!unknown_cell_area.empty()) {
 			log("\n");
@@ -165,6 +170,59 @@ struct statdata_t
 			log("\n");
 			log("   Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area);
 		}
+
+		if (tech == "xilinx")
+		{
+			int lut6_cnt = num_cells_by_type["\\LUT6"];
+			int lut5_cnt = num_cells_by_type["\\LUT5"];
+			int lut4_cnt = num_cells_by_type["\\LUT4"];
+			int lut3_cnt = num_cells_by_type["\\LUT3"];
+			int lut2_cnt = num_cells_by_type["\\LUT2"];
+			int lut1_cnt = num_cells_by_type["\\LUT1"];
+			int lc_cnt = 0;
+
+			lc_cnt += lut6_cnt;
+
+			lc_cnt += lut5_cnt;
+			if (lut1_cnt) {
+				int cnt = std::min(lut5_cnt, lut1_cnt);
+				lut5_cnt -= cnt;
+				lut1_cnt -= cnt;
+			}
+
+			lc_cnt += lut4_cnt;
+			if (lut1_cnt) {
+				int cnt = std::min(lut4_cnt, lut1_cnt);
+				lut4_cnt -= cnt;
+				lut1_cnt -= cnt;
+			}
+			if (lut2_cnt) {
+				int cnt = std::min(lut4_cnt, lut2_cnt);
+				lut4_cnt -= cnt;
+				lut2_cnt -= cnt;
+			}
+
+			lc_cnt += lut3_cnt;
+			if (lut1_cnt) {
+				int cnt = std::min(lut3_cnt, lut1_cnt);
+				lut3_cnt -= cnt;
+				lut1_cnt -= cnt;
+			}
+			if (lut2_cnt) {
+				int cnt = std::min(lut3_cnt, lut2_cnt);
+				lut3_cnt -= cnt;
+				lut2_cnt -= cnt;
+			}
+			if (lut3_cnt) {
+				int cnt = (lut3_cnt + 1) / 2;
+				lut3_cnt -= cnt;
+			}
+
+			lc_cnt += (lut2_cnt + lut1_cnt + 1) / 2;
+
+			log("\n");
+			log("   Estimated number of LCs: %10d\n", lc_cnt);
+		}
 	}
 };
 
@@ -226,6 +284,10 @@ struct StatPass : public Pass {
 		log("    -liberty <liberty_file>\n");
 		log("        use cell area information from the provided liberty file\n");
 		log("\n");
+		log("    -tech <technology>\n");
+		log("        print area estemate for the specified technology. Corrently supported\n");
+		log("        calues for <technology>: xilinx\n");
+		log("\n");
 		log("    -width\n");
 		log("        annotate internal cell types with their word width.\n");
 		log("        e.g. $add_8 for an 8 bit wide $add cell.\n");
@@ -239,6 +301,7 @@ struct StatPass : public Pass {
 		RTLIL::Module *top_mod = NULL;
 		std::map<RTLIL::IdString, statdata_t> mod_stat;
 		dict<IdString, double> cell_area;
+		string techname;
 
 		size_t argidx;
 		for (argidx = 1; argidx < args.size(); argidx++)
@@ -253,6 +316,10 @@ struct StatPass : public Pass {
 				read_liberty_cellarea(cell_area, liberty_file);
 				continue;
 			}
+			if (args[argidx] == "-tech" && argidx+1 < args.size()) {
+				techname = args[++argidx];
+				continue;
+			}
 			if (args[argidx] == "-top" && argidx+1 < args.size()) {
 				if (design->modules_.count(RTLIL::escape_id(args[argidx+1])) == 0)
 					log_cmd_error("Can't find module %s.\n", args[argidx+1].c_str());
@@ -263,13 +330,16 @@ struct StatPass : public Pass {
 		}
 		extra_args(args, argidx, design);
 
+		if (techname != "" && techname != "xilinx")
+			log_cmd_error("Unsupported technology: '%s'\n", techname.c_str());
+
 		for (auto mod : design->selected_modules())
 		{
 			if (!top_mod && design->full_selection())
 				if (mod->get_bool_attribute("\\top"))
 					top_mod = mod;
 
-			statdata_t data(design, mod, width_mode, cell_area);
+			statdata_t data(design, mod, width_mode, cell_area, techname);
 			mod_stat[mod->name] = data;
 
 			log("\n");
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index b022972c9..c20cac09b 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -269,7 +269,7 @@ struct SynthXilinxPass : public ScriptPass
 
 		if (check_label("check")) {
 			run("hierarchy -check");
-			run("stat");
+			run("stat -tech xilinx");
 			run("check -noinit");
 		}
 
-- 
cgit v1.2.3