mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Redesign of cell cost API
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
		
							parent
							
								
									8110fb9266
								
							
						
					
					
						commit
						100c377451
					
				
					 2 changed files with 102 additions and 98 deletions
				
			
		
							
								
								
									
										158
									
								
								kernel/cost.h
									
										
									
									
									
								
							
							
						
						
									
										158
									
								
								kernel/cost.h
									
										
									
									
									
								
							|  | @ -24,86 +24,92 @@ | |||
| 
 | ||||
| YOSYS_NAMESPACE_BEGIN | ||||
| 
 | ||||
| int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false); | ||||
| 
 | ||||
| inline int get_cell_cost(RTLIL::IdString type, const dict<RTLIL::IdString, RTLIL::Const> ¶meters = dict<RTLIL::IdString, RTLIL::Const>(), | ||||
| 		RTLIL::Design *design = nullptr, dict<RTLIL::IdString, int> *mod_cost_cache = nullptr, bool cmos_cost = false) | ||||
| struct CellCosts | ||||
| { | ||||
| 	static dict<RTLIL::IdString, int> gate_cost = { | ||||
| 		{ "$_BUF_",    1 }, | ||||
| 		{ "$_NOT_",    2 }, | ||||
| 		{ "$_AND_",    4 }, | ||||
| 		{ "$_NAND_",   4 }, | ||||
| 		{ "$_OR_",     4 }, | ||||
| 		{ "$_NOR_",    4 }, | ||||
| 		{ "$_ANDNOT_", 4 }, | ||||
| 		{ "$_ORNOT_",  4 }, | ||||
| 		{ "$_XOR_",    8 }, | ||||
| 		{ "$_XNOR_",   8 }, | ||||
| 		{ "$_AOI3_",   6 }, | ||||
| 		{ "$_OAI3_",   6 }, | ||||
| 		{ "$_AOI4_",   8 }, | ||||
| 		{ "$_OAI4_",   8 }, | ||||
| 		{ "$_MUX_",    4 }, | ||||
| 		{ "$_NMUX_",   4 } | ||||
| 	}; | ||||
| 
 | ||||
| 	// match costs in "stat -tech cmos"
 | ||||
| 	static dict<RTLIL::IdString, int> cmos_gate_cost = { | ||||
| 		{ "$_BUF_",     1 }, | ||||
| 		{ "$_NOT_",     2 }, | ||||
| 		{ "$_AND_",     6 }, | ||||
| 		{ "$_NAND_",    4 }, | ||||
| 		{ "$_OR_",      6 }, | ||||
| 		{ "$_NOR_",     4 }, | ||||
| 		{ "$_ANDNOT_",  6 }, | ||||
| 		{ "$_ORNOT_",   6 }, | ||||
| 		{ "$_XOR_",    12 }, | ||||
| 		{ "$_XNOR_",   12 }, | ||||
| 		{ "$_AOI3_",    6 }, | ||||
| 		{ "$_OAI3_",    6 }, | ||||
| 		{ "$_AOI4_",    8 }, | ||||
| 		{ "$_OAI4_",    8 }, | ||||
| 		{ "$_MUX_",    12 }, | ||||
| 		{ "$_NMUX_",   10 } | ||||
| 	}; | ||||
| 
 | ||||
| 	if (cmos_cost && cmos_gate_cost.count(type)) | ||||
| 		return cmos_gate_cost.at(type); | ||||
| 
 | ||||
| 	if (gate_cost.count(type)) | ||||
| 		return gate_cost.at(type); | ||||
| 
 | ||||
| 	if (parameters.empty() && design && design->module(type)) | ||||
| 	{ | ||||
| 		RTLIL::Module *mod = design->module(type); | ||||
| 
 | ||||
| 		if (mod->attributes.count("\\cost")) | ||||
| 			return mod->attributes.at("\\cost").as_int(); | ||||
| 
 | ||||
| 		dict<RTLIL::IdString, int> local_mod_cost_cache; | ||||
| 		if (mod_cost_cache == nullptr) | ||||
| 			mod_cost_cache = &local_mod_cost_cache; | ||||
| 
 | ||||
| 		if (mod_cost_cache->count(mod->name)) | ||||
| 			return mod_cost_cache->at(mod->name); | ||||
| 
 | ||||
| 		int module_cost = 1; | ||||
| 		for (auto c : mod->cells()) | ||||
| 			module_cost += get_cell_cost(c, mod_cost_cache); | ||||
| 
 | ||||
| 		(*mod_cost_cache)[mod->name] = module_cost; | ||||
| 		return module_cost; | ||||
| 	static const dict<RTLIL::IdString, int>& default_gate_cost() { | ||||
| 		static const dict<RTLIL::IdString, int> db = { | ||||
| 			{ "$_BUF_",    1 }, | ||||
| 			{ "$_NOT_",    2 }, | ||||
| 			{ "$_AND_",    4 }, | ||||
| 			{ "$_NAND_",   4 }, | ||||
| 			{ "$_OR_",     4 }, | ||||
| 			{ "$_NOR_",    4 }, | ||||
| 			{ "$_ANDNOT_", 4 }, | ||||
| 			{ "$_ORNOT_",  4 }, | ||||
| 			{ "$_XOR_",    6 }, | ||||
| 			{ "$_XNOR_",   6 }, | ||||
| 			{ "$_AOI3_",   6 }, | ||||
| 			{ "$_OAI3_",   6 }, | ||||
| 			{ "$_AOI4_",   8 }, | ||||
| 			{ "$_OAI4_",   8 }, | ||||
| 			{ "$_MUX_",    4 }, | ||||
| 			{ "$_NMUX_",   4 } | ||||
| 		}; | ||||
| 		return db; | ||||
| 	} | ||||
| 
 | ||||
| 	log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters)); | ||||
| 	return 1; | ||||
| } | ||||
| 	static const dict<RTLIL::IdString, int>& cmos_gate_cost() { | ||||
| 		static const dict<RTLIL::IdString, int> db = { | ||||
| 			{ "$_BUF_",     1 }, | ||||
| 			{ "$_NOT_",     2 }, | ||||
| 			{ "$_AND_",     6 }, | ||||
| 			{ "$_NAND_",    4 }, | ||||
| 			{ "$_OR_",      6 }, | ||||
| 			{ "$_NOR_",     4 }, | ||||
| 			{ "$_ANDNOT_",  6 }, | ||||
| 			{ "$_ORNOT_",   6 }, | ||||
| 			{ "$_XOR_",    12 }, | ||||
| 			{ "$_XNOR_",   12 }, | ||||
| 			{ "$_AOI3_",    6 }, | ||||
| 			{ "$_OAI3_",    6 }, | ||||
| 			{ "$_AOI4_",    8 }, | ||||
| 			{ "$_OAI4_",    8 }, | ||||
| 			{ "$_MUX_",    12 }, | ||||
| 			{ "$_NMUX_",   10 } | ||||
| 		}; | ||||
| 		return db; | ||||
| 	} | ||||
| 
 | ||||
| inline int get_cell_cost(RTLIL::Cell *cell, dict<RTLIL::IdString, int> *mod_cost_cache, bool cmos_cost) | ||||
| { | ||||
| 	return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache, cmos_cost); | ||||
| } | ||||
| 	dict<RTLIL::IdString, int> mod_cost_cache; | ||||
| 	const dict<RTLIL::IdString, int> *gate_cost = nullptr; | ||||
| 	Design *design = nullptr; | ||||
| 
 | ||||
| 	int get(RTLIL::IdString type) const | ||||
| 	{ | ||||
| 		if (gate_cost && gate_cost->count(type)) | ||||
| 			return gate_cost->at(type); | ||||
| 
 | ||||
| 		log_warning("Can't determine cost of %s cell.\n", log_id(type)); | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	int get(RTLIL::Cell *cell) | ||||
| 	{ | ||||
| 		if (gate_cost && gate_cost->count(cell->type)) | ||||
| 			return gate_cost->at(cell->type); | ||||
| 
 | ||||
| 		if (design && design->module(cell->type) && cell->parameters.empty()) | ||||
| 		{ | ||||
| 			RTLIL::Module *mod = design->module(cell->type); | ||||
| 
 | ||||
| 			if (mod->attributes.count("\\cost")) | ||||
| 				return mod->attributes.at("\\cost").as_int(); | ||||
| 
 | ||||
| 			if (mod_cost_cache.count(mod->name)) | ||||
| 				return mod_cost_cache.at(mod->name); | ||||
| 
 | ||||
| 			int module_cost = 1; | ||||
| 			for (auto c : mod->cells()) | ||||
| 				module_cost += get(c); | ||||
| 
 | ||||
| 			mod_cost_cache[mod->name] = module_cost; | ||||
| 			return module_cost; | ||||
| 		} | ||||
| 
 | ||||
| 		log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters)); | ||||
| 		return 1; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| YOSYS_NAMESPACE_END | ||||
| 
 | ||||
|  |  | |||
|  | @ -931,9 +931,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | |||
| 	{ | ||||
| 		log_header(design, "Executing ABC.\n"); | ||||
| 
 | ||||
| 		auto cell_cost = [](IdString cell_type) { | ||||
| 			return get_cell_cost(cell_type, dict<RTLIL::IdString, RTLIL::Const>(), nullptr, nullptr, cmos_cost); | ||||
| 		}; | ||||
| 		auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost(); | ||||
| 
 | ||||
| 		buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); | ||||
| 		f = fopen(buffer.c_str(), "wt"); | ||||
|  | @ -941,42 +939,42 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin | |||
| 			log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); | ||||
| 		fprintf(f, "GATE ZERO    1 Y=CONST0;\n"); | ||||
| 		fprintf(f, "GATE ONE     1 Y=CONST1;\n"); | ||||
| 		fprintf(f, "GATE BUF    %d Y=A;                  PIN * NONINV  1 999 1 0 1 0\n", cell_cost("$_BUF_")); | ||||
| 		fprintf(f, "GATE NOT    %d Y=!A;                 PIN * INV     1 999 1 0 1 0\n", cell_cost("$_NOT_")); | ||||
| 		fprintf(f, "GATE BUF    %d Y=A;                  PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_BUF_")); | ||||
| 		fprintf(f, "GATE NOT    %d Y=!A;                 PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NOT_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("AND")) | ||||
| 			fprintf(f, "GATE AND    %d Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost("$_AND_")); | ||||
| 			fprintf(f, "GATE AND    %d Y=A*B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_AND_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("NAND")) | ||||
| 			fprintf(f, "GATE NAND   %d Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n", cell_cost("$_NAND_")); | ||||
| 			fprintf(f, "GATE NAND   %d Y=!(A*B);             PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NAND_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("OR")) | ||||
| 			fprintf(f, "GATE OR     %d Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost("$_OR_")); | ||||
| 			fprintf(f, "GATE OR     %d Y=A+B;                PIN * NONINV  1 999 1 0 1 0\n", cell_cost.at("$_OR_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("NOR")) | ||||
| 			fprintf(f, "GATE NOR    %d Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n", cell_cost("$_NOR_")); | ||||
| 			fprintf(f, "GATE NOR    %d Y=!(A+B);             PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_NOR_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("XOR")) | ||||
| 			fprintf(f, "GATE XOR    %d Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_XOR_")); | ||||
| 			fprintf(f, "GATE XOR    %d Y=(A*!B)+(!A*B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("XNOR")) | ||||
| 			fprintf(f, "GATE XNOR   %d Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_XNOR_")); | ||||
| 			fprintf(f, "GATE XNOR   %d Y=(A*B)+(!A*!B);      PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) | ||||
| 			fprintf(f, "GATE ANDNOT %d Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_ANDNOT_")); | ||||
| 			fprintf(f, "GATE ANDNOT %d Y=A*!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("ORNOT")) | ||||
| 			fprintf(f, "GATE ORNOT  %d Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_ORNOT_")); | ||||
| 			fprintf(f, "GATE ORNOT  %d Y=A+!B;               PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("AOI3")) | ||||
| 			fprintf(f, "GATE AOI3   %d Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n", cell_cost("$_AOI3_")); | ||||
| 			fprintf(f, "GATE AOI3   %d Y=!((A*B)+C);         PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_AOI3_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("OAI3")) | ||||
| 			fprintf(f, "GATE OAI3   %d Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n", cell_cost("$_OAI3_")); | ||||
| 			fprintf(f, "GATE OAI3   %d Y=!((A+B)*C);         PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_OAI3_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("AOI4")) | ||||
| 			fprintf(f, "GATE AOI4   %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", cell_cost("$_AOI4_")); | ||||
| 			fprintf(f, "GATE AOI4   %d Y=!((A*B)+(C*D));     PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_AOI4_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("OAI4")) | ||||
| 			fprintf(f, "GATE OAI4   %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", cell_cost("$_OAI4_")); | ||||
| 			fprintf(f, "GATE OAI4   %d Y=!((A+B)*(C+D));     PIN * INV     1 999 1 0 1 0\n", cell_cost.at("$_OAI4_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("MUX")) | ||||
| 			fprintf(f, "GATE MUX    %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_MUX_")); | ||||
| 			fprintf(f, "GATE MUX    %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_")); | ||||
| 		if (enabled_gates.empty() || enabled_gates.count("NMUX")) | ||||
| 			fprintf(f, "GATE NMUX   %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_NMUX_")); | ||||
| 			fprintf(f, "GATE NMUX   %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_")); | ||||
| 		if (map_mux4) | ||||
| 			fprintf(f, "GATE MUX4   %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost("$_MUX_")); | ||||
| 			fprintf(f, "GATE MUX4   %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at("$_MUX_")); | ||||
| 		if (map_mux8) | ||||
| 			fprintf(f, "GATE MUX8   %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost("$_MUX_")); | ||||
| 			fprintf(f, "GATE MUX8   %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at("$_MUX_")); | ||||
| 		if (map_mux16) | ||||
| 			fprintf(f, "GATE MUX16  %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost("$_MUX_")); | ||||
| 			fprintf(f, "GATE MUX16  %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at("$_MUX_")); | ||||
| 		fclose(f); | ||||
| 
 | ||||
| 		if (!lut_costs.empty()) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue