mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Added $assert cell
This commit is contained in:
		
							parent
							
								
									9a1eb45c75
								
							
						
					
					
						commit
						1e67099b77
					
				
					 7 changed files with 120 additions and 1 deletions
				
			
		|  | @ -1276,6 +1276,38 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | |||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	// generate $assert cells
 | ||||
| 	case AST_ASSERT: | ||||
| 		{ | ||||
| 			log_assert(children.size() == 2); | ||||
| 
 | ||||
| 			RTLIL::SigSpec check = children[0]->genRTLIL(); | ||||
| 			log_assert(check.width == 1); | ||||
| 
 | ||||
| 			RTLIL::SigSpec en = children[1]->genRTLIL(); | ||||
| 			log_assert(en.width == 1); | ||||
| 
 | ||||
| 			std::stringstream sstr; | ||||
| 			sstr << "$assert$" << filename << ":" << linenum << "$" << (RTLIL::autoidx++); | ||||
| 
 | ||||
| 			RTLIL::Cell *cell = new RTLIL::Cell; | ||||
| 			cell->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum); | ||||
| 			cell->name = sstr.str(); | ||||
| 			cell->type = "$assert"; | ||||
| 			current_module->cells[cell->name] = cell; | ||||
| 
 | ||||
| 			for (auto &attr : attributes) { | ||||
| 				if (attr.second->type != AST_CONSTANT) | ||||
| 					log_error("Attribute `%s' with non-constant value at %s:%d!\n", | ||||
| 							attr.first.c_str(), filename.c_str(), linenum); | ||||
| 				cell->attributes[attr.first] = attr.second->asAttrConst(); | ||||
| 			} | ||||
| 
 | ||||
| 			cell->connections["\\A"] = check; | ||||
| 			cell->connections["\\EN"] = en; | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	// add entries to current_module->connections for assignments (outside of always blocks)
 | ||||
| 	case AST_ASSIGN: | ||||
| 		{ | ||||
|  |  | |||
|  | @ -966,6 +966,66 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 	} | ||||
| skip_dynamic_range_lvalue_expansion:; | ||||
| 
 | ||||
| 	if (stage > 1 && type == AST_ASSERT && current_block != NULL) | ||||
| 	{ | ||||
| 		std::stringstream sstr; | ||||
| 		sstr << "$assert$" << filename << ":" << linenum << "$" << (RTLIL::autoidx++); | ||||
| 		std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN"; | ||||
| 
 | ||||
| 		AstNode *wire_check = new AstNode(AST_WIRE); | ||||
| 		wire_check->str = id_check; | ||||
| 		current_ast_mod->children.push_back(wire_check); | ||||
| 		current_scope[wire_check->str] = wire_check; | ||||
| 		while (wire_check->simplify(true, false, false, 1, -1, false)) { } | ||||
| 
 | ||||
| 		AstNode *wire_en = new AstNode(AST_WIRE); | ||||
| 		wire_en->str = id_en; | ||||
| 		current_ast_mod->children.push_back(wire_en); | ||||
| 		current_scope[wire_en->str] = wire_en; | ||||
| 		while (wire_en->simplify(true, false, false, 1, -1, false)) { } | ||||
| 
 | ||||
| 		std::vector<RTLIL::State> x_bit; | ||||
| 		x_bit.push_back(RTLIL::State::Sx); | ||||
| 
 | ||||
| 		AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bit, false)); | ||||
| 		assign_check->children[0]->str = id_check; | ||||
| 
 | ||||
| 		AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1)); | ||||
| 		assign_en->children[0]->str = id_en; | ||||
| 
 | ||||
| 		AstNode *default_signals = new AstNode(AST_BLOCK); | ||||
| 		default_signals->children.push_back(assign_check); | ||||
| 		default_signals->children.push_back(assign_en); | ||||
| 		current_top_block->children.insert(current_top_block->children.begin(), default_signals); | ||||
| 
 | ||||
| 		assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone())); | ||||
| 		assign_check->children[0]->str = id_check; | ||||
| 
 | ||||
| 		assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1)); | ||||
| 		assign_en->children[0]->str = id_en; | ||||
| 
 | ||||
| 		newNode = new AstNode(AST_BLOCK); | ||||
| 		newNode->children.push_back(assign_check); | ||||
| 		newNode->children.push_back(assign_en); | ||||
| 
 | ||||
| 		AstNode *assertnode = new AstNode(AST_ASSERT); | ||||
| 		assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); | ||||
| 		assertnode->children.push_back(new AstNode(AST_IDENTIFIER)); | ||||
| 		assertnode->children[0]->str = id_check; | ||||
| 		assertnode->children[1]->str = id_en; | ||||
| 		assertnode->attributes.swap(attributes); | ||||
| 		current_ast_mod->children.push_back(assertnode); | ||||
| 
 | ||||
| 		goto apply_newNode; | ||||
| 	} | ||||
| 
 | ||||
| 	if (stage > 1 && type == AST_ASSERT && children.size() == 1) | ||||
| 	{ | ||||
| 		children[0] = new AstNode(AST_REDUCE_BOOL, children[0]->clone()); | ||||
| 		children.push_back(mkconst_int(1, false, 1)); | ||||
| 		did_something = true; | ||||
| 	} | ||||
| 
 | ||||
| 	// found right-hand side identifier for memory -> replace with memory read port
 | ||||
| 	if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue && | ||||
| 			children[0]->type == AST_RANGE && children[0]->children.size() == 1) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue