diff --git a/PExpr.cc b/PExpr.cc index 2b4c222ce..bad03ed26 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -447,11 +447,13 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type) bool PEIdent::has_aa_term(Design*des, NetScope*scope) const { NetNet* net = 0; + ivl_type_t cls_val; const NetExpr*par = 0; ivl_type_t par_type; NetEvent* eve = 0; - scope = symbol_search(this, des, scope, path_, net, par, eve, par_type); + scope = symbol_search(this, des, scope, path_, net, par, eve, + par_type, cls_val); if (scope) return scope->is_auto(); diff --git a/elab_expr.cc b/elab_expr.cc index 99ffcad5a..0b2bf86b1 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -634,9 +634,6 @@ unsigned PEBComp::test_width(Design*des, NetScope*scope, width_mode_t&) case 'n': /* != */ case 'E': /* === */ case 'N': /* !== */ - // FIXME: A class variable/array inside a class is not - // reported correctly so this cannot be used. -#if 0 if ((l_type == IVL_VT_CLASS || r_type == IVL_VT_CLASS) && l_type != r_type) { cerr << get_fileline() << ": error: " @@ -645,7 +642,6 @@ unsigned PEBComp::test_width(Design*des, NetScope*scope, width_mode_t&) << human_readable_op(op_) << "' operator." << endl; des->errors += 1; } -#endif break; default: if (l_type == IVL_VT_CLASS || r_type == IVL_VT_CLASS) { @@ -3924,10 +3920,11 @@ unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&) } NetNet*net = 0; + ivl_type_t cls_val = 0; const NetExpr*par = 0; ivl_type_t par_type = 0; NetEvent*eve = 0; - symbol_search(this, des, scope, use_path, net, par, eve, par_type); + symbol_search(this, des, scope, use_path, net, par, eve, par_type, cls_val); if (net == 0) { if (debug_elaborate) cerr << get_fileline() << ": PEIdent::test_width_method_: " @@ -3970,6 +3967,7 @@ unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&) unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) { NetNet* net = 0; + ivl_type_t cls_val = 0; const NetExpr*par = 0; ivl_type_t par_type = 0; NetEvent* eve = 0; @@ -3985,7 +3983,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) } NetScope*found_in = symbol_search(this, des, use_scope, path_, - net, par, eve, par_type); + net, par, eve, par_type, cls_val); // If there is a part/bit select expression, then process it // here. This constrains the results no matter what kind the @@ -4063,6 +4061,15 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) return expr_width_; } + // Look for a class property. + if (gn_system_verilog() && cls_val) { + expr_type_ = cls_val->base_type(); + expr_width_ = cls_val->packed_width(); + min_width_ = expr_width_; + signed_flag_ = cls_val->get_signed(); + return expr_width_; + } + if (use_width != UINT_MAX) { expr_type_ = IVL_VT_LOGIC; // Assume bit/parts selects are logic expr_width_ = use_width; @@ -4161,7 +4168,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) use_path.pop_back(); ivl_assert(*this, net == 0); - symbol_search(this, des, scope, use_path, net, par, eve, par_type); + symbol_search(this, des, scope, use_path, net, par, eve, par_type, cls_val); // Check to see if we have a net and if so is it a structure? if (net != 0) { @@ -4222,6 +4229,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, bool need_const = NEED_CONST & flags; NetNet* net = 0; + ivl_type_t cls_val = 0; const NetExpr*par = 0; ivl_type_t par_type = 0; NetEvent* eve = 0; @@ -4236,7 +4244,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, return tmp; } - symbol_search(this, des, use_scope, path_, net, par, eve, par_type); + symbol_search(this, des, use_scope, path_, net, par, eve, par_type, cls_val); if (net == 0 && gn_system_verilog() && path_.size() >= 2) { // NOTE: this is assuming the member_path is only one @@ -4248,7 +4256,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, use_path.pop_back(); ivl_assert(*this, net == 0); - symbol_search(this, des, use_scope, use_path, net, par, eve, par_type); + symbol_search(this, des, use_scope, use_path, net, par, eve, + par_type, cls_val); if (net == 0) { // Nope, no struct/class with member. @@ -4501,6 +4510,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, assert(scope); NetNet* net = 0; + ivl_type_t cls_val = 0; const NetExpr*par = 0; ivl_type_t par_type = 0; NetEvent* eve = 0; @@ -4562,7 +4572,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, NetScope*found_in = 0; while (net==0 && par==0 && eve==0 && !base_path.empty()) { found_in = symbol_search(this, des, use_scope, base_path, - net, par, eve, par_type); + net, par, eve, par_type, cls_val); if (net) break; if (par) break; if (eve) break; diff --git a/elab_sig.cc b/elab_sig.cc index c027ce033..d61cfa61f 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2021 Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -720,8 +720,19 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope, // that expression here. if (ports_->at(idx).defe != 0) { if (tmp->port_type() == NetNet::PINPUT) { - tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe, - -1, scope->need_const_func()); + // Elaborate a class port default in the context of + // the class type. + if (tmp->data_type() == IVL_VT_CLASS) { + tmp_def = elab_and_eval(des, scope, + ports_->at(idx).defe, + tmp->net_type(), + scope->need_const_func()); + } else { + tmp_def = elab_and_eval(des, scope, + ports_->at(idx).defe, + -1, + scope->need_const_func()); + } if (tmp_def == 0) { cerr << get_fileline() << ": error: Unable to evaluate " diff --git a/elaborate.cc b/elaborate.cc index f16358c00..01e41290d 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3770,6 +3770,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, use_path.pop_back(); NetNet *net; + ivl_type_t cls_val = 0; const NetExpr *par; ivl_type_t par_type = 0; NetEvent *eve; @@ -3787,7 +3788,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope, // resolve to a class object. Note that the "this" symbol // (internally represented as "@") is handled by there being a // "this" object in the instance scope. - symbol_search(this, des, scope, use_path, net, par, eve, par_type); + symbol_search(this, des, scope, use_path, net, par, eve, par_type, cls_val); if (net == 0) return 0; diff --git a/netmisc.cc b/netmisc.cc index 63ce3c2d2..4f21eeca7 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2020 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2021 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -858,16 +858,12 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe, pe->test_width(des, scope, mode); - // FIXME: A class variable/array inside a class is not - // reported correctly so this cannot be used. -#if 0 if (pe->expr_type() == IVL_VT_CLASS) { cerr << pe->get_fileline() << ": Error: " << "Class/null r-value not allowed in this context." << endl; des->errors += 1; return 0; } -#endif // Get the final expression width. If the expression is unsized, // this may be different from the value returned by test_width(). diff --git a/netmisc.h b/netmisc.h index 97a46ef50..94398c0a9 100644 --- a/netmisc.h +++ b/netmisc.h @@ -46,6 +46,7 @@ struct symbol_search_results { inline symbol_search_results() { scope = 0; net = 0; + cls_val = 0; par_val = 0; par_type = 0; eve = 0; @@ -54,6 +55,7 @@ struct symbol_search_results { inline bool is_scope() const { if (net) return false; if (eve) return false; + if (cls_val) return false; if (par_val) return false; if (scope) return true; return false; @@ -62,6 +64,7 @@ struct symbol_search_results { inline bool is_found() const { if (net) return true; if (eve) return true; + if (cls_val) return true; if (par_val) return true; if (scope) return true; return false; @@ -72,6 +75,8 @@ struct symbol_search_results { NetScope*scope; // If this was a net, the signal itself. NetNet*net; + // For a class property we only have type information. + ivl_type_t cls_val; // If this was a parameter, the value expression and the // optional value dimensions. const NetExpr*par_val; @@ -132,7 +137,8 @@ extern NetScope* symbol_search(const LineInfo*li, NetNet*&net, /* net/reg */ const NetExpr*&par,/* parameter/expr */ NetEvent*&eve, /* named event */ - ivl_type_t&par_type); + ivl_type_t&par_type, + ivl_type_t&cls_val); inline NetScope* symbol_search(const LineInfo*li, Design*des, @@ -143,7 +149,9 @@ inline NetScope* symbol_search(const LineInfo*li, NetEvent*&eve /* named event */) { ivl_type_t par_type; - return symbol_search(li, des, start, path, net, par, eve, par_type); + ivl_type_t cls_val; + return symbol_search(li, des, start, path, net, par, eve, + par_type, cls_val); } /* diff --git a/symbol_search.cc b/symbol_search.cc index 3185c6e04..8565b00b7 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -19,6 +19,8 @@ */ # include "netlist.h" +# include "netclass.h" +# include "netparray.h" # include "netmisc.h" # include "compiler.h" # include "ivl_assert.h" @@ -168,6 +170,21 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, res->path_item = path_tail; return true; } + + // Static items are just normal signals and are found above. + if (scope->type() == NetScope::CLASS) { + netclass_t*clsnet = scope->find_class(des, scope->basename()); + int pidx = clsnet->property_idx_from_name(path_tail.name); + if (pidx >= 0) { + ivl_type_t prop_type = clsnet->get_prop_type(pidx); + const netuarray_t*tmp_ua = dynamic_cast(prop_type); + if (tmp_ua) prop_type = tmp_ua->element_type(); + res->scope = scope; + res->cls_val = prop_type; + res->path_item = path_tail; + return true; + } + } } if (NetScope*import_scope = scope->find_import(des, path_tail.name)) { @@ -275,12 +292,14 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope, NetNet*&net, const NetExpr*&par, NetEvent*&eve, - ivl_type_t&par_type) + ivl_type_t&par_type, + ivl_type_t&cls_val) { symbol_search_results recurse; bool flag = symbol_search(li, des, scope, path, &recurse); net = 0; + cls_val = 0; par = 0; par_type = 0; eve = 0; @@ -297,6 +316,7 @@ NetScope*symbol_search(const LineInfo*li, Design*des, NetScope*scope, // Convert the extended results to the compatible results. net = recurse.net; + cls_val = recurse.cls_val; par = recurse.par_val; par_type = recurse.par_type; eve = recurse.eve;