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 <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-10-02 10:56:15 +02:00
parent a582f66089
commit 710267e9bb
2 changed files with 6 additions and 6 deletions

View File

@ -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<const netclass_t*>(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<const netclass_t*>(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);

View File

@ -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<const netclass_t *>(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;
}