From 710267e9bb54efec6ef2f9c06cc874e8e2099f7b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 2 Oct 2022 10:56:15 +0200 Subject: [PATCH] Elaborate member selects in the scope where they are used There are a few cases where a member select on a package scoped identifier is evaluated in the scope of the package rather than the scope where the identifier is referenced. This leads to incorrect behavior if a local symbol is used as an index in a part select of the referenced member select. E.g. ``` package P; localparam N = 1; struct packed { logic [3:0] x; } s = 4'b0101; endpackage module test; localparam N = 2; initial $display(P::s.x[N]); // Will print 0, should print 1 endmodule ``` Use the scope where the member select is used, rather than the scope where the identifier is defined, to fix this. Signed-off-by: Lars-Peter Clausen --- elab_expr.cc | 8 ++++---- elab_lval.cc | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index f0660db93..11ceaafe4 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4369,7 +4369,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, if (!sr.path_tail.empty()) { if (net->struct_type()) { - return check_for_struct_members(this, des, use_scope, net, + return check_for_struct_members(this, des, scope, net, sr.path_head.back().index, sr.path_tail); } else if (dynamic_cast(sr.type)) { @@ -4710,7 +4710,7 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope, << endl; } - return check_for_struct_members(this, des, use_scope, sr.net, + return check_for_struct_members(this, des, scope, sr.net, sr.path_head.back().index, sr.path_tail); } @@ -4890,7 +4890,7 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope, } if (dynamic_cast(sr.type) && !sr.path_tail.empty()) { - return elaborate_expr_class_field_(des, use_scope, sr, + return elaborate_expr_class_field_(des, scope, sr, expr_wid, flags); } @@ -4908,7 +4908,7 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope, ivl_assert(*this, sr.path_tail.size() == 1); const name_component_t member_comp = sr.path_tail.front(); ivl_assert(*this, member_comp.index.empty()); - return check_for_enum_methods(this, des, use_scope, + return check_for_enum_methods(this, des, scope, netenum, sr.path_head, member_comp.name, expr, NULL, 0); diff --git a/elab_lval.cc b/elab_lval.cc index 3379b658e..f38abbfa9 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -279,7 +279,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, // then we can handled it with the net_packed_member_ method. if (reg->struct_type() && !member_path.empty()) { NetAssign_*lv = new NetAssign_(reg); - elaborate_lval_net_packed_member_(des, use_scope, lv, member_path); + elaborate_lval_net_packed_member_(des, scope, lv, member_path); return lv; } @@ -287,7 +287,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, // net_class_member_ method. const netclass_t *class_type = dynamic_cast(sr.type); if (class_type && !member_path.empty() && gn_system_verilog()) { - NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, class_type, reg, member_path); + NetAssign_*lv = elaborate_lval_net_class_member_(des, scope, class_type, reg, member_path); return lv; }