mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Start Tcl design inspection methods
This commit is contained in:
		
							parent
							
								
									8c2d1a16d0
								
							
						
					
					
						commit
						ccd98d21c1
					
				
					 1 changed files with 298 additions and 0 deletions
				
			
		
							
								
								
									
										298
									
								
								kernel/yosys.cc
									
										
									
									
									
								
							
							
						
						
									
										298
									
								
								kernel/yosys.cc
									
										
									
									
									
								
							|  | @ -829,11 +829,309 @@ static int tcl_yosys_cmd(ClientData, Tcl_Interp *interp, int argc, const char *a | ||||||
| 	return TCL_OK; | 	return TCL_OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #define FLAG(name) \ | ||||||
|  | 	if (!strcmp(argv[i], "-" #name)) { \ | ||||||
|  | 		name##_flag = true; \ | ||||||
|  | 		continue; \ | ||||||
|  | 	} \ | ||||||
|  | 
 | ||||||
|  | #define ERROR(str) \ | ||||||
|  | 	{ \ | ||||||
|  | 		Tcl_SetResult(interp, (char *)(str), TCL_STATIC); \ | ||||||
|  | 		return TCL_ERROR; \ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | static int tcl_get_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[]) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	bool mod_flag = false, string_flag = false, int_flag = false, bool_flag = false; | ||||||
|  | 	for (i = 1; i < argc; i++) { | ||||||
|  | 		FLAG(mod) | ||||||
|  | 		FLAG(string) | ||||||
|  | 		FLAG(int) | ||||||
|  | 		FLAG(bool) | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((mod_flag && i != argc - 2) || | ||||||
|  | 			(!mod_flag && i != argc - 3) || | ||||||
|  | 			(string_flag + int_flag + bool_flag > 1)) | ||||||
|  | 		ERROR("bad usage: expected \"get_attr -mod [-string|-int|-bool] <module> <attrname>\"" | ||||||
|  | 			  " or \"get_attr [-string|-int|-bool] <module> <identifier> <attrname>\"") | ||||||
|  | 
 | ||||||
|  | 	IdString mod_id, obj_id, attr_id; | ||||||
|  | 	mod_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	if (!mod_flag) | ||||||
|  | 		obj_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	attr_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 
 | ||||||
|  | 	RTLIL::Module *mod = yosys_design->module(mod_id); | ||||||
|  | 	if (!mod) | ||||||
|  | 		ERROR("module not found") | ||||||
|  | 
 | ||||||
|  | 	RTLIL::AttrObject *obj = nullptr; | ||||||
|  | 	if (mod_flag) { | ||||||
|  | 		obj = mod; | ||||||
|  | 	} else { | ||||||
|  | 		obj = mod->wire(obj_id); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->memories.at(obj_id, nullptr); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->cell(obj_id); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->processes.at(obj_id, nullptr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!obj) | ||||||
|  | 		ERROR("object not found") | ||||||
|  | 
 | ||||||
|  | 	if (string_flag) { | ||||||
|  | 		Tcl_SetResult(interp, (char *) obj->get_string_attribute(attr_id).c_str(), TCL_VOLATILE); | ||||||
|  | 	} else if (int_flag) { | ||||||
|  | 		if (!obj->has_attribute(attr_id)) | ||||||
|  | 			ERROR("attribute missing (required for -int)"); | ||||||
|  | 
 | ||||||
|  | 		RTLIL::Const &value = obj->attributes.at(attr_id); | ||||||
|  | 		if (value.size() > 32) | ||||||
|  | 			ERROR("value too large") | ||||||
|  | 
 | ||||||
|  | 		// FIXME: 32'hffffffff will return as negative despite is_signed=false
 | ||||||
|  | 		Tcl_SetResult(interp, (char *) std::to_string(value.as_int()).c_str(), TCL_VOLATILE); | ||||||
|  | 	} else if (bool_flag) { | ||||||
|  | 		bool value = obj->get_bool_attribute(attr_id); | ||||||
|  | 		Tcl_SetResult(interp, (char *) std::to_string(value).c_str(), TCL_VOLATILE); | ||||||
|  | 	} else { | ||||||
|  | 		if (!obj->has_attribute(attr_id)) | ||||||
|  | 			ERROR("attribute missing (required unless -bool or -string)") | ||||||
|  | 
 | ||||||
|  | 		Tcl_SetResult(interp, (char *) obj->attributes.at(attr_id).as_string().c_str(), TCL_VOLATILE); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return TCL_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tcl_has_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[]) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	bool mod_flag = false; | ||||||
|  | 	for (i = 1; i < argc; i++) { | ||||||
|  | 		FLAG(mod) | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((mod_flag && i != argc - 2) || | ||||||
|  | 			(!mod_flag && i != argc - 3)) | ||||||
|  | 		ERROR("bad usage: expected \"has_attr -mod <module> <attrname>\"" | ||||||
|  | 			  " or \"has_attr <module> <identifier> <attrname>\"") | ||||||
|  | 
 | ||||||
|  | 	IdString mod_id, obj_id, attr_id; | ||||||
|  | 	mod_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	if (!mod_flag) | ||||||
|  | 		obj_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	attr_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 
 | ||||||
|  | 	RTLIL::Module *mod = yosys_design->module(mod_id); | ||||||
|  | 	if (!mod) | ||||||
|  | 		ERROR("module not found") | ||||||
|  | 
 | ||||||
|  | 	RTLIL::AttrObject *obj = nullptr; | ||||||
|  | 	if (mod_flag) { | ||||||
|  | 		obj = mod; | ||||||
|  | 	} else { | ||||||
|  | 		obj = mod->wire(obj_id); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->memories.at(obj_id, nullptr); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->cell(obj_id); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->processes.at(obj_id, nullptr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!obj) | ||||||
|  | 		ERROR("object not found") | ||||||
|  | 
 | ||||||
|  | 	Tcl_SetResult(interp, (char *) std::to_string(obj->has_attribute(attr_id)).c_str(), TCL_VOLATILE); | ||||||
|  | 	return TCL_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tcl_set_attr(ClientData, Tcl_Interp *interp, int argc, const char *argv[]) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	bool mod_flag = false, string_flag = false, int_flag = false, bool_flag = false; | ||||||
|  | 	bool false_flag = false, true_flag = false; | ||||||
|  | 	for (i = 1; i < argc; i++) { | ||||||
|  | 		FLAG(mod) | ||||||
|  | 		FLAG(string) | ||||||
|  | 		FLAG(int) | ||||||
|  | 		FLAG(bool) | ||||||
|  | 		FLAG(false) | ||||||
|  | 		FLAG(true) | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((i != argc - (2 + !mod_flag + !(true_flag || false_flag))) || | ||||||
|  | 			(string_flag + int_flag + bool_flag + true_flag + false_flag > 1)) | ||||||
|  | 		ERROR("bad usage: expected \"set_attr -mod [-string|-int|-bool] <module> <attrname> <value>\"" | ||||||
|  | 			  " or \"set_attr [-string|-int|-bool] <module> <identifier> <attrname> <value>\"" | ||||||
|  | 			  " or \"set_attr [-true|-false] <module> <identifier> <attrname>\"" | ||||||
|  | 			  " or \"set_attr -mod [-true|-false| <module> <attrname>\"") | ||||||
|  | 
 | ||||||
|  | 	IdString mod_id, obj_id, attr_id; | ||||||
|  | 	mod_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	if (!mod_flag) | ||||||
|  | 		obj_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	attr_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 
 | ||||||
|  | 	RTLIL::Module *mod = yosys_design->module(mod_id); | ||||||
|  | 	if (!mod) | ||||||
|  | 		ERROR("module not found") | ||||||
|  | 
 | ||||||
|  | 	RTLIL::AttrObject *obj = nullptr; | ||||||
|  | 	if (mod_flag) { | ||||||
|  | 		obj = mod; | ||||||
|  | 	} else { | ||||||
|  | 		obj = mod->wire(obj_id); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->memories.at(obj_id, nullptr); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->cell(obj_id); | ||||||
|  | 		if (!obj) | ||||||
|  | 			obj = mod->processes.at(obj_id, nullptr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!obj) | ||||||
|  | 		ERROR("object not found") | ||||||
|  | 
 | ||||||
|  | 	if (string_flag) { | ||||||
|  | 		obj->set_string_attribute(attr_id, argv[i++]); | ||||||
|  | 	} else if (int_flag) { | ||||||
|  | 		obj->attributes[attr_id] = atoi(argv[i++]); | ||||||
|  | 	} else if (bool_flag) { | ||||||
|  | 		obj->set_bool_attribute(attr_id, atoi(argv[i++]) != 0); | ||||||
|  | 	} else if (true_flag) { | ||||||
|  | 		obj->set_bool_attribute(attr_id, true); | ||||||
|  | 	} else if (false_flag) { | ||||||
|  | 		obj->set_bool_attribute(attr_id, false); | ||||||
|  | 	} else { | ||||||
|  | 		obj->attributes[attr_id] = Const::from_string(std::string(argv[i++])); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return TCL_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tcl_get_param(ClientData, Tcl_Interp *interp, int argc, const char *argv[]) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	bool string_flag = false, int_flag = false; | ||||||
|  | 	for (i = 1; i < argc; i++) { | ||||||
|  | 		FLAG(string) | ||||||
|  | 		FLAG(int) | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((i != argc - 3) || | ||||||
|  | 			(string_flag + int_flag > 1)) | ||||||
|  | 		ERROR("bad usage: expected \"get_param [-string|-int] <module> <cellid> <paramname>") | ||||||
|  | 
 | ||||||
|  | 	IdString mod_id, cell_id, param_id; | ||||||
|  | 	mod_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	cell_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	param_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 
 | ||||||
|  | 	RTLIL::Module *mod = yosys_design->module(mod_id); | ||||||
|  | 	if (!mod) | ||||||
|  | 		ERROR("module not found") | ||||||
|  | 
 | ||||||
|  | 	RTLIL::Cell *cell = mod->cell(cell_id); | ||||||
|  | 	if (!cell) | ||||||
|  | 		ERROR("object not found") | ||||||
|  | 
 | ||||||
|  | 	if (!cell->hasParam(param_id)) | ||||||
|  | 		ERROR("parameter missing") | ||||||
|  | 
 | ||||||
|  | 	const RTLIL::Const &value = cell->getParam(param_id); | ||||||
|  | 
 | ||||||
|  | 	if (string_flag) { | ||||||
|  | 		Tcl_SetResult(interp, (char *) value.decode_string().c_str(), TCL_VOLATILE); | ||||||
|  | 	} else if (int_flag) { | ||||||
|  | 		if (value.size() > 32) | ||||||
|  | 			ERROR("value too large") | ||||||
|  | 
 | ||||||
|  | 		Tcl_SetResult(interp, (char *) std::to_string(value.as_int()).c_str(), TCL_VOLATILE); | ||||||
|  | 	} else { | ||||||
|  | 		Tcl_SetResult(interp, (char *) value.as_string().c_str(), TCL_VOLATILE); | ||||||
|  | 	} | ||||||
|  | 	return TCL_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int tcl_set_param(ClientData, Tcl_Interp *interp, int argc, const char *argv[]) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	bool string_flag = false, int_flag = false; | ||||||
|  | 	for (i = 1; i < argc; i++) { | ||||||
|  | 		FLAG(string) | ||||||
|  | 		FLAG(int) | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if ((i != argc - 4) || | ||||||
|  | 			(string_flag + int_flag > 1)) | ||||||
|  | 		ERROR("bad usage: expected \"get_param [-string|-int] <module> <cellid> <paramname> <value>") | ||||||
|  | 
 | ||||||
|  | 	IdString mod_id, cell_id, param_id; | ||||||
|  | 	mod_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	cell_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 	param_id = RTLIL::escape_id(argv[i++]); | ||||||
|  | 
 | ||||||
|  | 	RTLIL::Module *mod = yosys_design->module(mod_id); | ||||||
|  | 	if (!mod) | ||||||
|  | 		ERROR("module not found") | ||||||
|  | 
 | ||||||
|  | 	RTLIL::Cell *cell = mod->cell(cell_id); | ||||||
|  | 	if (!cell) | ||||||
|  | 		ERROR("object not found") | ||||||
|  | 
 | ||||||
|  | 	if (string_flag) { | ||||||
|  | 		cell->setParam(param_id, Const(std::string(argv[i++]))); | ||||||
|  | 	} else if (int_flag) { | ||||||
|  | 		cell->setParam(param_id, Const(atoi(argv[i++]))); | ||||||
|  | 	} else { | ||||||
|  | 		cell->setParam(param_id, Const::from_string(std::string(argv[i++]))); | ||||||
|  | 	} | ||||||
|  | 	return TCL_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int yosys_tcl_iterp_init(Tcl_Interp *interp) | int yosys_tcl_iterp_init(Tcl_Interp *interp) | ||||||
| { | { | ||||||
| 	if (Tcl_Init(interp)!=TCL_OK) | 	if (Tcl_Init(interp)!=TCL_OK) | ||||||
| 		log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno())); | 		log_warning("Tcl_Init() call failed - %s\n",Tcl_ErrnoMsg(Tcl_GetErrno())); | ||||||
| 	Tcl_CreateCommand(interp, "yosys", tcl_yosys_cmd, NULL, NULL); | 	Tcl_CreateCommand(interp, "yosys", tcl_yosys_cmd, NULL, NULL); | ||||||
|  | 	Tcl_CreateCommand(interp, "rtlil::get_attr", tcl_get_attr, NULL, NULL); | ||||||
|  | 	Tcl_CreateCommand(interp, "rtlil::has_attr", tcl_has_attr, NULL, NULL); | ||||||
|  | 	Tcl_CreateCommand(interp, "rtlil::set_attr", tcl_set_attr, NULL, NULL); | ||||||
|  | 	Tcl_CreateCommand(interp, "rtlil::get_param", tcl_get_param, NULL, NULL); | ||||||
|  | 	Tcl_CreateCommand(interp, "rtlil::set_param", tcl_set_param, NULL, NULL); | ||||||
|  | 
 | ||||||
|  | 	// TODO:
 | ||||||
|  | 	//
 | ||||||
|  | 	// port_list
 | ||||||
|  | 	// wire_list
 | ||||||
|  | 	// cell_list
 | ||||||
|  | 	// wire_width
 | ||||||
|  | 	//
 | ||||||
|  | 	// add_wire
 | ||||||
|  | 	// add_cell
 | ||||||
|  | 	// rename_wire
 | ||||||
|  | 	// rename_cell
 | ||||||
|  | 	// remove
 | ||||||
|  | 	//
 | ||||||
|  | 	// SigSpec land
 | ||||||
|  | 	//
 | ||||||
|  | 	// get_conn
 | ||||||
|  | 	// set_conn
 | ||||||
|  | 	// unpack
 | ||||||
|  | 	// pack
 | ||||||
|  | 
 | ||||||
| 	return TCL_OK ; | 	return TCL_OK ; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue