mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Improve STAT
This commit is contained in:
		
							parent
							
								
									8c71226d00
								
							
						
					
					
						commit
						a0dde68487
					
				
					 1 changed files with 472 additions and 145 deletions
				
			
		|  | @ -19,13 +19,14 @@ | |||
| 
 | ||||
| #include <iterator> | ||||
| 
 | ||||
| #include "kernel/yosys.h" | ||||
| #include "kernel/celltypes.h" | ||||
| #include "passes/techmap/libparse.h" | ||||
| #include "kernel/cost.h" | ||||
| #include "kernel/gzip.h" | ||||
| #include "kernel/yosys.h" | ||||
| #include "libs/json11/json11.hpp" | ||||
| #include "kernel/log_help.h" | ||||
| #include "passes/techmap/libparse.h" | ||||
| #include <charconv> | ||||
| 
 | ||||
| USING_YOSYS_NAMESPACE | ||||
| PRIVATE_NAMESPACE_BEGIN | ||||
|  | @ -35,137 +36,225 @@ struct cell_area_t { | |||
| 	bool is_sequential; | ||||
| }; | ||||
| 
 | ||||
| struct statdata_t | ||||
| { | ||||
| 	#define STAT_INT_MEMBERS X(num_wires) X(num_wire_bits) X(num_pub_wires) X(num_pub_wire_bits) \ | ||||
| 			X(num_ports) X(num_port_bits) X(num_memories) X(num_memory_bits) X(num_cells) \ | ||||
| 			X(num_processes) | ||||
| struct statdata_t { | ||||
| #define STAT_INT_MEMBERS                                                                                                                             \ | ||||
| 	X(num_wires)                                                                                                                                 \ | ||||
| 	X(num_wire_bits)                                                                                                                             \ | ||||
| 	X(num_pub_wires) X(num_pub_wire_bits) X(num_ports) X(num_port_bits) X(num_memories) X(num_memory_bits) X(num_cells) X(num_processes) | ||||
| 
 | ||||
| 	#define STAT_NUMERIC_MEMBERS STAT_INT_MEMBERS X(area) X(sequential_area) | ||||
| #define STAT_NUMERIC_MEMBERS STAT_INT_MEMBERS X(area) X(sequential_area) | ||||
| 
 | ||||
| 	#define X(_name) unsigned int _name; | ||||
| #define X(_name) unsigned int _name; | ||||
| 	STAT_INT_MEMBERS | ||||
| 	#undef X | ||||
| #undef X | ||||
| #define X(_name) unsigned int local_##_name; | ||||
| 	STAT_INT_MEMBERS | ||||
| #undef X | ||||
| 	double area = 0; | ||||
| 	double sequential_area = 0; | ||||
| 	double local_area = 0; | ||||
| 	double local_sequential_area = 0; | ||||
| 	double submodule_area = 0; | ||||
| 	int num_submodules = 0; | ||||
| 	std::map<RTLIL::IdString, unsigned int, RTLIL::sort_by_id_str> num_submodules_by_type; | ||||
| 	std::map<RTLIL::IdString, double, RTLIL::sort_by_id_str> submodules_area_by_type; | ||||
| 
 | ||||
| 	std::map<RTLIL::IdString, unsigned int, RTLIL::sort_by_id_str> local_num_cells_by_type; | ||||
| 	std::map<RTLIL::IdString, double, RTLIL::sort_by_id_str> local_area_cells_by_type; | ||||
| 	std::map<RTLIL::IdString, double, RTLIL::sort_by_id_str> local_seq_area_cells_by_type; | ||||
| 	string tech; | ||||
| 
 | ||||
| 	std::map<RTLIL::IdString, unsigned int, RTLIL::sort_by_id_str> num_cells_by_type; | ||||
| 	std::map<RTLIL::IdString, double, RTLIL::sort_by_id_str> area_cells_by_type; | ||||
| 	std::map<RTLIL::IdString, double, RTLIL::sort_by_id_str> seq_area_cells_by_type; | ||||
| 	std::set<RTLIL::IdString> unknown_cell_area; | ||||
| 
 | ||||
| 	statdata_t operator+(const statdata_t &other) const | ||||
| 	{ | ||||
| 		statdata_t sum = other; | ||||
| 	#define X(_name) sum._name += _name; | ||||
| #define X(_name) sum._name += _name; | ||||
| 		STAT_NUMERIC_MEMBERS | ||||
| 	#undef X | ||||
| #undef X | ||||
| 		for (auto &it : num_cells_by_type) | ||||
| 			sum.num_cells_by_type[it.first] += it.second; | ||||
| 		return sum; | ||||
| 	} | ||||
| 
 | ||||
| 	statdata_t operator*(unsigned int other) const | ||||
| 	{ | ||||
| 		statdata_t sum = *this; | ||||
| 	#define X(_name) sum._name *= other; | ||||
| #define X(_name) sum._name *= other; | ||||
| 		STAT_NUMERIC_MEMBERS | ||||
| 	#undef X | ||||
| #undef X | ||||
| 		for (auto &it : sum.num_cells_by_type) | ||||
| 			it.second *= other; | ||||
| 		return sum; | ||||
| 	} | ||||
| 	statdata_t add(const statdata_t &other) | ||||
| 	{ | ||||
| #define X(_name) _name += other._name; | ||||
| 		STAT_NUMERIC_MEMBERS | ||||
| #undef X | ||||
| 		for (auto &it : other.num_cells_by_type) { | ||||
| 			if (num_cells_by_type.count(it.first)) | ||||
| 				num_cells_by_type[it.first] += it.second; | ||||
| 			else | ||||
| 				num_cells_by_type[it.first] = it.second; | ||||
| 		} | ||||
| 		for (auto &it : other.submodules_area_by_type) { | ||||
| 			if (submodules_area_by_type.count(it.first)) | ||||
| 				submodules_area_by_type[it.first] += it.second; | ||||
| 			else | ||||
| 				submodules_area_by_type[it.first] = it.second; | ||||
| 		} | ||||
| 		for (auto &it : other.area_cells_by_type) { | ||||
| 			if (area_cells_by_type.count(it.first)) | ||||
| 				area_cells_by_type[it.first] += it.second; | ||||
| 			else | ||||
| 				area_cells_by_type[it.first] = it.second; | ||||
| 		} | ||||
| 		for (auto &it : other.seq_area_cells_by_type) { | ||||
| 			if (seq_area_cells_by_type.count(it.first)) | ||||
| 				seq_area_cells_by_type[it.first] += it.second; | ||||
| 			else | ||||
| 				seq_area_cells_by_type[it.first] = it.second; | ||||
| 		} | ||||
| 		unknown_cell_area.insert(other.unknown_cell_area.begin(), other.unknown_cell_area.end()); | ||||
| 		return *this; | ||||
| 	} | ||||
| 
 | ||||
| 	statdata_t() | ||||
| 	{ | ||||
| 	#define X(_name) _name = 0; | ||||
| #define X(_name) _name = 0; | ||||
| 		STAT_NUMERIC_MEMBERS | ||||
| 	#undef X | ||||
| #undef X | ||||
| 	} | ||||
| 
 | ||||
| 	statdata_t(RTLIL::Design *design, RTLIL::Module *mod, bool width_mode, const dict<IdString, cell_area_t> &cell_area, string techname) | ||||
| 	statdata_t(cell_area_t &cell_data, string techname) | ||||
| 	{ | ||||
| 		tech = techname; | ||||
| 		area = cell_data.area; | ||||
| 		if (cell_data.is_sequential) { | ||||
| 			sequential_area = cell_data.area; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	statdata_t(const RTLIL::Design *design, const RTLIL::Module *mod, bool width_mode, dict<IdString, cell_area_t> &cell_area, string techname) | ||||
| 	{ | ||||
| 		tech = techname; | ||||
| 
 | ||||
| 	#define X(_name) _name = 0; | ||||
| #define X(_name) _name = 0; | ||||
| 		STAT_NUMERIC_MEMBERS | ||||
| 	#undef X | ||||
| #undef X | ||||
| #define X(_name) local_##_name = 0; | ||||
| 		STAT_NUMERIC_MEMBERS | ||||
| #undef X | ||||
| 		// additional_cell_area
 | ||||
| 
 | ||||
| 		for (auto wire : mod->selected_wires()) | ||||
| 		{ | ||||
| 		for (auto wire : mod->selected_wires()) { | ||||
| 			if (wire->port_input || wire->port_output) { | ||||
| 				num_ports++; | ||||
| 				local_num_ports++; | ||||
| 				num_port_bits += wire->width; | ||||
| 				local_num_port_bits += wire->width; | ||||
| 			} | ||||
| 
 | ||||
| 			if (wire->name.isPublic()) { | ||||
| 				num_pub_wires++; | ||||
| 				local_num_pub_wires++; | ||||
| 				num_pub_wire_bits += wire->width; | ||||
| 				local_num_pub_wire_bits += wire->width; | ||||
| 			} | ||||
| 
 | ||||
| 			num_wires++; | ||||
| 			local_num_wires++; | ||||
| 			num_wire_bits += wire->width; | ||||
| 			local_num_wire_bits += wire->width; | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto &it : mod->memories) { | ||||
| 			if (!design->selected(mod, it.second)) | ||||
| 				continue; | ||||
| 			num_memories++; | ||||
| 			local_num_memories++; | ||||
| 			num_memory_bits += it.second->width * it.second->size; | ||||
| 			local_num_memory_bits += it.second->width * it.second->size; | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto cell : mod->selected_cells()) | ||||
| 		{ | ||||
| 		for (auto cell : mod->selected_cells()) { | ||||
| 			RTLIL::IdString cell_type = cell->type; | ||||
| 
 | ||||
| 			if (width_mode) | ||||
| 			{ | ||||
| 				if (cell_type.in(ID($not), ID($pos), ID($neg), | ||||
| 						ID($logic_not), ID($logic_and), ID($logic_or), | ||||
| 						ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), | ||||
| 						ID($lut), ID($and), ID($or), ID($xor), ID($xnor), | ||||
| 						ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), | ||||
| 						ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), | ||||
| 						ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow), ID($alu))) { | ||||
| 			if (width_mode) { | ||||
| 				if (cell_type.in(ID($not), ID($pos), ID($neg), ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_and), | ||||
| 						 ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($lut), ID($and), ID($or), | ||||
| 						 ID($xor), ID($xnor), ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), ID($lt), | ||||
| 						 ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), ID($add), ID($sub), ID($mul), | ||||
| 						 ID($div), ID($mod), ID($divfloor), ID($modfloor), ID($pow), ID($alu))) { | ||||
| 					int width_a = cell->hasPort(ID::A) ? GetSize(cell->getPort(ID::A)) : 0; | ||||
| 					int width_b = cell->hasPort(ID::B) ? GetSize(cell->getPort(ID::B)) : 0; | ||||
| 					int width_y = cell->hasPort(ID::Y) ? GetSize(cell->getPort(ID::Y)) : 0; | ||||
| 					cell_type = stringf("%s_%d", cell_type.c_str(), max<int>({width_a, width_b, width_y})); | ||||
| 				} | ||||
| 				else if (cell_type.in(ID($mux), ID($pmux))) | ||||
| 				} else if (cell_type.in(ID($mux))) | ||||
| 					cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y))); | ||||
| 				else if (cell_type == ID($bmux)) | ||||
| 					cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)), GetSize(cell->getPort(ID::S))); | ||||
| 				else if (cell_type.in(ID($bmux), ID($pmux))) | ||||
| 					cell_type = | ||||
| 					  stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Y)), GetSize(cell->getPort(ID::S))); | ||||
| 				else if (cell_type == ID($demux)) | ||||
| 					cell_type = stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::S))); | ||||
| 				else if (cell_type.in( | ||||
| 						ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), | ||||
| 						ID($adff), ID($adffe), ID($sdff), ID($sdffe), ID($sdffce), | ||||
| 						ID($aldff), ID($aldffe), ID($dlatch), ID($adlatch), ID($dlatchsr))) | ||||
| 					cell_type = | ||||
| 					  stringf("%s_%d_%d", cell_type.c_str(), GetSize(cell->getPort(ID::A)), GetSize(cell->getPort(ID::S))); | ||||
| 				else if (cell_type.in(ID($sr), ID($ff), ID($dff), ID($dffe), ID($dffsr), ID($dffsre), ID($adff), ID($adffe), | ||||
| 						      ID($sdff), ID($sdffe), ID($sdffce), ID($aldff), ID($aldffe), ID($dlatch), ID($adlatch), | ||||
| 						      ID($dlatchsr))) | ||||
| 					cell_type = stringf("%s_%d", cell_type.c_str(), GetSize(cell->getPort(ID::Q))); | ||||
| 			} | ||||
| 
 | ||||
| 			if (!cell_area.empty()) { | ||||
| 
 | ||||
| 				if (cell_area.count(cell_type)) { | ||||
| 					cell_area_t cell_data = cell_area.at(cell_type); | ||||
| 					if (cell_data.is_sequential) { | ||||
| 						sequential_area += cell_data.area; | ||||
| 						local_sequential_area += cell_data.area; | ||||
| 					} | ||||
| 					area += cell_data.area; | ||||
| 				} | ||||
| 				else { | ||||
| 					unknown_cell_area.insert(cell_type); | ||||
| 				} | ||||
| 			} | ||||
| 					num_cells++; | ||||
| 					num_cells_by_type[cell_type]++; | ||||
| 					area_cells_by_type[cell_type] += cell_data.area; | ||||
| 					seq_area_cells_by_type[cell_type] += cell_data.is_sequential ? cell_data.area : 0; | ||||
| 					local_area_cells_by_type[cell_type] += cell_data.area; | ||||
| 					local_seq_area_cells_by_type[cell_type] += cell_data.is_sequential ? cell_data.area : 0; | ||||
| 					local_area += cell_data.area; | ||||
| 					local_num_cells++; | ||||
| 					local_num_cells_by_type[cell_type]++; | ||||
| 
 | ||||
| 			num_cells++; | ||||
| 			num_cells_by_type[cell_type]++; | ||||
| 				} else { | ||||
| 					unknown_cell_area.insert(cell_type); | ||||
| 					num_cells++; | ||||
| 					num_cells_by_type[cell_type]++; | ||||
| 					local_num_cells++; | ||||
| 					local_num_cells_by_type[cell_type]++; | ||||
| 					area_cells_by_type[cell_type] = 0; | ||||
| 					seq_area_cells_by_type[cell_type] = 0; | ||||
| 					local_area_cells_by_type[cell_type] = 0; | ||||
| 					local_seq_area_cells_by_type[cell_type] = 0; | ||||
| 				} | ||||
| 			} else { | ||||
| 				num_cells++; | ||||
| 				num_cells_by_type[cell_type]++; | ||||
| 				area_cells_by_type[cell_type] = 0; | ||||
| 				seq_area_cells_by_type[cell_type] = 0; | ||||
| 				local_num_cells++; | ||||
| 				local_num_cells_by_type[cell_type]++; | ||||
| 				local_area_cells_by_type[cell_type] = 0; | ||||
| 				local_seq_area_cells_by_type[cell_type] = 0; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto &it : mod->processes) { | ||||
| 			if (!design->selected(mod, it.second)) | ||||
| 				continue; | ||||
| 			num_processes++; | ||||
| 			local_num_processes++; | ||||
| 		} | ||||
| 		RTLIL::IdString cell_name = mod->name; | ||||
| 		auto s = cell_name.str(); | ||||
| 	} | ||||
| 
 | ||||
| 	unsigned int estimate_xilinx_lc() | ||||
|  | @ -238,22 +327,119 @@ struct statdata_t | |||
| 		return tran_cnt; | ||||
| 	} | ||||
| 
 | ||||
| 	void log_data(RTLIL::IdString mod_name, bool top_mod) | ||||
| 	/*
 | ||||
| 	format a floating point value to a of 8 characters, with at most 7 digits or scientific notation | ||||
| 	uses - to mark zero or very small values | ||||
| 	*/ | ||||
| 	std::string f_val(double value) | ||||
| 	{ | ||||
| 		log("   Number of wires:             %6u\n", num_wires); | ||||
| 		log("   Number of wire bits:         %6u\n", num_wire_bits); | ||||
| 		log("   Number of public wires:      %6u\n", num_pub_wires); | ||||
| 		log("   Number of public wire bits:  %6u\n", num_pub_wire_bits); | ||||
| 		log("   Number of ports:             %6u\n", num_ports); | ||||
| 		log("   Number of port bits:         %6u\n", num_port_bits); | ||||
| 		log("   Number of memories:          %6u\n", num_memories); | ||||
| 		log("   Number of memory bits:       %6u\n", num_memory_bits); | ||||
| 		log("   Number of processes:         %6u\n", num_processes); | ||||
| 		log("   Number of cells:             %6u\n", num_cells); | ||||
| 		for (auto &it : num_cells_by_type) | ||||
| 			if (it.second) | ||||
| 				log("     %-26s %6u\n", log_id(it.first), it.second); | ||||
| 		if (std::abs(value) < 1e-12) | ||||
| 			return "       -"; | ||||
| 
 | ||||
| 		char buf[16]; | ||||
| 
 | ||||
| 		int len = std::snprintf(buf, sizeof(buf), "%.3f", value); | ||||
| 
 | ||||
| 		while (len > 0 && buf[len - 1] == '0') | ||||
| 			--len; | ||||
| 		if (len > 0 && buf[len - 1] == '.') | ||||
| 			--len; | ||||
| 		buf[len] = '\0'; | ||||
| 
 | ||||
| 		if (len <= 7) { | ||||
| 			return std::string(8 - len, ' ') + std::string(buf); | ||||
| 		} | ||||
| 
 | ||||
| 		// use scientific notation, this should always fit in 8 characters
 | ||||
| 		std::snprintf(buf, sizeof(buf), "%8.3G", value); | ||||
| 
 | ||||
| 		return std::string(buf); | ||||
| 	} | ||||
| 
 | ||||
| 	void print_log_line(const std::string &name, unsigned int count_local, double area_local, unsigned int count_global, double area_global, | ||||
| 			    int spacer = 0, bool print_area = true, bool print_hierarchical = true) | ||||
| 	{ | ||||
| 		const std::string indent(2 * spacer, ' '); | ||||
| 
 | ||||
| 		std::string count_local_str = f_val(static_cast<double>(count_local)); | ||||
| 		std::string count_global_str = f_val(static_cast<double>(count_global)); | ||||
| 		std::string area_local_str = f_val(area_local); | ||||
| 		std::string area_global_str = f_val(area_global); | ||||
| 
 | ||||
| 		if (print_area) { | ||||
| 			if (print_hierarchical) { | ||||
| 				log(" %s %s %s %s %s%s\n", count_global_str.c_str(), area_global_str.c_str(), count_local_str.c_str(), | ||||
| 				    area_local_str.c_str(), indent.c_str(), name.c_str()); | ||||
| 			} else { | ||||
| 				if (count_local > 0) | ||||
| 					log(" %s %s %s%s\n", count_local_str.c_str(), area_local_str.c_str(), indent.c_str(), name.c_str()); | ||||
| 			} | ||||
| 		} else { | ||||
| 			if (print_hierarchical) { | ||||
| 				log(" %s %s %s%s\n", count_global_str.c_str(), count_local_str.c_str(), indent.c_str(), name.c_str()); | ||||
| 			} else { | ||||
| 				if (count_local > 0) | ||||
| 					log(" %s %s%s\n", count_local_str.c_str(), indent.c_str(), name.c_str()); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	void print_log_header(bool print_area = true, bool print_hierarchical = true) | ||||
| 	{ | ||||
| 		if (print_area) { | ||||
| 			if (print_hierarchical) { | ||||
| 				log(" %8s-%8s-%8s-%8s-%s\n", "+", "--------", "--------", "--------", "Count including submodules."); | ||||
| 				log(" %8s %8s-%8s-%8s-%s\n", "|", "+", "--------", "--------", "Area including submodules."); | ||||
| 				log(" %8s %8s %8s-%8s-%s\n", "|", "|", "+", "--------", "Local count, excluding submodules."); | ||||
| 				log(" %8s %8s %8s %8s-%s\n", "|", "|", "|", "+", "Local area, excluding submodules."); | ||||
| 				log(" %8s %8s %8s %8s \n", "|", "|", "|", "|"); | ||||
| 			} else { | ||||
| 				log(" %8s-%8s-%s\n", "+", "--------", "Local Count including submodules."); | ||||
| 				log(" %8s %8s-%s\n", "|", "+", "Local Area including submodules."); | ||||
| 				log(" %8s %8s \n", "|", "|"); | ||||
| 			} | ||||
| 		} else { | ||||
| 			if (print_hierarchical) { | ||||
| 				log(" %8s-%8s-%8s-%s\n", "+", "--------", "--------", "Count including submodules."); | ||||
| 				log(" %8s %8s-%8s-%s\n", "|", "+", "--------", "Local count, excluding submodules."); | ||||
| 				log(" %8s %8s \n", "|", "|"); | ||||
| 			} else { | ||||
| 				log(" %8s-%8s-%s\n", "+", "--------", "Local Count including submodules."); | ||||
| 				log(" %8s \n", "|"); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	void log_data(RTLIL::IdString mod_name, bool top_mod, bool print_area = true, bool print_hierarchical = true) | ||||
| 	{ | ||||
| 
 | ||||
| 		print_log_header(print_area, print_hierarchical); | ||||
| 
 | ||||
| 		print_log_line("wires", local_num_wires, 0, num_wires, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("wire bits", local_num_wire_bits, 0, num_wire_bits, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("public wires", local_num_pub_wires, 0, num_pub_wires, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("public wire bits", local_num_pub_wire_bits, 0, num_pub_wire_bits, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("ports", local_num_ports, 0, num_ports, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("port bits", local_num_port_bits, 0, num_port_bits, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("memories", local_num_memories, 0, num_memories, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("memory bits", local_num_memory_bits, 0, num_memory_bits, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("processes", local_num_processes, 0, num_processes, 0, 0, print_area, print_hierarchical); | ||||
| 		print_log_line("cells", local_num_cells, local_area, num_cells, area, 0, print_area, print_hierarchical); | ||||
| 		for (auto &it : num_cells_by_type) | ||||
| 			if (it.second) { | ||||
| 				auto name = string(log_id(it.first)); | ||||
| 				print_log_line(name, local_num_cells_by_type.count(it.first) ? local_num_cells_by_type.at(it.first) : 0, | ||||
| 					       local_area_cells_by_type.count(it.first) ? local_area_cells_by_type.at(it.first) : 0, it.second, | ||||
| 					       area_cells_by_type.at(it.first), 1, print_area, print_hierarchical); | ||||
| 			} | ||||
| 		if (num_submodules > 0) { | ||||
| 			print_log_line("submodules", num_submodules, 0, num_submodules, submodule_area, 0, print_area, print_hierarchical); | ||||
| 			for (auto &it : num_submodules_by_type) | ||||
| 				if (it.second) | ||||
| 					print_log_line(string(log_id(it.first)), it.second, 0, it.second, | ||||
| 						       submodules_area_by_type.count(it.first) ? submodules_area_by_type.at(it.first) : 0, 1, | ||||
| 						       print_area, print_hierarchical); | ||||
| 		} | ||||
| 		if (!unknown_cell_area.empty()) { | ||||
| 			log("\n"); | ||||
| 			for (auto cell_type : unknown_cell_area) | ||||
|  | @ -263,17 +449,15 @@ struct statdata_t | |||
| 		if (area != 0) { | ||||
| 			log("\n"); | ||||
| 			log("   Chip area for %smodule '%s': %f\n", (top_mod) ? "top " : "", mod_name.c_str(), area); | ||||
| 			log("     of which used for sequential elements: %f (%.2f%%)\n", sequential_area, 100.0*sequential_area/area); | ||||
| 			log("     of which used for sequential elements: %f (%.2f%%)\n", sequential_area, 100.0 * sequential_area / area); | ||||
| 		} | ||||
| 
 | ||||
| 		if (tech == "xilinx") | ||||
| 		{ | ||||
| 		if (tech == "xilinx") { | ||||
| 			log("\n"); | ||||
| 			log("   Estimated number of LCs: %10u\n", estimate_xilinx_lc()); | ||||
| 		} | ||||
| 
 | ||||
| 		if (tech == "cmos") | ||||
| 		{ | ||||
| 		if (tech == "cmos") { | ||||
| 			bool tran_cnt_exact = true; | ||||
| 			unsigned int tran_cnt = cmos_transistor_count(&tran_cnt_exact); | ||||
| 
 | ||||
|  | @ -282,87 +466,203 @@ struct statdata_t | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	void log_data_json(const char *mod_name, bool first_module) | ||||
| 	string json_line(unsigned int count_local, double area_local, unsigned int count_global, double area_global) | ||||
| 	{ | ||||
| 
 | ||||
| 		return stringf("{ \"count\": \"%u\", \"area\": \"%f\", \"local_count\": \"%u\", \"local_area\": \"%f\" }", count_global, area_global, | ||||
| 			       count_local, area_local); | ||||
| 	} | ||||
| 
 | ||||
| 	void log_data_json(const char *mod_name, bool first_module, bool hierarchical = false) | ||||
| 	{ | ||||
| 		if (!first_module) | ||||
| 			log(",\n"); | ||||
| 		log("      %s: {\n", json11::Json(mod_name).dump().c_str()); | ||||
| 		log("         \"num_wires\":         %u,\n", num_wires); | ||||
| 		log("         \"num_wire_bits\":     %u,\n", num_wire_bits); | ||||
| 		log("         \"num_pub_wires\":     %u,\n", num_pub_wires); | ||||
| 		log("         \"num_pub_wire_bits\": %u,\n", num_pub_wire_bits); | ||||
| 		log("         \"num_ports\":         %u,\n", num_ports); | ||||
| 		log("         \"num_port_bits\":     %u,\n", num_port_bits); | ||||
| 		log("         \"num_memories\":      %u,\n", num_memories); | ||||
| 		log("         \"num_memory_bits\":   %u,\n", num_memory_bits); | ||||
| 		log("         \"num_processes\":     %u,\n", num_processes); | ||||
| 		log("         \"num_cells\":         %u,\n", num_cells); | ||||
| 		if (area != 0) { | ||||
| 			log("         \"area\":              %f,\n", area); | ||||
| 		} | ||||
| 		log("         \"num_cells_by_type\": {\n"); | ||||
| 		bool first_line = true; | ||||
| 		for (auto &it : num_cells_by_type) | ||||
| 			if (it.second) { | ||||
| 				if (!first_line) | ||||
| 					log(",\n"); | ||||
| 				log("            %s: %u", json11::Json(log_id(it.first)).dump().c_str(), it.second); | ||||
| 				first_line = false; | ||||
| 		if (hierarchical) { | ||||
| 			log("      %s: {\n", json11::Json(mod_name).dump().c_str()); | ||||
| 			log("         \"num_wires\":         %s,\n", json_line(local_num_wires, 0, num_wires, 0).c_str()); | ||||
| 			log("         \"num_wire_bits\":     %s,\n", json_line(local_num_wire_bits, 0, num_wire_bits, 0).c_str()); | ||||
| 			log("         \"num_pub_wires\":     %s,\n", json_line(local_num_pub_wires, 0, num_pub_wires, 0).c_str()); | ||||
| 			log("         \"num_pub_wire_bits\": %s,\n", json_line(local_num_pub_wire_bits, 0, num_pub_wire_bits, 0).c_str()); | ||||
| 			log("         \"num_ports\":         %s,\n", json_line(local_num_ports, 0, num_ports, 0).c_str()); | ||||
| 			log("         \"num_port_bits\":     %s,\n", json_line(local_num_port_bits, 0, num_port_bits, 0).c_str()); | ||||
| 			log("         \"num_memories\":      %s,\n", json_line(local_num_memories, 0, num_memories, 0).c_str()); | ||||
| 			log("         \"num_memory_bits\":   %s,\n", json_line(local_num_memory_bits, 0, num_memory_bits, 0).c_str()); | ||||
| 			log("         \"num_processes\":     %s,\n", json_line(local_num_processes, 0, num_processes, 0).c_str()); | ||||
| 			log("         \"num_cells\":         %s,\n", json_line(local_num_cells, local_area, num_cells, area).c_str()); | ||||
| 			log("         \"num_submodules\":       %s,\n", json_line(0, 0, num_submodules, submodule_area).c_str()); | ||||
| 			log("         \"sequential_area\":    %s,\n", json_line(0, local_sequential_area, 0, sequential_area).c_str()); | ||||
| 
 | ||||
| 			log("         \"num_cells_by_type\": {\n"); | ||||
| 			bool first_line = true; | ||||
| 			for (auto &it : num_cells_by_type) | ||||
| 				if (it.second) { | ||||
| 					if (!first_line) | ||||
| 						log(",\n"); | ||||
| 					log("            %s: %s", json11::Json(log_id(it.first)).dump().c_str(), | ||||
| 					    json_line(local_num_cells_by_type.count(it.first) ? local_num_cells_by_type.at(it.first) : 0, | ||||
| 						      local_area_cells_by_type.count(it.first) ? local_area_cells_by_type.at(it.first) : 0, it.second, | ||||
| 						      area_cells_by_type.at(it.first)) | ||||
| 					      .c_str()); | ||||
| 					first_line = false; | ||||
| 				} | ||||
| 			log("\n      },\n"); | ||||
| 			log("         \"num_submodules_by_type\": {\n"); | ||||
| 			first_line = true; | ||||
| 			for (auto &it : num_submodules_by_type) | ||||
| 				if (it.second) { | ||||
| 					if (!first_line) | ||||
| 						log(",\n"); | ||||
| 					log("            %s: %s", json11::Json(log_id(it.first)).dump().c_str(), | ||||
| 					    json_line(0, 0, it.second, | ||||
| 						      submodules_area_by_type.count(it.first) ? submodules_area_by_type.at(it.first) : 0) | ||||
| 					      .c_str()); | ||||
| 					first_line = false; | ||||
| 				} | ||||
| 			log("\n      }\n"); | ||||
| 			if (tech == "xilinx") { | ||||
| 				log("         \"estimated_num_lc\": %u,\n", estimate_xilinx_lc()); | ||||
| 			} | ||||
| 		log("\n"); | ||||
| 		log("         }"); | ||||
| 		if (tech == "xilinx") | ||||
| 		{ | ||||
| 			log(",\n"); | ||||
| 			log("         \"estimated_num_lc\": %u", estimate_xilinx_lc()); | ||||
| 			if (tech == "cmos") { | ||||
| 				bool tran_cnt_exact = true; | ||||
| 				unsigned int tran_cnt = cmos_transistor_count(&tran_cnt_exact); | ||||
| 				log("		 \"estimated_num_transistors\": \"%u%s\"\n", tran_cnt, tran_cnt_exact ? "" : "+"); | ||||
| 			} | ||||
| 			log("      }"); | ||||
| 
 | ||||
| 		} else { | ||||
| 
 | ||||
| 			log("      %s: {\n", json11::Json(mod_name).dump().c_str()); | ||||
| 			log("         \"num_wires\":         %u,\n", num_wires); | ||||
| 			log("         \"num_wire_bits\":     %u,\n", num_wire_bits); | ||||
| 			log("         \"num_pub_wires\":     %u,\n", num_pub_wires); | ||||
| 			log("         \"num_pub_wire_bits\": %u,\n", num_pub_wire_bits); | ||||
| 			log("         \"num_ports\":         %u,\n", num_ports); | ||||
| 			log("         \"num_port_bits\":     %u,\n", num_port_bits); | ||||
| 			log("         \"num_memories\":      %u,\n", num_memories); | ||||
| 			log("         \"num_memory_bits\":   %u,\n", num_memory_bits); | ||||
| 			log("         \"num_processes\":     %u,\n", num_processes); | ||||
| 			log("         \"num_cells\":         %u,\n", local_num_cells); | ||||
| 			log("         \"num_submodules\":       %u,\n", num_submodules); | ||||
| 			if (area != 0) { | ||||
| 				log("         \"area\":              %f,\n", area); | ||||
| 				log("         \"sequential_area\":    %f,\n", sequential_area); | ||||
| 			} | ||||
| 			log("         \"num_cells_by_type\": {\n"); | ||||
| 			bool first_line = true; | ||||
| 			for (auto &it : local_num_cells_by_type) | ||||
| 				if (it.second) { | ||||
| 					if (!first_line) | ||||
| 						log(",\n"); | ||||
| 					log("            %s: %u", json11::Json(log_id(it.first)).dump().c_str(), it.second); | ||||
| 					first_line = false; | ||||
| 				} | ||||
| 			for (auto &it : num_submodules_by_type) | ||||
| 				if (it.second) { | ||||
| 					if (!first_line) | ||||
| 						log(",\n"); | ||||
| 					log("            %s: %u", json11::Json(log_id(it.first)).dump().c_str(), it.second); | ||||
| 					first_line = false; | ||||
| 				} | ||||
| 			log("\n"); | ||||
| 			log("         }"); | ||||
| 			if (tech == "xilinx") { | ||||
| 				log(",\n"); | ||||
| 				log("         \"estimated_num_lc\": %u", estimate_xilinx_lc()); | ||||
| 			} | ||||
| 			if (tech == "cmos") { | ||||
| 				bool tran_cnt_exact = true; | ||||
| 				unsigned int tran_cnt = cmos_transistor_count(&tran_cnt_exact); | ||||
| 				log(",\n"); | ||||
| 				log("         \"estimated_num_transistors\": \"%u%s\"", tran_cnt, tran_cnt_exact ? "" : "+"); | ||||
| 			} | ||||
| 			log("\n"); | ||||
| 			log("      }"); | ||||
| 		} | ||||
| 		if (tech == "cmos") | ||||
| 		{ | ||||
| 			bool tran_cnt_exact = true; | ||||
| 			unsigned int tran_cnt = cmos_transistor_count(&tran_cnt_exact); | ||||
| 			log(",\n"); | ||||
| 			log("         \"estimated_num_transistors\": \"%u%s\"", tran_cnt, tran_cnt_exact ? "" : "+"); | ||||
| 		} | ||||
| 		log("\n"); | ||||
| 		log("      }"); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| statdata_t hierarchy_worker(std::map<RTLIL::IdString, statdata_t> &mod_stat, RTLIL::IdString mod, int level, bool quiet = false) | ||||
| statdata_t hierarchy_worker(std::map<RTLIL::IdString, statdata_t> &mod_stat, RTLIL::IdString mod, int level, bool quiet = false, bool has_area = true, | ||||
| 			    bool hierarchy_mode = true) | ||||
| { | ||||
| 	statdata_t mod_data = mod_stat.at(mod); | ||||
| 	std::map<RTLIL::IdString, unsigned int, RTLIL::sort_by_id_str> num_cells_by_type; | ||||
| 	num_cells_by_type.swap(mod_data.num_cells_by_type); | ||||
| 
 | ||||
| 	for (auto &it : num_cells_by_type) | ||||
| 	for (auto &it : mod_data.num_submodules_by_type) { | ||||
| 		if (mod_stat.count(it.first) > 0) { | ||||
| 			if (!quiet) | ||||
| 				log("     %*s%-*s %6u\n", 2*level, "", 26-2*level, log_id(it.first), it.second); | ||||
| 			mod_data = mod_data + hierarchy_worker(mod_stat, it.first, level+1, quiet) * it.second; | ||||
| 			mod_data.num_cells -= it.second; | ||||
| 		} else { | ||||
| 			mod_data.num_cells_by_type[it.first] += it.second; | ||||
| 				mod_data.print_log_line(string(log_id(it.first)), mod_stat.at(it.first).local_num_cells, | ||||
| 							mod_stat.at(it.first).local_area, mod_stat.at(it.first).num_cells, mod_stat.at(it.first).area, | ||||
| 							level, has_area, hierarchy_mode); | ||||
| 			hierarchy_worker(mod_stat, it.first, level + 1, quiet, has_area, hierarchy_mode) * it.second; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return mod_data; | ||||
| } | ||||
| 
 | ||||
| statdata_t hierarchy_builder(const RTLIL::Design *design, const RTLIL::Module *top_mod, std::map<RTLIL::IdString, statdata_t> &mod_stat, | ||||
| 			     bool width_mode, dict<IdString, cell_area_t> &cell_area, string techname) | ||||
| { | ||||
| 	if (top_mod == nullptr) | ||||
| 		top_mod = design->top_module(); | ||||
| 	statdata_t mod_data(design, top_mod, width_mode, cell_area, techname); | ||||
| 	for (auto cell : top_mod->selected_cells()) { | ||||
| 		if (cell_area.count(cell->type) == 0) { | ||||
| 			if (design->has(cell->type)) { | ||||
| 				if (!(design->module(cell->type)->attributes.count(ID::blackbox))) { | ||||
| 					// deal with modules
 | ||||
| 					mod_data.add( | ||||
| 					  hierarchy_builder(design, design->module(cell->type), mod_stat, width_mode, cell_area, techname)); | ||||
| 					mod_data.num_submodules_by_type[cell->type]++; | ||||
| 					mod_data.submodules_area_by_type[cell->type] += mod_stat.at(cell->type).area; | ||||
| 					mod_data.submodule_area += mod_stat.at(cell->type).area; | ||||
| 					mod_data.num_submodules++; | ||||
| 					mod_data.unknown_cell_area.erase(cell->type); | ||||
| 					mod_data.num_cells -= mod_data.num_cells_by_type.erase(cell->type); | ||||
| 					mod_data.area_cells_by_type.erase(cell->type); | ||||
| 					mod_data.local_num_cells -= mod_data.local_num_cells_by_type.erase(cell->type); | ||||
| 					mod_data.local_area_cells_by_type.erase(cell->type); | ||||
| 				} else { | ||||
| 					// deal with blackbox cells
 | ||||
| 					if (design->module(cell->type)->attributes.count(ID::area) && | ||||
| 					    design->module(cell->type)->attributes.at(ID::area).size() == 0) { | ||||
| 						mod_data.num_submodules_by_type[cell->type]++; | ||||
| 						mod_data.num_submodules++; | ||||
| 						mod_data.submodules_area_by_type[cell->type] += | ||||
| 						  double(design->module(cell->type)->attributes.at(ID::area).as_int()); | ||||
| 						mod_data.area += double(design->module(cell->type)->attributes.at(ID::area).as_int()); | ||||
| 						mod_data.unknown_cell_area.erase(cell->type); | ||||
| 					} else { | ||||
| 						mod_data.unknown_cell_area.insert(cell->type); | ||||
| 						mod_data.num_submodules++; | ||||
| 						mod_data.num_submodules_by_type[cell->type]++; | ||||
| 						mod_data.submodules_area_by_type[cell->type] = 0; | ||||
| 						mod_data.seq_area_cells_by_type[cell->type] = 0; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	mod_stat[top_mod->name] = mod_data; | ||||
| 	return mod_data; | ||||
| } | ||||
| 
 | ||||
| void read_liberty_cellarea(dict<IdString, cell_area_t> &cell_area, string liberty_file) | ||||
| { | ||||
| 	std::istream* f = uncompressed(liberty_file.c_str()); | ||||
| 	std::istream *f = uncompressed(liberty_file.c_str()); | ||||
| 	yosys_input_files.insert(liberty_file); | ||||
| 	LibertyParser libparser(*f, liberty_file); | ||||
| 	delete f; | ||||
| 
 | ||||
| 	for (auto cell : libparser.ast->children) | ||||
| 	{ | ||||
| 	for (auto cell : libparser.ast->children) { | ||||
| 		if (cell->id != "cell" || cell->args.size() != 1) | ||||
| 			continue; | ||||
| 
 | ||||
| 		const LibertyAst *ar = cell->find("area"); | ||||
| 		bool is_flip_flop = cell->find("ff") != nullptr; | ||||
| 		if (ar != nullptr && !ar->value.empty()) | ||||
| 			cell_area["\\" + cell->args[0]] = {/*area=*/atof(ar->value.c_str()), is_flip_flop}; | ||||
| 		if (ar != nullptr && !ar->value.empty()) { | ||||
| 			string prefix = cell->args[0].substr(0, 1) == "$" ? "" : "\\"; | ||||
| 			cell_area[prefix + cell->args[0]] = {atof(ar->value.c_str()), is_flip_flop}; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -381,6 +681,7 @@ struct StatPass : public Pass { | |||
| 		log("\n"); | ||||
| 		log("Print some statistics (number of objects) on the selected portion of the\n"); | ||||
| 		log("design.\n"); | ||||
| 		log("Extracts the area of cells from a liberty file, if provided.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -top <module>\n"); | ||||
| 		log("        print design hierarchy with this module as top. if the design is fully\n"); | ||||
|  | @ -402,35 +703,38 @@ struct StatPass : public Pass { | |||
| 		log("        output the statistics in a machine-readable JSON format.\n"); | ||||
| 		log("        this is output to the console; use \"tee\" to output to a file.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -hierarchy\n"); | ||||
| 		log("        print hierarchical statistics, i.e. The area and number of cells include submodules.\n"); | ||||
| 		log(" 	     this changes the format of the json output.\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) override | ||||
| 	{ | ||||
| 		bool width_mode = false, json_mode = false; | ||||
| 		bool width_mode = false, json_mode = false, hierarchy_mode = false; | ||||
| 		RTLIL::Module *top_mod = nullptr; | ||||
| 		std::map<RTLIL::IdString, statdata_t> mod_stat; | ||||
| 		dict<IdString, cell_area_t> cell_area; | ||||
| 		string techname; | ||||
| 
 | ||||
| 		size_t argidx; | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | ||||
| 		{ | ||||
| 		for (argidx = 1; argidx < args.size(); argidx++) { | ||||
| 			if (args[argidx] == "-width") { | ||||
| 				width_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-liberty" && argidx+1 < args.size()) { | ||||
| 			if (args[argidx] == "-liberty" && argidx + 1 < args.size()) { | ||||
| 				string liberty_file = args[++argidx]; | ||||
| 				rewrite_filename(liberty_file); | ||||
| 				read_liberty_cellarea(cell_area, liberty_file); | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-tech" && argidx+1 < args.size()) { | ||||
| 			if (args[argidx] == "-tech" && argidx + 1 < args.size()) { | ||||
| 				techname = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-top" && argidx+1 < args.size()) { | ||||
| 				if (design->module(RTLIL::escape_id(args[argidx+1])) == nullptr) | ||||
| 					log_cmd_error("Can't find module %s.\n", args[argidx+1].c_str()); | ||||
| 			if (args[argidx] == "-top" && argidx + 1 < args.size()) { | ||||
| 				if (design->module(RTLIL::escape_id(args[argidx + 1])) == nullptr) | ||||
| 					log_cmd_error("Can't find module %s.\n", args[argidx + 1].c_str()); | ||||
| 				top_mod = design->module(RTLIL::escape_id(args[++argidx])); | ||||
| 				continue; | ||||
| 			} | ||||
|  | @ -438,11 +742,15 @@ struct StatPass : public Pass { | |||
| 				json_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-hierarchy") { | ||||
| 				hierarchy_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		if(!json_mode) | ||||
| 		if (!json_mode) | ||||
| 			log_header(design, "Printing statistics.\n"); | ||||
| 
 | ||||
| 		if (techname != "" && techname != "xilinx" && techname != "cmos" && !json_mode) | ||||
|  | @ -457,24 +765,40 @@ struct StatPass : public Pass { | |||
| 			log("   \"modules\": {\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		printf("building cell area\n"); | ||||
| 		if (top_mod != nullptr) { | ||||
| 			hierarchy_builder(design, top_mod, mod_stat, width_mode, cell_area, techname); | ||||
| 		} else { | ||||
| 			for (auto mod : design->selected_modules()) { | ||||
| 				if (mod_stat.count(mod->name) == 0) { | ||||
| 					hierarchy_builder(design, mod, mod_stat, width_mode, cell_area, techname); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		printf("built hierarchy\n"); | ||||
| 		bool first_module = true; | ||||
| 		for (auto mod : design->selected_modules()) | ||||
| 		{ | ||||
| 		// determine if anything has a area.
 | ||||
| 		bool has_area = false; | ||||
| 		for (auto &it : mod_stat) { | ||||
| 			if (it.second.area > 0 || it.second.sequential_area > 0) { | ||||
| 				has_area = true; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		for (auto mod : design->selected_modules()) { | ||||
| 			if (!top_mod && design->full_selection()) | ||||
| 				if (mod->get_bool_attribute(ID::top)) | ||||
| 					top_mod = mod; | ||||
| 
 | ||||
| 			statdata_t data(design, mod, width_mode, cell_area, techname); | ||||
| 			mod_stat[mod->name] = data; | ||||
| 
 | ||||
| 			statdata_t data = mod_stat.at(mod->name); | ||||
| 			if (json_mode) { | ||||
| 				data.log_data_json(mod->name.c_str(), first_module); | ||||
| 				data.log_data_json(mod->name.c_str(), first_module, hierarchy_mode); | ||||
| 				first_module = false; | ||||
| 			} else { | ||||
| 				log("\n"); | ||||
| 				log("=== %s%s ===\n", log_id(mod->name), mod->is_selected_whole() ? "" : " (partially selected)"); | ||||
| 				log("\n"); | ||||
| 				data.log_data(mod->name, false); | ||||
| 				data.log_data(mod->name, false, has_area, hierarchy_mode); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | @ -483,22 +807,24 @@ struct StatPass : public Pass { | |||
| 			log(top_mod == nullptr ? "   }\n" : "   },\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		if (top_mod != nullptr) | ||||
| 		{ | ||||
| 		if (top_mod != nullptr) { | ||||
| 			if (!json_mode && GetSize(mod_stat) > 1) { | ||||
| 				log("\n"); | ||||
| 				log("=== design hierarchy ===\n"); | ||||
| 				log("\n"); | ||||
| 				log("   %-28s %6d\n", log_id(top_mod->name), 1); | ||||
| 				mod_stat[top_mod->name].print_log_header(has_area, hierarchy_mode); | ||||
| 				mod_stat[top_mod->name].print_log_line(log_id(top_mod->name), mod_stat[top_mod->name].local_num_cells, | ||||
| 								       mod_stat[top_mod->name].local_area, mod_stat[top_mod->name].num_cells, | ||||
| 								       mod_stat[top_mod->name].area, 0, has_area, hierarchy_mode); | ||||
| 			} | ||||
| 
 | ||||
| 			statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0, /*quiet=*/json_mode); | ||||
| 			statdata_t data = hierarchy_worker(mod_stat, top_mod->name, 0, /*quiet=*/json_mode, has_area, hierarchy_mode); | ||||
| 
 | ||||
| 			if (json_mode) | ||||
| 				data.log_data_json("design", true); | ||||
| 				data.log_data_json("design", true, true); | ||||
| 			else if (GetSize(mod_stat) > 1) { | ||||
| 				log("\n"); | ||||
| 				data.log_data(top_mod->name, true); | ||||
| 				data.log_data(top_mod->name, true, has_area, hierarchy_mode); | ||||
| 			} | ||||
| 
 | ||||
| 			design->scratchpad_set_int("stat.num_wires", data.num_wires); | ||||
|  | @ -520,6 +846,7 @@ struct StatPass : public Pass { | |||
| 		} | ||||
| 
 | ||||
| 		log("\n"); | ||||
| 		printf("processed statistics\n"); | ||||
| 	} | ||||
| } StatPass; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue