2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * The Verilog frontend.
22 * This frontend is using the AST frontend library (see frontends/ast/).
23 * Thus this frontend does not generate RTLIL code directly but creates an
24 * AST directly from the Verilog parse tree and then passes this AST to
25 * the AST frontend library.
29 * This is the actual bison parser for Verilog code. The AST ist created directly
30 * from the bison reduce functions here. Note that this code uses a few global
31 * variables to hold the state of the AST generator and therefore this parser is
40 #include "frontends/verilog/verilog_frontend.h"
41 #include "kernel/log.h"
45 using namespace VERILOG_FRONTEND;
48 namespace VERILOG_FRONTEND {
50 std::map<std::string, int> port_stubs;
51 std::map<std::string, AstNode*> *attr_list, default_attr_list;
52 std::stack<std::map<std::string, AstNode*> *> attr_list_stack;
53 std::map<std::string, AstNode*> *albuf;
54 std::vector<AstNode*> ast_stack;
55 struct AstNode *astbuf1, *astbuf2, *astbuf3;
56 struct AstNode *current_function_or_task;
57 struct AstNode *current_ast, *current_ast_mod;
58 int current_function_or_task_port_id;
59 std::vector<char> case_type_stack;
60 bool do_not_require_port_stubs;
61 bool default_nettype_wire;
62 bool sv_mode, formal_mode, lib_mode, specify_mode;
63 bool noassert_mode, noassume_mode, norestrict_mode;
64 bool assume_asserts_mode, assert_assumes_mode;
65 bool current_wire_rand, current_wire_const;
66 bool current_modport_input, current_modport_output;
71 static void append_attr(AstNode *ast, std::map<std::string, AstNode*> *al)
73 for (auto &it : *al) {
74 if (ast->attributes.count(it.first) > 0)
75 delete ast->attributes[it.first];
76 ast->attributes[it.first] = it.second;
81 static void append_attr_clone(AstNode *ast, std::map<std::string, AstNode*> *al)
83 for (auto &it : *al) {
84 if (ast->attributes.count(it.first) > 0)
85 delete ast->attributes[it.first];
86 ast->attributes[it.first] = it.second->clone();
90 static void free_attr(std::map<std::string, AstNode*> *al)
97 struct specify_target {
102 struct specify_triple {
103 AstNode *t_min, *t_avg, *t_max;
106 struct specify_rise_fall {
113 %define api.prefix {frontend_verilog_yy}
115 /* The union is defined in the header, so we need to provide all the
116 * includes it requires
121 #include "frontends/verilog/verilog_frontend.h"
126 struct YOSYS_NAMESPACE_PREFIX AST::AstNode *ast;
127 std::map<std::string, YOSYS_NAMESPACE_PREFIX AST::AstNode*> *al;
128 struct specify_target *specify_target_ptr;
129 struct specify_triple *specify_triple_ptr;
130 struct specify_rise_fall *specify_rise_fall_ptr;
135 %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
136 %token <string> TOK_SVA_LABEL TOK_SPECIFY_OPER TOK_ELAB_TASK
137 %token TOK_ASSERT TOK_ASSUME TOK_RESTRICT TOK_COVER TOK_FINAL
138 %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
139 %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
140 %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
141 %token TOK_INTERFACE TOK_ENDINTERFACE TOK_MODPORT TOK_VAR
142 %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_WAND TOK_WOR TOK_REG TOK_LOGIC
143 %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
144 %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
145 %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR TOK_AUTOMATIC
146 %token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT
147 %token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK TOK_SPECIFY
148 %token TOK_IGNORED_SPECIFY TOK_ENDSPECIFY TOK_SPECPARAM TOK_SPECIFY_AND
149 %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
150 %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
151 %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
152 %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
153 %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
154 %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY
156 %type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
157 %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
158 %type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id
159 %type <boolean> opt_signed opt_property unique_case_attr
160 %type <al> attr case_attr
162 %type <specify_target_ptr> specify_target
163 %type <specify_triple_ptr> specify_triple
164 %type <specify_rise_fall_ptr> specify_rise_fall
165 %type <ast> specify_if specify_condition specify_opt_arg
166 %type <ch> specify_edge
168 // operator precedence from low to high
174 %left OP_EQ OP_NE OP_EQX OP_NEX
175 %left '<' OP_LE OP_GE '>'
176 %left OP_SHL OP_SHR OP_SSHL OP_SSHR
182 %define parse.error verbose
183 %define parse.lac full
194 ast_stack.push_back(current_ast);
196 ast_stack.pop_back();
197 log_assert(GetSize(ast_stack) == 0);
198 for (auto &it : default_attr_list)
200 default_attr_list.clear();
206 task_func_decl design |
208 localparam_decl design |
215 if (attr_list != nullptr)
216 attr_list_stack.push(attr_list);
217 attr_list = new std::map<std::string, AstNode*>;
218 for (auto &it : default_attr_list)
219 (*attr_list)[it.first] = it.second->clone();
222 if (!attr_list_stack.empty()) {
223 attr_list = attr_list_stack.top();
224 attr_list_stack.pop();
230 attr_opt ATTR_BEGIN opt_attr_list ATTR_END |
235 if (attr_list != nullptr)
236 attr_list_stack.push(attr_list);
237 attr_list = new std::map<std::string, AstNode*>;
238 for (auto &it : default_attr_list)
240 default_attr_list.clear();
242 attr_list->swap(default_attr_list);
244 if (!attr_list_stack.empty()) {
245 attr_list = attr_list_stack.top();
246 attr_list_stack.pop();
252 attr_list | /* empty */;
256 attr_list ',' attr_assign;
260 if (attr_list->count(*$1) != 0)
261 delete (*attr_list)[*$1];
262 (*attr_list)[*$1] = AstNode::mkconst_int(1, false);
265 hierarchical_id '=' expr {
266 if (attr_list->count(*$1) != 0)
267 delete (*attr_list)[*$1];
268 (*attr_list)[*$1] = $3;
276 hierarchical_id TOK_PACKAGESEP TOK_ID {
277 if ($3->substr(0, 1) == "\\")
278 *$1 += "::" + $3->substr(1);
284 hierarchical_id '.' TOK_ID {
285 if ($3->substr(0, 1) == "\\")
286 *$1 += "." + $3->substr(1);
294 attr TOK_MODULE TOK_ID {
295 do_not_require_port_stubs = false;
296 AstNode *mod = new AstNode(AST_MODULE);
297 ast_stack.back()->children.push_back(mod);
298 ast_stack.push_back(mod);
299 current_ast_mod = mod;
303 append_attr(mod, $1);
305 } module_para_opt module_args_opt ';' module_body TOK_ENDMODULE {
306 if (port_stubs.size() != 0)
307 frontend_verilog_yyerror("Missing details for module port `%s'.",
308 port_stubs.begin()->first.c_str());
309 ast_stack.pop_back();
310 log_assert(ast_stack.size() == 1);
311 current_ast_mod = NULL;
315 '#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | /* empty */;
318 single_module_para | module_para_list ',' single_module_para;
323 if (astbuf1) delete astbuf1;
324 astbuf1 = new AstNode(AST_PARAMETER);
325 astbuf1->children.push_back(AstNode::mkconst_int(0, true));
326 } param_signed param_integer param_range single_param_decl |
328 if (astbuf1) delete astbuf1;
329 astbuf1 = new AstNode(AST_LOCALPARAM);
330 astbuf1->children.push_back(AstNode::mkconst_int(0, true));
331 } param_signed param_integer param_range single_param_decl |
335 '(' ')' | /* empty */ | '(' module_args optional_comma ')';
338 module_arg | module_args ',' module_arg;
343 module_arg_opt_assignment:
345 if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
346 AstNode *wire = new AstNode(AST_IDENTIFIER);
347 wire->str = ast_stack.back()->children.back()->str;
348 if (ast_stack.back()->children.back()->is_reg)
349 ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));
351 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
353 frontend_verilog_yyerror("SystemVerilog interface in module port list cannot have a default value.");
359 if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
360 AstNode *node = ast_stack.back()->children.back()->clone();
362 node->port_id = ++port_counter;
363 ast_stack.back()->children.push_back(node);
365 if (port_stubs.count(*$1) != 0)
366 frontend_verilog_yyerror("Duplicate module port `%s'.", $1->c_str());
367 port_stubs[*$1] = ++port_counter;
370 } module_arg_opt_assignment |
372 astbuf1 = new AstNode(AST_INTERFACEPORT);
373 astbuf1->children.push_back(new AstNode(AST_INTERFACEPORTTYPE));
374 astbuf1->children[0]->str = *$1;
376 } TOK_ID { /* SV interfaces */
378 frontend_verilog_yyerror("Interface found in port list (%s). This is not supported unless read_verilog is called with -sv!", $3->c_str());
379 astbuf2 = astbuf1->clone(); // really only needed if multiple instances of same type.
382 astbuf2->port_id = ++port_counter;
383 ast_stack.back()->children.push_back(astbuf2);
384 delete astbuf1; // really only needed if multiple instances of same type.
385 } module_arg_opt_assignment |
386 attr wire_type range TOK_ID {
389 node->port_id = ++port_counter;
391 node->children.push_back($3);
392 if (!node->is_input && !node->is_output)
393 frontend_verilog_yyerror("Module port `%s' is neither input nor output.", $4->c_str());
394 if (node->is_reg && node->is_input && !node->is_output && !sv_mode)
395 frontend_verilog_yyerror("Input port `%s' is declared as register.", $4->c_str());
396 ast_stack.back()->children.push_back(node);
397 append_attr(node, $1);
399 } module_arg_opt_assignment |
401 do_not_require_port_stubs = true;
405 attr TOK_PACKAGE TOK_ID {
406 AstNode *mod = new AstNode(AST_PACKAGE);
407 ast_stack.back()->children.push_back(mod);
408 ast_stack.push_back(mod);
409 current_ast_mod = mod;
411 append_attr(mod, $1);
412 } ';' package_body TOK_ENDPACKAGE {
413 ast_stack.pop_back();
414 current_ast_mod = NULL;
418 package_body package_body_stmt |;
424 TOK_INTERFACE TOK_ID {
425 do_not_require_port_stubs = false;
426 AstNode *intf = new AstNode(AST_INTERFACE);
427 ast_stack.back()->children.push_back(intf);
428 ast_stack.push_back(intf);
429 current_ast_mod = intf;
434 } module_para_opt module_args_opt ';' interface_body TOK_ENDINTERFACE {
435 if (port_stubs.size() != 0)
436 frontend_verilog_yyerror("Missing details for module port `%s'.",
437 port_stubs.begin()->first.c_str());
438 ast_stack.pop_back();
439 log_assert(ast_stack.size() == 1);
440 current_ast_mod = NULL;
444 interface_body interface_body_stmt |;
447 param_decl | localparam_decl | defparam_decl | wire_decl | always_stmt | assign_stmt |
451 '#' TOK_ID { delete $2; } |
452 '#' TOK_CONSTVAL { delete $2; } |
453 '#' TOK_REALVAL { delete $2; } |
454 '#' '(' expr ')' { delete $3; } |
455 '#' '(' expr ':' expr ':' expr ')' { delete $3; delete $5; delete $7; };
458 non_opt_delay | /* empty */;
462 astbuf3 = new AstNode(AST_WIRE);
463 current_wire_rand = false;
464 current_wire_const = false;
465 } wire_type_token_list delay {
469 wire_type_token_list:
470 wire_type_token | wire_type_token_list wire_type_token |
475 astbuf3->is_input = true;
478 astbuf3->is_output = true;
481 astbuf3->is_input = true;
482 astbuf3->is_output = true;
489 astbuf3->is_wor = true;
492 astbuf3->is_wand = true;
495 astbuf3->is_reg = true;
498 astbuf3->is_logic = true;
501 astbuf3->is_logic = true;
504 astbuf3->is_reg = true;
505 astbuf3->range_left = 31;
506 astbuf3->range_right = 0;
507 astbuf3->is_signed = true;
510 astbuf3->type = AST_GENVAR;
511 astbuf3->is_reg = true;
512 astbuf3->range_left = 31;
513 astbuf3->range_right = 0;
516 astbuf3->is_signed = true;
519 current_wire_rand = true;
522 current_wire_const = true;
526 '[' expr ':' expr ']' {
527 $$ = new AstNode(AST_RANGE);
528 $$->children.push_back($2);
529 $$->children.push_back($4);
531 '[' expr TOK_POS_INDEXED expr ']' {
532 $$ = new AstNode(AST_RANGE);
533 $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, $2->clone(), $4), AstNode::mkconst_int(1, true)));
534 $$->children.push_back(new AstNode(AST_ADD, $2, AstNode::mkconst_int(0, true)));
536 '[' expr TOK_NEG_INDEXED expr ']' {
537 $$ = new AstNode(AST_RANGE);
538 $$->children.push_back(new AstNode(AST_ADD, $2, AstNode::mkconst_int(0, true)));
539 $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, $2->clone(), AstNode::mkconst_int(1, true)), $4));
542 $$ = new AstNode(AST_RANGE);
543 $$->children.push_back($2);
547 non_opt_range non_opt_range {
548 $$ = new AstNode(AST_MULTIRANGE, $1, $2);
550 non_opt_multirange non_opt_range {
552 $$->children.push_back($2);
565 non_opt_multirange { $$ = $1; };
572 $$ = new AstNode(AST_RANGE);
573 $$->children.push_back(AstNode::mkconst_int(31, true));
574 $$->children.push_back(AstNode::mkconst_int(0, true));
575 $$->is_signed = true;
579 module_body module_body_stmt |
580 /* the following line makes the generate..endgenrate keywords optional */
581 module_body gen_stmt |
585 task_func_decl | specify_block |param_decl | localparam_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt |
586 always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block;
589 TOK_CHECKER TOK_ID ';' {
590 AstNode *node = new AstNode(AST_GENBLOCK);
592 ast_stack.back()->children.push_back(node);
593 ast_stack.push_back(node);
594 } module_body TOK_ENDCHECKER {
596 ast_stack.pop_back();
600 attr TOK_DPI_FUNCTION TOK_ID TOK_ID {
601 current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$3), AstNode::mkconst_str(*$4));
602 current_function_or_task->str = *$4;
603 append_attr(current_function_or_task, $1);
604 ast_stack.back()->children.push_back(current_function_or_task);
607 } opt_dpi_function_args ';' {
608 current_function_or_task = NULL;
610 attr TOK_DPI_FUNCTION TOK_ID '=' TOK_ID TOK_ID {
611 current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$5), AstNode::mkconst_str(*$3));
612 current_function_or_task->str = *$6;
613 append_attr(current_function_or_task, $1);
614 ast_stack.back()->children.push_back(current_function_or_task);
618 } opt_dpi_function_args ';' {
619 current_function_or_task = NULL;
621 attr TOK_DPI_FUNCTION TOK_ID ':' TOK_ID '=' TOK_ID TOK_ID {
622 current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$7), AstNode::mkconst_str(*$3 + ":" + RTLIL::unescape_id(*$5)));
623 current_function_or_task->str = *$8;
624 append_attr(current_function_or_task, $1);
625 ast_stack.back()->children.push_back(current_function_or_task);
630 } opt_dpi_function_args ';' {
631 current_function_or_task = NULL;
633 attr TOK_TASK opt_automatic TOK_ID {
634 current_function_or_task = new AstNode(AST_TASK);
635 current_function_or_task->str = *$4;
636 append_attr(current_function_or_task, $1);
637 ast_stack.back()->children.push_back(current_function_or_task);
638 ast_stack.push_back(current_function_or_task);
639 current_function_or_task_port_id = 1;
641 } task_func_args_opt ';' task_func_body TOK_ENDTASK {
642 current_function_or_task = NULL;
643 ast_stack.pop_back();
645 attr TOK_FUNCTION opt_automatic opt_signed range_or_signed_int TOK_ID {
646 current_function_or_task = new AstNode(AST_FUNCTION);
647 current_function_or_task->str = *$6;
648 append_attr(current_function_or_task, $1);
649 ast_stack.back()->children.push_back(current_function_or_task);
650 ast_stack.push_back(current_function_or_task);
651 AstNode *outreg = new AstNode(AST_WIRE);
653 outreg->is_signed = $4;
654 outreg->is_reg = true;
656 outreg->children.push_back($5);
657 outreg->is_signed = $4 || $5->is_signed;
658 $5->is_signed = false;
660 current_function_or_task->children.push_back(outreg);
661 current_function_or_task_port_id = 1;
663 } task_func_args_opt ';' task_func_body TOK_ENDFUNCTION {
664 current_function_or_task = NULL;
665 ast_stack.pop_back();
670 current_function_or_task->children.push_back(AstNode::mkconst_str(*$1));
675 current_function_or_task->children.push_back(AstNode::mkconst_str(*$1));
679 opt_dpi_function_args:
680 '(' dpi_function_args ')' |
684 dpi_function_args ',' dpi_function_arg |
685 dpi_function_args ',' |
702 '(' ')' | /* empty */ | '(' {
706 } task_func_args optional_comma {
714 task_func_port | task_func_args ',' task_func_port;
717 attr wire_type range {
727 if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
729 frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions (task/function arguments)");
731 astbuf2 = new AstNode(AST_RANGE);
732 astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
733 astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true));
736 if (astbuf2 && astbuf2->children.size() != 2)
737 frontend_verilog_yyerror("task/function argument range must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
738 } wire_name | wire_name;
741 task_func_body behavioral_stmt |
744 /*************************** specify parser ***************************/
747 TOK_SPECIFY specify_item_list TOK_ENDSPECIFY;
750 specify_item specify_item_list |
754 specify_if '(' specify_edge expr TOK_SPECIFY_OPER specify_target ')' '=' specify_rise_fall ';' {
755 AstNode *en_expr = $1;
756 char specify_edge = $3;
757 AstNode *src_expr = $4;
759 specify_target *target = $6;
760 specify_rise_fall *timing = $9;
762 if (specify_edge != 0 && target->dat == nullptr)
763 frontend_verilog_yyerror("Found specify edge but no data spec.\n");
765 AstNode *cell = new AstNode(AST_CELL);
766 ast_stack.back()->children.push_back(cell);
767 cell->str = stringf("$specify$%d", autoidx++);
768 cell->children.push_back(new AstNode(AST_CELLTYPE));
769 cell->children.back()->str = target->dat ? "$specify3" : "$specify2";
771 char oper_polarity = 0;
772 char oper_type = oper->at(0);
774 if (oper->size() == 3) {
775 oper_polarity = oper->at(0);
776 oper_type = oper->at(1);
779 cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_type == '*', false, 1)));
780 cell->children.back()->str = "\\FULL";
782 cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_polarity != 0, false, 1)));
783 cell->children.back()->str = "\\SRC_DST_PEN";
785 cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(oper_polarity == '+', false, 1)));
786 cell->children.back()->str = "\\SRC_DST_POL";
788 cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_min));
789 cell->children.back()->str = "\\T_RISE_MIN";
791 cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_avg));
792 cell->children.back()->str = "\\T_RISE_TYP";
794 cell->children.push_back(new AstNode(AST_PARASET, timing->rise.t_max));
795 cell->children.back()->str = "\\T_RISE_MAX";
797 cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_min));
798 cell->children.back()->str = "\\T_FALL_MIN";
800 cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_avg));
801 cell->children.back()->str = "\\T_FALL_TYP";
803 cell->children.push_back(new AstNode(AST_PARASET, timing->fall.t_max));
804 cell->children.back()->str = "\\T_FALL_MAX";
806 cell->children.push_back(new AstNode(AST_ARGUMENT, en_expr ? en_expr : AstNode::mkconst_int(1, false, 1)));
807 cell->children.back()->str = "\\EN";
809 cell->children.push_back(new AstNode(AST_ARGUMENT, src_expr));
810 cell->children.back()->str = "\\SRC";
812 cell->children.push_back(new AstNode(AST_ARGUMENT, target->dst));
813 cell->children.back()->str = "\\DST";
817 cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(specify_edge != 0, false, 1)));
818 cell->children.back()->str = "\\EDGE_EN";
820 cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(specify_edge == 'p', false, 1)));
821 cell->children.back()->str = "\\EDGE_POL";
823 cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(target->polarity_op != 0, false, 1)));
824 cell->children.back()->str = "\\DAT_DST_PEN";
826 cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_int(target->polarity_op == '+', false, 1)));
827 cell->children.back()->str = "\\DAT_DST_POL";
829 cell->children.push_back(new AstNode(AST_ARGUMENT, target->dat));
830 cell->children.back()->str = "\\DAT";
837 TOK_ID '(' specify_edge expr specify_condition ',' specify_edge expr specify_condition ',' expr specify_opt_arg ')' ';' {
838 if (*$1 != "$setup" && *$1 != "$hold" && *$1 != "$setuphold" && *$1 != "$removal" && *$1 != "$recovery" &&
839 *$1 != "$recrem" && *$1 != "$skew" && *$1 != "$timeskew" && *$1 != "$fullskew" && *$1 != "$nochange")
840 frontend_verilog_yyerror("Unsupported specify rule type: %s\n", $1->c_str());
842 AstNode *src_pen = AstNode::mkconst_int($3 != 0, false, 1);
843 AstNode *src_pol = AstNode::mkconst_int($3 == 'p', false, 1);
844 AstNode *src_expr = $4, *src_en = $5 ? $5 : AstNode::mkconst_int(1, false, 1);
846 AstNode *dst_pen = AstNode::mkconst_int($7 != 0, false, 1);
847 AstNode *dst_pol = AstNode::mkconst_int($7 == 'p', false, 1);
848 AstNode *dst_expr = $8, *dst_en = $9 ? $9 : AstNode::mkconst_int(1, false, 1);
850 AstNode *limit = $11;
851 AstNode *limit2 = $12;
853 AstNode *cell = new AstNode(AST_CELL);
854 ast_stack.back()->children.push_back(cell);
855 cell->str = stringf("$specify$%d", autoidx++);
856 cell->children.push_back(new AstNode(AST_CELLTYPE));
857 cell->children.back()->str = "$specrule";
859 cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_str(*$1)));
860 cell->children.back()->str = "\\TYPE";
862 cell->children.push_back(new AstNode(AST_PARASET, limit));
863 cell->children.back()->str = "\\T_LIMIT";
865 cell->children.push_back(new AstNode(AST_PARASET, limit2 ? limit2 : AstNode::mkconst_int(0, true)));
866 cell->children.back()->str = "\\T_LIMIT2";
868 cell->children.push_back(new AstNode(AST_PARASET, src_pen));
869 cell->children.back()->str = "\\SRC_PEN";
871 cell->children.push_back(new AstNode(AST_PARASET, src_pol));
872 cell->children.back()->str = "\\SRC_POL";
874 cell->children.push_back(new AstNode(AST_PARASET, dst_pen));
875 cell->children.back()->str = "\\DST_PEN";
877 cell->children.push_back(new AstNode(AST_PARASET, dst_pol));
878 cell->children.back()->str = "\\DST_POL";
880 cell->children.push_back(new AstNode(AST_ARGUMENT, src_en));
881 cell->children.back()->str = "\\SRC_EN";
883 cell->children.push_back(new AstNode(AST_ARGUMENT, src_expr));
884 cell->children.back()->str = "\\SRC";
886 cell->children.push_back(new AstNode(AST_ARGUMENT, dst_en));
887 cell->children.back()->str = "\\DST_EN";
889 cell->children.push_back(new AstNode(AST_ARGUMENT, dst_expr));
890 cell->children.back()->str = "\\DST";
904 TOK_IF '(' expr ')' {
912 TOK_SPECIFY_AND expr {
921 $$ = new specify_target;
926 '(' expr ':' expr ')'{
927 $$ = new specify_target;
932 '(' expr TOK_NEG_INDEXED expr ')'{
933 $$ = new specify_target;
934 $$->polarity_op = '-';
938 '(' expr TOK_POS_INDEXED expr ')'{
939 $$ = new specify_target;
940 $$->polarity_op = '+';
946 TOK_POSEDGE { $$ = 'p'; } |
947 TOK_NEGEDGE { $$ = 'n'; } |
952 $$ = new specify_rise_fall;
954 $$->fall.t_min = $1->t_min->clone();
955 $$->fall.t_avg = $1->t_avg->clone();
956 $$->fall.t_max = $1->t_max->clone();
959 '(' specify_triple ',' specify_triple ')' {
960 $$ = new specify_rise_fall;
969 $$ = new specify_triple;
971 $$->t_avg = $1->clone();
972 $$->t_max = $1->clone();
974 expr ':' expr ':' expr {
975 $$ = new specify_triple;
981 /******************** ignored specify parser **************************/
983 ignored_specify_block:
984 TOK_IGNORED_SPECIFY ignored_specify_item_opt TOK_ENDSPECIFY |
985 TOK_IGNORED_SPECIFY TOK_ENDSPECIFY ;
987 ignored_specify_item_opt:
988 ignored_specify_item_opt ignored_specify_item |
989 ignored_specify_item ;
991 ignored_specify_item:
992 specparam_declaration
993 // | pulsestyle_declaration
994 // | showcancelled_declaration
996 | system_timing_declaration
999 specparam_declaration:
1000 TOK_SPECPARAM list_of_specparam_assignments ';' |
1001 TOK_SPECPARAM specparam_range list_of_specparam_assignments ';' ;
1003 // IEEE 1364-2005 calls this sinmply 'range' but the current 'range' rule allows empty match
1004 // and the 'non_opt_range' rule allows index ranges not allowed by 1364-2005
1005 // exxxxtending this for SV specparam would change this anyhow
1007 '[' ignspec_constant_expression ':' ignspec_constant_expression ']' ;
1009 list_of_specparam_assignments:
1010 specparam_assignment | list_of_specparam_assignments ',' specparam_assignment;
1012 specparam_assignment:
1013 ignspec_id '=' constant_mintypmax_expression ;
1016 pulsestyle_declaration :
1019 showcancelled_declaration :
1024 simple_path_declaration ';'
1025 // | edge_sensitive_path_declaration
1026 // | state_dependent_path_declaration
1029 simple_path_declaration :
1030 parallel_path_description '=' path_delay_value |
1031 full_path_description '=' path_delay_value
1035 '(' path_delay_expression list_of_path_delay_extra_expressions ')'
1036 | path_delay_expression
1037 | path_delay_expression list_of_path_delay_extra_expressions
1040 list_of_path_delay_extra_expressions :
1042 t_path_delay_expression
1043 | trise_path_delay_expression ',' tfall_path_delay_expression
1044 | trise_path_delay_expression ',' tfall_path_delay_expression ',' tz_path_delay_expression
1045 | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ','
1046 tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression
1047 | t01_path_delay_expression ',' t10_path_delay_expression ',' t0z_path_delay_expression ','
1048 tz1_path_delay_expression ',' t1z_path_delay_expression ',' tz0_path_delay_expression ','
1049 t0x_path_delay_expression ',' tx1_path_delay_expression ',' t1x_path_delay_expression ','
1050 tx0_path_delay_expression ',' txz_path_delay_expression ',' tzx_path_delay_expression
1052 ',' path_delay_expression
1053 | ',' path_delay_expression ',' path_delay_expression
1054 | ',' path_delay_expression ',' path_delay_expression ','
1055 path_delay_expression ',' path_delay_expression ',' path_delay_expression
1056 | ',' path_delay_expression ',' path_delay_expression ','
1057 path_delay_expression ',' path_delay_expression ',' path_delay_expression ','
1058 path_delay_expression ',' path_delay_expression ',' path_delay_expression ','
1059 path_delay_expression ',' path_delay_expression ',' path_delay_expression
1062 parallel_path_description :
1063 '(' specify_input_terminal_descriptor opt_polarity_operator '=' '>' specify_output_terminal_descriptor ')' ;
1065 full_path_description :
1066 '(' list_of_path_inputs '*' '>' list_of_path_outputs ')' ;
1068 // This was broken into 2 rules to solve shift/reduce conflicts
1069 list_of_path_inputs :
1070 specify_input_terminal_descriptor opt_polarity_operator |
1071 specify_input_terminal_descriptor more_path_inputs opt_polarity_operator ;
1074 ',' specify_input_terminal_descriptor |
1075 more_path_inputs ',' specify_input_terminal_descriptor ;
1077 list_of_path_outputs :
1078 specify_output_terminal_descriptor |
1079 list_of_path_outputs ',' specify_output_terminal_descriptor ;
1081 opt_polarity_operator :
1086 // Good enough for the time being
1087 specify_input_terminal_descriptor :
1090 // Good enough for the time being
1091 specify_output_terminal_descriptor :
1094 system_timing_declaration :
1095 ignspec_id '(' system_timing_args ')' ';' ;
1098 TOK_POSEDGE ignspec_id |
1099 TOK_NEGEDGE ignspec_id |
1102 system_timing_args :
1104 system_timing_args ',' system_timing_arg ;
1107 t_path_delay_expression :
1108 path_delay_expression;
1110 trise_path_delay_expression :
1111 path_delay_expression;
1113 tfall_path_delay_expression :
1114 path_delay_expression;
1116 tz_path_delay_expression :
1117 path_delay_expression;
1119 t01_path_delay_expression :
1120 path_delay_expression;
1122 t10_path_delay_expression :
1123 path_delay_expression;
1125 t0z_path_delay_expression :
1126 path_delay_expression;
1128 tz1_path_delay_expression :
1129 path_delay_expression;
1131 t1z_path_delay_expression :
1132 path_delay_expression;
1134 tz0_path_delay_expression :
1135 path_delay_expression;
1137 t0x_path_delay_expression :
1138 path_delay_expression;
1140 tx1_path_delay_expression :
1141 path_delay_expression;
1143 t1x_path_delay_expression :
1144 path_delay_expression;
1146 tx0_path_delay_expression :
1147 path_delay_expression;
1149 txz_path_delay_expression :
1150 path_delay_expression;
1152 tzx_path_delay_expression :
1153 path_delay_expression;
1156 path_delay_expression :
1157 ignspec_constant_expression;
1159 constant_mintypmax_expression :
1160 ignspec_constant_expression
1161 | ignspec_constant_expression ':' ignspec_constant_expression ':' ignspec_constant_expression
1164 // for the time being this is OK, but we may write our own expr here.
1165 // as I'm not sure it is legal to use a full expr here (probably not)
1166 // On the other hand, other rules requiring constant expressions also use 'expr'
1167 // (such as param assignment), so we may leave this as-is, perhaps adding runtime checks for constant-ness
1168 ignspec_constant_expression:
1169 expr { delete $1; };
1172 expr { delete $1; };
1175 TOK_ID { delete $1; };
1177 /**********************************************************************/
1181 astbuf1->is_signed = true;
1186 if (astbuf1->children.size() != 1)
1187 frontend_verilog_yyerror("Internal error in param_integer - should not happen?");
1188 astbuf1->children.push_back(new AstNode(AST_RANGE));
1189 astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true));
1190 astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true));
1191 astbuf1->is_signed = true;
1196 if (astbuf1->children.size() != 1)
1197 frontend_verilog_yyerror("Parameter already declared as integer, cannot set to real.");
1198 astbuf1->children.push_back(new AstNode(AST_REALVALUE));
1204 if (astbuf1->children.size() != 1)
1205 frontend_verilog_yyerror("integer/real parameters should not have a range.");
1206 astbuf1->children.push_back($1);
1211 attr TOK_PARAMETER {
1212 astbuf1 = new AstNode(AST_PARAMETER);
1213 astbuf1->children.push_back(AstNode::mkconst_int(0, true));
1214 } param_signed param_integer param_real param_range param_decl_list ';' {
1219 attr TOK_LOCALPARAM {
1220 astbuf1 = new AstNode(AST_LOCALPARAM);
1221 astbuf1->children.push_back(AstNode::mkconst_int(0, true));
1222 } param_signed param_integer param_real param_range param_decl_list ';' {
1227 single_param_decl | param_decl_list ',' single_param_decl;
1232 if (astbuf1 == nullptr) {
1234 frontend_verilog_yyerror("In pure Verilog (not SystemVerilog), parameter/localparam with an initializer must use the parameter/localparam keyword");
1235 node = new AstNode(AST_PARAMETER);
1236 node->children.push_back(AstNode::mkconst_int(0, true));
1238 node = astbuf1->clone();
1241 delete node->children[0];
1242 node->children[0] = $3;
1243 ast_stack.back()->children.push_back(node);
1248 TOK_DEFPARAM defparam_decl_list ';';
1251 single_defparam_decl | defparam_decl_list ',' single_defparam_decl;
1253 single_defparam_decl:
1254 range rvalue '=' expr {
1255 AstNode *node = new AstNode(AST_DEFPARAM);
1256 node->children.push_back($2);
1257 node->children.push_back($4);
1259 node->children.push_back($1);
1260 ast_stack.back()->children.push_back(node);
1264 attr wire_type range {
1268 if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
1270 frontend_verilog_yyerror("integer/genvar types cannot have packed dimensions.");
1272 astbuf2 = new AstNode(AST_RANGE);
1273 astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
1274 astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true));
1277 if (astbuf2 && astbuf2->children.size() != 2)
1278 frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
1281 if (astbuf2 != NULL)
1285 attr TOK_SUPPLY0 TOK_ID {
1286 ast_stack.back()->children.push_back(new AstNode(AST_WIRE));
1287 ast_stack.back()->children.back()->str = *$3;
1288 append_attr(ast_stack.back()->children.back(), $1);
1289 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(0, false, 1)));
1290 ast_stack.back()->children.back()->children[0]->str = *$3;
1292 } opt_supply_wires ';' |
1293 attr TOK_SUPPLY1 TOK_ID {
1294 ast_stack.back()->children.push_back(new AstNode(AST_WIRE));
1295 ast_stack.back()->children.back()->str = *$3;
1296 append_attr(ast_stack.back()->children.back(), $1);
1297 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(1, false, 1)));
1298 ast_stack.back()->children.back()->children[0]->str = *$3;
1300 } opt_supply_wires ';';
1304 opt_supply_wires ',' TOK_ID {
1305 AstNode *wire_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-2)->clone();
1306 AstNode *assign_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-1)->clone();
1307 wire_node->str = *$3;
1308 assign_node->children[0]->str = *$3;
1309 ast_stack.back()->children.push_back(wire_node);
1310 ast_stack.back()->children.push_back(assign_node);
1315 wire_name_and_opt_assign | wire_name_list ',' wire_name_and_opt_assign;
1317 wire_name_and_opt_assign:
1319 bool attr_anyconst = false;
1320 bool attr_anyseq = false;
1321 bool attr_allconst = false;
1322 bool attr_allseq = false;
1323 if (ast_stack.back()->children.back()->get_bool_attribute("\\anyconst")) {
1324 delete ast_stack.back()->children.back()->attributes.at("\\anyconst");
1325 ast_stack.back()->children.back()->attributes.erase("\\anyconst");
1326 attr_anyconst = true;
1328 if (ast_stack.back()->children.back()->get_bool_attribute("\\anyseq")) {
1329 delete ast_stack.back()->children.back()->attributes.at("\\anyseq");
1330 ast_stack.back()->children.back()->attributes.erase("\\anyseq");
1333 if (ast_stack.back()->children.back()->get_bool_attribute("\\allconst")) {
1334 delete ast_stack.back()->children.back()->attributes.at("\\allconst");
1335 ast_stack.back()->children.back()->attributes.erase("\\allconst");
1336 attr_allconst = true;
1338 if (ast_stack.back()->children.back()->get_bool_attribute("\\allseq")) {
1339 delete ast_stack.back()->children.back()->attributes.at("\\allseq");
1340 ast_stack.back()->children.back()->attributes.erase("\\allseq");
1343 if (current_wire_rand || attr_anyconst || attr_anyseq || attr_allconst || attr_allseq) {
1344 AstNode *wire = new AstNode(AST_IDENTIFIER);
1345 AstNode *fcall = new AstNode(AST_FCALL);
1346 wire->str = ast_stack.back()->children.back()->str;
1347 fcall->str = current_wire_const ? "\\$anyconst" : "\\$anyseq";
1349 fcall->str = "\\$anyconst";
1351 fcall->str = "\\$anyseq";
1353 fcall->str = "\\$allconst";
1355 fcall->str = "\\$allseq";
1356 fcall->attributes["\\reg"] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str));
1357 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, fcall));
1360 wire_name '=' expr {
1361 AstNode *wire = new AstNode(AST_IDENTIFIER);
1362 wire->str = ast_stack.back()->children.back()->str;
1363 if (astbuf1->is_reg)
1364 ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3))));
1366 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3));
1370 TOK_ID range_or_multirange {
1371 if (astbuf1 == nullptr)
1372 frontend_verilog_yyerror("Internal error - should not happen - no AST_WIRE node.");
1373 AstNode *node = astbuf1->clone();
1375 append_attr_clone(node, albuf);
1376 if (astbuf2 != NULL)
1377 node->children.push_back(astbuf2->clone());
1379 if (node->is_input || node->is_output)
1380 frontend_verilog_yyerror("input/output/inout ports cannot have unpacked dimensions.");
1382 AstNode *rng = new AstNode(AST_RANGE);
1383 rng->children.push_back(AstNode::mkconst_int(0, true));
1384 rng->children.push_back(AstNode::mkconst_int(0, true));
1385 node->children.push_back(rng);
1387 node->type = AST_MEMORY;
1388 node->children.push_back($2);
1390 if (current_function_or_task == NULL) {
1391 if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) {
1392 port_stubs[*$1] = ++port_counter;
1394 if (port_stubs.count(*$1) != 0) {
1395 if (!node->is_input && !node->is_output)
1396 frontend_verilog_yyerror("Module port `%s' is neither input nor output.", $1->c_str());
1397 if (node->is_reg && node->is_input && !node->is_output && !sv_mode)
1398 frontend_verilog_yyerror("Input port `%s' is declared as register.", $1->c_str());
1399 node->port_id = port_stubs[*$1];
1400 port_stubs.erase(*$1);
1402 if (node->is_input || node->is_output)
1403 frontend_verilog_yyerror("Module port `%s' is not declared in module header.", $1->c_str());
1406 if (node->is_input || node->is_output)
1407 node->port_id = current_function_or_task_port_id++;
1409 ast_stack.back()->children.push_back(node);
1415 TOK_ASSIGN delay assign_expr_list ';';
1418 assign_expr | assign_expr_list ',' assign_expr;
1422 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3));
1427 astbuf1 = new AstNode(AST_CELL);
1428 append_attr(astbuf1, $1);
1429 astbuf1->children.push_back(new AstNode(AST_CELLTYPE));
1430 astbuf1->children[0]->str = *$2;
1432 } cell_parameter_list_opt cell_list ';' {
1435 attr tok_prim_wrapper delay {
1436 astbuf1 = new AstNode(AST_PRIMITIVE);
1438 append_attr(astbuf1, $1);
1449 $$ = new std::string("or");
1454 cell_list ',' single_cell;
1458 astbuf2 = astbuf1->clone();
1459 if (astbuf2->type != AST_PRIMITIVE)
1462 ast_stack.back()->children.push_back(astbuf2);
1463 } '(' cell_port_list ')' |
1464 TOK_ID non_opt_range {
1465 astbuf2 = astbuf1->clone();
1466 if (astbuf2->type != AST_PRIMITIVE)
1469 ast_stack.back()->children.push_back(new AstNode(AST_CELLARRAY, $2, astbuf2));
1470 } '(' cell_port_list ')';
1474 prim_list ',' single_prim;
1479 astbuf2 = astbuf1->clone();
1480 ast_stack.back()->children.push_back(astbuf2);
1481 } '(' cell_port_list ')';
1483 cell_parameter_list_opt:
1484 '#' '(' cell_parameter_list ')' | /* empty */;
1486 cell_parameter_list:
1487 cell_parameter | cell_parameter_list ',' cell_parameter;
1492 AstNode *node = new AstNode(AST_PARASET);
1493 astbuf1->children.push_back(node);
1494 node->children.push_back($1);
1496 '.' TOK_ID '(' expr ')' {
1497 AstNode *node = new AstNode(AST_PARASET);
1499 astbuf1->children.push_back(node);
1500 node->children.push_back($4);
1505 cell_port_list_rules {
1506 // remove empty args from end of list
1507 while (!astbuf2->children.empty()) {
1508 AstNode *node = astbuf2->children.back();
1509 if (node->type != AST_ARGUMENT) break;
1510 if (!node->children.empty()) break;
1511 if (!node->str.empty()) break;
1512 astbuf2->children.pop_back();
1517 bool has_positional_args = false;
1518 bool has_named_args = false;
1519 for (auto node : astbuf2->children) {
1520 if (node->type != AST_ARGUMENT) continue;
1521 if (node->str.empty())
1522 has_positional_args = true;
1524 has_named_args = true;
1527 if (has_positional_args && has_named_args)
1528 frontend_verilog_yyerror("Mix of positional and named cell ports.");
1531 cell_port_list_rules:
1532 cell_port | cell_port_list_rules ',' cell_port;
1536 AstNode *node = new AstNode(AST_ARGUMENT);
1537 astbuf2->children.push_back(node);
1541 AstNode *node = new AstNode(AST_ARGUMENT);
1542 astbuf2->children.push_back(node);
1543 node->children.push_back($2);
1546 attr '.' TOK_ID '(' expr ')' {
1547 AstNode *node = new AstNode(AST_ARGUMENT);
1549 astbuf2->children.push_back(node);
1550 node->children.push_back($5);
1554 attr '.' TOK_ID '(' ')' {
1555 AstNode *node = new AstNode(AST_ARGUMENT);
1557 astbuf2->children.push_back(node);
1562 AstNode *node = new AstNode(AST_ARGUMENT);
1564 astbuf2->children.push_back(node);
1565 node->children.push_back(new AstNode(AST_IDENTIFIER));
1566 node->children.back()->str = *$3;
1573 AstNode *node = new AstNode(AST_ALWAYS);
1574 append_attr(node, $1);
1575 ast_stack.back()->children.push_back(node);
1576 ast_stack.push_back(node);
1578 AstNode *block = new AstNode(AST_BLOCK);
1579 ast_stack.back()->children.push_back(block);
1580 ast_stack.push_back(block);
1582 ast_stack.pop_back();
1583 ast_stack.pop_back();
1586 AstNode *node = new AstNode(AST_INITIAL);
1587 append_attr(node, $1);
1588 ast_stack.back()->children.push_back(node);
1589 ast_stack.push_back(node);
1590 AstNode *block = new AstNode(AST_BLOCK);
1591 ast_stack.back()->children.push_back(block);
1592 ast_stack.push_back(block);
1594 ast_stack.pop_back();
1595 ast_stack.pop_back();
1599 '@' '(' always_events ')' |
1601 '@' ATTR_BEGIN ')' |
1608 always_events TOK_OR always_event |
1609 always_events ',' always_event;
1613 AstNode *node = new AstNode(AST_POSEDGE);
1614 ast_stack.back()->children.push_back(node);
1615 node->children.push_back($2);
1618 AstNode *node = new AstNode(AST_NEGEDGE);
1619 ast_stack.back()->children.push_back(node);
1620 node->children.push_back($2);
1623 AstNode *node = new AstNode(AST_EDGE);
1624 ast_stack.back()->children.push_back(node);
1625 node->children.push_back($1);
1656 TOK_MODPORT TOK_ID {
1657 AstNode *modport = new AstNode(AST_MODPORT);
1658 ast_stack.back()->children.push_back(modport);
1659 ast_stack.push_back(modport);
1662 } modport_args_opt {
1663 ast_stack.pop_back();
1664 log_assert(ast_stack.size() == 2);
1668 '(' ')' | '(' modport_args optional_comma ')';
1671 modport_arg | modport_args ',' modport_arg;
1674 modport_type_token modport_member |
1679 AstNode *modport_member = new AstNode(AST_MODPORTMEMBER);
1680 ast_stack.back()->children.push_back(modport_member);
1681 modport_member->str = *$1;
1682 modport_member->is_input = current_modport_input;
1683 modport_member->is_output = current_modport_output;
1688 TOK_INPUT {current_modport_input = 1; current_modport_output = 0;} | TOK_OUTPUT {current_modport_input = 0; current_modport_output = 1;}
1691 opt_sva_label TOK_ASSERT opt_property '(' expr ')' ';' {
1692 if (noassert_mode) {
1695 AstNode *node = new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5);
1698 ast_stack.back()->children.push_back(node);
1703 opt_sva_label TOK_ASSUME opt_property '(' expr ')' ';' {
1704 if (noassume_mode) {
1707 AstNode *node = new AstNode(assert_assumes_mode ? AST_ASSERT : AST_ASSUME, $5);
1710 ast_stack.back()->children.push_back(node);
1715 opt_sva_label TOK_ASSERT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
1716 if (noassert_mode) {
1719 AstNode *node = new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6);
1722 ast_stack.back()->children.push_back(node);
1727 opt_sva_label TOK_ASSUME opt_property '(' TOK_EVENTUALLY expr ')' ';' {
1728 if (noassume_mode) {
1731 AstNode *node = new AstNode(assert_assumes_mode ? AST_LIVE : AST_FAIR, $6);
1734 ast_stack.back()->children.push_back(node);
1739 opt_sva_label TOK_COVER opt_property '(' expr ')' ';' {
1740 AstNode *node = new AstNode(AST_COVER, $5);
1741 if ($1 != nullptr) {
1745 ast_stack.back()->children.push_back(node);
1747 opt_sva_label TOK_COVER opt_property '(' ')' ';' {
1748 AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
1749 if ($1 != nullptr) {
1753 ast_stack.back()->children.push_back(node);
1755 opt_sva_label TOK_COVER ';' {
1756 AstNode *node = new AstNode(AST_COVER, AstNode::mkconst_int(1, false));
1757 if ($1 != nullptr) {
1761 ast_stack.back()->children.push_back(node);
1763 opt_sva_label TOK_RESTRICT opt_property '(' expr ')' ';' {
1764 if (norestrict_mode) {
1767 AstNode *node = new AstNode(AST_ASSUME, $5);
1770 ast_stack.back()->children.push_back(node);
1773 log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
1777 opt_sva_label TOK_RESTRICT opt_property '(' TOK_EVENTUALLY expr ')' ';' {
1778 if (norestrict_mode) {
1781 AstNode *node = new AstNode(AST_FAIR, $6);
1784 ast_stack.back()->children.push_back(node);
1787 log_file_warning(current_filename, get_line_num(), "SystemVerilog does not allow \"restrict\" without \"property\".\n");
1793 opt_sva_label TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
1794 ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $5));
1795 if ($1 != nullptr) {
1796 ast_stack.back()->children.back()->str = *$1;
1800 opt_sva_label TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
1801 ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
1802 if ($1 != nullptr) {
1803 ast_stack.back()->children.back()->str = *$1;
1807 opt_sva_label TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
1808 ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $6));
1809 if ($1 != nullptr) {
1810 ast_stack.back()->children.back()->str = *$1;
1814 opt_sva_label TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
1815 ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
1816 if ($1 != nullptr) {
1817 ast_stack.back()->children.back()->str = *$1;
1821 opt_sva_label TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
1822 ast_stack.back()->children.push_back(new AstNode(AST_COVER, $5));
1823 if ($1 != nullptr) {
1824 ast_stack.back()->children.back()->str = *$1;
1828 opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
1829 if (norestrict_mode) {
1832 ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $5));
1833 if ($1 != nullptr) {
1834 ast_stack.back()->children.back()->str = *$1;
1839 opt_sva_label TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
1840 if (norestrict_mode) {
1843 ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $6));
1844 if ($1 != nullptr) {
1845 ast_stack.back()->children.back()->str = *$1;
1851 simple_behavioral_stmt:
1852 lvalue '=' delay expr {
1853 AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4);
1854 ast_stack.back()->children.push_back(node);
1856 lvalue TOK_INCREMENT {
1857 AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_ADD, $1->clone(), AstNode::mkconst_int(1, true)));
1858 ast_stack.back()->children.push_back(node);
1860 lvalue TOK_DECREMENT {
1861 AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_SUB, $1->clone(), AstNode::mkconst_int(1, true)));
1862 ast_stack.back()->children.push_back(node);
1864 lvalue OP_LE delay expr {
1865 AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4);
1866 ast_stack.back()->children.push_back(node);
1869 // this production creates the obligatory if-else shift/reduce conflict
1871 defattr | assert | wire_decl | param_decl | localparam_decl |
1872 non_opt_delay behavioral_stmt |
1873 simple_behavioral_stmt ';' | ';' |
1874 hierarchical_id attr {
1875 AstNode *node = new AstNode(AST_TCALL);
1878 ast_stack.back()->children.push_back(node);
1879 ast_stack.push_back(node);
1880 append_attr(node, $2);
1882 ast_stack.pop_back();
1884 attr TOK_BEGIN opt_label {
1885 AstNode *node = new AstNode(AST_BLOCK);
1886 ast_stack.back()->children.push_back(node);
1887 ast_stack.push_back(node);
1888 append_attr(node, $1);
1891 } behavioral_stmt_list TOK_END opt_label {
1892 if ($3 != NULL && $7 != NULL && *$3 != *$7)
1893 frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1);
1898 ast_stack.pop_back();
1901 AstNode *node = new AstNode(AST_FOR);
1902 ast_stack.back()->children.push_back(node);
1903 ast_stack.push_back(node);
1904 append_attr(node, $1);
1905 } simple_behavioral_stmt ';' expr {
1906 ast_stack.back()->children.push_back($7);
1907 } ';' simple_behavioral_stmt ')' {
1908 AstNode *block = new AstNode(AST_BLOCK);
1909 ast_stack.back()->children.push_back(block);
1910 ast_stack.push_back(block);
1912 ast_stack.pop_back();
1913 ast_stack.pop_back();
1915 attr TOK_WHILE '(' expr ')' {
1916 AstNode *node = new AstNode(AST_WHILE);
1917 ast_stack.back()->children.push_back(node);
1918 ast_stack.push_back(node);
1919 append_attr(node, $1);
1920 AstNode *block = new AstNode(AST_BLOCK);
1921 ast_stack.back()->children.push_back($4);
1922 ast_stack.back()->children.push_back(block);
1923 ast_stack.push_back(block);
1925 ast_stack.pop_back();
1926 ast_stack.pop_back();
1928 attr TOK_REPEAT '(' expr ')' {
1929 AstNode *node = new AstNode(AST_REPEAT);
1930 ast_stack.back()->children.push_back(node);
1931 ast_stack.push_back(node);
1932 append_attr(node, $1);
1933 AstNode *block = new AstNode(AST_BLOCK);
1934 ast_stack.back()->children.push_back($4);
1935 ast_stack.back()->children.push_back(block);
1936 ast_stack.push_back(block);
1938 ast_stack.pop_back();
1939 ast_stack.pop_back();
1941 attr TOK_IF '(' expr ')' {
1942 AstNode *node = new AstNode(AST_CASE);
1943 AstNode *block = new AstNode(AST_BLOCK);
1944 AstNode *cond = new AstNode(AST_COND, AstNode::mkconst_int(1, false, 1), block);
1945 ast_stack.back()->children.push_back(node);
1946 node->children.push_back(new AstNode(AST_REDUCE_BOOL, $4));
1947 node->children.push_back(cond);
1948 ast_stack.push_back(node);
1949 ast_stack.push_back(block);
1950 append_attr(node, $1);
1951 } behavioral_stmt optional_else {
1952 ast_stack.pop_back();
1953 ast_stack.pop_back();
1955 case_attr case_type '(' expr ')' {
1956 AstNode *node = new AstNode(AST_CASE, $4);
1957 ast_stack.back()->children.push_back(node);
1958 ast_stack.push_back(node);
1959 append_attr(node, $1);
1960 } opt_synopsys_attr case_body TOK_ENDCASE {
1961 case_type_stack.pop_back();
1962 ast_stack.pop_back();
1969 TOK_PRIORITY case_attr {
1972 TOK_UNIQUE case_attr {
1977 attr unique_case_attr {
1978 if ($2) (*$1)["\\parallel_case"] = AstNode::mkconst_int(1, false);
1984 case_type_stack.push_back(0);
1987 case_type_stack.push_back('x');
1990 case_type_stack.push_back('z');
1994 opt_synopsys_attr TOK_SYNOPSYS_FULL_CASE {
1995 if (ast_stack.back()->attributes.count("\\full_case") == 0)
1996 ast_stack.back()->attributes["\\full_case"] = AstNode::mkconst_int(1, false);
1998 opt_synopsys_attr TOK_SYNOPSYS_PARALLEL_CASE {
1999 if (ast_stack.back()->attributes.count("\\parallel_case") == 0)
2000 ast_stack.back()->attributes["\\parallel_case"] = AstNode::mkconst_int(1, false);
2004 behavioral_stmt_list:
2005 behavioral_stmt_list behavioral_stmt |
2010 AstNode *block = new AstNode(AST_BLOCK);
2011 AstNode *cond = new AstNode(AST_COND, new AstNode(AST_DEFAULT), block);
2012 ast_stack.pop_back();
2013 ast_stack.back()->children.push_back(cond);
2014 ast_stack.push_back(block);
2016 /* empty */ %prec FAKE_THEN;
2019 case_body case_item |
2024 AstNode *node = new AstNode(
2025 case_type_stack.size() && case_type_stack.back() == 'x' ? AST_CONDX :
2026 case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND);
2027 ast_stack.back()->children.push_back(node);
2028 ast_stack.push_back(node);
2030 AstNode *block = new AstNode(AST_BLOCK);
2031 ast_stack.back()->children.push_back(block);
2032 ast_stack.push_back(block);
2033 case_type_stack.push_back(0);
2035 case_type_stack.pop_back();
2036 ast_stack.pop_back();
2037 ast_stack.pop_back();
2041 gen_case_body gen_case_item |
2046 AstNode *node = new AstNode(
2047 case_type_stack.size() && case_type_stack.back() == 'x' ? AST_CONDX :
2048 case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND);
2049 ast_stack.back()->children.push_back(node);
2050 ast_stack.push_back(node);
2052 case_type_stack.push_back(0);
2053 } gen_stmt_or_null {
2054 case_type_stack.pop_back();
2055 ast_stack.pop_back();
2059 case_expr_list ':' |
2064 ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT));
2067 ast_stack.back()->children.push_back(new AstNode(AST_IDENTIFIER));
2068 ast_stack.back()->children.back()->str = *$1;
2072 ast_stack.back()->children.push_back($1);
2074 case_expr_list ',' expr {
2075 ast_stack.back()->children.push_back($3);
2079 hierarchical_id '[' expr ']' '.' rvalue {
2080 $$ = new AstNode(AST_PREFIX, $3, $6);
2084 hierarchical_id range {
2085 $$ = new AstNode(AST_IDENTIFIER, $2);
2088 if ($2 == nullptr && ($$->str == "\\$initstate" ||
2089 $$->str == "\\$anyconst" || $$->str == "\\$anyseq" ||
2090 $$->str == "\\$allconst" || $$->str == "\\$allseq"))
2091 $$->type = AST_FCALL;
2093 hierarchical_id non_opt_multirange {
2094 $$ = new AstNode(AST_IDENTIFIER, $2);
2103 '{' lvalue_concat_list '}' {
2109 $$ = new AstNode(AST_CONCAT);
2110 $$->children.push_back($1);
2112 expr ',' lvalue_concat_list {
2114 $$->children.push_back($1);
2118 '(' arg_list optional_comma ')' |
2127 arg_list ',' single_arg;
2131 ast_stack.back()->children.push_back($1);
2135 module_gen_body gen_stmt_or_module_body_stmt |
2138 gen_stmt_or_module_body_stmt:
2139 gen_stmt | module_body_stmt;
2141 // this production creates the obligatory if-else shift/reduce conflict
2144 AstNode *node = new AstNode(AST_GENFOR);
2145 ast_stack.back()->children.push_back(node);
2146 ast_stack.push_back(node);
2147 } simple_behavioral_stmt ';' expr {
2148 ast_stack.back()->children.push_back($6);
2149 } ';' simple_behavioral_stmt ')' gen_stmt_block {
2150 ast_stack.pop_back();
2152 TOK_IF '(' expr ')' {
2153 AstNode *node = new AstNode(AST_GENIF);
2154 ast_stack.back()->children.push_back(node);
2155 ast_stack.push_back(node);
2156 ast_stack.back()->children.push_back($3);
2157 } gen_stmt_block opt_gen_else {
2158 ast_stack.pop_back();
2160 case_type '(' expr ')' {
2161 AstNode *node = new AstNode(AST_GENCASE, $3);
2162 ast_stack.back()->children.push_back(node);
2163 ast_stack.push_back(node);
2164 } gen_case_body TOK_ENDCASE {
2165 case_type_stack.pop_back();
2166 ast_stack.pop_back();
2168 TOK_BEGIN opt_label {
2169 AstNode *node = new AstNode(AST_GENBLOCK);
2170 node->str = $2 ? *$2 : std::string();
2171 ast_stack.back()->children.push_back(node);
2172 ast_stack.push_back(node);
2173 } module_gen_body TOK_END opt_label {
2178 ast_stack.pop_back();
2181 AstNode *node = new AstNode(AST_TECALL);
2184 ast_stack.back()->children.push_back(node);
2185 ast_stack.push_back(node);
2187 ast_stack.pop_back();
2192 AstNode *node = new AstNode(AST_GENBLOCK);
2193 ast_stack.back()->children.push_back(node);
2194 ast_stack.push_back(node);
2195 } gen_stmt_or_module_body_stmt {
2196 ast_stack.pop_back();
2200 gen_stmt_block | ';';
2203 TOK_ELSE gen_stmt_or_null | /* empty */ %prec FAKE_THEN;
2209 basic_expr '?' attr expr ':' expr {
2210 $$ = new AstNode(AST_TERNARY);
2211 $$->children.push_back($1);
2212 $$->children.push_back($4);
2213 $$->children.push_back($6);
2214 append_attr($$, $3);
2221 '(' expr ')' TOK_CONSTVAL {
2222 if ($4->substr(0, 1) != "'")
2223 frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
2225 AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
2227 log_error("Value conversion failed: `%s'\n", $4->c_str());
2228 $$ = new AstNode(AST_TO_BITS, bits, val);
2231 hierarchical_id TOK_CONSTVAL {
2232 if ($2->substr(0, 1) != "'")
2233 frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
2234 AstNode *bits = new AstNode(AST_IDENTIFIER);
2236 AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
2238 log_error("Value conversion failed: `%s'\n", $2->c_str());
2239 $$ = new AstNode(AST_TO_BITS, bits, val);
2243 TOK_CONSTVAL TOK_CONSTVAL {
2244 $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
2245 if ($$ == NULL || (*$2)[0] != '\'')
2246 log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str());
2251 $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
2253 log_error("Value conversion failed: `%s'\n", $1->c_str());
2257 $$ = new AstNode(AST_REALVALUE);
2258 char *p = (char*)malloc(GetSize(*$1) + 1), *q;
2259 for (int i = 0, j = 0; j < GetSize(*$1); j++)
2260 if ((*$1)[j] != '_')
2261 p[i++] = (*$1)[j], p[i] = 0;
2262 $$->realvalue = strtod(p, &q);
2263 log_assert(*q == 0);
2268 $$ = AstNode::mkconst_str(*$1);
2271 hierarchical_id attr {
2272 AstNode *node = new AstNode(AST_FCALL);
2275 ast_stack.push_back(node);
2276 append_attr(node, $2);
2277 } '(' arg_list optional_comma ')' {
2278 $$ = ast_stack.back();
2279 ast_stack.pop_back();
2281 TOK_TO_SIGNED attr '(' expr ')' {
2282 $$ = new AstNode(AST_TO_SIGNED, $4);
2283 append_attr($$, $2);
2285 TOK_TO_UNSIGNED attr '(' expr ')' {
2286 $$ = new AstNode(AST_TO_UNSIGNED, $4);
2287 append_attr($$, $2);
2292 '(' expr ':' expr ':' expr ')' {
2297 '{' concat_list '}' {
2300 '{' expr '{' concat_list '}' '}' {
2301 $$ = new AstNode(AST_REPLICATE, $2, $4);
2303 '~' attr basic_expr %prec UNARY_OPS {
2304 $$ = new AstNode(AST_BIT_NOT, $3);
2305 append_attr($$, $2);
2307 basic_expr '&' attr basic_expr {
2308 $$ = new AstNode(AST_BIT_AND, $1, $4);
2309 append_attr($$, $3);
2311 basic_expr OP_NAND attr basic_expr {
2312 $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_AND, $1, $4));
2313 append_attr($$, $3);
2315 basic_expr '|' attr basic_expr {
2316 $$ = new AstNode(AST_BIT_OR, $1, $4);
2317 append_attr($$, $3);
2319 basic_expr OP_NOR attr basic_expr {
2320 $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_OR, $1, $4));
2321 append_attr($$, $3);
2323 basic_expr '^' attr basic_expr {
2324 $$ = new AstNode(AST_BIT_XOR, $1, $4);
2325 append_attr($$, $3);
2327 basic_expr OP_XNOR attr basic_expr {
2328 $$ = new AstNode(AST_BIT_XNOR, $1, $4);
2329 append_attr($$, $3);
2331 '&' attr basic_expr %prec UNARY_OPS {
2332 $$ = new AstNode(AST_REDUCE_AND, $3);
2333 append_attr($$, $2);
2335 OP_NAND attr basic_expr %prec UNARY_OPS {
2336 $$ = new AstNode(AST_REDUCE_AND, $3);
2337 append_attr($$, $2);
2338 $$ = new AstNode(AST_LOGIC_NOT, $$);
2340 '|' attr basic_expr %prec UNARY_OPS {
2341 $$ = new AstNode(AST_REDUCE_OR, $3);
2342 append_attr($$, $2);
2344 OP_NOR attr basic_expr %prec UNARY_OPS {
2345 $$ = new AstNode(AST_REDUCE_OR, $3);
2346 append_attr($$, $2);
2347 $$ = new AstNode(AST_LOGIC_NOT, $$);
2349 '^' attr basic_expr %prec UNARY_OPS {
2350 $$ = new AstNode(AST_REDUCE_XOR, $3);
2351 append_attr($$, $2);
2353 OP_XNOR attr basic_expr %prec UNARY_OPS {
2354 $$ = new AstNode(AST_REDUCE_XNOR, $3);
2355 append_attr($$, $2);
2357 basic_expr OP_SHL attr basic_expr {
2358 $$ = new AstNode(AST_SHIFT_LEFT, $1, $4);
2359 append_attr($$, $3);
2361 basic_expr OP_SHR attr basic_expr {
2362 $$ = new AstNode(AST_SHIFT_RIGHT, $1, $4);
2363 append_attr($$, $3);
2365 basic_expr OP_SSHL attr basic_expr {
2366 $$ = new AstNode(AST_SHIFT_SLEFT, $1, $4);
2367 append_attr($$, $3);
2369 basic_expr OP_SSHR attr basic_expr {
2370 $$ = new AstNode(AST_SHIFT_SRIGHT, $1, $4);
2371 append_attr($$, $3);
2373 basic_expr '<' attr basic_expr {
2374 $$ = new AstNode(AST_LT, $1, $4);
2375 append_attr($$, $3);
2377 basic_expr OP_LE attr basic_expr {
2378 $$ = new AstNode(AST_LE, $1, $4);
2379 append_attr($$, $3);
2381 basic_expr OP_EQ attr basic_expr {
2382 $$ = new AstNode(AST_EQ, $1, $4);
2383 append_attr($$, $3);
2385 basic_expr OP_NE attr basic_expr {
2386 $$ = new AstNode(AST_NE, $1, $4);
2387 append_attr($$, $3);
2389 basic_expr OP_EQX attr basic_expr {
2390 $$ = new AstNode(AST_EQX, $1, $4);
2391 append_attr($$, $3);
2393 basic_expr OP_NEX attr basic_expr {
2394 $$ = new AstNode(AST_NEX, $1, $4);
2395 append_attr($$, $3);
2397 basic_expr OP_GE attr basic_expr {
2398 $$ = new AstNode(AST_GE, $1, $4);
2399 append_attr($$, $3);
2401 basic_expr '>' attr basic_expr {
2402 $$ = new AstNode(AST_GT, $1, $4);
2403 append_attr($$, $3);
2405 basic_expr '+' attr basic_expr {
2406 $$ = new AstNode(AST_ADD, $1, $4);
2407 append_attr($$, $3);
2409 basic_expr '-' attr basic_expr {
2410 $$ = new AstNode(AST_SUB, $1, $4);
2411 append_attr($$, $3);
2413 basic_expr '*' attr basic_expr {
2414 $$ = new AstNode(AST_MUL, $1, $4);
2415 append_attr($$, $3);
2417 basic_expr '/' attr basic_expr {
2418 $$ = new AstNode(AST_DIV, $1, $4);
2419 append_attr($$, $3);
2421 basic_expr '%' attr basic_expr {
2422 $$ = new AstNode(AST_MOD, $1, $4);
2423 append_attr($$, $3);
2425 basic_expr OP_POW attr basic_expr {
2426 $$ = new AstNode(AST_POW, $1, $4);
2427 append_attr($$, $3);
2429 '+' attr basic_expr %prec UNARY_OPS {
2430 $$ = new AstNode(AST_POS, $3);
2431 append_attr($$, $2);
2433 '-' attr basic_expr %prec UNARY_OPS {
2434 $$ = new AstNode(AST_NEG, $3);
2435 append_attr($$, $2);
2437 basic_expr OP_LAND attr basic_expr {
2438 $$ = new AstNode(AST_LOGIC_AND, $1, $4);
2439 append_attr($$, $3);
2441 basic_expr OP_LOR attr basic_expr {
2442 $$ = new AstNode(AST_LOGIC_OR, $1, $4);
2443 append_attr($$, $3);
2445 '!' attr basic_expr %prec UNARY_OPS {
2446 $$ = new AstNode(AST_LOGIC_NOT, $3);
2447 append_attr($$, $2);
2452 $$ = new AstNode(AST_CONCAT, $1);
2454 expr ',' concat_list {
2456 $$->children.push_back($1);