diff options
Diffstat (limited to 'frontends/verilog/verilog_parser.y')
-rw-r--r-- | frontends/verilog/verilog_parser.y | 440 |
1 files changed, 395 insertions, 45 deletions
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 5bbda535..2389d7d3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -59,6 +59,7 @@ namespace VERILOG_FRONTEND { bool default_nettype_wire; bool sv_mode, formal_mode, lib_mode; bool norestrict_mode, assume_asserts_mode; + bool current_wire_rand, current_wire_const; std::istream *lexin; } YOSYS_NAMESPACE_END @@ -100,27 +101,29 @@ static void free_attr(std::map<std::string, AstNode*> *al) bool boolean; } -%token <string> TOK_STRING TOK_ID TOK_CONST TOK_REALVAL TOK_PRIMITIVE +%token <string> TOK_STRING TOK_ID TOK_CONSTVAL 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_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP -%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG +%token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG TOK_LOGIC %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL %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 +%token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC %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 TOK_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM %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_ASSUME -%token TOK_RESTRICT TOK_PROPERTY +%token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF +%token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY +%token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY %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 tok_prim_wrapper hierarchical_id -%type <boolean> opt_signed -%type <al> attr +%type <boolean> opt_signed unique_case_attr +%type <al> attr case_attr // operator precedence from low to high %left OP_LOR @@ -139,7 +142,9 @@ static void free_attr(std::map<std::string, AstNode*> *al) %define parse.error verbose %define parse.lac full -%expect 2 +%nonassoc FAKE_THEN +%nonassoc TOK_ELSE + %debug %% @@ -269,7 +274,13 @@ single_module_para: if (astbuf1) delete astbuf1; astbuf1 = new AstNode(AST_PARAMETER); astbuf1->children.push_back(AstNode::mkconst_int(0, true)); - } param_signed param_integer param_range single_param_decl | single_param_decl; + } param_signed param_integer param_range single_param_decl | + TOK_LOCALPARAM { + if (astbuf1) delete astbuf1; + astbuf1 = new AstNode(AST_LOCALPARAM); + astbuf1->children.push_back(AstNode::mkconst_int(0, true)); + } param_signed param_integer param_range single_param_decl | + single_param_decl; module_args_opt: '(' ')' | /* empty */ | '(' module_args optional_comma ')'; @@ -346,6 +357,9 @@ package_body_stmt: localparam_decl; non_opt_delay: + '#' TOK_ID { delete $2; } | + '#' TOK_CONSTVAL { delete $2; } | + '#' TOK_REALVAL { delete $2; } | '#' '(' expr ')' { delete $3; } | '#' '(' expr ':' expr ':' expr ')' { delete $3; delete $5; delete $7; }; @@ -355,14 +369,17 @@ delay: wire_type: { astbuf3 = new AstNode(AST_WIRE); + current_wire_rand = false; + current_wire_const = false; } wire_type_token_list delay { $$ = astbuf3; }; wire_type_token_list: - wire_type_token | wire_type_token_list wire_type_token; + wire_type_token | wire_type_token_list wire_type_token | + wire_type_token_io ; -wire_type_token: +wire_type_token_io: TOK_INPUT { astbuf3->is_input = true; } | @@ -372,12 +389,17 @@ wire_type_token: TOK_INOUT { astbuf3->is_input = true; astbuf3->is_output = true; - } | + }; + +wire_type_token: TOK_WIRE { } | TOK_REG { astbuf3->is_reg = true; } | + TOK_LOGIC { + astbuf3->is_logic = true; + } | TOK_INTEGER { astbuf3->is_reg = true; astbuf3->range_left = 31; @@ -392,6 +414,12 @@ wire_type_token: } | TOK_SIGNED { astbuf3->is_signed = true; + } | + TOK_RAND { + current_wire_rand = true; + } | + TOK_CONST { + current_wire_const = true; }; non_opt_range: @@ -454,8 +482,19 @@ module_body: /* empty */; module_body_stmt: - task_func_decl | param_decl | localparam_decl | defparam_decl | wire_decl | assign_stmt | cell_stmt | - always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property; + task_func_decl | specify_block |param_decl | localparam_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; + +checker_decl: + TOK_CHECKER TOK_ID ';' { + AstNode *node = new AstNode(AST_GENBLOCK); + node->str = *$2; + ast_stack.back()->children.push_back(node); + ast_stack.push_back(node); + } module_body TOK_ENDCHECKER { + delete $2; + ast_stack.pop_back(); + }; task_func_decl: attr TOK_DPI_FUNCTION TOK_ID TOK_ID { @@ -491,35 +530,36 @@ task_func_decl: } opt_dpi_function_args ';' { current_function_or_task = NULL; } | - attr TOK_TASK TOK_ID { + attr TOK_TASK opt_automatic TOK_ID { current_function_or_task = new AstNode(AST_TASK); - current_function_or_task->str = *$3; + current_function_or_task->str = *$4; append_attr(current_function_or_task, $1); ast_stack.back()->children.push_back(current_function_or_task); ast_stack.push_back(current_function_or_task); current_function_or_task_port_id = 1; - delete $3; + delete $4; } task_func_args_opt ';' task_func_body TOK_ENDTASK { current_function_or_task = NULL; ast_stack.pop_back(); } | - attr TOK_FUNCTION opt_signed range_or_signed_int TOK_ID { + attr TOK_FUNCTION opt_automatic opt_signed range_or_signed_int TOK_ID { current_function_or_task = new AstNode(AST_FUNCTION); - current_function_or_task->str = *$5; + current_function_or_task->str = *$6; append_attr(current_function_or_task, $1); ast_stack.back()->children.push_back(current_function_or_task); ast_stack.push_back(current_function_or_task); AstNode *outreg = new AstNode(AST_WIRE); - outreg->str = *$5; - outreg->is_signed = $3; - if ($4 != NULL) { - outreg->children.push_back($4); - outreg->is_signed = $3 || $4->is_signed; - $4->is_signed = false; + outreg->str = *$6; + outreg->is_signed = $4; + outreg->is_reg = true; + if ($5 != NULL) { + outreg->children.push_back($5); + outreg->is_signed = $4 || $5->is_signed; + $5->is_signed = false; } current_function_or_task->children.push_back(outreg); current_function_or_task_port_id = 1; - delete $5; + delete $6; } task_func_args_opt ';' task_func_body TOK_ENDFUNCTION { current_function_or_task = NULL; ast_stack.pop_back(); @@ -546,6 +586,10 @@ dpi_function_args: dpi_function_arg | /* empty */; +opt_automatic: + TOK_AUTOMATIC | + /* empty */; + opt_signed: TOK_SIGNED { $$ = true; @@ -597,6 +641,194 @@ task_func_body: task_func_body behavioral_stmt | /* empty */; +specify_block: + TOK_SPECIFY specify_item_opt TOK_ENDSPECIFY | + TOK_SPECIFY TOK_ENDSPECIFY ; + +specify_item_opt: + specify_item_opt specify_item | + specify_item ; + +specify_item: + specparam_declaration + // | pulsestyle_declaration + // | showcancelled_declaration + | path_declaration + | system_timing_declaration + ; + +specparam_declaration: + TOK_SPECPARAM list_of_specparam_assignments ';' | + TOK_SPECPARAM specparam_range list_of_specparam_assignments ';' ; + +// IEEE 1364-2005 calls this sinmply 'range' but the current 'range' rule allows empty match +// and the 'non_opt_range' rule allows index ranges not allowed by 1364-2005 +// exxxxtending this for SV specparam would change this anyhow +specparam_range: + '[' constant_expression ':' constant_expression ']' ; + +list_of_specparam_assignments: + specparam_assignment | list_of_specparam_assignments ',' specparam_assignment; + +specparam_assignment: + TOK_ID '=' constant_mintypmax_expression ; + +/* +pulsestyle_declaration : + ; + +showcancelled_declaration : + ; +*/ + +path_declaration : + simple_path_declaration ';' + // | edge_sensitive_path_declaration + // | state_dependent_path_declaration + ; + +simple_path_declaration : + parallel_path_description '=' path_delay_value | + full_path_description '=' path_delay_value + ; + +path_delay_value : + '(' path_delay_expression list_of_path_delay_extra_expressions ')' + | path_delay_expression + | path_delay_expression list_of_path_delay_extra_expressions + ; + +list_of_path_delay_extra_expressions : +/* + t_path_delay_expression + | trise_path_delay_expression ',' tfall_path_delay_expression + | trise_path_delay_expression ',' tfall_path_delay_expression ',' tz_path_delay_expression + | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ',' + tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression + | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ',' + tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression ',' + t0x_path_delay_expression ',' tx1_path_delay_expression ',' t1x_path_delay_expression ',' + tx0_path_delay_expression ',' txz_path_delay_expression ',' tzx_path_delay_expression +*/ + ',' path_delay_expression + | ',' path_delay_expression ',' path_delay_expression + | ',' path_delay_expression ',' path_delay_expression ',' + path_delay_expression ',' path_delay_expression ',' path_delay_expression + | ',' path_delay_expression ',' path_delay_expression ',' + path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' + path_delay_expression ',' path_delay_expression ',' path_delay_expression ',' + path_delay_expression ',' path_delay_expression ',' path_delay_expression + ; + +parallel_path_description : + '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ; + +full_path_description : + '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' ; + +// This was broken into 2 rules to solve shift/reduce conflicts +list_of_path_inputs : + specify_input_terminal_descriptor opt_polarity_operator | + specify_input_terminal_descriptor more_path_inputs opt_polarity_operator ; + +more_path_inputs : + ',' specify_input_terminal_descriptor | + more_path_inputs ',' specify_input_terminal_descriptor ; + +list_of_path_outputs : + specify_output_terminal_descriptor | + list_of_path_outputs ',' specify_output_terminal_descriptor ; + +opt_polarity_operator : + '+' + | '-' + | ; + +// Good enough for the time being +specify_input_terminal_descriptor : + TOK_ID ; + +// Good enough for the time being +specify_output_terminal_descriptor : + TOK_ID ; + +system_timing_declaration : + TOK_ID '(' system_timing_args ')' ';' ; + +system_timing_arg : + TOK_POSEDGE TOK_ID | + TOK_NEGEDGE TOK_ID | + expr ; + +system_timing_args : + system_timing_arg | + system_timing_args ',' system_timing_arg ; + +/* +t_path_delay_expression : + path_delay_expression; + +trise_path_delay_expression : + path_delay_expression; + +tfall_path_delay_expression : + path_delay_expression; + +tz_path_delay_expression : + path_delay_expression; + +t01_path_delay_expression : + path_delay_expression; + +t10_path_delay_expression : + path_delay_expression; + +t0z_path_delay_expression : + path_delay_expression; + +tz1_path_delay_expression : + path_delay_expression; + +t1z_path_delay_expression : + path_delay_expression; + +tz0_path_delay_expression : + path_delay_expression; + +t0x_path_delay_expression : + path_delay_expression; + +tx1_path_delay_expression : + path_delay_expression; + +t1x_path_delay_expression : + path_delay_expression; + +tx0_path_delay_expression : + path_delay_expression; + +txz_path_delay_expression : + path_delay_expression; + +tzx_path_delay_expression : + path_delay_expression; +*/ + +path_delay_expression : + constant_expression; + +constant_mintypmax_expression : + constant_expression + | constant_expression ':' constant_expression ':' constant_expression + ; + +// for the time being this is OK, but we may write our own expr here. +// as I'm not sure it is legal to use a full expr here (probably not) +// On the other hand, other rules requiring constant expressions also use 'expr' +// (such as param assignment), so we may leave this as-is, perhaps assing runtime checks for constant-ness +constant_expression: + expr ; + param_signed: TOK_SIGNED { astbuf1->is_signed = true; @@ -666,14 +898,13 @@ defparam_decl_list: single_defparam_decl | defparam_decl_list ',' single_defparam_decl; single_defparam_decl: - range hierarchical_id '=' expr { + range rvalue '=' expr { AstNode *node = new AstNode(AST_DEFPARAM); - node->str = *$2; + node->children.push_back($2); node->children.push_back($4); if ($1 != NULL) node->children.push_back($1); ast_stack.back()->children.push_back(node); - delete $2; }; wire_decl: @@ -731,7 +962,48 @@ wire_name_list: wire_name_and_opt_assign | wire_name_list ',' wire_name_and_opt_assign; wire_name_and_opt_assign: - wire_name | + wire_name { + bool attr_anyconst = false; + bool attr_anyseq = false; + bool attr_allconst = false; + bool attr_allseq = false; + if (ast_stack.back()->children.back()->get_bool_attribute("\\anyconst")) { + delete ast_stack.back()->children.back()->attributes.at("\\anyconst"); + ast_stack.back()->children.back()->attributes.erase("\\anyconst"); + attr_anyconst = true; + } + if (ast_stack.back()->children.back()->get_bool_attribute("\\anyseq")) { + delete ast_stack.back()->children.back()->attributes.at("\\anyseq"); + ast_stack.back()->children.back()->attributes.erase("\\anyseq"); + attr_anyseq = true; + } + if (ast_stack.back()->children.back()->get_bool_attribute("\\allconst")) { + delete ast_stack.back()->children.back()->attributes.at("\\allconst"); + ast_stack.back()->children.back()->attributes.erase("\\allconst"); + attr_allconst = true; + } + if (ast_stack.back()->children.back()->get_bool_attribute("\\allseq")) { + delete ast_stack.back()->children.back()->attributes.at("\\allseq"); + ast_stack.back()->children.back()->attributes.erase("\\allseq"); + attr_allseq = true; + } + if (current_wire_rand || attr_anyconst || attr_anyseq || attr_allconst || attr_allseq) { + AstNode *wire = new AstNode(AST_IDENTIFIER); + AstNode *fcall = new AstNode(AST_FCALL); + wire->str = ast_stack.back()->children.back()->str; + fcall->str = current_wire_const ? "\\$anyconst" : "\\$anyseq"; + if (attr_anyconst) + fcall->str = "\\$anyconst"; + if (attr_anyseq) + fcall->str = "\\$anyseq"; + if (attr_allconst) + fcall->str = "\\$allconst"; + if (attr_allseq) + fcall->str = "\\$allseq"; + fcall->attributes["\\reg"] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str)); + ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, fcall)); + } + } | wire_name '=' expr { AstNode *wire = new AstNode(AST_IDENTIFIER); wire->str = ast_stack.back()->children.back()->str; @@ -782,6 +1054,7 @@ wire_name: node->port_id = current_function_or_task_port_id++; } ast_stack.back()->children.push_back(node); + delete $1; }; @@ -994,18 +1267,45 @@ opt_label: $$ = NULL; }; +opt_property: + TOK_PROPERTY | /* empty */; + +opt_stmt_label: + TOK_ID ':' | /* empty */; + assert: - TOK_ASSERT '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $3)); + opt_stmt_label TOK_ASSERT opt_property '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5)); + } | + opt_stmt_label TOK_ASSUME opt_property '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + } | + opt_stmt_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6)); + } | + opt_stmt_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); } | - TOK_ASSUME '(' expr ')' ';' { - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $3)); + opt_stmt_label TOK_COVER opt_property '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5)); } | - TOK_RESTRICT '(' expr ')' ';' { + opt_stmt_label TOK_COVER opt_property '(' ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false))); + } | + opt_stmt_label TOK_COVER ';' { + ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false))); + } | + opt_stmt_label TOK_RESTRICT opt_property '(' expr ')' ';' { if (norestrict_mode) - delete $3; + delete $5; + else + ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5)); + } | + opt_stmt_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' { + if (norestrict_mode) + delete $6; else - ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $3)); + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6)); }; assert_property: @@ -1015,11 +1315,26 @@ assert_property: TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' { ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); } | + TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5)); + } | + TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); + } | + TOK_COVER TOK_PROPERTY '(' expr ')' ';' { + ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4)); + } | TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' { if (norestrict_mode) delete $4; else ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4)); + } | + TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' { + if (norestrict_mode) + delete $5; + else + ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5)); }; simple_behavioral_stmt: @@ -1027,6 +1342,14 @@ simple_behavioral_stmt: AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4); ast_stack.back()->children.push_back(node); } | + lvalue TOK_INCREMENT { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_ADD, $1->clone(), AstNode::mkconst_int(1, true))); + ast_stack.back()->children.push_back(node); + } | + lvalue TOK_DECREMENT { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_SUB, $1->clone(), AstNode::mkconst_int(1, true))); + ast_stack.back()->children.push_back(node); + } | lvalue OP_LE delay expr { AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4); ast_stack.back()->children.push_back(node); @@ -1118,7 +1441,7 @@ behavioral_stmt: ast_stack.pop_back(); ast_stack.pop_back(); } | - attr case_type '(' expr ')' { + case_attr case_type '(' expr ')' { AstNode *node = new AstNode(AST_CASE, $4); ast_stack.back()->children.push_back(node); ast_stack.push_back(node); @@ -1128,6 +1451,23 @@ behavioral_stmt: ast_stack.pop_back(); }; +unique_case_attr: + /* empty */ { + $$ = false; + } | + TOK_PRIORITY case_attr { + $$ = $2; + } | + TOK_UNIQUE case_attr { + $$ = true; + }; + +case_attr: + attr unique_case_attr { + if ($2) (*$1)["\\parallel_case"] = AstNode::mkconst_int(1, false); + $$ = $1; + }; + case_type: TOK_CASE { case_type_stack.push_back(0); @@ -1162,7 +1502,7 @@ optional_else: ast_stack.back()->children.push_back(cond); ast_stack.push_back(block); } behavioral_stmt | - /* empty */; + /* empty */ %prec FAKE_THEN; case_body: case_body case_item | @@ -1229,7 +1569,9 @@ rvalue: $$ = new AstNode(AST_IDENTIFIER, $2); $$->str = *$1; delete $1; - if ($2 == nullptr && formal_mode && ($$->str == "\\$initstate" || $$->str == "\\$anyconst" || $$->str == "\\$anyseq")) + if ($2 == nullptr && ($$->str == "\\$initstate" || + $$->str == "\\$anyconst" || $$->str == "\\$anyseq" || + $$->str == "\\$allconst" || $$->str == "\\$allseq")) $$->type = AST_FCALL; } | hierarchical_id non_opt_multirange { @@ -1333,7 +1675,7 @@ gen_stmt_or_null: gen_stmt_block | ';'; opt_gen_else: - TOK_ELSE gen_stmt_or_null | /* empty */; + TOK_ELSE gen_stmt_or_null | /* empty */ %prec FAKE_THEN; expr: basic_expr { @@ -1351,7 +1693,7 @@ basic_expr: rvalue { $$ = $1; } | - '(' expr ')' TOK_CONST { + '(' expr ')' TOK_CONSTVAL { if ($4->substr(0, 1) != "'") frontend_verilog_yyerror("Syntax error."); AstNode *bits = $2; @@ -1361,7 +1703,7 @@ basic_expr: $$ = new AstNode(AST_TO_BITS, bits, val); delete $4; } | - hierarchical_id TOK_CONST { + hierarchical_id TOK_CONSTVAL { if ($2->substr(0, 1) != "'") frontend_verilog_yyerror("Syntax error."); AstNode *bits = new AstNode(AST_IDENTIFIER); @@ -1373,14 +1715,14 @@ basic_expr: delete $1; delete $2; } | - TOK_CONST TOK_CONST { + TOK_CONSTVAL TOK_CONSTVAL { $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); if ($$ == NULL || (*$2)[0] != '\'') log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str()); delete $1; delete $2; } | - TOK_CONST { + TOK_CONSTVAL { $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); if ($$ == NULL) log_error("Value conversion failed: `%s'\n", $1->c_str()); @@ -1441,10 +1783,18 @@ basic_expr: $$ = new AstNode(AST_BIT_AND, $1, $4); append_attr($$, $3); } | + basic_expr OP_NAND attr basic_expr { + $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_AND, $1, $4)); + append_attr($$, $3); + } | basic_expr '|' attr basic_expr { $$ = new AstNode(AST_BIT_OR, $1, $4); append_attr($$, $3); } | + basic_expr OP_NOR attr basic_expr { + $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_OR, $1, $4)); + append_attr($$, $3); + } | basic_expr '^' attr basic_expr { $$ = new AstNode(AST_BIT_XOR, $1, $4); append_attr($$, $3); |