diff options
Diffstat (limited to 'frontends/verilog')
-rw-r--r-- | frontends/verilog/verilog_frontend.cc | 2 | ||||
-rw-r--r-- | frontends/verilog/verilog_frontend.h | 2 | ||||
-rw-r--r-- | frontends/verilog/verilog_lexer.l | 15 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 156 |
4 files changed, 101 insertions, 74 deletions
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc index 6879e0943..26abe49b5 100644 --- a/frontends/verilog/verilog_frontend.cc +++ b/frontends/verilog/verilog_frontend.cc @@ -48,7 +48,7 @@ static void error_on_dpi_function(AST::AstNode *node) error_on_dpi_function(child); } -static void add_package_types(std::map<std::string, AST::AstNode *> &user_types, std::vector<AST::AstNode *> &package_list) +static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std::vector<AST::AstNode *> &package_list) { // prime the parser's user type lookup table with the package qualified names // of typedefed names in the packages seen so far. diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h index 444cc7297..aa7881038 100644 --- a/frontends/verilog/verilog_frontend.h +++ b/frontends/verilog/verilog_frontend.h @@ -50,7 +50,7 @@ namespace VERILOG_FRONTEND extern std::vector<UserTypeMap *> user_type_stack; // names of package typedef'ed types - extern std::map<std::string, AST::AstNode*> pkg_user_types; + extern dict<std::string, AST::AstNode*> pkg_user_types; // state of `default_nettype extern bool default_nettype_wire; diff --git a/frontends/verilog/verilog_lexer.l b/frontends/verilog/verilog_lexer.l index f6a3ac4db..02fa0031b 100644 --- a/frontends/verilog/verilog_lexer.l +++ b/frontends/verilog/verilog_lexer.l @@ -48,16 +48,18 @@ USING_YOSYS_NAMESPACE using namespace AST; using namespace VERILOG_FRONTEND; +#define YYSTYPE FRONTEND_VERILOG_YYSTYPE +#define YYLTYPE FRONTEND_VERILOG_YYLTYPE + YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { std::vector<std::string> fn_stack; std::vector<int> ln_stack; + YYLTYPE real_location; + YYLTYPE old_location; } YOSYS_NAMESPACE_END -#define YYSTYPE FRONTEND_VERILOG_YYSTYPE -#define YYLTYPE FRONTEND_VERILOG_YYLTYPE - #define SV_KEYWORD(_tok) \ if (sv_mode) return _tok; \ log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\ @@ -73,9 +75,6 @@ YOSYS_NAMESPACE_END #define YY_INPUT(buf,result,max_size) \ result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size) -YYLTYPE real_location; -YYLTYPE old_location; - #define YY_USER_ACTION \ old_location = real_location; \ real_location.first_line = real_location.last_line; \ @@ -128,7 +127,9 @@ static bool isUserType(std::string &s) %x BASED_CONST %% - int comment_caller; + // Initialise comment_caller to something to avoid a "maybe undefined" + // warning from GCC. + int comment_caller = INITIAL; <INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* { fn_stack.push_back(current_filename); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 4a5aba79e..c8223f41d 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -50,12 +50,12 @@ using namespace VERILOG_FRONTEND; YOSYS_NAMESPACE_BEGIN namespace VERILOG_FRONTEND { int port_counter; - std::map<std::string, int> port_stubs; - std::map<std::string, AstNode*> *attr_list, default_attr_list; - std::stack<std::map<std::string, AstNode*> *> attr_list_stack; - std::map<std::string, AstNode*> *albuf; + dict<std::string, int> port_stubs; + dict<IdString, AstNode*> *attr_list, default_attr_list; + std::stack<dict<IdString, AstNode*> *> attr_list_stack; + dict<IdString, AstNode*> *albuf; std::vector<UserTypeMap*> user_type_stack; - std::map<std::string, AstNode*> pkg_user_types; + dict<std::string, AstNode*> pkg_user_types; std::vector<AstNode*> ast_stack; struct AstNode *astbuf1, *astbuf2, *astbuf3; struct AstNode *current_function_or_task; @@ -87,7 +87,7 @@ YOSYS_NAMESPACE_END int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param); -static void append_attr(AstNode *ast, std::map<std::string, AstNode*> *al) +static void append_attr(AstNode *ast, dict<IdString, AstNode*> *al) { for (auto &it : *al) { if (ast->attributes.count(it.first) > 0) @@ -97,7 +97,7 @@ static void append_attr(AstNode *ast, std::map<std::string, AstNode*> *al) delete al; } -static void append_attr_clone(AstNode *ast, std::map<std::string, AstNode*> *al) +static void append_attr_clone(AstNode *ast, dict<IdString, AstNode*> *al) { for (auto &it : *al) { if (ast->attributes.count(it.first) > 0) @@ -106,7 +106,7 @@ static void append_attr_clone(AstNode *ast, std::map<std::string, AstNode*> *al) } } -static void free_attr(std::map<std::string, AstNode*> *al) +static void free_attr(dict<IdString, AstNode*> *al) { for (auto &it : *al) delete it.second; @@ -192,7 +192,7 @@ static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned = %union { std::string *string; struct YOSYS_NAMESPACE_PREFIX AST::AstNode *ast; - std::map<std::string, YOSYS_NAMESPACE_PREFIX AST::AstNode*> *al; + YOSYS_NAMESPACE_PREFIX dict<YOSYS_NAMESPACE_PREFIX RTLIL::IdString, YOSYS_NAMESPACE_PREFIX AST::AstNode*> *al; struct specify_target *specify_target_ptr; struct specify_triple *specify_triple_ptr; struct specify_rise_fall *specify_rise_fall_ptr; @@ -289,7 +289,7 @@ attr: { if (attr_list != nullptr) attr_list_stack.push(attr_list); - attr_list = new std::map<std::string, AstNode*>; + attr_list = new dict<IdString, AstNode*>; for (auto &it : default_attr_list) (*attr_list)[it.first] = it.second->clone(); } attr_opt { @@ -311,7 +311,7 @@ defattr: DEFATTR_BEGIN { if (attr_list != nullptr) attr_list_stack.push(attr_list); - attr_list = new std::map<std::string, AstNode*>; + attr_list = new dict<IdString, AstNode*>; for (auto &it : default_attr_list) delete it.second; default_attr_list.clear(); @@ -645,13 +645,13 @@ non_opt_range: } | '[' expr TOK_POS_INDEXED expr ']' { $$ = new AstNode(AST_RANGE); - AstNode *expr = new AstNode(AST_CONCAT, $2); + AstNode *expr = new AstNode(AST_SELFSZ, $2); $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), $4), AstNode::mkconst_int(1, true))); $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); } | '[' expr TOK_NEG_INDEXED expr ']' { $$ = new AstNode(AST_RANGE); - AstNode *expr = new AstNode(AST_CONCAT, $2); + AstNode *expr = new AstNode(AST_SELFSZ, $2); $$->children.push_back(new AstNode(AST_ADD, expr, AstNode::mkconst_int(0, true))); $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, expr->clone(), AstNode::mkconst_int(1, true)), $4)); } | @@ -853,7 +853,19 @@ task_func_port: } if (astbuf2 && astbuf2->children.size() != 2) frontend_verilog_yyerror("task/function argument range must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]"); - } wire_name | wire_name; + } wire_name | + { + if (!astbuf1) { + if (!sv_mode) + frontend_verilog_yyerror("task/function argument direction missing"); + albuf = new dict<IdString, AstNode*>; + astbuf1 = new AstNode(AST_WIRE); + current_wire_rand = false; + current_wire_const = false; + astbuf1->is_input = true; + astbuf2 = NULL; + } + } wire_name; task_func_body: task_func_body behavioral_stmt | @@ -885,6 +897,7 @@ specify_item: cell->str = stringf("$specify$%d", autoidx++); cell->children.push_back(new AstNode(AST_CELLTYPE)); cell->children.back()->str = target->dat ? "$specify3" : "$specify2"; + SET_AST_NODE_LOC(cell, en_expr ? @1 : @2, @10); char oper_polarity = 0; char oper_type = oper->at(0); @@ -973,6 +986,7 @@ specify_item: cell->str = stringf("$specify$%d", autoidx++); cell->children.push_back(new AstNode(AST_CELLTYPE)); cell->children.back()->str = "$specrule"; + SET_AST_NODE_LOC(cell, @1, @14); cell->children.push_back(new AstNode(AST_PARASET, AstNode::mkconst_str(*$1))); cell->children.back()->str = "\\TYPE"; @@ -1099,8 +1113,8 @@ specify_rise_fall: $$->fall = *$4; delete $2; delete $4; - delete $6; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + delete $6; + log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); } | '(' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ')' { $$ = new specify_rise_fall; @@ -1108,11 +1122,11 @@ specify_rise_fall: $$->fall = *$4; delete $2; delete $4; - delete $6; - delete $8; - delete $10; - delete $12; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + delete $6; + delete $8; + delete $10; + delete $12; + log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); } | '(' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ',' specify_triple ')' { $$ = new specify_rise_fall; @@ -1120,17 +1134,17 @@ specify_rise_fall: $$->fall = *$4; delete $2; delete $4; - delete $6; - delete $8; - delete $10; - delete $12; - delete $14; - delete $16; - delete $18; - delete $20; - delete $22; - delete $24; - log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); + delete $6; + delete $8; + delete $10; + delete $12; + delete $14; + delete $16; + delete $18; + delete $20; + delete $22; + delete $24; + log_file_warning(current_filename, get_line_num(), "Path delay expressions beyond rise/fall not currently supported. Ignoring.\n"); } specify_triple: @@ -1388,7 +1402,7 @@ enum_type: TOK_ENUM { delete astbuf1; astbuf1 = tnode; tnode->type = AST_WIRE; - tnode->attributes["\\enum_type"] = AstNode::mkconst_str(astbuf2->str); + tnode->attributes[ID::enum_type] = AstNode::mkconst_str(astbuf2->str); // drop constant but keep any range delete tnode->children[0]; tnode->children.erase(tnode->children.begin()); } @@ -1747,7 +1761,9 @@ single_prim: /* no name */ { astbuf2 = astbuf1->clone(); ast_stack.back()->children.push_back(astbuf2); - } '(' cell_port_list ')'; + } '(' cell_port_list ')' { + SET_AST_NODE_LOC(astbuf2, @1, @$); + } cell_parameter_list_opt: '#' '(' cell_parameter_list ')' | /* empty */; @@ -2187,49 +2203,56 @@ assert_property: }; simple_behavioral_stmt: - lvalue '=' delay expr { - AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4); + attr lvalue '=' delay expr { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, $5); ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @1, @4); + SET_AST_NODE_LOC(node, @2, @5); + append_attr(node, $1); } | - lvalue TOK_INCREMENT { - AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_ADD, $1->clone(), AstNode::mkconst_int(1, true))); + attr lvalue TOK_INCREMENT { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, new AstNode(AST_ADD, $2->clone(), AstNode::mkconst_int(1, true))); ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @1, @2); + SET_AST_NODE_LOC(node, @2, @3); + append_attr(node, $1); } | - lvalue TOK_DECREMENT { - AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_SUB, $1->clone(), AstNode::mkconst_int(1, true))); + attr lvalue TOK_DECREMENT { + AstNode *node = new AstNode(AST_ASSIGN_EQ, $2, new AstNode(AST_SUB, $2->clone(), AstNode::mkconst_int(1, true))); ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @1, @2); + SET_AST_NODE_LOC(node, @2, @3); + append_attr(node, $1); } | - lvalue OP_LE delay expr { - AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4); + attr lvalue OP_LE delay expr { + AstNode *node = new AstNode(AST_ASSIGN_LE, $2, $5); ast_stack.back()->children.push_back(node); - SET_AST_NODE_LOC(node, @1, @4); + SET_AST_NODE_LOC(node, @2, @5); + append_attr(node, $1); }; // this production creates the obligatory if-else shift/reduce conflict behavioral_stmt: defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | non_opt_delay behavioral_stmt | - simple_behavioral_stmt ';' | ';' | - hierarchical_id attr { + simple_behavioral_stmt ';' | + attr ';' { + free_attr($1); + } | + attr hierarchical_id { AstNode *node = new AstNode(AST_TCALL); - node->str = *$1; - delete $1; + node->str = *$2; + delete $2; ast_stack.back()->children.push_back(node); ast_stack.push_back(node); - append_attr(node, $2); + append_attr(node, $1); } opt_arg_list ';'{ ast_stack.pop_back(); } | - TOK_MSG_TASKS attr { + attr TOK_MSG_TASKS { AstNode *node = new AstNode(AST_TCALL); - node->str = *$1; - delete $1; + node->str = *$2; + delete $2; ast_stack.back()->children.push_back(node); ast_stack.push_back(node); - append_attr(node, $2); + append_attr(node, $1); } opt_arg_list ';'{ ast_stack.pop_back(); } | @@ -2326,8 +2349,6 @@ behavioral_stmt: ast_stack.pop_back(); }; - ; - unique_case_attr: /* empty */ { $$ = false; @@ -2341,7 +2362,7 @@ unique_case_attr: case_attr: attr unique_case_attr { - if ($2) (*$1)["\\parallel_case"] = AstNode::mkconst_int(1, false); + if ($2) (*$1)[ID::parallel_case] = AstNode::mkconst_int(1, false); $$ = $1; }; @@ -2422,7 +2443,7 @@ gen_case_item: } case_select { case_type_stack.push_back(0); SET_AST_NODE_LOC(ast_stack.back(), @2, @2); - } gen_stmt_or_null { + } gen_stmt_block { case_type_stack.pop_back(); ast_stack.pop_back(); }; @@ -2514,7 +2535,10 @@ module_gen_body: /* empty */; gen_stmt_or_module_body_stmt: - gen_stmt | module_body_stmt; + gen_stmt | module_body_stmt | + attr ';' { + free_attr($1); + }; // this production creates the obligatory if-else shift/reduce conflict gen_stmt: @@ -2533,7 +2557,12 @@ gen_stmt: ast_stack.back()->children.push_back(node); ast_stack.push_back(node); ast_stack.back()->children.push_back($3); - } gen_stmt_block opt_gen_else { + AstNode *block = new AstNode(AST_GENBLOCK); + ast_stack.back()->children.push_back(block); + ast_stack.push_back(block); + } gen_stmt_block { + ast_stack.pop_back(); + } opt_gen_else { SET_AST_NODE_LOC(ast_stack.back(), @1, @7); ast_stack.pop_back(); } | @@ -2581,11 +2610,8 @@ gen_stmt_block: ast_stack.pop_back(); }; -gen_stmt_or_null: - gen_stmt_block | ';'; - opt_gen_else: - TOK_ELSE gen_stmt_or_null | /* empty */ %prec FAKE_THEN; + TOK_ELSE gen_stmt_block | /* empty */ %prec FAKE_THEN; expr: basic_expr { |