mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Initial implementation of elaboration system tasks
(IEEE1800-2017 section 20.11) This PR allows us to use $info/$warning/$error/$fatal **at elaboration time** within a generate block. This is very useful to stop a synthesis of a parametrized block when an illegal combination of parameters is chosen.
This commit is contained in:
		
							parent
							
								
									98925f6c4b
								
							
						
					
					
						commit
						ac10e7d96d
					
				
					 10 changed files with 107 additions and 5 deletions
				
			
		|  | @ -154,6 +154,7 @@ std::string AST::type2str(AstNodeType type) | |||
| 	X(AST_GENIF) | ||||
| 	X(AST_GENCASE) | ||||
| 	X(AST_GENBLOCK) | ||||
| 	X(AST_TECALL) | ||||
| 	X(AST_POSEDGE) | ||||
| 	X(AST_NEGEDGE) | ||||
| 	X(AST_EDGE) | ||||
|  |  | |||
|  | @ -137,7 +137,8 @@ namespace AST | |||
| 		AST_GENIF, | ||||
| 		AST_GENCASE, | ||||
| 		AST_GENBLOCK, | ||||
| 
 | ||||
| 		AST_TECALL, | ||||
| 		 | ||||
| 		AST_POSEDGE, | ||||
| 		AST_NEGEDGE, | ||||
| 		AST_EDGE, | ||||
|  | @ -233,6 +234,7 @@ namespace AST | |||
| 		bool mem2reg_check(pool<AstNode*> &mem2reg_set); | ||||
| 		void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes); | ||||
| 		void meminfo(int &mem_width, int &mem_size, int &addr_bits); | ||||
| 		bool check_elab_tasks(void); | ||||
| 
 | ||||
| 		// additional functionality for evaluating constant functions
 | ||||
| 		struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; }; | ||||
|  |  | |||
|  | @ -856,6 +856,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) | |||
| 	case AST_GENVAR: | ||||
| 	case AST_GENFOR: | ||||
| 	case AST_GENBLOCK: | ||||
| 	case AST_TECALL: | ||||
| 	case AST_GENIF: | ||||
| 	case AST_GENCASE: | ||||
| 	case AST_PACKAGE: | ||||
|  |  | |||
|  | @ -1146,7 +1146,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 
 | ||||
| 			if (type == AST_GENFOR) { | ||||
| 				for (size_t i = 0; i < buf->children.size(); i++) { | ||||
| 					buf->children[i]->simplify(false, false, false, stage, -1, false, false); | ||||
| 					if (!buf->children[i]->check_elab_tasks()) | ||||
| 						buf->children[i]->simplify(false, false, false, stage, -1, false, false); | ||||
| 					current_ast_mod->children.push_back(buf->children[i]); | ||||
| 				} | ||||
| 			} else { | ||||
|  | @ -1261,7 +1262,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 			} | ||||
| 
 | ||||
| 			for (size_t i = 0; i < buf->children.size(); i++) { | ||||
| 				buf->children[i]->simplify(false, false, false, stage, -1, false, false); | ||||
| 				if (!buf->children[i]->check_elab_tasks()) | ||||
| 					buf->children[i]->simplify(false, false, false, stage, -1, false, false); | ||||
| 				current_ast_mod->children.push_back(buf->children[i]); | ||||
| 			} | ||||
| 
 | ||||
|  | @ -1340,7 +1342,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 			} | ||||
| 
 | ||||
| 			for (size_t i = 0; i < buf->children.size(); i++) { | ||||
| 				buf->children[i]->simplify(false, false, false, stage, -1, false, false); | ||||
| 				if (!buf->children[i]->check_elab_tasks()) | ||||
| 					buf->children[i]->simplify(false, false, false, stage, -1, false, false); | ||||
| 				current_ast_mod->children.push_back(buf->children[i]); | ||||
| 			} | ||||
| 
 | ||||
|  | @ -2969,6 +2972,44 @@ static void mark_memories_assign_lhs_complex(dict<AstNode*, pool<std::string>> & | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // handle $info(), $warning(), $error(), $fatal()
 | ||||
| // we don't do that in simplify() because we don't know 
 | ||||
| bool AstNode::check_elab_tasks(void) | ||||
| { | ||||
| 	if (type == AST_TECALL) { | ||||
| 		int sz = children.size(); | ||||
| 		if (str == "$info") { | ||||
| 			if (sz > 0) | ||||
| 				log_file_info(filename, linenum, "%s.\n", children[0]->str.c_str()); | ||||
| 			else | ||||
| 				log_file_info(filename, linenum, "\n"); | ||||
| 		} else if (str == "$warning") { | ||||
| 			if (sz > 0) | ||||
| 				log_file_warning(filename, linenum, "%s.\n", children[0]->str.c_str()); | ||||
| 			else | ||||
| 				log_file_warning(filename, linenum, "\n"); | ||||
| 		} else if (str == "$error") { | ||||
| 			if (sz > 0) | ||||
| 				log_file_error(filename, linenum, "%s.\n", children[0]->str.c_str()); | ||||
| 			else | ||||
| 				log_file_error(filename, linenum, "\n"); | ||||
| 		} else if (str == "$fatal") { | ||||
| 			// TODO: 1st parameter, if exists, is 0,1 or 2, and passed to $finish()
 | ||||
| 			// if no parameter is given, default value is 1
 | ||||
| 			// dollar_finish(sz ? children[0] : 1);
 | ||||
| 			// perhaps create & use log_file_fatal()
 | ||||
| 			if (sz > 0) | ||||
| 				log_file_error(filename, linenum, "FATAL: %s.\n", children[0]->str.c_str()); | ||||
| 			else | ||||
| 				log_file_error(filename, linenum, "FATAL.\n"); | ||||
| 		} else { | ||||
| 			log_file_error(filename, linenum, "Unknown elabortoon system task '%s'.\n", str.c_str()); | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| 
 | ||||
| } | ||||
| // find memories that should be replaced by registers
 | ||||
| void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places, | ||||
| 		dict<AstNode*, uint32_t> &mem2reg_candidates, dict<AstNode*, uint32_t> &proc_flags, uint32_t &flags) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue