diff options
author | Claire Wolf <clifford@clifford.at> | 2020-02-20 18:17:25 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-20 18:17:25 +0100 |
commit | cd044a2bb6adf7a5e00d4a6c075e9489d852d733 (patch) | |
tree | 025e868ba44465bba10799be98e89e1aea77894a /frontends/verilog | |
parent | cd60f079d6c96e1d8a00c3c081fab1148d432b44 (diff) | |
parent | 1c16311d104caa19e8aff35a0df1595c73fa1638 (diff) | |
download | yosys-cd044a2bb6adf7a5e00d4a6c075e9489d852d733.tar.gz yosys-cd044a2bb6adf7a5e00d4a6c075e9489d852d733.tar.bz2 yosys-cd044a2bb6adf7a5e00d4a6c075e9489d852d733.zip |
Merge pull request #1642 from jjj11x/jjj11x/sv-enum
Enum support
Diffstat (limited to 'frontends/verilog')
-rw-r--r-- | frontends/verilog/verilog_parser.y | 106 |
1 files changed, 104 insertions, 2 deletions
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 8840cf4e8..9001aa162 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -108,6 +108,20 @@ struct specify_rise_fall { specify_triple fall; }; +static AstNode *makeRange(int msb = 31, int lsb = 0, bool isSigned = true) +{ + auto range = new AstNode(AST_RANGE); + range->children.push_back(AstNode::mkconst_int(msb, true)); + range->children.push_back(AstNode::mkconst_int(lsb, true)); + range->is_signed = isSigned; + return range; +} + +static void addRange(AstNode *parent, int msb = 31, int lsb = 0, bool isSigned = true) +{ + auto range = makeRange(msb, lsb, isSigned); + parent->children.push_back(range); +} %} %define api.prefix {frontend_verilog_yy} @@ -157,6 +171,7 @@ struct specify_rise_fall { %type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list %type <string> opt_label opt_sva_label tok_prim_wrapper hierarchical_id hierarchical_type_id +%type <ast> opt_enum_init %type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff %type <al> attr case_attr @@ -428,7 +443,9 @@ package: }; package_body: - package_body package_body_stmt |; + package_body package_body_stmt + | // optional + ; package_body_stmt: typedef_decl | @@ -604,6 +621,7 @@ module_body: module_body_stmt: task_func_decl | specify_block | param_decl | localparam_decl | typedef_decl | defparam_decl | specparam_declaration | wire_decl | assign_stmt | cell_stmt | + enum_decl | always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl | ignored_specify_block; checker_decl: @@ -1224,6 +1242,85 @@ single_defparam_decl: ast_stack.back()->children.push_back(node); }; +enum_type: TOK_ENUM { + static int enum_count; + // create parent node for the enum + astbuf2 = new AstNode(AST_ENUM); + ast_stack.back()->children.push_back(astbuf2); + astbuf2->str = std::string("$enum"); + astbuf2->str += std::to_string(enum_count++); + // create the template for the names + astbuf1 = new AstNode(AST_ENUM_ITEM); + astbuf1->children.push_back(AstNode::mkconst_int(0, true)); + } param_signed enum_base_type '{' enum_name_list '}' { // create template for the enum vars + auto tnode = astbuf1->clone(); + delete astbuf1; + astbuf1 = tnode; + tnode->type = AST_WIRE; + tnode->attributes["\\enum_type"] = AstNode::mkconst_str(astbuf2->str); + // drop constant but keep any range + delete tnode->children[0]; + tnode->children.erase(tnode->children.begin()); } + ; + +enum_base_type: int_vec param_range + | int_atom + | /* nothing */ {astbuf1->is_reg = true; addRange(astbuf1); } + ; + +int_atom: TOK_INTEGER {astbuf1->is_reg=true; addRange(astbuf1); } // probably should do byte, range [7:0] here + ; + +int_vec: TOK_REG {astbuf1->is_reg = true;} + | TOK_LOGIC {astbuf1->is_logic = true;} + ; + +enum_name_list: + enum_name_decl + | enum_name_list ',' enum_name_decl + ; + +enum_name_decl: + TOK_ID opt_enum_init { + // put in fn + log_assert(astbuf1); + log_assert(astbuf2); + auto node = astbuf1->clone(); + node->str = *$1; + delete $1; + delete node->children[0]; + node->children[0] = $2 ?: new AstNode(AST_NONE); + astbuf2->children.push_back(node); + } + ; + +opt_enum_init: + '=' basic_expr { $$ = $2; } // TODO: restrict this + | /* optional */ { $$ = NULL; } + ; + +enum_var_list: + enum_var + | enum_var_list ',' enum_var + ; + +enum_var: TOK_ID { + log_assert(astbuf1); + log_assert(astbuf2); + auto node = astbuf1->clone(); + ast_stack.back()->children.push_back(node); + node->str = *$1; + delete $1; + node->is_enum = true; + } + ; + +enum_decl: enum_type enum_var_list ';' { + //enum_type creates astbuf1 for use by typedef only + delete astbuf1; + } + ; + wire_decl: attr wire_type range { albuf = $1; @@ -1434,7 +1531,12 @@ typedef_decl: ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); ast_stack.back()->children.back()->str = *$4; - }; + } | + TOK_TYPEDEF enum_type TOK_ID ';' { + ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1)); + ast_stack.back()->children.back()->str = *$3; + } + ; cell_stmt: attr TOK_ID { |