diff options
Diffstat (limited to 'frontends/verilog')
| -rw-r--r-- | frontends/verilog/preproc.cc | 18 | ||||
| -rw-r--r-- | frontends/verilog/verilog_frontend.cc | 16 | ||||
| -rw-r--r-- | frontends/verilog/verilog_lexer.l | 6 | ||||
| -rw-r--r-- | frontends/verilog/verilog_parser.y | 119 | 
4 files changed, 136 insertions, 23 deletions
| diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc index dea22ee8a..7e107dc26 100644 --- a/frontends/verilog/preproc.cc +++ b/frontends/verilog/preproc.cc @@ -490,13 +490,17 @@ std::string frontend_verilog_preproc(std::istream &f, std::string filename, cons  			}  			while (newline_count-- > 0)  				return_char('\n'); -			// printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str()); -			defines_map[name] = value; -			if (state == 2) -				defines_with_args.insert(name); -			else -				defines_with_args.erase(name); -			global_defines_cache[name] = std::pair<std::string, bool>(value, state == 2); +			if (strchr("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ$0123456789", name[0])) { +				// printf("define: >>%s<< -> >>%s<<\n", name.c_str(), value.c_str()); +				defines_map[name] = value; +				if (state == 2) +					defines_with_args.insert(name); +				else +					defines_with_args.erase(name); +				global_defines_cache[name] = std::pair<std::string, bool>(value, state == 2); +			} else { +				log_file_error(filename, 0, "Invalid name for macro definition: >>%s<<.\n", name.c_str()); +			}  			continue;  		} diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 0e2bead6f..058d750c3 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -553,6 +553,12 @@ struct VerilogDefines : public Pass {  		log("    -Uname[=definition]\n");  		log("        undefine the preprocessor symbol 'name'\n");  		log("\n"); +		log("    -reset\n"); +		log("        clear list of defined preprocessor symbols\n"); +		log("\n"); +		log("    -list\n"); +		log("        list currently defined preprocessor symbols\n"); +		log("\n");  	}  	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE  	{ @@ -588,6 +594,16 @@ struct VerilogDefines : public Pass {  				design->verilog_defines.erase(name);  				continue;  			} +			if (arg == "-reset") { +				design->verilog_defines.clear(); +				continue; +			} +			if (arg == "-list") { +				for (auto &it : design->verilog_defines) { +					log("`define %s%s %s\n", it.first.c_str(), it.second.second ? "()" : "", it.second.first.c_str()); +				} +				continue; +			}  			break;  		} diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index 4acfb414d..c8984c2c4 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -188,9 +188,9 @@ YOSYS_NAMESPACE_END  "unique0"      { SV_KEYWORD(TOK_UNIQUE); }  "priority"     { SV_KEYWORD(TOK_PRIORITY); } -"always_comb"  { SV_KEYWORD(TOK_ALWAYS); } -"always_ff"    { SV_KEYWORD(TOK_ALWAYS); } -"always_latch" { SV_KEYWORD(TOK_ALWAYS); } +"always_comb"  { SV_KEYWORD(TOK_ALWAYS_COMB); } +"always_ff"    { SV_KEYWORD(TOK_ALWAYS_FF); } +"always_latch" { SV_KEYWORD(TOK_ALWAYS_LATCH); }   /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex      to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4afd72b73..daea3b43a 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -141,6 +141,7 @@ struct specify_rise_fall {  %token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR  %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC  %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL +%token TOK_ALWAYS_FF TOK_ALWAYS_COMB TOK_ALWAYS_LATCH  %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT  %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC  %token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT @@ -155,8 +156,8 @@ struct specify_rise_fall {  %type <ast> range range_or_multirange  non_opt_range non_opt_multirange range_or_signed_int  %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list -%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id -%type <boolean> opt_signed opt_property unique_case_attr +%type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id +%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff  %type <al> attr case_attr  %type <specify_target_ptr> specify_target @@ -206,6 +207,7 @@ design:  	task_func_decl design |  	param_decl design |  	localparam_decl design | +	typedef_decl design |  	package design |  	interface design |  	/* empty */; @@ -290,6 +292,9 @@ hierarchical_id:  		$$ = $1;  	}; +hierarchical_type_id: +	'(' hierarchical_id ')' { $$ = $2; }; +  module:  	attr TOK_MODULE TOK_ID {  		do_not_require_port_stubs = false; @@ -324,13 +329,13 @@ single_module_para:  		astbuf1 = new AstNode(AST_PARAMETER);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true));  		append_attr(astbuf1, $1); -	} param_signed param_integer param_range single_param_decl | +	} param_type single_param_decl |  	attr TOK_LOCALPARAM {  		if (astbuf1) delete astbuf1;  		astbuf1 = new AstNode(AST_LOCALPARAM);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true));  		append_attr(astbuf1, $1); -	} param_signed param_integer param_range single_param_decl | +	} param_type single_param_decl |  	single_param_decl;  module_args_opt: @@ -426,6 +431,7 @@ package_body:  	package_body package_body_stmt |;  package_body_stmt: +	typedef_decl |  	localparam_decl;  interface: @@ -452,7 +458,7 @@ interface_body:  	interface_body interface_body_stmt |;  interface_body_stmt: -	param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt | +	param_decl | localparam_decl | typedef_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |  	modport_stmt;  non_opt_delay: @@ -475,8 +481,14 @@ wire_type:  	};  wire_type_token_list: -	wire_type_token | wire_type_token_list wire_type_token | -	wire_type_token_io ; +	wire_type_token | +	wire_type_token_list wire_type_token | +	wire_type_token_io | +	hierarchical_type_id { +		astbuf3->is_custom_type = true; +		astbuf3->children.push_back(new AstNode(AST_WIRETYPE)); +		astbuf3->children.back()->str = *$1; +	};  wire_type_token_io:  	TOK_INPUT { @@ -591,7 +603,7 @@ module_body:  	/* empty */;  module_body_stmt: -	task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | +	task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |  	always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;  checker_decl: @@ -1149,12 +1161,20 @@ param_range:  		}  	}; +param_type: +	param_signed param_integer param_real param_range | +	hierarchical_type_id { +		astbuf1->is_custom_type = true; +		astbuf1->children.push_back(new AstNode(AST_WIRETYPE)); +		astbuf1->children.back()->str = *$1; +	}; +  param_decl:  	attr TOK_PARAMETER {  		astbuf1 = new AstNode(AST_PARAMETER);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true));  		append_attr(astbuf1, $1); -	} param_signed param_integer param_real param_range param_decl_list ';' { +	} param_type param_decl_list ';' {  		delete astbuf1;  	}; @@ -1163,7 +1183,7 @@ localparam_decl:  		astbuf1 = new AstNode(AST_LOCALPARAM);  		astbuf1->children.push_back(AstNode::mkconst_int(0, true));  		append_attr(astbuf1, $1); -	} param_signed param_integer param_real param_range param_decl_list ';' { +	} param_type param_decl_list ';' {  		delete astbuf1;  	}; @@ -1327,7 +1347,7 @@ wire_name:  		if ($2 != NULL) {  			if (node->is_input || node->is_output)  				frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions."); -			if (!astbuf2) { +			if (!astbuf2 && !node->is_custom_type) {  				AstNode *rng = new AstNode(AST_RANGE);  				rng->children.push_back(AstNode::mkconst_int(0, true));  				rng->children.push_back(AstNode::mkconst_int(0, true)); @@ -1377,6 +1397,45 @@ assign_expr:  		ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3));  	}; +typedef_decl: +	TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' { +		astbuf1 = $2; +		astbuf2 = $3; +		if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) { +			if (astbuf2) { +				frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions."); +			} else { +				astbuf2 = new AstNode(AST_RANGE); +				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true)); +				astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true)); +			} +		} +		if (astbuf2 && astbuf2->children.size() != 2) +			frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]"); +		if (astbuf2) +			astbuf1->children.push_back(astbuf2); + +		if ($5 != NULL) { +			if (!astbuf2) { +				AstNode *rng = new AstNode(AST_RANGE); +				rng->children.push_back(AstNode::mkconst_int(0, true)); +				rng->children.push_back(AstNode::mkconst_int(0, true)); +				astbuf1->children.push_back(rng); +			} +			astbuf1->type = AST_MEMORY; +			auto *rangeNode = $5; +			if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) { +				// SV array size [n], rewrite as [n-1:0] +				rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true)); +				rangeNode->children.push_back(AstNode::mkconst_int(0, false)); +			} +			astbuf1->children.push_back(rangeNode); +		} + +		ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); +		ast_stack.back()->children.back()->str = *$4; +	}; +  cell_stmt:  	attr TOK_ID {  		astbuf1 = new AstNode(AST_CELL); @@ -1523,10 +1582,28 @@ cell_port:  		free_attr($1);  	}; +always_comb_or_latch: +	TOK_ALWAYS_COMB { +		$$ = false; +	} | +	TOK_ALWAYS_LATCH { +		$$ = true; +	}; + +always_or_always_ff: +	TOK_ALWAYS { +		$$ = false; +	} | +	TOK_ALWAYS_FF { +		$$ = true; +	}; +  always_stmt: -	attr TOK_ALWAYS { +	attr always_or_always_ff {  		AstNode *node = new AstNode(AST_ALWAYS);  		append_attr(node, $1); +		if ($2) +			node->attributes[ID(always_ff)] = AstNode::mkconst_int(1, false);  		ast_stack.back()->children.push_back(node);  		ast_stack.push_back(node);  	} always_cond { @@ -1537,6 +1614,22 @@ always_stmt:  		ast_stack.pop_back();  		ast_stack.pop_back();  	} | +	attr always_comb_or_latch { +		AstNode *node = new AstNode(AST_ALWAYS); +		append_attr(node, $1); +		if ($2) +			node->attributes[ID(always_latch)] = AstNode::mkconst_int(1, false); +		else +			node->attributes[ID(always_comb)] = AstNode::mkconst_int(1, false); +		ast_stack.back()->children.push_back(node); +		ast_stack.push_back(node); +		AstNode *block = new AstNode(AST_BLOCK); +		ast_stack.back()->children.push_back(block); +		ast_stack.push_back(block); +	} behavioral_stmt { +		ast_stack.pop_back(); +		ast_stack.pop_back(); +	} |  	attr TOK_INITIAL {  		AstNode *node = new AstNode(AST_INITIAL);  		append_attr(node, $1); @@ -1823,7 +1916,7 @@ simple_behavioral_stmt:  // this production creates the obligatory if-else shift/reduce conflict  behavioral_stmt: -	defattr | assert | wire_decl | param_decl | localparam_decl | +	defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl |  	non_opt_delay behavioral_stmt |  	simple_behavioral_stmt ';' | ';' |  	hierarchical_id attr { | 
