Merge pull request #842 from larsclausen/class-static-prop-base
Allow access to static properties of base classes
This commit is contained in:
commit
53854bb064
5
PExpr.h
5
PExpr.h
|
|
@ -407,6 +407,11 @@ class PEIdent : public PExpr {
|
||||||
std::list<long>&prefix_indices) const;
|
std::list<long>&prefix_indices) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
NetAssign_ *elaborate_lval_var_(Design *des, NetScope *scope,
|
||||||
|
bool is_force, bool is_cassign,
|
||||||
|
NetNet *reg, ivl_type_t data_type,
|
||||||
|
pform_name_t tail_path) const;
|
||||||
NetAssign_*elaborate_lval_method_class_member_(Design*, NetScope*) const;
|
NetAssign_*elaborate_lval_method_class_member_(Design*, NetScope*) const;
|
||||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*,
|
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*,
|
||||||
bool need_const_idx) const;
|
bool need_const_idx) const;
|
||||||
|
|
|
||||||
34
elab_lval.cc
34
elab_lval.cc
|
|
@ -227,6 +227,15 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return elaborate_lval_var_(des, scope, is_force, is_cassign, reg,
|
||||||
|
sr.type, member_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
NetAssign_*PEIdent::elaborate_lval_var_(Design *des, NetScope *scope,
|
||||||
|
bool is_force, bool is_cassign,
|
||||||
|
NetNet *reg, ivl_type_t data_type,
|
||||||
|
pform_name_t tail_path) const
|
||||||
|
{
|
||||||
// We are processing the tail of a string of names. For
|
// We are processing the tail of a string of names. For
|
||||||
// example, the Verilog may be "a.b.c", so we are processing
|
// example, the Verilog may be "a.b.c", so we are processing
|
||||||
// "c" at this point.
|
// "c" at this point.
|
||||||
|
|
@ -266,7 +275,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
&& (reg->type() != NetNet::UNRESOLVED_WIRE)
|
&& (reg->type() != NetNet::UNRESOLVED_WIRE)
|
||||||
&& !is_force) {
|
&& !is_force) {
|
||||||
cerr << get_fileline() << ": error: " << path_ <<
|
cerr << get_fileline() << ": error: " << path_ <<
|
||||||
" is not a valid l-value in " << scope_path(use_scope) <<
|
" is not a valid l-value in " << scope_path(scope) <<
|
||||||
"." << endl;
|
"." << endl;
|
||||||
cerr << reg->get_fileline() << ": : " << path_ <<
|
cerr << reg->get_fileline() << ": : " << path_ <<
|
||||||
" is declared here as " << reg->type() << "." << endl;
|
" is declared here as " << reg->type() << "." << endl;
|
||||||
|
|
@ -277,25 +286,23 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||||
|
|
||||||
// If we find that the matched variable is a packed struct,
|
// If we find that the matched variable is a packed struct,
|
||||||
// then we can handled it with the net_packed_member_ method.
|
// then we can handled it with the net_packed_member_ method.
|
||||||
if (reg->struct_type() && !member_path.empty()) {
|
if (reg->struct_type() && !tail_path.empty()) {
|
||||||
NetAssign_*lv = new NetAssign_(reg);
|
NetAssign_*lv = new NetAssign_(reg);
|
||||||
elaborate_lval_net_packed_member_(des, scope, lv, member_path);
|
elaborate_lval_net_packed_member_(des, scope, lv, tail_path);
|
||||||
return lv;
|
return lv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the variable is a class object, then handle it with the
|
// If the variable is a class object, then handle it with the
|
||||||
// net_class_member_ method.
|
// net_class_member_ method.
|
||||||
const netclass_t *class_type = dynamic_cast<const netclass_t *>(sr.type);
|
const netclass_t *class_type = dynamic_cast<const netclass_t *>(data_type);
|
||||||
if (class_type && !member_path.empty() && gn_system_verilog()) {
|
if (class_type && !tail_path.empty() && gn_system_verilog())
|
||||||
NetAssign_*lv = elaborate_lval_net_class_member_(des, scope, class_type, reg, member_path);
|
return elaborate_lval_net_class_member_(des, scope, class_type, reg, tail_path);
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Past this point, we should have taken care of the cases
|
// Past this point, we should have taken care of the cases
|
||||||
// where the name is a member/method of a struct/class.
|
// where the name is a member/method of a struct/class.
|
||||||
// XXXX ivl_assert(*this, method_name.nil());
|
// XXXX ivl_assert(*this, method_name.nil());
|
||||||
ivl_assert(*this, member_path.empty());
|
ivl_assert(*this, tail_path.empty());
|
||||||
|
|
||||||
bool need_const_idx = is_cassign || is_force || (reg->type()==NetNet::UNRESOLVED_WIRE);
|
bool need_const_idx = is_cassign || is_force || (reg->type()==NetNet::UNRESOLVED_WIRE);
|
||||||
|
|
||||||
|
|
@ -380,10 +387,11 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||||
|
|
||||||
property_qualifier_t qual = class_type->get_prop_qual(pidx);
|
property_qualifier_t qual = class_type->get_prop_qual(pidx);
|
||||||
|
|
||||||
// Static properties are handled as normal signals. Regular symbol
|
if (qual.test_static()) {
|
||||||
// search will find it.
|
NetNet *sig = class_type->find_static_property(member_name);
|
||||||
if (qual.test_static())
|
return elaborate_lval_var_(des, scope, false, false, sig,
|
||||||
return 0;
|
class_type, {});
|
||||||
|
}
|
||||||
|
|
||||||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||||
ivl_assert(*this, scope_method);
|
ivl_assert(*this, scope_method);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Check that it is possible to access static properties of a base class
|
||||||
|
|
||||||
|
class B;
|
||||||
|
static int x = 0;
|
||||||
|
static int y = 0;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class C extends B;
|
||||||
|
|
||||||
|
task t(int a, int b);
|
||||||
|
x = a;
|
||||||
|
this.y = b;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
function int f;
|
||||||
|
return x + this.y;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
endclass
|
||||||
|
|
||||||
|
module test;
|
||||||
|
bit failed = 1'b0;
|
||||||
|
|
||||||
|
`define check(expr, val) \
|
||||||
|
if (expr !== val) begin \
|
||||||
|
$display("FAILED: `%s`, expected %b, got %b", `"expr`", val, expr); \
|
||||||
|
failed = 1'b1; \
|
||||||
|
end
|
||||||
|
|
||||||
|
C c = new;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// Check access inside the class
|
||||||
|
c.t(10, 20);
|
||||||
|
`check(c.f(), 30)
|
||||||
|
|
||||||
|
// Check access outside of the class
|
||||||
|
c.x = 40;
|
||||||
|
`check(c.x, 40)
|
||||||
|
|
||||||
|
if (!failed) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -590,6 +590,7 @@ sv_class_return normal,-g2009 ivltests
|
||||||
sv_class_static_prop1 normal,-g2009 ivltests
|
sv_class_static_prop1 normal,-g2009 ivltests
|
||||||
sv_class_static_prop2 normal,-g2009 ivltests
|
sv_class_static_prop2 normal,-g2009 ivltests
|
||||||
sv_class_static_prop3 normal,-g2009 ivltests
|
sv_class_static_prop3 normal,-g2009 ivltests
|
||||||
|
sv_class_static_prop4 normal,-g2009 ivltests
|
||||||
sv_class_super1 normal,-g2009 ivltests
|
sv_class_super1 normal,-g2009 ivltests
|
||||||
sv_class_super2 normal,-g2009 ivltests
|
sv_class_super2 normal,-g2009 ivltests
|
||||||
sv_class_super3 normal,-g2009 ivltests
|
sv_class_super3 normal,-g2009 ivltests
|
||||||
|
|
|
||||||
|
|
@ -437,6 +437,7 @@ sv_class_return CE,-g2009 ivltests
|
||||||
sv_class_static_prop1 CE,-g2009 ivltests
|
sv_class_static_prop1 CE,-g2009 ivltests
|
||||||
sv_class_static_prop2 CE,-g2009 ivltests
|
sv_class_static_prop2 CE,-g2009 ivltests
|
||||||
sv_class_static_prop3 CE,-g2009 ivltests
|
sv_class_static_prop3 CE,-g2009 ivltests
|
||||||
|
sv_class_static_prop4 CE,-g2009 ivltests
|
||||||
sv_class_super1 CE,-g2009 ivltests
|
sv_class_super1 CE,-g2009 ivltests
|
||||||
sv_class_super2 CE,-g2009 ivltests
|
sv_class_super2 CE,-g2009 ivltests
|
||||||
sv_class_super3 CE,-g2009 ivltests
|
sv_class_super3 CE,-g2009 ivltests
|
||||||
|
|
|
||||||
10
netclass.cc
10
netclass.cc
|
|
@ -174,8 +174,14 @@ NetScope*netclass_t::method_from_name(perm_string name) const
|
||||||
|
|
||||||
NetNet* netclass_t::find_static_property(perm_string name) const
|
NetNet* netclass_t::find_static_property(perm_string name) const
|
||||||
{
|
{
|
||||||
NetNet*tmp = class_scope_->find_signal(name);
|
NetNet *net = class_scope_->find_signal(name);
|
||||||
return tmp;
|
if (net)
|
||||||
|
return net;
|
||||||
|
|
||||||
|
if (super_)
|
||||||
|
return super_->find_static_property(name);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool netclass_t::test_scope_is_method(const NetScope*scope) const
|
bool netclass_t::test_scope_is_method(const NetScope*scope) const
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue