diff --git a/PExpr.h b/PExpr.h index 14ba1577a..8114eff2b 100644 --- a/PExpr.h +++ b/PExpr.h @@ -417,6 +417,7 @@ class PEIdent : public PExpr { index_component_t::ctype_t, bool need_const_idx) const; NetAssign_*elaborate_lval_net_class_member_(Design*, NetScope*, + const netclass_t *class_type, NetNet*, pform_name_t) const; bool elaborate_lval_net_packed_member_(Design*, NetScope*, @@ -511,8 +512,7 @@ class PEIdent : public PExpr { unsigned flags) const; NetExpr *elaborate_expr_class_field_(Design*des, NetScope*scope, - NetNet*net, - const name_component_t&comp, + const symbol_search_results &sr, unsigned expr_wid, unsigned flags) const; diff --git a/elab_expr.cc b/elab_expr.cc index 9088387bd..c084b8029 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1480,8 +1480,7 @@ unsigned PECallFunction::test_width_method_(Design*, NetScope*, // and the scope is the scope where the instance lives. The class method // in turn defines it's own scope. Use that to find the return value. if (search_results.net && search_results.net->data_type()==IVL_VT_CLASS) { - NetNet*net = search_results.net; - const netclass_t*class_type = net->class_type(); + const netclass_t *class_type = dynamic_cast(search_results.type); ivl_assert(*this, class_type); NetScope*method = class_type->method_from_name(method_name); @@ -2536,12 +2535,26 @@ static NetExpr* class_static_property_expression(const LineInfo*li, } NetExpr* PEIdent::elaborate_expr_class_field_(Design*des, NetScope*scope, - NetNet*net, - const name_component_t&comp, + const symbol_search_results &sr, unsigned expr_wid, unsigned flags) const { - const netclass_t*class_type = net->class_type(); + + const netclass_t *class_type = dynamic_cast(sr.type); + const name_component_t comp = sr.path_tail.front(); + + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_expr: " + << "Ident " << sr.path_head + << " look for property " << comp << endl; + } + + if (sr.path_tail.size() > 1) { + cerr << get_fileline() << ": sorry: " + << "Nested member path not yet supported for class properties." + << endl; + return nullptr; + } ivl_type_t par_type; const NetExpr *par_val = class_type->get_parameter(des, comp.name, par_type); @@ -2562,7 +2575,7 @@ NetExpr* PEIdent::elaborate_expr_class_field_(Design*des, NetScope*scope, if (debug_elaborate) { cerr << get_fileline() << ": check_for_class_property: " << "Property " << comp.name - << " of net " << net->name() + << " of net " << sr.net->name() << ", context scope=" << scope_path(scope) << endl; } @@ -2582,7 +2595,7 @@ NetExpr* PEIdent::elaborate_expr_class_field_(Design*des, NetScope*scope, prop_name); } - NetEProperty*tmp = new NetEProperty(net, comp.name); + NetEProperty*tmp = new NetEProperty(sr.net, pidx); tmp->set_line(*this); return tmp; } @@ -2751,6 +2764,7 @@ NetExpr* PECallFunction::elaborate_expr_(Design*des, NetScope*scope, use_search_results.path_tail.push_back(search_results.path_head.back()); use_search_results.path_head.push_back(name_component_t(perm_string::literal(THIS_TOKEN))); use_search_results.net = scope->find_signal(perm_string::literal(THIS_TOKEN)); + use_search_results.type = use_search_results.net->net_type(); ivl_assert(*this, use_search_results.net); return elaborate_expr_method_(des, scope, use_search_results); @@ -3026,12 +3040,12 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, if (search_results.par_val) cerr << get_fileline() << ": PECallFunction::elaborate_expr_method_: " << "search_results.par_val: " << *search_results.par_val << endl; - if (search_results.par_type) + if (search_results.type) cerr << get_fileline() << ": PECallFunction::elaborate_expr_method_: " - << "search_results.par_type: " << *search_results.par_type << endl; + << "search_results.type: " << *search_results.type << endl; } - if (search_results.par_val && search_results.par_type) { + if (search_results.par_val && search_results.type) { return elaborate_expr_method_par_(des, scope, search_results); } @@ -3177,7 +3191,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope, perm_string method_name = search_results.path_tail.back().name; NetNet*net = search_results.net; - const netclass_t*class_type = net->class_type(); + const netclass_t*class_type = dynamic_cast(search_results.type); ivl_assert(*this, class_type); NetScope*method = class_type->method_from_name(method_name); @@ -3285,10 +3299,10 @@ NetExpr* PECallFunction::elaborate_expr_method_par_(Design*des, NetScope*scope, const { ivl_assert(*this, search_results.par_val); - ivl_assert(*this, search_results.par_type); + ivl_assert(*this, search_results.type); const NetExpr*par_val = search_results.par_val; - ivl_type_t par_type = search_results.par_type; + ivl_type_t par_type = search_results.type; perm_string method_name = search_results.path_tail.back().name; // If the parameter is of type string, then look for the standard string @@ -4230,8 +4244,8 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) // Similarly, if this net is an object, the path tail may // be a class property. - if (sr.net->class_type() != 0 && !sr.path_tail.empty()) { - const netclass_t*class_type = sr.net->class_type(); + const netclass_t *class_type = dynamic_cast(sr.type); + if (class_type && !sr.path_tail.empty()) { perm_string pname = peek_tail_name(sr.path_tail); ivl_type_t par_type; const NetExpr *par = class_type->get_parameter(des, pname, par_type); @@ -4349,24 +4363,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, return check_for_struct_members(this, des, use_scope, net, sr.path_head.back().index, sr.path_tail); - } else if (net->class_type()) { - const name_component_t member_comp = sr.path_tail.front(); - - if (debug_elaborate) { - cerr << get_fileline() << ": PEIdent::elaborate_expr: " - << "Ident " << sr.path_head - << " look for property " << member_comp << endl; - } - - if (sr.path_tail.size() > 1) { - cerr << get_fileline() << ": sorry: " - << "Nested member path not yet supported in this context." - << endl; - return nullptr; - } - - return elaborate_expr_class_field_(des, scope, net, - member_comp, 0, flags); + } else if (dynamic_cast(sr.type)) { + return elaborate_expr_class_field_(des, scope, sr, 0, flags); } } @@ -4570,7 +4568,7 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope, << " canonical index: " << *canon_index << endl; } - NetEProperty*tmp = new NetEProperty(this_net, member_name, canon_index); + NetEProperty*tmp = new NetEProperty(this_net, pidx, canon_index); tmp->set_line(*this); return tmp; } @@ -4667,7 +4665,7 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope, } return elaborate_expr_param_or_specparam_(des, scope, sr.par_val, - sr.scope, sr.par_type, + sr.scope, sr.type, expr_wid, flags); } @@ -4882,18 +4880,8 @@ NetExpr* PEIdent::elaborate_expr_(Design*des, NetScope*scope, return 0; } - if (sr.net->class_type() && !sr.path_tail.empty()) { - if (debug_elaborate) { - cerr << get_fileline() << ": PEIdent::elaborate_expr: " - "Ident " << sr.path_head - << " look for class property " << sr.path_tail - << endl; - } - - ivl_assert(*this, sr.path_tail.size() == 1); - const name_component_t member_comp = sr.path_tail.front(); - return elaborate_expr_class_field_(des, use_scope, - sr.net, member_comp, + if (dynamic_cast(sr.type) && !sr.path_tail.empty()) { + return elaborate_expr_class_field_(des, use_scope, sr, expr_wid, flags); } diff --git a/elab_lval.cc b/elab_lval.cc index cdbf52b0e..3c8a82c69 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -285,8 +285,9 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, // If the variable is a class object, then handle it with the // net_class_member_ method. - if (reg->class_type() && !member_path.empty() && gn_system_verilog()) { - NetAssign_*lv = elaborate_lval_net_class_member_(des, use_scope, reg, member_path); + 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); return lv; } @@ -475,7 +476,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des, } NetAssign_*this_lval = new NetAssign_(this_net); - this_lval->set_property(member_name); + this_lval->set_property(member_name, pidx); if (canon_index) this_lval->set_word(canon_index); return this_lval; @@ -1078,7 +1079,8 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des, * obj, and member_path=base.x. */ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope, - NetNet*sig, pform_name_t member_path) const + const netclass_t *class_type, NetNet*sig, + pform_name_t member_path) const { if (debug_elaborate) { cerr << get_fileline() << ": PEIdent::elaborate_lval_net_class_member_: " @@ -1086,7 +1088,6 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope << " of " << sig->name() << "." << endl; } - const netclass_t*class_type = sig->class_type(); ivl_assert(*this, class_type); // Iterate over the member_path. This handles nested class @@ -1149,7 +1150,7 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope } lv = lv? new NetAssign_(lv) : new NetAssign_(sig); - lv->set_property(method_name); + lv->set_property(method_name, pidx); // Now get the type of the property. ivl_type_t ptype = class_type->get_prop_type(pidx); diff --git a/elaborate.cc b/elaborate.cc index 25e47d236..41ce06ca0 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3906,7 +3906,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, "$ivl_queue_method$pop_back"); } - if (const netclass_t*class_type = net->class_type()) { + if (const netclass_t*class_type = dynamic_cast(par_type)) { NetScope*task = class_type->method_from_name(method_name); if (task == 0) { // If an implicit this was added it is not an error if we diff --git a/net_assign.cc b/net_assign.cc index d3ecf5215..45379b265 100644 --- a/net_assign.cc +++ b/net_assign.cc @@ -158,10 +158,7 @@ const ivl_type_s* NetAssign_::net_type() const return ntype; if (const netclass_t*class_type = dynamic_cast(ntype)) { - int pidx = class_type->property_idx_from_name(member_); - ivl_assert(*this, pidx >= 0); - ivl_type_t tmp = class_type->get_prop_type(pidx); - return tmp; + return class_type->get_prop_type(member_idx_); } if (const netdarray_t*darray = dynamic_cast (ntype)) { @@ -178,10 +175,7 @@ const ivl_type_s* NetAssign_::net_type() const if (member_.nil()) return sig_->net_type(); - int pidx = class_type->property_idx_from_name(member_); - ivl_assert(*sig_, pidx >= 0); - ivl_type_t tmp = class_type->get_prop_type(pidx); - return tmp; + return class_type->get_prop_type(member_idx_); } if (const netdarray_t*darray = dynamic_cast (sig_->net_type())) { @@ -246,10 +240,10 @@ void NetAssign_::set_part(NetExpr*base, unsigned wid, sel_type_ = sel_type; } -void NetAssign_::set_property(const perm_string&mname) +void NetAssign_::set_property(const perm_string&mname, unsigned idx) { - //ivl_assert(*sig_, sig_->class_type()); member_ = mname; + member_idx_ = idx; } /* diff --git a/net_expr.cc b/net_expr.cc index db163e84a..25f10dcb5 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -382,13 +382,12 @@ NetENull::~NetENull() { } -NetEProperty::NetEProperty(NetNet*net, perm_string pnam, NetExpr*idx) -: net_(net), index_(idx) +NetEProperty::NetEProperty(NetNet*net, size_t pidx, NetExpr*idx) +: net_(net), pidx_(pidx), index_(idx) { const netclass_t*use_type = dynamic_cast(net->net_type()); assert(use_type); - pidx_ = use_type->property_idx_from_name(pnam); ivl_type_t prop_type = use_type->get_prop_type(pidx_); expr_width(prop_type->packed_width()); cast_signed(prop_type->get_signed()); diff --git a/netlist.h b/netlist.h index 78cb7a8ef..45cb82ee8 100644 --- a/netlist.h +++ b/netlist.h @@ -2838,8 +2838,8 @@ class NetAssign_ { ivl_select_type_t = IVL_SEL_OTHER); // Set the member or property name if the signal type is a // class. - void set_property(const perm_string&name); - inline perm_string get_property(void) const { return member_; } + void set_property(const perm_string&name, unsigned int idx); + inline int get_property_idx(void) const { return member_idx_; } // Determine if the assigned object is signed or unsigned. // This is used when determining the expression type for @@ -2897,6 +2897,7 @@ class NetAssign_ { NetExpr*word_; // member/property if signal is a class. perm_string member_; + int member_idx_ = -1; bool signed_; bool turn_sig_to_wire_on_release_; @@ -4579,7 +4580,7 @@ class NetENull : public NetExpr { */ class NetEProperty : public NetExpr { public: - NetEProperty(NetNet*n, perm_string pname, NetExpr*canon_index =0); + NetEProperty(NetNet*n, size_t pidx_, NetExpr*canon_index =0); ~NetEProperty(); inline const NetNet* get_sig() const { return net_; } diff --git a/netmisc.h b/netmisc.h index 621a95757..c523b4e61 100644 --- a/netmisc.h +++ b/netmisc.h @@ -48,7 +48,7 @@ struct symbol_search_results { net = 0; cls_val = 0; par_val = 0; - par_type = 0; + type = 0; eve = 0; } @@ -80,7 +80,7 @@ struct symbol_search_results { // If this was a parameter, the value expression and the // optional value dimensions. const NetExpr*par_val; - ivl_type_t par_type; + ivl_type_t type; // If this is a named event, ... NetEvent*eve; diff --git a/symbol_search.cc b/symbol_search.cc index 2815777c7..2b6cc707f 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -132,12 +132,6 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, if (scope->genvar_tmp.str() && path_tail.name == scope->genvar_tmp) return false; - if (path_tail.name == "#") { - cerr << li->get_fileline() << ": sorry: " - << "Implicit class handle \"super\" not supported." << endl; - return false; - } - // These items cannot be seen outside the bounding module where // the search starts. But we continue searching up because scope // names can match. For example: @@ -151,10 +145,26 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, // ... top.not_ok; // Matches. // endmodule if (!passed_module_boundary) { + // Special case `super` keyword. Return the `this` object, but + // with the type of the base class. + if (path_tail.name == "#") { + if (NetNet *net = scope->find_signal(perm_string::literal(THIS_TOKEN))) { + const netclass_t *class_type = dynamic_cast(net->net_type()); + path.push_back(path_tail); + res->scope = scope; + res->net = net; + res->type = class_type->get_super(); + res->path_head = path; + return true; + } + return false; + } + if (NetNet*net = scope->find_signal(path_tail.name)) { path.push_back(path_tail); res->scope = scope; res->net = net; + res->type = net->net_type(); res->path_head = path; return true; } @@ -167,7 +177,7 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, return true; } - if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->par_type)) { + if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->type)) { path.push_back(path_tail); res->scope = scope; res->par_val = par; @@ -326,7 +336,7 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope, net = recurse.net; cls_val = recurse.cls_val; par = recurse.par_val; - par_type = recurse.par_type; + par_type = recurse.type; eve = recurse.eve; if (! flag) { return 0; diff --git a/t-dll-proc.cc b/t-dll-proc.cc index 27ec54785..ab4ee69d2 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -179,8 +179,6 @@ bool dll_target::make_single_lval_(const LineInfo*li, struct ivl_lval_s*cur, con cur->width_ = asn->lwidth(); - ivl_type_t nest_type = 0; - if (asn->sig()) { cur->type_ = IVL_LVAL_REG; cur->n.sig = find_signal(des_, asn->sig()); @@ -188,7 +186,6 @@ bool dll_target::make_single_lval_(const LineInfo*li, struct ivl_lval_s*cur, con } else { const NetAssign_*asn_nest = asn->nest(); ivl_assert(*li, asn_nest); - nest_type = asn_nest->net_type(); struct ivl_lval_s*cur_nest = new struct ivl_lval_s; make_single_lval_(li, cur_nest, asn_nest); @@ -209,22 +206,7 @@ bool dll_target::make_single_lval_(const LineInfo*li, struct ivl_lval_s*cur, con expr_ = 0; } - cur->property_idx = -1; - perm_string pname = asn->get_property(); - if (!pname.nil()) { - const netclass_t*use_type; - switch (cur->type_) { - case IVL_LVAL_LVAL: - assert(nest_type); - use_type = dynamic_cast (nest_type); - break; - default: - use_type = dynamic_cast (cur->n.sig->net_type); - break; - } - assert(use_type); - cur->property_idx = use_type->property_idx_from_name(pname); - } + cur->property_idx = asn->get_property_idx(); return flag; }