mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	This PR should be the base for discussion, do not merge it yet!
It correctly detects reg/wire mix and incorrect use on blocking,nonblocking assignments within blocks and assign statements. What it DOES'T do: Detect registers connected to output ports of instances. Where it FAILS: memorty nonblocking assignments causes spurious (I assume??) errors on yosys-generated "_ADDR", "_DATA", "EN" signals. You can test it with tests/simple/reg_wire_error.v (look inside for the comments to enable/disable specific lines)
This commit is contained in:
		
							parent
							
								
									efaef82f75
								
							
						
					
					
						commit
						2b9c75f8e3
					
				
					 6 changed files with 63 additions and 4 deletions
				
			
		|  | @ -191,6 +191,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch | |||
| 	is_input = false; | ||||
| 	is_output = false; | ||||
| 	is_reg = false; | ||||
| 	is_logic = false; | ||||
| 	is_signed = false; | ||||
| 	is_string = false; | ||||
| 	range_valid = false; | ||||
|  | @ -285,7 +286,9 @@ void AstNode::dumpAst(FILE *f, std::string indent) const | |||
| 		fprintf(f, " input"); | ||||
| 	if (is_output) | ||||
| 		fprintf(f, " output"); | ||||
| 	if (is_reg) | ||||
| 	if (is_logic) | ||||
| 		fprintf(f, " logic"); | ||||
| 	if (is_reg) // this is an AST dump, not Verilog - if we see "logic reg" that's fine.
 | ||||
| 		fprintf(f, " reg"); | ||||
| 	if (is_signed) | ||||
| 		fprintf(f, " signed"); | ||||
|  | @ -652,6 +655,8 @@ bool AstNode::operator==(const AstNode &other) const | |||
| 		return false; | ||||
| 	if (is_output != other.is_output) | ||||
| 		return false; | ||||
| 	if (is_logic != other.is_logic) | ||||
| 		return false; | ||||
| 	if (is_reg != other.is_reg) | ||||
| 		return false; | ||||
| 	if (is_signed != other.is_signed) | ||||
|  |  | |||
|  | @ -168,7 +168,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_signed, is_string, range_valid, range_swapped; | ||||
| 		bool is_input, is_output, is_reg, is_logic, is_signed, is_string, range_valid, range_swapped; | ||||
| 		int port_id, range_left, range_right; | ||||
| 		uint32_t integer; | ||||
| 		double realvalue; | ||||
|  |  | |||
|  | @ -327,6 +327,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 			if (node->type == AST_WIRE) { | ||||
| 				if (this_wire_scope.count(node->str) > 0) { | ||||
| 					AstNode *first_node = this_wire_scope[node->str]; | ||||
| 					if (first_node->is_input && node->is_reg) | ||||
| 						goto wires_are_incompatible; | ||||
| 					if (!node->is_input && !node->is_output && node->is_reg && node->children.size() == 0) | ||||
| 						goto wires_are_compatible; | ||||
| 					if (first_node->children.size() == 0 && node->children.size() == 1 && node->children[0]->type == AST_RANGE) { | ||||
|  | @ -361,6 +363,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 						first_node->is_output = true; | ||||
| 					if (node->is_reg) | ||||
| 						first_node->is_reg = true; | ||||
| 					if (node->is_logic) | ||||
| 						first_node->is_logic = true; | ||||
| 					if (node->is_signed) | ||||
| 						first_node->is_signed = true; | ||||
| 					for (auto &it : node->attributes) { | ||||
|  | @ -440,6 +444,12 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 		children[1]->detectSignWidth(width_hint, sign_hint); | ||||
| 		width_hint = max(width_hint, backup_width_hint); | ||||
| 		child_0_is_self_determined = true; | ||||
| 		if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && children[0]->id2ast->is_logic) | ||||
| 			children[0]->id2ast->is_reg = true; // if logic type is used in a block asignment
 | ||||
| 		if ((type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ) && !children[0]->id2ast->is_reg) | ||||
| 			log_warning("wire '%s' is assigned in a block at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); | ||||
| 		if (type == AST_ASSIGN && children[0]->id2ast->is_reg) | ||||
| 			log_error("reg '%s' is assigned in a continuous assignment at %s:%d.\n", children[0]->str.c_str(), filename.c_str(), linenum); | ||||
| 		break; | ||||
| 
 | ||||
| 	case AST_PARAMETER: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue