diff --git a/elab_expr.cc b/elab_expr.cc index 1e8e2e502..0080d9971 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2486,8 +2486,8 @@ static NetExpr* check_for_struct_members(const LineInfo*li, } else if (const netenum_t*tmp_enum = dynamic_cast (member_type)) { - // If the element is an enum, then we don't have - // anything special to do. + // If the element is an enum, then we only need to check if + // there is a part select for it if (debug_elaborate) { cerr << li->get_fileline() << ": check_for_struct_members: " << "Tail element is an enum" << *tmp_enum @@ -2495,6 +2495,24 @@ static NetExpr* check_for_struct_members(const LineInfo*li, } struct_type = 0; + if (!member_comp.index.empty()) { + + if (member_comp.index.size() > 1) { + cerr << li->get_fileline() << ": error: " + << "Too many index expressions for enum member." << endl; + des->errors += 1; + return 0; + } + + long tail_off = 0; + unsigned long tail_wid = 0; + bool rc = calculate_part(li, des, scope, member_comp.index.back(), tail_off, tail_wid); + if (! rc) return 0; + + off += tail_off; + use_width = tail_wid; + } + } else if (const netvector_t*mem_vec = dynamic_cast(member_type)) { if (debug_elaborate) { diff --git a/eval_tree.cc b/eval_tree.cc index 04e9975e3..df8680d73 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -2172,10 +2172,17 @@ static bool get_array_info(const NetExpr*arg, long dim, long &left, long &right, bool&defer) { if (const NetEConstParam*param = dynamic_cast(arg)) { - ivl_assert(*arg, dim == 1); - left = param->expr_width() - 1; - right = 0; - return false; + ivl_assert(*arg, dim == 1); + left = param->expr_width() - 1; + right = 0; + return false; + } + if (const NetESelect*select = dynamic_cast(arg)) { + const netranges_t&dim_vals = select->net_type()->slice_dimensions(); + const netrange_t&range = dim_vals[dim-1]; + left = range.get_msb(); + right = range.get_lsb(); + return false; } /* The argument must be a signal that has enough dimensions. */ const NetESignal*esig = dynamic_cast(arg); diff --git a/ivtest/ivltests/struct_enum_partsel.v b/ivtest/ivltests/struct_enum_partsel.v new file mode 100644 index 000000000..b0aac672b --- /dev/null +++ b/ivtest/ivltests/struct_enum_partsel.v @@ -0,0 +1,24 @@ +module main; + + typedef enum logic [2:0] { + ENUM_VAL = 3'b110 + } enumtype; + + typedef struct packed { + enumtype e; + } structtype; + + structtype s; + + initial + begin + s.e = ENUM_VAL; + $display("s.e[2] = %d, s.e[1] = %d, s.e[0] = %d", s.e[2], s.e[1], s.e[0]); + if ((s.e[2] != 1'b1) || (s.e[1] != 1'b1) || (s.e[0] != 1'b0)) begin + $display("FAILED"); + $finish; + end + $display("PASSED"); + end + +endmodule diff --git a/ivtest/ivltests/struct_field_left_right.v b/ivtest/ivltests/struct_field_left_right.v new file mode 100644 index 000000000..a7f138376 --- /dev/null +++ b/ivtest/ivltests/struct_field_left_right.v @@ -0,0 +1,23 @@ +module main; + + typedef struct packed { + logic [15:8] f; + } structtype; + + structtype s; + + initial + begin + $display("$left(s.f) = %2d, $right(s.f) = %2d", $left(s.f), $right(s.f)); + if ($left(s.f) !== 15) begin + $display("FAILED -- $left(s.f) = %2d", $left(s.f)); + $finish; + end + if ($right(s.f) !== 8) begin + $display("FAILED -- $right(s.f) = %2d", $right(s.f)); + $finish; + end + $display("PASSED"); + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 1cb5a3912..80c3adc3e 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -46,6 +46,8 @@ pr903 vvp_tests/pr903.json pr903-vlog95 vvp_tests/pr903-vlog95.json pv_wr_fn_vec2 vvp_tests/pv_wr_fn_vec2.json pv_wr_fn_vec4 vvp_tests/pv_wr_fn_vec4.json +struct_enum_partsel vvp_tests/struct_enum_partsel.json +struct_field_left_right vvp_tests/struct_field_left_right.json struct_packed_write_read vvp_tests/struct_packed_write_read.json struct_packed_write_read2 vvp_tests/struct_packed_write_read2.json sv_2state_array_init_prop vvp_tests/sv_2state_array_init_prop.json diff --git a/ivtest/vvp_tests/struct_enum_partsel.json b/ivtest/vvp_tests/struct_enum_partsel.json new file mode 100644 index 000000000..ac0bd0049 --- /dev/null +++ b/ivtest/vvp_tests/struct_enum_partsel.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "struct_enum_partsel.v", + "iverilog-args" : [ "-g2009" ] +} diff --git a/ivtest/vvp_tests/struct_field_left_right.json b/ivtest/vvp_tests/struct_field_left_right.json new file mode 100644 index 000000000..a3cdb9f34 --- /dev/null +++ b/ivtest/vvp_tests/struct_field_left_right.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "struct_field_left_right.v", + "iverilog-args" : [ "-g2009" ] +}