mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Assign from rvalue via temporary register in nowrshmsk CASE
Avoid repeating complex rvalue expressions for each condition.
This commit is contained in:
		
							parent
							
								
									dbec704b49
								
							
						
					
					
						commit
						1a2b4759e8
					
				
					 3 changed files with 35 additions and 3 deletions
				
			
		|  | @ -850,6 +850,25 @@ AstNode *AstNode::mkconst_str(const std::string &str) | ||||||
| 	return node; | 	return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // create a temporary register
 | ||||||
|  | AstNode *AstNode::mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed) | ||||||
|  | { | ||||||
|  | 	AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(range_left, true), mkconst_int(range_right, true))); | ||||||
|  | 	wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++); | ||||||
|  | 	if (nosync) | ||||||
|  | 		wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); | ||||||
|  | 	wire->is_signed = is_signed; | ||||||
|  | 	wire->is_logic = true; | ||||||
|  | 	mod->children.push_back(wire); | ||||||
|  | 	while (wire->simplify(true, 1, -1, false)) { } | ||||||
|  | 
 | ||||||
|  | 	AstNode *ident = new AstNode(AST_IDENTIFIER); | ||||||
|  | 	ident->str = wire->str; | ||||||
|  | 	ident->id2ast = wire; | ||||||
|  | 
 | ||||||
|  | 	return ident; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool AstNode::bits_only_01() const | bool AstNode::bits_only_01() const | ||||||
| { | { | ||||||
| 	for (auto bit : bits) | 	for (auto bit : bits) | ||||||
|  |  | ||||||
|  | @ -321,6 +321,9 @@ namespace AST | ||||||
| 		static AstNode *mkconst_str(const std::vector<RTLIL::State> &v); | 		static AstNode *mkconst_str(const std::vector<RTLIL::State> &v); | ||||||
| 		static AstNode *mkconst_str(const std::string &str); | 		static AstNode *mkconst_str(const std::string &str); | ||||||
| 
 | 
 | ||||||
|  | 		// helper function to create an AST node for a temporary register
 | ||||||
|  | 		AstNode *mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed); | ||||||
|  | 
 | ||||||
| 		// helper function for creating sign-extended const objects
 | 		// helper function for creating sign-extended const objects
 | ||||||
| 		RTLIL::Const bitsAsConst(int width, bool is_signed); | 		RTLIL::Const bitsAsConst(int width, bool is_signed); | ||||||
| 		RTLIL::Const bitsAsConst(int width = -1); | 		RTLIL::Const bitsAsConst(int width = -1); | ||||||
|  |  | ||||||
|  | @ -2932,8 +2932,18 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin | ||||||
| 			long long max_offset = (1ll << (max_width - case_sign_hint)) - 1; | 			long long max_offset = (1ll << (max_width - case_sign_hint)) - 1; | ||||||
| 			long long min_offset = case_sign_hint ? -(1ll << (max_width - 1)) : 0; | 			long long min_offset = case_sign_hint ? -(1ll << (max_width - 1)) : 0; | ||||||
| 
 | 
 | ||||||
|  | 			// A temporary register holds the result of the (possibly complex) rvalue expression,
 | ||||||
|  | 			// avoiding repetition in each AST_COND below.
 | ||||||
|  | 			int rvalue_width; | ||||||
|  | 			bool rvalue_sign; | ||||||
|  | 			children[1]->detectSignWidth(rvalue_width, rvalue_sign); | ||||||
|  | 			AstNode *rvalue = mktemp_logic("$bitselwrite$rvalue$", current_ast_mod, true, rvalue_width - 1, 0, rvalue_sign); | ||||||
|  | 			AstNode *caseNode = new AstNode(AST_CASE, shift_expr); | ||||||
|  | 			newNode = new AstNode(AST_BLOCK, | ||||||
|  | 					      new AstNode(AST_ASSIGN_EQ, rvalue, children[1]->clone()), | ||||||
|  | 					      caseNode); | ||||||
|  | 
 | ||||||
| 			did_something = true; | 			did_something = true; | ||||||
| 			newNode = new AstNode(AST_CASE, shift_expr); |  | ||||||
| 			for (int i = 1 - result_width; i < wire_width; i++) { | 			for (int i = 1 - result_width; i < wire_width; i++) { | ||||||
| 				// Out of range indexes are handled in genrtlil.cc
 | 				// Out of range indexes are handled in genrtlil.cc
 | ||||||
| 				int start_bit = wire_offset + i; | 				int start_bit = wire_offset + i; | ||||||
|  | @ -2951,8 +2961,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin | ||||||
| 					lvalue->set_attribute(ID::wiretype, member_node->clone()); | 					lvalue->set_attribute(ID::wiretype, member_node->clone()); | ||||||
| 				lvalue->children.push_back(new AstNode(AST_RANGE, | 				lvalue->children.push_back(new AstNode(AST_RANGE, | ||||||
| 						mkconst_int(end_bit, true), mkconst_int(start_bit, true))); | 						mkconst_int(end_bit, true), mkconst_int(start_bit, true))); | ||||||
| 				cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone()))); | 				cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, rvalue->clone()))); | ||||||
| 				newNode->children.push_back(cond); | 				caseNode->children.push_back(cond); | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			// mask and shift operations
 | 			// mask and shift operations
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue