aboutsummaryrefslogtreecommitdiffstats
path: root/frontends/verilog
diff options
context:
space:
mode:
authorClaire Wolf <clifford@clifford.at>2020-02-20 18:17:25 +0100
committerGitHub <noreply@github.com>2020-02-20 18:17:25 +0100
commitcd044a2bb6adf7a5e00d4a6c075e9489d852d733 (patch)
tree025e868ba44465bba10799be98e89e1aea77894a /frontends/verilog
parentcd60f079d6c96e1d8a00c3c081fab1148d432b44 (diff)
parent1c16311d104caa19e8aff35a0df1595c73fa1638 (diff)
downloadyosys-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.y106
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 {