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:
parent
a582f66089
commit
710267e9bb
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue