mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +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_left = -1; | ||||||
| 	range_right = 0; | 	range_right = 0; | ||||||
| 	integer = 0; | 	integer = 0; | ||||||
|  | 	realvalue = 0; | ||||||
| 	id2ast = NULL; | 	id2ast = NULL; | ||||||
| 	basic_prep = false; | 	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 ? "" : "!"); | 		fprintf(f, " range=[%d:%d]%s", range_left, range_right, range_valid ? "" : "!"); | ||||||
| 	if (integer != 0) | 	if (integer != 0) | ||||||
| 		fprintf(f, " int=%u", (int)integer); | 		fprintf(f, " int=%u", (int)integer); | ||||||
|  | 	if (realvalue != 0) | ||||||
|  | 		fprintf(f, " real=%e", realvalue); | ||||||
| 	fprintf(f, "\n"); | 	fprintf(f, "\n"); | ||||||
| 
 | 
 | ||||||
| 	for (auto &it : attributes) { | 	for (auto &it : attributes) { | ||||||
|  | @ -775,18 +778,20 @@ double AstNode::asReal(bool is_signed) | ||||||
| 		RTLIL::Const val; | 		RTLIL::Const val; | ||||||
| 		val.bits = bits; | 		val.bits = bits; | ||||||
| 
 | 
 | ||||||
| 		double p = exp2(val.bits.size()-32); | 		double p = exp2(int(val.bits.size())-32); | ||||||
| 		if (val.bits.size() > 32) | 		if (val.bits.size() > 32) | ||||||
| 			val.bits.erase(val.bits.begin(), val.bits.begin()+(val.bits.size()-32)); | 			val.bits.erase(val.bits.begin(), val.bits.begin()+(int(val.bits.size())-32)); | ||||||
| 		int32_t v = val.as_int() << (32-val.bits.size()); | 		int32_t v = val.as_int() << (32-int(val.bits.size())); | ||||||
| 
 | 
 | ||||||
| 		if (is_signed) | 		if (is_signed) | ||||||
| 			return v * p; | 			return v * p; | ||||||
| 		return uint32_t(v) * p; | 		return uint32_t(v) * p; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	if (type == AST_REALVALUE) | 	if (type == AST_REALVALUE) | ||||||
| 		return realvalue; | 		return realvalue; | ||||||
| 	return 0; | 
 | ||||||
|  | 	log_abort(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // create a new AstModule from an AST_MODULE AST node
 | // 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; | 	AstNode *newNode = NULL; | ||||||
| 	bool did_something = false; | 	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) | 	if (stage == 0) | ||||||
| 	{ | 	{ | ||||||
| 		assert(type == AST_MODULE); | 		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) | 		while (!children[0]->basic_prep && children[0]->simplify(false, false, false, stage, -1, false, true) == true) | ||||||
| 			did_something = true; | 			did_something = true; | ||||||
| 		children[0]->detectSignWidth(width_hint, sign_hint); | 		children[0]->detectSignWidth(width_hint, sign_hint); | ||||||
| 		if (children.size() > 1) { | 		if (children.size() > 1 && children[1]->type == AST_RANGE) { | ||||||
| 			assert(children[1]->type == AST_RANGE); |  | ||||||
| 			while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true) | 			while (!children[1]->basic_prep && children[1]->simplify(false, false, false, stage, -1, false, true) == true) | ||||||
| 				did_something = true; | 				did_something = true; | ||||||
| 			if (!children[1]->range_valid) | 			if (!children[1]->range_valid) | ||||||
|  | @ -519,7 +525,17 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// trim/extend parameters
 | 	// trim/extend parameters
 | ||||||
| 	if ((type == AST_PARAMETER || type == AST_LOCALPARAM) && children[0]->type == AST_CONSTANT && children.size() > 1) { | 	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) | 				if (!children[1]->range_valid) | ||||||
| 					log_error("Non-constant width range on parameter decl at %s:%d.\n", filename.c_str(), linenum); | 					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; | 				int width = children[1]->range_left - children[1]->range_right + 1; | ||||||
|  | @ -532,6 +548,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | ||||||
| 				} | 				} | ||||||
| 				children[0]->is_signed = is_signed; | 				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; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	// annotate identifiers using scope resolution and create auto-wires as needed
 | 	// annotate identifiers using scope resolution and create auto-wires as needed
 | ||||||
| 	if (type == AST_IDENTIFIER) { | 	if (type == AST_IDENTIFIER) { | ||||||
|  |  | ||||||
|  | @ -168,6 +168,7 @@ namespace VERILOG_FRONTEND { | ||||||
| "integer" { return TOK_INTEGER; } | "integer" { return TOK_INTEGER; } | ||||||
| "signed"  { return TOK_SIGNED; } | "signed"  { return TOK_SIGNED; } | ||||||
| "genvar"  { return TOK_GENVAR; } | "genvar"  { return TOK_GENVAR; } | ||||||
|  | "real"    { return TOK_REAL; } | ||||||
| 
 | 
 | ||||||
| [0-9]+ { | [0-9]+ { | ||||||
| 	frontend_verilog_yylval.string = new std::string(yytext); | 	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_]+)? { | [0-9][0-9_]*\.[0-9][0-9_]*([eE][-+]?[0-9_]+)? { | ||||||
| 	frontend_verilog_yylval.string = new std::string(yytext); | 	frontend_verilog_yylval.string = new std::string(yytext); | ||||||
| 	return TOK_REAL; | 	return TOK_REALVAL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [0-9][0-9_]*[eE][-+]?[0-9_]+ { | [0-9][0-9_]*[eE][-+]?[0-9_]+ { | ||||||
| 	frontend_verilog_yylval.string = new std::string(yytext); | 	frontend_verilog_yylval.string = new std::string(yytext); | ||||||
| 	return TOK_REAL; | 	return TOK_REALVAL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| \"		{ BEGIN(STRING); } | \"		{ BEGIN(STRING); } | ||||||
|  |  | ||||||
|  | @ -94,7 +94,7 @@ static void free_attr(std::map<std::string, AstNode*> *al) | ||||||
| 	bool boolean; | 	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 ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END | ||||||
| %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM | %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM | ||||||
| %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG | %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_POSEDGE TOK_NEGEDGE TOK_OR | ||||||
| %token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT | %token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT | ||||||
| %token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK | %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_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE | ||||||
| %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED | %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED | ||||||
| %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_PROPERTY | %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)); | 		astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true)); | ||||||
| 	} | /* empty */; | 	} | /* 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: | param_range: | ||||||
| 	range { | 	range { | ||||||
| 		if ($1 != NULL) { | 		if ($1 != NULL) { | ||||||
|  | @ -451,7 +458,7 @@ param_decl: | ||||||
| 	TOK_PARAMETER { | 	TOK_PARAMETER { | ||||||
| 		astbuf1 = new AstNode(AST_PARAMETER); | 		astbuf1 = new AstNode(AST_PARAMETER); | ||||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | 		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; | 		delete astbuf1; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | @ -459,7 +466,7 @@ localparam_decl: | ||||||
| 	TOK_LOCALPARAM { | 	TOK_LOCALPARAM { | ||||||
| 		astbuf1 = new AstNode(AST_LOCALPARAM); | 		astbuf1 = new AstNode(AST_LOCALPARAM); | ||||||
| 		astbuf1->children.push_back(AstNode::mkconst_int(0, true)); | 		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; | 		delete astbuf1; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | @ -1133,7 +1140,7 @@ basic_expr: | ||||||
| 			log_error("Value conversion failed: `%s'\n", $1->c_str()); | 			log_error("Value conversion failed: `%s'\n", $1->c_str()); | ||||||
| 		delete $1; | 		delete $1; | ||||||
| 	} | | 	} | | ||||||
| 	TOK_REAL { | 	TOK_REALVAL { | ||||||
| 		$$ = new AstNode(AST_REALVALUE); | 		$$ = new AstNode(AST_REALVALUE); | ||||||
| 		char *p = strdup($1->c_str()), *q; | 		char *p = strdup($1->c_str()), *q; | ||||||
| 		for (int i = 0, j = 0; !p[j]; j++) | 		for (int i = 0, j = 0; !p[j]; j++) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue