mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Added handling of real-valued parameters/localparams
This commit is contained in:
		
							parent
							
								
									fc7b6d172a
								
							
						
					
					
						commit
						9bd7d5c468
					
				
					 4 changed files with 62 additions and 24 deletions
				
			
		|  | @ -185,6 +185,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2) | |||
| 	range_left = -1; | ||||
| 	range_right = 0; | ||||
| 	integer = 0; | ||||
| 	realvalue = 0; | ||||
| 	id2ast = NULL; | ||||
| 	basic_prep = false; | ||||
| 
 | ||||
|  | @ -278,6 +279,8 @@ void AstNode::dumpAst(FILE *f, std::string indent) | |||
| 		fprintf(f, " range=[%d:%d]%s", range_left, range_right, range_valid ? "" : "!"); | ||||
| 	if (integer != 0) | ||||
| 		fprintf(f, " int=%u", (int)integer); | ||||
| 	if (realvalue != 0) | ||||
| 		fprintf(f, " real=%e", realvalue); | ||||
| 	fprintf(f, "\n"); | ||||
| 
 | ||||
| 	for (auto &it : attributes) { | ||||
|  | @ -775,18 +778,20 @@ double AstNode::asReal(bool is_signed) | |||
| 		RTLIL::Const val; | ||||
| 		val.bits = bits; | ||||
| 
 | ||||
| 		double p = exp2(val.bits.size()-32); | ||||
| 		double p = exp2(int(val.bits.size())-32); | ||||
| 		if (val.bits.size() > 32) | ||||
| 			val.bits.erase(val.bits.begin(), val.bits.begin()+(val.bits.size()-32)); | ||||
| 		int32_t v = val.as_int() << (32-val.bits.size()); | ||||
| 			val.bits.erase(val.bits.begin(), val.bits.begin()+(int(val.bits.size())-32)); | ||||
| 		int32_t v = val.as_int() << (32-int(val.bits.size())); | ||||
| 
 | ||||
| 		if (is_signed) | ||||
| 			return v * p; | ||||
| 		return uint32_t(v) * p; | ||||
| 	} | ||||
| 
 | ||||
| 	if (type == AST_REALVALUE) | ||||
| 		return realvalue; | ||||
| 	return 0; | ||||
| 
 | ||||
| 	log_abort(); | ||||
| } | ||||
| 
 | ||||
| // create a new AstModule from an AST_MODULE AST node
 | ||||
|  |  | |||
|  | @ -48,6 +48,13 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 	AstNode *newNode = NULL; | ||||
| 	bool did_something = false; | ||||
| 
 | ||||
| #if 0 | ||||
| 	log("-------------\n"); | ||||
| 	log("const_fold=%d, at_zero=%d, in_lvalue=%d, stage=%d, width_hint=%d, sign_hint=%d, in_param=%d\n", | ||||
| 			int(const_fold), int(at_zero), int(in_lvalue), int(stage), int(width_hint), int(sign_hint), int(in_param)); | ||||
| 	dumpAst(NULL, "> "); | ||||
| #endif | ||||
| 
 | ||||
| 	if (stage == 0) | ||||
| 	{ | ||||
| 		assert(type == AST_MODULE); | ||||
|  | @ -260,8 +267,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 		while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true) | ||||
| 			did_something = true; | ||||
| 		children[0]->detectSignWidth(width_hint, sign_hint); | ||||
| 		if (children.size() > 1) { | ||||
| 			assert(children[1]->type == AST_RANGE); | ||||
| 		if (children.size() > 1 && children[1]->type == AST_RANGE) { | ||||
| 			while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true) | ||||
| 				did_something = true; | ||||
| 			if (!children[1]->range_valid) | ||||
|  | @ -519,18 +525,37 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | |||
| 	} | ||||
| 
 | ||||
| 	// trim/extend parameters
 | ||||
| 	if ((type == AST_PARAMETER || type == AST_LOCALPARAM) && children[0]->type == AST_CONSTANT && children.size() > 1) { | ||||
| 		if (!children[1]->range_valid) | ||||
| 			log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum); | ||||
| 		int width = children[1]->range_left - children[1]->range_right + 1; | ||||
| 		if (width != int(children[0]->bits.size())) { | ||||
| 			RTLIL::SigSpec sig(children[0]->bits); | ||||
| 			sig.extend_u0(width, children[0]->is_signed); | ||||
| 			AstNode *old_child_0 = children[0]; | ||||
| 			children[0] = mkconst_bits(sig.as_const().bits, children[0]->is_signed); | ||||
| 			delete old_child_0; | ||||
| 	if (type == AST_PARAMETER || type == AST_LOCALPARAM) { | ||||
| 		if (children.size() > 1 && children[1]->type == AST_RANGE) { | ||||
| 			if (children[0]->type == AST_REALVALUE) { | ||||
| 				int intvalue = round(children[0]->realvalue); | ||||
| 				log("Warning: converting real value %e to integer %d at %s:%d.\n", | ||||
| 						children[0]->realvalue, intvalue, filename.c_str(), linenum); | ||||
| 				delete children[0]; | ||||
| 				children[0] = mkconst_int(intvalue, sign_hint); | ||||
| 				did_something = true; | ||||
| 			} | ||||
| 			if (children[0]->type == AST_CONSTANT) { | ||||
| 				if (!children[1]->range_valid) | ||||
| 					log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum); | ||||
| 				int width = children[1]->range_left - children[1]->range_right + 1; | ||||
| 				if (width != int(children[0]->bits.size())) { | ||||
| 					RTLIL::SigSpec sig(children[0]->bits); | ||||
| 					sig.extend_u0(width, children[0]->is_signed); | ||||
| 					AstNode *old_child_0 = children[0]; | ||||
| 					children[0] = mkconst_bits(sig.as_const().bits, children[0]->is_signed); | ||||
| 					delete old_child_0; | ||||
| 				} | ||||
| 				children[0]->is_signed = is_signed; | ||||
| 			} | ||||
| 		} else | ||||
| 		if (children.size() > 1 && children[1]->type == AST_REALVALUE && children[0]->type == AST_CONSTANT) { | ||||
| 			double as_realvalue = children[0]->asReal(sign_hint); | ||||
| 			delete children[0]; | ||||
| 			children[0] = new AstNode(AST_REALVALUE); | ||||
| 			children[0]->realvalue = as_realvalue; | ||||
| 			did_something = true; | ||||
| 		} | ||||
| 		children[0]->is_signed = is_signed; | ||||
| 	} | ||||
| 
 | ||||
| 	// annotate identifiers using scope resolution and create auto-wires as needed
 | ||||
|  |  | |||
|  | @ -168,6 +168,7 @@ namespace VERILOG_FRONTEND { | |||
| "integer" { return TOK_INTEGER; } | ||||
| "signed"  { return TOK_SIGNED; } | ||||
| "genvar"  { return TOK_GENVAR; } | ||||
| "real"    { return TOK_REAL; } | ||||
| 
 | ||||
| [0-9]+ { | ||||
| 	frontend_verilog_yylval.string = new std::string(yytext); | ||||
|  | @ -181,12 +182,12 @@ namespace VERILOG_FRONTEND { | |||
| 
 | ||||
| [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? { | ||||
| 	frontend_verilog_yylval.string = new std::string(yytext); | ||||
| 	return TOK_REAL; | ||||
| 	return TOK_REALVAL; | ||||
| } | ||||
| 
 | ||||
| [0-9][0-9_]*[eE][-+]?[0-9_]+ { | ||||
| 	frontend_verilog_yylval.string = new std::string(yytext); | ||||
| 	return TOK_REAL; | ||||
| 	return TOK_REALVAL; | ||||
| } | ||||
| 
 | ||||
| \"		{ BEGIN(STRING); } | ||||
|  |  | |||
|  | @ -94,7 +94,7 @@ static void free_attr(std::map<std::string, AstNode*> *al) | |||
| 	bool boolean; | ||||
| } | ||||
| 
 | ||||
| %token <string> TOK_STRING TOK_ID TOK_CONST TOK_REAL TOK_PRIMITIVE | ||||
| %token <string> TOK_STRING TOK_ID TOK_CONST TOK_REALVAL TOK_PRIMITIVE | ||||
| %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END | ||||
| %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM | ||||
| %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG | ||||
|  | @ -103,7 +103,7 @@ static void free_attr(std::map<std::string, AstNode*> *al) | |||
| %token TOK_POSEDGE TOK_NEGEDGE TOK_OR | ||||
| %token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT | ||||
| %token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK | ||||
| %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR | ||||
| %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL | ||||
| %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE | ||||
| %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED | ||||
| %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_PROPERTY | ||||
|  | @ -438,6 +438,13 @@ param_integer: | |||
| 		astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 	} | /* empty */; | ||||
| 
 | ||||
| param_real: | ||||
| 	TOK_REAL { | ||||
| 		if (astbuf1->children.size() != 1) | ||||
| 			frontend_verilog_yyerror("Syntax error."); | ||||
| 		astbuf1->children.push_back(new AstNode(AST_REALVALUE)); | ||||
| 	} | /* empty */; | ||||
| 
 | ||||
| param_range: | ||||
| 	range { | ||||
| 		if ($1 != NULL) { | ||||
|  | @ -451,7 +458,7 @@ param_decl: | |||
| 	TOK_PARAMETER { | ||||
| 		astbuf1 = new AstNode(AST_PARAMETER); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 	} param_signed param_integer param_range param_decl_list ';' { | ||||
| 	} param_signed param_integer param_real param_range param_decl_list ';' { | ||||
| 		delete astbuf1; | ||||
| 	}; | ||||
| 
 | ||||
|  | @ -459,7 +466,7 @@ localparam_decl: | |||
| 	TOK_LOCALPARAM { | ||||
| 		astbuf1 = new AstNode(AST_LOCALPARAM); | ||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | ||||
| 	} param_signed param_integer param_range param_decl_list ';' { | ||||
| 	} param_signed param_integer param_real param_range param_decl_list ';' { | ||||
| 		delete astbuf1; | ||||
| 	}; | ||||
| 
 | ||||
|  | @ -1133,7 +1140,7 @@ basic_expr: | |||
| 			log_error("Value conversion failed: `%s'\n", $1->c_str()); | ||||
| 		delete $1; | ||||
| 	} | | ||||
| 	TOK_REAL { | ||||
| 	TOK_REALVAL { | ||||
| 		$$ = new AstNode(AST_REALVALUE); | ||||
| 		char *p = strdup($1->c_str()), *q; | ||||
| 		for (int i = 0, j = 0; !p[j]; j++) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue