mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Add "nowrshmsk" attribute, fix shift-and-mask bit slice write for signed offset, fixes #1990
Signed-off-by: Claire Wolf <claire@symbioticeda.com>
This commit is contained in:
		
							parent
							
								
									ca3fc3c882
								
							
						
					
					
						commit
						bbbce0d1c5
					
				
					 6 changed files with 57 additions and 7 deletions
				
			
		|  | @ -281,6 +281,9 @@ Verilog Attributes and non-standard features | |||
|   temporary variable within an always block. This is mostly used internally | ||||
|   by Yosys to synthesize Verilog functions and access arrays. | ||||
| 
 | ||||
| - The ``nowrshmsk`` attribute on a register prohibits the generation of | ||||
|   shift-and-mask type circuits for writing to bit slices of that register. | ||||
| 
 | ||||
| - The ``onehot`` attribute on wires mark them as one-hot state register. This | ||||
|   is used for example for memory port sharing and set by the fsm_map pass. | ||||
| 
 | ||||
|  |  | |||
|  | @ -110,6 +110,8 @@ std::string AST::type2str(AstNodeType type) | |||
| 	X(AST_SHIFT_RIGHT) | ||||
| 	X(AST_SHIFT_SLEFT) | ||||
| 	X(AST_SHIFT_SRIGHT) | ||||
| 	X(AST_SHIFTX) | ||||
| 	X(AST_SHIFT) | ||||
| 	X(AST_LT) | ||||
| 	X(AST_LE) | ||||
| 	X(AST_EQ) | ||||
|  | @ -628,6 +630,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const | |||
| 	if (0) { case AST_SHIFT_RIGHT:  txt = ">>";  } | ||||
| 	if (0) { case AST_SHIFT_SLEFT:  txt = "<<<"; } | ||||
| 	if (0) { case AST_SHIFT_SRIGHT: txt = ">>>"; } | ||||
| 	if (0) { case AST_SHIFTX:       txt = "@shiftx@"; } | ||||
| 	if (0) { case AST_SHIFT:        txt = "@shift@"; } | ||||
| 	if (0) { case AST_LT:           txt = "<";   } | ||||
| 	if (0) { case AST_LE:           txt = "<=";  } | ||||
| 	if (0) { case AST_EQ:           txt = "==";  } | ||||
|  |  | |||
|  | @ -91,6 +91,8 @@ namespace AST | |||
| 		AST_SHIFT_RIGHT, | ||||
| 		AST_SHIFT_SLEFT, | ||||
| 		AST_SHIFT_SRIGHT, | ||||
| 		AST_SHIFTX, | ||||
| 		AST_SHIFT, | ||||
| 		AST_LT, | ||||
| 		AST_LE, | ||||
| 		AST_EQ, | ||||
|  |  | |||
|  | @ -856,6 +856,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun | |||
| 	case AST_SHIFT_RIGHT: | ||||
| 	case AST_SHIFT_SLEFT: | ||||
| 	case AST_SHIFT_SRIGHT: | ||||
| 	case AST_SHIFTX: | ||||
| 	case AST_SHIFT: | ||||
| 	case AST_POW: | ||||
| 		children[0]->detectSignWidthWorker(width_hint, sign_hint, found_real); | ||||
| 		break; | ||||
|  | @ -1356,6 +1358,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | |||
| 	if (0) { case AST_SHIFT_RIGHT:  type_name = ID($shr); } | ||||
| 	if (0) { case AST_SHIFT_SLEFT:  type_name = ID($sshl); } | ||||
| 	if (0) { case AST_SHIFT_SRIGHT: type_name = ID($sshr); } | ||||
| 	if (0) { case AST_SHIFTX:       type_name = ID($shiftx); } | ||||
| 	if (0) { case AST_SHIFT:        type_name = ID($shift); } | ||||
| 		{ | ||||
| 			if (width_hint < 0) | ||||
| 				detectSignWidth(width_hint, sign_hint); | ||||
|  |  | |||
|  | @ -1786,7 +1786,18 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 			result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; | ||||
| 		} | ||||
| 
 | ||||
| 		if (0) | ||||
| 		bool use_case_method = false; | ||||
| 
 | ||||
| 		if (children[0]->id2ast->attributes.count(ID::nowrshmsk)) { | ||||
| 			AstNode *node = children[0]->id2ast->attributes.at(ID::nowrshmsk); | ||||
| 			while (node->simplify(true, false, false, stage, -1, false, false)) { } | ||||
| 			if (node->type != AST_CONSTANT) | ||||
| 				log_file_error(filename, location.first_line, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children[0]->id2ast->str.c_str()); | ||||
| 			if (node->asAttrConst().as_bool()) | ||||
| 				use_case_method = true; | ||||
| 		} | ||||
| 
 | ||||
| 		if (use_case_method) | ||||
| 		{ | ||||
| 			// big case block
 | ||||
| 
 | ||||
|  | @ -1794,10 +1805,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 			newNode = new AstNode(AST_CASE, shift_expr); | ||||
| 			for (int i = 0; i < source_width; i++) { | ||||
| 				int start_bit = children[0]->id2ast->range_right + i; | ||||
| 				int end_bit = std::min(start_bit+result_width,source_width) - 1; | ||||
| 				AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true)); | ||||
| 				AstNode *lvalue = children[0]->clone(); | ||||
| 				lvalue->delete_children(); | ||||
| 				int end_bit = std::min(start_bit+result_width,source_width) - 1; | ||||
| 				lvalue->children.push_back(new AstNode(AST_RANGE, | ||||
| 						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()))); | ||||
|  | @ -1844,11 +1855,36 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 
 | ||||
| 			AstNode *shamt = shift_expr; | ||||
| 
 | ||||
| 			newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), | ||||
| 					new AstNode(AST_SHIFT_LEFT, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), shamt->clone()))); | ||||
| 			newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_data->clone(), | ||||
| 					new AstNode(AST_SHIFT_LEFT, new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()), shamt))); | ||||
| 			newNode->children.push_back(new AstNode(type, lvalue, new AstNode(AST_BIT_OR, new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)), ref_data))); | ||||
| 			int start_bit = children[0]->id2ast->range_right; | ||||
| 			bool use_shift = shamt->is_signed; | ||||
| 
 | ||||
| 			if (start_bit != 0) { | ||||
| 				shamt = new AstNode(AST_SUB, shamt, mkconst_int(start_bit, true)); | ||||
| 				use_shift = true; | ||||
| 			} | ||||
| 
 | ||||
| 			AstNode *t; | ||||
| 
 | ||||
| 			t = mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false); | ||||
| 			if (use_shift) | ||||
| 				t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt->clone())); | ||||
| 			else | ||||
| 				t = new AstNode(AST_SHIFT_LEFT, t, shamt->clone()); | ||||
| 			t = new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), t); | ||||
| 			newNode->children.push_back(t); | ||||
| 
 | ||||
| 			t = new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()); | ||||
| 			if (use_shift) | ||||
| 				t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt)); | ||||
| 			else | ||||
| 				t = new AstNode(AST_SHIFT_LEFT, t, shamt); | ||||
| 			t = new AstNode(AST_ASSIGN_EQ, ref_data->clone(), t); | ||||
| 			newNode->children.push_back(t); | ||||
| 
 | ||||
| 			t = new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)); | ||||
| 			t = new AstNode(AST_BIT_OR, t, ref_data); | ||||
| 			t = new AstNode(type, lvalue, t); | ||||
| 			newNode->children.push_back(t); | ||||
| 		} | ||||
| 
 | ||||
| 		goto apply_newNode; | ||||
|  |  | |||
|  | @ -123,6 +123,7 @@ X(nomem2init) | |||
| X(nomem2reg) | ||||
| X(nomeminit) | ||||
| X(nosync) | ||||
| X(nowrshmsk) | ||||
| X(O) | ||||
| X(OFFSET) | ||||
| X(onehot) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue