aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--frontends/verilog/verilog_parser.y25
-rw-r--r--tests/svtypes/struct_simple.sv9
-rw-r--r--tests/svtypes/union_simple.sv11
3 files changed, 38 insertions, 7 deletions
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index fff02f33a..e72d09524 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -238,7 +238,6 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%union {
std::string *string;
struct YOSYS_NAMESPACE_PREFIX AST::AstNode *ast;
- YOSYS_NAMESPACE_PREFIX AST::AstNodeType type;
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;
@@ -279,7 +278,7 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode)
%type <ast> opt_enum_init enum_type struct_type non_wire_data_type
%type <boolean> opt_signed opt_property unique_case_attr always_comb_or_latch always_or_always_ff
%type <al> attr case_attr
-%type <type> struct_union
+%type <ast> struct_union
%type <specify_target_ptr> specify_target
%type <specify_triple_ptr> specify_triple specify_opt_triple
@@ -1507,14 +1506,16 @@ enum_decl: enum_type enum_var_list ';' { delete $1; }
struct_decl: struct_type struct_var_list ';' { delete astbuf2; }
;
-struct_type: struct_union { astbuf2 = new AstNode($1); } opt_packed '{' struct_member_list '}' { $$ = astbuf2; }
+struct_type: struct_union { astbuf2 = $1; } struct_body { $$ = astbuf2; }
;
struct_union:
- TOK_STRUCT { $$ = AST_STRUCT; }
- | TOK_UNION { $$ = AST_UNION; }
+ TOK_STRUCT { $$ = new AstNode(AST_STRUCT); }
+ | TOK_UNION { $$ = new AstNode(AST_UNION); }
;
+struct_body: opt_packed '{' struct_member_list '}'
+ ;
opt_packed: TOK_PACKED opt_signed_struct
| { frontend_verilog_yyerror("Only PACKED supported at this time"); }
@@ -1547,10 +1548,10 @@ member_name: TOK_ID {
}
;
-struct_member_type: { astbuf1 = new AstNode(AST_STRUCT_ITEM); } member_type_token_list
+struct_member_type: { astbuf1 = new AstNode(AST_STRUCT_ITEM); } member_type_token
;
-member_type_token_list:
+member_type_token:
member_type
| hierarchical_type_id {
// use a clone of the typedef definition nodes
@@ -1569,6 +1570,16 @@ member_type_token_list:
delete astbuf1;
astbuf1 = template_node;
}
+ | struct_union {
+ // stash state on ast_stack
+ ast_stack.push_back(astbuf2);
+ astbuf2 = $1;
+ } struct_body {
+ astbuf1 = astbuf2;
+ // recover state
+ astbuf2 = ast_stack.back();
+ ast_stack.pop_back();
+ }
;
member_type: type_atom type_signing
diff --git a/tests/svtypes/struct_simple.sv b/tests/svtypes/struct_simple.sv
index e29489fb7..c74289cc3 100644
--- a/tests/svtypes/struct_simple.sv
+++ b/tests/svtypes/struct_simple.sv
@@ -15,6 +15,13 @@ module top;
bit [7:0] d;
} pack1;
+ struct packed {
+ byte a;
+ struct packed {
+ byte x, y;
+ } b;
+ } s2;
+
assign s.a = '1;
assign s.b = '1;
assign s.c = 8'hAA;
@@ -25,6 +32,7 @@ module top;
assign pack1.b = 16'hAAAA;
assign pack1.c = '1;
assign pack1.d = 8'h55;
+ assign s2.b.x = 'h42;
always_comb assert(s.a == 1'b1);
always_comb assert(s.c == 8'hAA);
@@ -35,5 +43,6 @@ module top;
always_comb assert(pack1.c == 8'hFF);
always_comb assert(pack1[15:8] == 8'hFF);
always_comb assert(pack1.d == 8'h55);
+ always_comb assert(s2.b.x == 'h42);
endmodule
diff --git a/tests/svtypes/union_simple.sv b/tests/svtypes/union_simple.sv
index fc23fe6e8..12e4b376f 100644
--- a/tests/svtypes/union_simple.sv
+++ b/tests/svtypes/union_simple.sv
@@ -58,4 +58,15 @@ module top;
assert(ir1.u.imm == 'hAA01);
end
+ union packed {
+ int word;
+ struct packed {
+ byte a, b, c, d;
+ } byte4;
+ } u;
+ assign u.word = 'h42;
+ always_comb begin
+ assert(u.byte4.d == 'h42);
+ end
+
endmodule