mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Use "(id)" instead of "id" for types as temporary hack
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
		
						commit
						e84cedfae4
					
				
					 17 changed files with 315 additions and 20 deletions
				
			
		
							
								
								
									
										1
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -708,6 +708,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) | |||
| 	+cd tests/various && bash run-test.sh | ||||
| 	+cd tests/sat && bash run-test.sh | ||||
| 	+cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/svtypes && bash run-test.sh $(SEEDOPT) | ||||
| 	+cd tests/proc && bash run-test.sh | ||||
| 	+cd tests/opt && bash run-test.sh | ||||
| 	+cd tests/aiger && bash run-test.sh $(ABCOPT) | ||||
|  |  | |||
|  | @ -510,6 +510,8 @@ from SystemVerilog: | |||
|   into a design with ``read_verilog``, all its packages are available to | ||||
|   SystemVerilog files being read into the same design afterwards. | ||||
| 
 | ||||
| - typedefs are supported (including inside packages) | ||||
| 
 | ||||
| - SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether | ||||
|   ports are inputs or outputs are supported. | ||||
| 
 | ||||
|  |  | |||
|  | @ -164,6 +164,8 @@ std::string AST::type2str(AstNodeType type) | |||
| 	X(AST_MODPORT) | ||||
| 	X(AST_MODPORTMEMBER) | ||||
| 	X(AST_PACKAGE) | ||||
| 	X(AST_WIRETYPE) | ||||
| 	X(AST_TYPEDEF) | ||||
| #undef X | ||||
| 	default: | ||||
| 		log_abort(); | ||||
|  | @ -206,6 +208,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch | |||
| 	was_checked = false; | ||||
| 	range_valid = false; | ||||
| 	range_swapped = false; | ||||
| 	is_custom_type = false; | ||||
| 	port_id = 0; | ||||
| 	range_left = -1; | ||||
| 	range_right = 0; | ||||
|  |  | |||
|  | @ -148,7 +148,10 @@ namespace AST | |||
| 		AST_INTERFACEPORTTYPE, | ||||
| 		AST_MODPORT, | ||||
| 		AST_MODPORTMEMBER, | ||||
| 		AST_PACKAGE | ||||
| 		AST_PACKAGE, | ||||
| 
 | ||||
| 		AST_WIRETYPE, | ||||
| 		AST_TYPEDEF | ||||
| 	}; | ||||
| 
 | ||||
| 	// convert an node type to a string (e.g. for debug output)
 | ||||
|  | @ -174,7 +177,7 @@ namespace AST | |||
| 		// node content - most of it is unused in most node types
 | ||||
| 		std::string str; | ||||
| 		std::vector<RTLIL::State> bits; | ||||
| 		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized; | ||||
| 		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, is_wand, is_wor, range_valid, range_swapped, was_checked, is_unsized, is_custom_type; | ||||
| 		int port_id, range_left, range_right; | ||||
| 		uint32_t integer; | ||||
| 		double realvalue; | ||||
|  |  | |||
|  | @ -863,6 +863,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | |||
| 	case AST_PACKAGE: | ||||
| 	case AST_MODPORT: | ||||
| 	case AST_MODPORTMEMBER: | ||||
| 	case AST_TYPEDEF: | ||||
| 		break; | ||||
| 	case AST_INTERFACEPORT: { | ||||
| 		// If a port in a module with unknown type is found, mark it with the attribute 'is_interface'
 | ||||
|  |  | |||
|  | @ -318,7 +318,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 	} | ||||
| 
 | ||||
| 	// activate const folding if this is anything that must be evaluated statically (ranges, parameters, attributes, etc.)
 | ||||
| 	if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX) | ||||
| 	if (type == AST_WIRE || type == AST_PARAMETER || type == AST_LOCALPARAM || type == AST_DEFPARAM || type == AST_PARASET || type == AST_RANGE || type == AST_PREFIX || type == AST_TYPEDEF) | ||||
| 		const_fold = true; | ||||
| 	if (type == AST_IDENTIFIER && current_scope.count(str) > 0 && (current_scope[str]->type == AST_PARAMETER || current_scope[str]->type == AST_LOCALPARAM)) | ||||
| 		const_fold = true; | ||||
|  | @ -336,6 +336,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 		std::map<std::string, AstNode*> this_wire_scope; | ||||
| 		for (size_t i = 0; i < children.size(); i++) { | ||||
| 			AstNode *node = children[i]; | ||||
| 
 | ||||
| 			if (node->type == AST_WIRE) { | ||||
| 				if (node->children.size() == 1 && node->children[0]->type == AST_RANGE) { | ||||
| 					for (auto c : node->children[0]->children) { | ||||
|  | @ -405,14 +406,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 				this_wire_scope[node->str] = node; | ||||
| 			} | ||||
| 			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_GENVAR || | ||||
| 					node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL) { | ||||
| 					node->type == AST_MEMORY || node->type == AST_FUNCTION || node->type == AST_TASK || node->type == AST_DPI_FUNCTION || node->type == AST_CELL || | ||||
| 					node->type == AST_TYPEDEF) { | ||||
| 				backup_scope[node->str] = current_scope[node->str]; | ||||
| 				current_scope[node->str] = node; | ||||
| 			} | ||||
| 		} | ||||
| 		for (size_t i = 0; i < children.size(); i++) { | ||||
| 			AstNode *node = children[i]; | ||||
| 			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY) | ||||
| 			if (node->type == AST_PARAMETER || node->type == AST_LOCALPARAM || node->type == AST_WIRE || node->type == AST_AUTOWIRE || node->type == AST_MEMORY || node->type == AST_TYPEDEF) | ||||
| 				while (node->simplify(true, false, false, 1, -1, false, node->type == AST_PARAMETER || node->type == AST_LOCALPARAM)) | ||||
| 					did_something = true; | ||||
| 		} | ||||
|  | @ -780,6 +782,99 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 		delete_children(); | ||||
| 	} | ||||
| 
 | ||||
| 	// resolve typedefs
 | ||||
| 	if (type == AST_TYPEDEF) { | ||||
| 		log_assert(children.size() == 1); | ||||
| 		log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY); | ||||
| 		while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) | ||||
| 			did_something = true; | ||||
| 		log_assert(!children[0]->is_custom_type); | ||||
| 	} | ||||
| 
 | ||||
| 	// resolve types of wires
 | ||||
| 	if (type == AST_WIRE || type == AST_MEMORY) { | ||||
| 		if (is_custom_type) { | ||||
| 			log_assert(children.size() >= 1); | ||||
| 			log_assert(children[0]->type == AST_WIRETYPE); | ||||
| 			if (!current_scope.count(children[0]->str)) | ||||
| 				log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[0]->str.c_str()); | ||||
| 			AstNode *resolved_type = current_scope.at(children[0]->str); | ||||
| 			if (resolved_type->type != AST_TYPEDEF) | ||||
| 				log_file_error(filename, linenum, "`%s' does not name a type\n", children[0]->str.c_str()); | ||||
| 			log_assert(resolved_type->children.size() == 1); | ||||
| 			AstNode *templ = resolved_type->children[0]; | ||||
| 			// Remove type reference
 | ||||
| 			delete children[0]; | ||||
| 			children.erase(children.begin()); | ||||
| 
 | ||||
| 			// Ensure typedef itself is fully simplified
 | ||||
| 			while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; | ||||
| 
 | ||||
| 			if (type == AST_WIRE) | ||||
| 				type = templ->type; | ||||
| 			is_reg = templ->is_reg; | ||||
| 			is_logic = templ->is_logic; | ||||
| 			is_signed = templ->is_signed; | ||||
| 			is_string = templ->is_string; | ||||
| 			is_custom_type = templ->is_custom_type; | ||||
| 
 | ||||
| 			range_valid = templ->range_valid; | ||||
| 			range_swapped = templ->range_swapped; | ||||
| 			range_left = templ->range_left; | ||||
| 			range_right = templ->range_right; | ||||
| 
 | ||||
| 			// Insert clones children from template at beginning
 | ||||
| 			for (int i  = 0; i < GetSize(templ->children); i++) | ||||
| 				children.insert(children.begin() + i, templ->children[i]->clone()); | ||||
| 			 | ||||
| 			if (type == AST_MEMORY && GetSize(children) == 1) { | ||||
| 				// Single-bit memories must have [0:0] range
 | ||||
| 				AstNode *rng = new AstNode(AST_RANGE); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				children.insert(children.begin(), rng); | ||||
| 			} | ||||
| 
 | ||||
| 			did_something = true; | ||||
| 		} | ||||
| 		log_assert(!is_custom_type); | ||||
| 	} | ||||
| 
 | ||||
| 	// resolve types of parameters
 | ||||
| 	if (type == AST_LOCALPARAM || type == AST_PARAMETER) { | ||||
| 		if (is_custom_type) { | ||||
| 			log_assert(children.size() == 2); | ||||
| 			log_assert(children[1]->type == AST_WIRETYPE); | ||||
| 			if (!current_scope.count(children[1]->str)) | ||||
| 				log_file_error(filename, linenum, "Unknown identifier `%s' used as type name\n", children[1]->str.c_str()); | ||||
| 			AstNode *resolved_type = current_scope.at(children[1]->str); | ||||
| 			if (resolved_type->type != AST_TYPEDEF) | ||||
| 				log_file_error(filename, linenum, "`%s' does not name a type\n", children[1]->str.c_str()); | ||||
| 			log_assert(resolved_type->children.size() == 1); | ||||
| 			AstNode *templ = resolved_type->children[0]; | ||||
| 			delete children[1]; | ||||
| 			children.pop_back(); | ||||
| 
 | ||||
| 			// Ensure typedef itself is fully simplified
 | ||||
| 			while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {}; | ||||
| 
 | ||||
| 			if (templ->type == AST_MEMORY) | ||||
| 				log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str()); | ||||
| 			is_signed = templ->is_signed; | ||||
| 			is_string = templ->is_string; | ||||
| 			is_custom_type = templ->is_custom_type; | ||||
| 
 | ||||
| 			range_valid = templ->range_valid; | ||||
| 			range_swapped = templ->range_swapped; | ||||
| 			range_left = templ->range_left; | ||||
| 			range_right = templ->range_right; | ||||
| 			for (auto template_child : templ->children) | ||||
| 				children.push_back(template_child->clone()); | ||||
| 			did_something = true; | ||||
| 		} | ||||
| 		log_assert(!is_custom_type); | ||||
| 	}	 | ||||
| 
 | ||||
| 	// resolve constant prefixes
 | ||||
| 	if (type == AST_PREFIX) { | ||||
| 		if (children[0]->type != AST_CONSTANT) { | ||||
|  | @ -1194,7 +1289,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 	if (type == AST_BLOCK && str.empty()) | ||||
| 	{ | ||||
| 		for (size_t i = 0; i < children.size(); i++) | ||||
| 			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) | ||||
| 			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) | ||||
| 				log_file_error(children[i]->filename, children[i]->linenum, "Local declaration in unnamed block is an unsupported SystemVerilog feature!\n"); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1206,7 +1301,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 
 | ||||
| 		std::vector<AstNode*> new_children; | ||||
| 		for (size_t i = 0; i < children.size(); i++) | ||||
| 			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM) { | ||||
| 			if (children[i]->type == AST_WIRE || children[i]->type == AST_MEMORY || children[i]->type == AST_PARAMETER || children[i]->type == AST_LOCALPARAM || children[i]->type == AST_TYPEDEF) { | ||||
| 				children[i]->simplify(false, false, false, stage, -1, false, false); | ||||
| 				current_ast_mod->children.push_back(children[i]); | ||||
| 				current_scope[children[i]->str] = children[i]; | ||||
|  | @ -2906,7 +3001,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL) && name_map.count(str) > 0) | ||||
| 	if ((type == AST_IDENTIFIER || type == AST_FCALL || type == AST_TCALL || type == AST_WIRETYPE) && name_map.count(str) > 0) | ||||
| 		str = name_map[str]; | ||||
| 
 | ||||
| 	std::map<std::string, std::string> backup_name_map; | ||||
|  | @ -2914,7 +3009,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma | |||
| 	for (size_t i = 0; i < children.size(); i++) { | ||||
| 		AstNode *child = children[i]; | ||||
| 		if (child->type == AST_WIRE || child->type == AST_MEMORY || child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || | ||||
| 				child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL) { | ||||
| 				child->type == AST_FUNCTION || child->type == AST_TASK || child->type == AST_CELL || child->type == AST_TYPEDEF) { | ||||
| 			if (backup_name_map.size() == 0) | ||||
| 				backup_name_map = name_map; | ||||
| 			std::string new_name = prefix[0] == '\\' ? prefix.substr(1) : prefix; | ||||
|  | @ -2945,6 +3040,7 @@ void AstNode::expand_genblock(std::string index_var, std::string prefix, std::ma | |||
| 			child->expand_genblock(index_var, prefix, name_map); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	if (backup_name_map.size() > 0) | ||||
| 		name_map.swap(backup_name_map); | ||||
| } | ||||
|  | @ -2998,6 +3094,9 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg | |||
| 	uint32_t children_flags = 0; | ||||
| 	int lhs_children_counter = 0; | ||||
| 
 | ||||
| 	if (type == AST_TYPEDEF) | ||||
| 		return; // don't touch content of typedefs
 | ||||
| 
 | ||||
| 	if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) | ||||
| 	{ | ||||
| 		// mark all memories that are used in a complex expression on the left side of an assignment
 | ||||
|  | @ -3155,6 +3254,9 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, | |||
| 	if (type == AST_FUNCTION || type == AST_TASK) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (type == AST_TYPEDEF) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast)) | ||||
| 	{ | ||||
| 		log_assert(children[0]->type == AST_CONSTANT); | ||||
|  |  | |||
|  | @ -155,7 +155,7 @@ struct specify_rise_fall { | |||
| 
 | ||||
| %type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int | ||||
| %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list | ||||
| %type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id | ||||
| %type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id | ||||
| %type <boolean> opt_signed opt_property unique_case_attr | ||||
| %type <al> attr case_attr | ||||
| 
 | ||||
|  | @ -206,6 +206,7 @@ design: | |||
| 	task_func_decl design | | ||||
| 	param_decl design | | ||||
| 	localparam_decl design | | ||||
| 	typedef_decl design | | ||||
| 	package design | | ||||
| 	interface design | | ||||
| 	/* empty */; | ||||
|  | @ -290,6 +291,9 @@ hierarchical_id: | |||
| 		$$ = $1; | ||||
| 	}; | ||||
| 
 | ||||
| hierarchical_type_id: | ||||
| 	'(' hierarchical_id ')' { $$ = $2; }; | ||||
| 
 | ||||
| module: | ||||
| 	attr TOK_MODULE TOK_ID { | ||||
| 		do_not_require_port_stubs = false; | ||||
|  | @ -324,13 +328,13 @@ single_module_para: | |||
| 		astbuf1 = new AstNode(AST_PARAMETER); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 		append_attr(astbuf1, $1); | ||||
| 	} param_signed param_integer param_range single_param_decl | | ||||
| 	} param_type single_param_decl | | ||||
| 	attr TOK_LOCALPARAM { | ||||
| 		if (astbuf1) delete astbuf1; | ||||
| 		astbuf1 = new AstNode(AST_LOCALPARAM); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 		append_attr(astbuf1, $1); | ||||
| 	} param_signed param_integer param_range single_param_decl | | ||||
| 	} param_type single_param_decl | | ||||
| 	single_param_decl; | ||||
| 
 | ||||
| module_args_opt: | ||||
|  | @ -426,6 +430,7 @@ package_body: | |||
| 	package_body package_body_stmt |; | ||||
| 
 | ||||
| package_body_stmt: | ||||
| 	typedef_decl | | ||||
| 	localparam_decl; | ||||
| 
 | ||||
| interface: | ||||
|  | @ -452,7 +457,7 @@ interface_body: | |||
| 	interface_body interface_body_stmt |; | ||||
| 
 | ||||
| interface_body_stmt: | ||||
| 	param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | | ||||
| 	param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | | ||||
| 	modport_stmt; | ||||
| 
 | ||||
| non_opt_delay: | ||||
|  | @ -475,8 +480,14 @@ wire_type: | |||
| 	}; | ||||
| 
 | ||||
| wire_type_token_list: | ||||
| 	wire_type_token | wire_type_token_list wire_type_token | | ||||
| 	wire_type_token_io ; | ||||
| 	wire_type_token | | ||||
| 	wire_type_token_list wire_type_token | | ||||
| 	wire_type_token_io | | ||||
| 	hierarchical_type_id { | ||||
| 		astbuf3->is_custom_type = true; | ||||
| 		astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); | ||||
| 		astbuf3->children.back()->str = *$1; | ||||
| 	}; | ||||
| 
 | ||||
| wire_type_token_io: | ||||
| 	TOK_INPUT { | ||||
|  | @ -591,7 +602,7 @@ module_body: | |||
| 	/* empty */; | ||||
| 
 | ||||
| module_body_stmt: | ||||
| 	task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | | ||||
| 	task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | | ||||
| 	always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; | ||||
| 
 | ||||
| checker_decl: | ||||
|  | @ -1149,12 +1160,20 @@ param_range: | |||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| param_type: | ||||
| 	param_signed param_integer param_real param_range | | ||||
| 	hierarchical_type_id { | ||||
| 		astbuf1->is_custom_type = true; | ||||
| 		astbuf1->children.push_back(new AstNode(AST_WIRETYPE)); | ||||
| 		astbuf1->children.back()->str = *$1; | ||||
| 	}; | ||||
| 
 | ||||
| param_decl: | ||||
| 	attr TOK_PARAMETER { | ||||
| 		astbuf1 = new AstNode(AST_PARAMETER); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 		append_attr(astbuf1, $1); | ||||
| 	} param_signed param_integer param_real param_range param_decl_list ';' { | ||||
| 	} param_type param_decl_list ';' { | ||||
| 		delete astbuf1; | ||||
| 	}; | ||||
| 
 | ||||
|  | @ -1163,7 +1182,7 @@ localparam_decl: | |||
| 		astbuf1 = new AstNode(AST_LOCALPARAM); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 		append_attr(astbuf1, $1); | ||||
| 	} param_signed param_integer param_real param_range param_decl_list ';' { | ||||
| 	} param_type param_decl_list ';' { | ||||
| 		delete astbuf1; | ||||
| 	}; | ||||
| 
 | ||||
|  | @ -1327,7 +1346,7 @@ wire_name: | |||
| 		if ($2 != NULL) { | ||||
| 			if (node->is_input || node->is_output) | ||||
| 				frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); | ||||
| 			if (!astbuf2) { | ||||
| 			if (!astbuf2 && !node->is_custom_type) { | ||||
| 				AstNode *rng = new AstNode(AST_RANGE); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
|  | @ -1377,6 +1396,45 @@ assign_expr: | |||
| 		ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3)); | ||||
| 	}; | ||||
| 
 | ||||
| typedef_decl: | ||||
| 	TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' { | ||||
| 		astbuf1 = $2; | ||||
| 		astbuf2 = $3; | ||||
| 		if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { | ||||
| 			if (astbuf2) { | ||||
| 				frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); | ||||
| 			} else { | ||||
| 				astbuf2 = new AstNode(AST_RANGE); | ||||
| 				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); | ||||
| 				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); | ||||
| 			} | ||||
| 		} | ||||
| 		if (astbuf2 && astbuf2->children.size() != 2) | ||||
| 			frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]"); | ||||
| 		if (astbuf2) | ||||
| 			astbuf1->children.push_back(astbuf2); | ||||
| 
 | ||||
| 		if ($5 != NULL) { | ||||
| 			if (!astbuf2) { | ||||
| 				AstNode *rng = new AstNode(AST_RANGE); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				rng->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 				astbuf1->children.push_back(rng); | ||||
| 			} | ||||
| 			astbuf1->type = AST_MEMORY; | ||||
| 			auto *rangeNode = $5; | ||||
| 			if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { | ||||
| 				// SV array size [n], rewrite as [n-1:0] | ||||
| 				rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); | ||||
| 				rangeNode->children.push_back(AstNode::mkconst_int(0, false)); | ||||
| 			} | ||||
| 			astbuf1->children.push_back(rangeNode); | ||||
| 		} | ||||
| 
 | ||||
| 		ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); | ||||
| 		ast_stack.back()->children.back()->str = *$4; | ||||
| 	}; | ||||
| 
 | ||||
| cell_stmt: | ||||
| 	attr TOK_ID { | ||||
| 		astbuf1 = new AstNode(AST_CELL); | ||||
|  | @ -1823,7 +1881,7 @@ simple_behavioral_stmt: | |||
| 
 | ||||
| // this production creates the obligatory if-else shift/reduce conflict | ||||
| behavioral_stmt: | ||||
| 	defattr | assert | wire_decl | param_decl | localparam_decl | | ||||
| 	defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | | ||||
| 	non_opt_delay behavioral_stmt | | ||||
| 	simple_behavioral_stmt ';' | ';' | | ||||
| 	hierarchical_id attr { | ||||
|  |  | |||
							
								
								
									
										3
									
								
								tests/svtypes/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tests/svtypes/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| /*.log | ||||
| /*.out | ||||
| /run-test.mk | ||||
							
								
								
									
										20
									
								
								tests/svtypes/run-test.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										20
									
								
								tests/svtypes/run-test.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,20 @@ | |||
| #!/usr/bin/env bash | ||||
| set -e | ||||
| { | ||||
| echo "all::" | ||||
| for x in *.ys; do | ||||
| 	echo "all:: run-$x" | ||||
| 	echo "run-$x:" | ||||
| 	echo "	@echo 'Running $x..'" | ||||
| 	echo "	@../../yosys -ql ${x%.ys}.log $x" | ||||
| done | ||||
| for x in *.sv; do | ||||
| 	if [ ! -f "${x%.sv}.ys"  ]; then | ||||
| 		echo "all:: check-$x" | ||||
| 		echo "check-$x:" | ||||
| 		echo "	@echo 'Checking $x..'" | ||||
| 		echo "	@../../yosys -ql ${x%.sv}.log -p \"prep -top top; sat -verify -prove-asserts\" $x" | ||||
| 	fi | ||||
| done | ||||
| } > run-test.mk | ||||
| exec ${MAKE:-make} -f run-test.mk | ||||
							
								
								
									
										10
									
								
								tests/svtypes/typedef_memory.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/svtypes/typedef_memory.sv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata); | ||||
| 	typedef logic [3:0] ram16x4_t[0:15]; | ||||
| 
 | ||||
| 	(ram16x4_t) mem; | ||||
| 
 | ||||
| 	always @(posedge clk) begin | ||||
| 		if (wen) mem[addr] <= wdata; | ||||
| 		rdata <= mem[addr]; | ||||
| 	end | ||||
| endmodule | ||||
							
								
								
									
										3
									
								
								tests/svtypes/typedef_memory.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tests/svtypes/typedef_memory.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| read_verilog -sv typedef_memory.sv | ||||
| prep -top top | ||||
| select -assert-count 1 t:$mem r:SIZE=16 %i r:WIDTH=4 %i | ||||
							
								
								
									
										10
									
								
								tests/svtypes/typedef_memory_2.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/svtypes/typedef_memory_2.sv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata); | ||||
| 	typedef logic [3:0] nibble; | ||||
| 
 | ||||
| 	(nibble) mem[0:15]; | ||||
| 
 | ||||
| 	always @(posedge clk) begin | ||||
| 		if (wen) mem[addr] <= wdata; | ||||
| 		rdata <= mem[addr]; | ||||
| 	end | ||||
| endmodule | ||||
							
								
								
									
										4
									
								
								tests/svtypes/typedef_memory_2.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								tests/svtypes/typedef_memory_2.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| read_verilog -sv typedef_memory_2.sv | ||||
| prep -top top | ||||
| dump | ||||
| select -assert-count 1 t:$mem r:SIZE=16 %i r:WIDTH=4 %i | ||||
							
								
								
									
										11
									
								
								tests/svtypes/typedef_package.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/svtypes/typedef_package.sv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| package pkg; | ||||
| 	typedef logic [7:0] uint8_t; | ||||
| endpackage | ||||
| 
 | ||||
| module top; | ||||
| 
 | ||||
| 	(* keep *) (pkg::uint8_t) a = 8'hAA; | ||||
| 
 | ||||
| 	always @* assert(a == 8'hAA); | ||||
| 
 | ||||
| endmodule | ||||
							
								
								
									
										22
									
								
								tests/svtypes/typedef_param.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/svtypes/typedef_param.sv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| `define STRINGIFY(x) `"x`" | ||||
| `define STATIC_ASSERT(x) if(!(x)) $error({"assert failed: ", `STRINGIFY(x)}) | ||||
| 
 | ||||
| module top; | ||||
| 
 | ||||
| 	typedef logic [1:0] uint2_t; | ||||
| 	typedef logic signed [3:0] int4_t; | ||||
| 	typedef logic signed [7:0] int8_t; | ||||
| 	typedef (int8_t) char_t; | ||||
| 
 | ||||
| 	parameter (uint2_t) int2 = 2'b10; | ||||
| 	localparam (int4_t) int4 = -1; | ||||
| 	localparam (int8_t) int8 = int4; | ||||
| 	localparam (char_t) ch = int8; | ||||
| 
 | ||||
| 
 | ||||
| 	`STATIC_ASSERT(int2 == 2'b10); | ||||
| 	`STATIC_ASSERT(int4 == 4'b1111); | ||||
| 	`STATIC_ASSERT(int8 == 8'b11111111); | ||||
| 	`STATIC_ASSERT(ch   == 8'b11111111); | ||||
| 
 | ||||
| endmodule | ||||
							
								
								
									
										23
									
								
								tests/svtypes/typedef_scopes.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/svtypes/typedef_scopes.sv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| 
 | ||||
| typedef logic [3:0] outer_uint4_t; | ||||
| 
 | ||||
| module top; | ||||
| 
 | ||||
| 	(outer_uint4_t) u4_i = 8'hA5; | ||||
| 	always @(*) assert(u4_i == 4'h5); | ||||
| 
 | ||||
| 	typedef logic [3:0] inner_type; | ||||
| 	(inner_type) inner_i1 = 8'h5A; | ||||
| 	always @(*) assert(inner_i1 == 4'hA); | ||||
| 
 | ||||
| 	if (1) begin: genblock | ||||
| 		typedef logic [7:0] inner_type; | ||||
| 		(inner_type) inner_gb_i = 8'hA5; | ||||
| 		always @(*) assert(inner_gb_i == 8'hA5); | ||||
| 	end | ||||
| 
 | ||||
| 	(inner_type) inner_i2 = 8'h42; | ||||
| 	always @(*) assert(inner_i2 == 4'h2); | ||||
| 
 | ||||
| 
 | ||||
| endmodule | ||||
							
								
								
									
										19
									
								
								tests/svtypes/typedef_simple.sv
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								tests/svtypes/typedef_simple.sv
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| module top; | ||||
| 
 | ||||
| 	typedef logic [1:0] uint2_t; | ||||
| 	typedef logic signed [3:0] int4_t; | ||||
| 	typedef logic signed [7:0] int8_t; | ||||
| 	typedef (int8_t) char_t; | ||||
| 
 | ||||
| 	(* keep *) (uint2_t) int2 = 2'b10; | ||||
| 	(* keep *) (int4_t) int4 = -1; | ||||
| 	(* keep *) (int8_t) int8 = int4; | ||||
| 	(* keep *) (char_t) ch = int8; | ||||
| 
 | ||||
| 
 | ||||
| 	always @* assert(int2 == 2'b10); | ||||
| 	always @* assert(int4 == 4'b1111); | ||||
| 	always @* assert(int8 == 8'b11111111); | ||||
| 	always @* assert(ch   == 8'b11111111); | ||||
| 
 | ||||
| endmodule | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue