mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Support for 'modports' for System Verilog interfaces
This commit is contained in:
		
							parent
							
								
									75009ada3c
								
							
						
					
					
						commit
						458a94059e
					
				
					 8 changed files with 121 additions and 14 deletions
				
			
		|  | @ -1118,7 +1118,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
 | // create a new parametric module (when needed) and return the name of the generated module - WITH support for interfaces
 | ||||||
| RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, bool mayfail) | RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) | ||||||
| { | { | ||||||
| 	AstNode *new_ast = NULL; | 	AstNode *new_ast = NULL; | ||||||
| 	std::string modname = derive_common(design, parameters, &new_ast, mayfail); | 	std::string modname = derive_common(design, parameters, &new_ast, mayfail); | ||||||
|  | @ -1143,14 +1143,46 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R | ||||||
| 		for(auto &intf : interfaces) { | 		for(auto &intf : interfaces) { | ||||||
| 			RTLIL::Module * intfmodule = intf.second; | 			RTLIL::Module * intfmodule = intf.second; | ||||||
| 			std::string intfname = intf.first.str(); | 			std::string intfname = intf.first.str(); | ||||||
|  | 			AstNode *modport = NULL; | ||||||
|  | 			if (modports.count(intfname) > 0) { | ||||||
|  | 				std::string interface_modport = modports.at(intfname).str(); | ||||||
|  | 				AstModule *ast_module_of_interface = (AstModule*)intfmodule; | ||||||
|  | 				AstNode *ast_node_of_interface = ast_module_of_interface->ast; | ||||||
|  | 				for (auto &ch : ast_node_of_interface->children) { | ||||||
|  | 					if (ch->type == AST_MODPORT) { | ||||||
|  | 						if (ch->str == interface_modport) { | ||||||
|  | 							modport = ch; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 			for (auto &wire_it : intfmodule->wires_){ | 			for (auto &wire_it : intfmodule->wires_){ | ||||||
| 				AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); | 				AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true))); | ||||||
| 				std::string origname = log_id(wire_it.first); | 				std::string origname = log_id(wire_it.first); | ||||||
| 				std::string newname = intfname + "." + origname; | 				std::string newname = intfname + "." + origname; | ||||||
| 				wire->str = newname; | 				wire->str = newname; | ||||||
| 				wire->is_input = true; | 				if (modport != NULL) { | ||||||
| 				wire->is_output = true; | 					bool found_in_modport = false; | ||||||
| 				new_ast->children.push_back(wire); | 					for (auto &ch : modport->children) { | ||||||
|  | 						if (ch->type == AST_MODPORTMEMBER) { | ||||||
|  | 							std::string compare_name = "\\" + origname; | ||||||
|  | 							if (ch->str == compare_name) { | ||||||
|  | 								found_in_modport = true; | ||||||
|  | 								wire->is_input = ch->is_input; | ||||||
|  | 								wire->is_output = ch->is_output; | ||||||
|  | 								break; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					if (found_in_modport) { // If not found in modport, do not create port
 | ||||||
|  | 						new_ast->children.push_back(wire); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				else { // If no modport, set inout
 | ||||||
|  | 					wire->is_input = true; | ||||||
|  | 					wire->is_output = true; | ||||||
|  | 					new_ast->children.push_back(wire); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -145,6 +145,8 @@ namespace AST | ||||||
| 		AST_INTERFACE, | 		AST_INTERFACE, | ||||||
| 		AST_INTERFACEPORT, | 		AST_INTERFACEPORT, | ||||||
| 		AST_INTERFACEPORTTYPE, | 		AST_INTERFACEPORTTYPE, | ||||||
|  | 		AST_MODPORT, | ||||||
|  | 		AST_MODPORTMEMBER, | ||||||
| 		AST_PACKAGE | 		AST_PACKAGE | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | @ -287,7 +289,7 @@ namespace AST | ||||||
| 		bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; | 		bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; | ||||||
| 		~AstModule() YS_OVERRIDE; | 		~AstModule() YS_OVERRIDE; | ||||||
| 		RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE; | 		RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE; | ||||||
| 		RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, bool mayfail) YS_OVERRIDE; | 		RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE; | ||||||
| 		std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool mayfail); | 		std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool mayfail); | ||||||
| 		void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE; | 		void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE; | ||||||
| 		RTLIL::Module *clone() const YS_OVERRIDE; | 		RTLIL::Module *clone() const YS_OVERRIDE; | ||||||
|  |  | ||||||
|  | @ -853,6 +853,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | ||||||
| 	case AST_GENIF: | 	case AST_GENIF: | ||||||
| 	case AST_GENCASE: | 	case AST_GENCASE: | ||||||
| 	case AST_PACKAGE: | 	case AST_PACKAGE: | ||||||
|  | 	case AST_MODPORT: | ||||||
|  | 	case AST_MODPORTMEMBER: | ||||||
| 		break; | 		break; | ||||||
| 	case AST_INTERFACEPORT: { | 	case AST_INTERFACEPORT: { | ||||||
| 		// If a port in a module with unknown type is found, mark it as "is_interface=true"
 | 		// If a port in a module with unknown type is found, mark it as "is_interface=true"
 | ||||||
|  | @ -865,6 +867,33 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | ||||||
| 		wire->port_input = true; | 		wire->port_input = true; | ||||||
| 		wire->port_output = true; | 		wire->port_output = true; | ||||||
| 		wire->set_bool_attribute("\\is_interface"); | 		wire->set_bool_attribute("\\is_interface"); | ||||||
|  | 		if (children.size() > 0) { | ||||||
|  | 			for(size_t i=0; i<children.size();i++) { | ||||||
|  | 				if(children[i]->type == AST_INTERFACEPORTTYPE) { | ||||||
|  | 					std::string name_type = children[i]->str; | ||||||
|  | 					size_t ndots = std::count(name_type.begin(), name_type.end(), '.'); | ||||||
|  | 					if (ndots == 0) { | ||||||
|  | 						wire->attributes["\\interface_type"] = name_type; | ||||||
|  | 					} | ||||||
|  | 					else { | ||||||
|  | 						std::stringstream name_type_stream(name_type); | ||||||
|  | 						std::string segment; | ||||||
|  | 						std::vector<std::string> seglist; | ||||||
|  | 						while(std::getline(name_type_stream, segment, '.')) { | ||||||
|  | 							seglist.push_back(segment); | ||||||
|  | 						} | ||||||
|  | 						if (ndots == 1) { | ||||||
|  | 							wire->attributes["\\interface_type"] = seglist[0]; | ||||||
|  | 							wire->attributes["\\interface_modport"] = seglist[1]; | ||||||
|  | 						} | ||||||
|  | 						else { | ||||||
|  | 							log_error("More than two '.' in signal port type (%s)\n", name_type.c_str()); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		wire->upto = 0; | 		wire->upto = 0; | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
|  | @ -61,6 +61,7 @@ namespace VERILOG_FRONTEND { | ||||||
| 	bool noassert_mode, noassume_mode, norestrict_mode; | 	bool noassert_mode, noassume_mode, norestrict_mode; | ||||||
| 	bool assume_asserts_mode, assert_assumes_mode; | 	bool assume_asserts_mode, assert_assumes_mode; | ||||||
| 	bool current_wire_rand, current_wire_const; | 	bool current_wire_rand, current_wire_const; | ||||||
|  | 	bool current_modport_input, current_modport_output; | ||||||
| 	std::istream *lexin; | 	std::istream *lexin; | ||||||
| } | } | ||||||
| YOSYS_NAMESPACE_END | YOSYS_NAMESPACE_END | ||||||
|  | @ -1325,7 +1326,16 @@ opt_stmt_label: | ||||||
| 	TOK_ID ':' | /* empty */; | 	TOK_ID ':' | /* empty */; | ||||||
| 
 | 
 | ||||||
| modport_stmt: | modport_stmt: | ||||||
|     TOK_MODPORT TOK_ID modport_args_opt ';' |     TOK_MODPORT TOK_ID { | ||||||
|  |         AstNode *modport = new AstNode(AST_MODPORT); | ||||||
|  |         ast_stack.back()->children.push_back(modport); | ||||||
|  |         ast_stack.push_back(modport); | ||||||
|  |         modport->str = *$2; | ||||||
|  |         delete $2; | ||||||
|  |     }  modport_args_opt { | ||||||
|  |         ast_stack.pop_back(); | ||||||
|  |         log_assert(ast_stack.size() == 2); | ||||||
|  |     } ';' | ||||||
| 
 | 
 | ||||||
| modport_args_opt: | modport_args_opt: | ||||||
|     '(' ')' | '(' modport_args optional_comma ')'; |     '(' ')' | '(' modport_args optional_comma ')'; | ||||||
|  | @ -1334,11 +1344,19 @@ modport_args: | ||||||
|     modport_arg | modport_args ',' modport_arg; |     modport_arg | modport_args ',' modport_arg; | ||||||
| 
 | 
 | ||||||
| modport_arg: | modport_arg: | ||||||
|     modport_type_token TOK_ID | |     modport_type_token TOK_ID { | ||||||
|  |         AstNode *modport_member = new AstNode(AST_MODPORTMEMBER); | ||||||
|  |         ast_stack.back()->children.push_back(modport_member); | ||||||
|  |         modport_member->str = *$2; | ||||||
|  |         modport_member->is_input = current_modport_input; | ||||||
|  |         modport_member->is_output = current_modport_output; | ||||||
|  |         delete $2; | ||||||
|  |     } | | ||||||
|     TOK_ID |     TOK_ID | ||||||
|  |     /* FIXME for TOK_ID without modport_type_token */ | ||||||
| 
 | 
 | ||||||
| modport_type_token: | modport_type_token: | ||||||
|     TOK_INPUT | TOK_OUTPUT |     TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;} | ||||||
| 
 | 
 | ||||||
| assert: | assert: | ||||||
| 	opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { | 	opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { | ||||||
|  |  | ||||||
|  | @ -654,7 +654,7 @@ RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLI | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, dict<RTLIL::IdString, RTLIL::Module*> , bool mayfail) | RTLIL::IdString RTLIL::Module::derive(RTLIL::Design*, dict<RTLIL::IdString, RTLIL::Const>, dict<RTLIL::IdString, RTLIL::Module*>, dict<RTLIL::IdString, RTLIL::IdString>, bool mayfail) | ||||||
| { | { | ||||||
| 	if (mayfail) | 	if (mayfail) | ||||||
| 		return RTLIL::IdString(); | 		return RTLIL::IdString(); | ||||||
|  |  | ||||||
|  | @ -907,7 +907,7 @@ public: | ||||||
| 	Module(); | 	Module(); | ||||||
| 	virtual ~Module(); | 	virtual ~Module(); | ||||||
| 	virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail = false); | 	virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail = false); | ||||||
| 	virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, bool mayfail = false); | 	virtual RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail = false); | ||||||
| 	virtual size_t count_id(RTLIL::IdString id); | 	virtual size_t count_id(RTLIL::IdString id); | ||||||
| 	virtual void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces); | 	virtual void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -174,6 +174,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check | ||||||
| 			cell->type = cell->type.str().substr(pos_type + 1); | 			cell->type = cell->type.str().substr(pos_type + 1); | ||||||
| 		} | 		} | ||||||
| 		dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule; | 		dict<RTLIL::IdString, RTLIL::Module*> interfaces_to_add_to_submodule; | ||||||
|  | 		dict<RTLIL::IdString, RTLIL::IdString> modports_used_in_submodule; | ||||||
| 
 | 
 | ||||||
| 		if (design->modules_.count(cell->type) == 0) | 		if (design->modules_.count(cell->type) == 0) | ||||||
| 		{ | 		{ | ||||||
|  | @ -224,6 +225,14 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check | ||||||
| 		// some lists, so that they can be replaced further down:
 | 		// some lists, so that they can be replaced further down:
 | ||||||
| 		for (auto &conn : cell->connections()) { | 		for (auto &conn : cell->connections()) { | ||||||
| 			if(mod->wires_.count(conn.first) != 0 && mod->wire(conn.first)->get_bool_attribute("\\is_interface")) { // Check if the connection is present as an interface in the sub-module's port list
 | 			if(mod->wires_.count(conn.first) != 0 && mod->wire(conn.first)->get_bool_attribute("\\is_interface")) { // Check if the connection is present as an interface in the sub-module's port list
 | ||||||
|  | 				//const pool<string> &interface_type_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_type");
 | ||||||
|  | 				//for (auto &d : interface_type_pool) { // TODO: Compare interface type to type in parent module
 | ||||||
|  | 				//}
 | ||||||
|  | 				const pool<string> &interface_modport_pool = mod->wire(conn.first)->get_strpool_attribute("\\interface_modport"); | ||||||
|  | 				std::string interface_modport = ""; | ||||||
|  | 				for (auto &d : interface_modport_pool) { | ||||||
|  | 					interface_modport = "\\" + d; | ||||||
|  | 				} | ||||||
| 				if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute("\\is_interface")) { | 				if(conn.second.bits().size() == 1 && conn.second.bits()[0].wire->get_bool_attribute("\\is_interface")) { | ||||||
| 					std::string interface_name_str = conn.second.bits()[0].wire->name.str(); | 					std::string interface_name_str = conn.second.bits()[0].wire->name.str(); | ||||||
| 					interface_name_str.replace(0,23,""); | 					interface_name_str.replace(0,23,""); | ||||||
|  | @ -247,6 +256,9 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check | ||||||
| 						} | 						} | ||||||
| 						connections_to_remove.push_back(conn.first); | 						connections_to_remove.push_back(conn.first); | ||||||
| 						interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name); | 						interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name); | ||||||
|  | 						if (interface_modport != "") { | ||||||
|  | 							modports_used_in_submodule[conn.first] = interface_modport; | ||||||
|  | 						} | ||||||
| 					  } | 					  } | ||||||
| 					  else will_do_step = true; | 					  else will_do_step = true; | ||||||
| 					} | 					} | ||||||
|  | @ -322,7 +334,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		cell->type = mod->derive(design, cell->parameters, interfaces_to_add_to_submodule); | 		cell->type = mod->derive(design, cell->parameters, interfaces_to_add_to_submodule, modports_used_in_submodule); | ||||||
| 		cell->parameters.clear(); | 		cell->parameters.clear(); | ||||||
| 		did_something = true; | 		did_something = true; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ module TopModule( | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|   assign MyInterfaceInstance.setting = 1; |   assign MyInterfaceInstance.setting = 1; | ||||||
|   assign MyInterfaceInstance.other_setting[2:0] = 3'b101; | //  assign MyInterfaceInstance.other_setting[2:0] = 3'b101;
 | ||||||
| 
 | 
 | ||||||
| endmodule | endmodule | ||||||
| 
 | 
 | ||||||
|  | @ -32,13 +32,25 @@ interface MyInterface #( | ||||||
| 
 | 
 | ||||||
|   logic [1:0] mysig_out; |   logic [1:0] mysig_out; | ||||||
| 
 | 
 | ||||||
|  |     modport submodule1 ( | ||||||
|  |         input  setting, | ||||||
|  |         output other_setting, | ||||||
|  |         output mysig_out | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     modport submodule2 ( | ||||||
|  |         input  setting, | ||||||
|  |         output other_setting, | ||||||
|  |         input  mysig_out | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
| endinterface | endinterface | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| module SubModule1( | module SubModule1( | ||||||
|     input logic clk, |     input logic clk, | ||||||
|     input logic rst, |     input logic rst, | ||||||
|     MyInterface u_MyInterface, |     MyInterface.submodule1 u_MyInterface, | ||||||
|     input logic [1:0] sig |     input logic [1:0] sig | ||||||
| 
 | 
 | ||||||
|   ); |   ); | ||||||
|  | @ -68,9 +80,11 @@ module SubModule2( | ||||||
| 
 | 
 | ||||||
|     input logic clk, |     input logic clk, | ||||||
|     input logic rst, |     input logic rst, | ||||||
|     MyInterface u_MyInterfaceInSub2, |     MyInterface.submodule2 u_MyInterfaceInSub2, | ||||||
|     input logic [1:0] sig |     input logic [1:0] sig | ||||||
| 
 | 
 | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|  |    assign u_MyInterfaceInSub2.other_setting[2:0] = 9; | ||||||
|  | 
 | ||||||
| endmodule | endmodule | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue