diff --git a/PWire.cc b/PWire.cc index d9a9899c6..dbe68afcb 100644 --- a/PWire.cc +++ b/PWire.cc @@ -33,7 +33,7 @@ PWire::PWire(perm_string n, : name_(n), type_(t), port_type_(pt), data_type_(dt), signed_(false), port_set_(false), net_set_(false), is_scalar_(false), - error_cnt_(0), set_data_type_(0), discipline_(0) + error_cnt_(0), discipline_(0) { switch (rt) { case SR_PORT: @@ -195,8 +195,11 @@ void PWire::set_unpacked_idx(const list&ranges) void PWire::set_data_type(data_type_t*type) { - assert(set_data_type_ == 0 || set_data_type_ == type); - set_data_type_ = type; + if (set_data_type_.get() == type) + return; + + assert(!set_data_type_.get()); + set_data_type_.reset(type); } void PWire::set_discipline(ivl_discipline_t d) diff --git a/PWire.h b/PWire.h index e9565a2d5..1f92fac9e 100644 --- a/PWire.h +++ b/PWire.h @@ -123,7 +123,7 @@ class PWire : public PNamedItem { // This is the complex type of the wire. the data_type_ may // modify how this is interpreted. - data_type_t*set_data_type_; + std::unique_ptr set_data_type_; ivl_discipline_t discipline_; diff --git a/elab_scope.cc b/elab_scope.cc index e798d0c91..a03d4df75 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -444,7 +444,7 @@ static void blend_class_constructors(PClass*pclass) // If we do not have an explicit constructor chain, but there // is a parent class, then create an implicit chain. - if (chain_new==0 && pclass->type->base_type!=0) { + if (chain_new==0 && pclass->type->base_type) { chain_new = new PChainConstructor(pclass->type->base_args); chain_new->set_line(*pclass); } @@ -512,16 +512,6 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) netclass_t*use_class = new netclass_t(use_type->name, use_base_class); - // If this is a package we need to remember the elaborated type so that - // scoped type references work. Since there is only one instance for each - // package this works. For classes defined in modules there might be - // multiple instances though. Each module instance will have its own class - // type instance, so the same does not work there. - if (scope->type() == NetScope::PACKAGE) { - ivl_assert(*pclass, use_type->save_elaborated_type == 0); - use_type->save_elaborated_type = use_class; - } - NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()), NetScope::CLASS, scope->unit()); class_scope->set_line(pclass); diff --git a/elab_sig.cc b/elab_sig.cc index f4e26c5bd..924fdb945 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -939,10 +939,10 @@ bool test_ranges_eeq(const vector&lef, const vector&rig) ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope, const std::vector&packed_dimensions) const { - if (set_data_type_ && !dynamic_cast(set_data_type_)) { - ivl_type_t use_type = set_data_type_->elaborate_type(des, scope); + vector_type_t *vec_type = dynamic_cast(set_data_type_.get()); + if (set_data_type_ && !vec_type) { ivl_assert(*this, packed_dimensions.empty()); - return use_type; + return set_data_type_->elaborate_type(des, scope); } // Fallback method. Create vector type. @@ -1003,10 +1003,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const unsigned wid = 1; vectorpacked_dimensions; - NetScope *type_scope = scope; - if (set_data_type_ && !set_data_type_->name.nil()) - type_scope = type_scope->find_typedef_scope(des, set_data_type_); - des->errors += error_cnt_; if (port_set_ || net_set_) { @@ -1046,7 +1042,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const cerr << get_fileline() << ": PWire::elaborate_sig: " << "Evaluate ranges for net " << basename() << endl; } - dimensions_ok &= evaluate_ranges(des, type_scope, this, nlist, net_); + dimensions_ok &= evaluate_ranges(des, scope, this, nlist, net_); } assert(net_set_ || net_.empty()); @@ -1147,10 +1143,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const wtype = NetNet::WIRE; } - ivl_type_t type = elaborate_type(des, type_scope, packed_dimensions); + ivl_type_t type = elaborate_type(des, scope, packed_dimensions); // Create the type for the unpacked dimensions. If the // unpacked_dimensions are empty this will just return the base type. - type = elaborate_array_type(des, type_scope, *this, type, unpacked_); + type = elaborate_array_type(des, scope, *this, type, unpacked_); list unpacked_dimensions; // If this is an unpacked array extract the base type and unpacked diff --git a/elab_type.cc b/elab_type.cc index a6be08f69..9c8280c61 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -18,6 +18,7 @@ */ # include "PExpr.h" +# include "PScope.h" # include "pform_types.h" # include "netlist.h" # include "netclass.h" @@ -40,10 +41,7 @@ using namespace std; */ ivl_type_t data_type_t::elaborate_type(Design*des, NetScope*scope) { - // User-defined types must be elaborated in the context - // where they were defined. - if (!name.nil()) - scope = scope->find_typedef_scope(des, this); + scope = find_scope(des, scope); ivl_assert(*this, scope); Definitions*use_definitions = scope; @@ -57,6 +55,11 @@ ivl_type_t data_type_t::elaborate_type(Design*des, NetScope*scope) return tmp; } +NetScope *data_type_t::find_scope(Design *, NetScope *scope) const +{ + return scope; +} + ivl_type_t data_type_t::elaborate_type_raw(Design*des, NetScope*) const { cerr << get_fileline() << ": internal error: " @@ -112,8 +115,6 @@ ivl_type_t atom_type_t::elaborate_type_raw(Design*des, NetScope*) const ivl_type_t class_type_t::elaborate_type_raw(Design*des, NetScope*scope) const { - if (save_elaborated_type) - return save_elaborated_type; return scope->find_class(des, name); } @@ -366,3 +367,26 @@ ivl_type_t uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const return elaborate_array_type(des, scope, *this, btype, *dims.get()); } + +ivl_type_t typeref_t::elaborate_type_raw(Design*des, NetScope*s) const +{ + if (!s) { + // Try to recover + return new netvector_t(IVL_VT_LOGIC); + } + + return type->elaborate_type(des, s); +} + +NetScope *typeref_t::find_scope(Design *des, NetScope *s) const +{ + // If a scope has been specified use that as a starting point for the + // search + if (scope) + s = des->find_package(scope->pscope_name()); + + if (!type->name.nil()) + s = s->find_typedef_scope(des, type); + + return s; +} diff --git a/parse.y b/parse.y index be48f8f94..ffe782bb5 100644 --- a/parse.y +++ b/parse.y @@ -27,6 +27,7 @@ # include "pform.h" # include "Statement.h" # include "PSpec.h" +# include "PPackage.h" # include # include # include @@ -1167,12 +1168,14 @@ ps_type_identifier /* IEEE1800-2017: A.9.3 */ : TYPE_IDENTIFIER { pform_set_type_referenced(@1, $1.text); delete[]$1.text; - $$ = $1.type; + $$ = new typeref_t($1.type); + FILE_NAME($$, @1); } | package_scope TYPE_IDENTIFIER { lex_in_package_scope(0); - $$ = $2.type; - delete[]$2.text; + $$ = new typeref_t($2.type, $1); + FILE_NAME($$, @2); + delete[] $2.text; } ; diff --git a/pform_dump.cc b/pform_dump.cc index 4e1be9146..f6bc1c1b3 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -173,6 +173,15 @@ ostream& data_type_t::debug_dump(ostream&out) const return out; } +std::ostream& typeref_t::debug_dump(ostream&out) const +{ + if (scope) + out << scope->pscope_name() << "::"; + out << type->name; + + return out; +} + ostream& atom_type_t::debug_dump(ostream&out) const { if (signed_flag) diff --git a/pform_pclass.cc b/pform_pclass.cc index f922b9df9..7a7547b8f 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -50,7 +50,7 @@ void pform_start_class_declaration(const struct vlltype&loc, pform_cur_class = class_scope; assert(type->base_type == 0); - type->base_type = base_type; + type->base_type.reset(base_type); assert(type->base_args.empty()); if (base_exprs) { diff --git a/pform_types.h b/pform_types.h index 02a8a9e2a..2ef0585c6 100644 --- a/pform_types.h +++ b/pform_types.h @@ -41,6 +41,7 @@ class Design; class NetScope; class Definitions; class PExpr; +class PScope; class PWire; class Statement; class netclass_t; @@ -161,6 +162,8 @@ class data_type_t : public PNamedItem { virtual SymbolType symbol_type() const; + virtual NetScope *find_scope(Design* des, NetScope *scope) const; + perm_string name; private: @@ -171,6 +174,19 @@ class data_type_t : public PNamedItem { std::map cache_type_elaborate_; }; +struct typeref_t : public data_type_t { + explicit typeref_t(data_type_t *t, PScope *s = 0) : scope(s), type(t) {} + + ivl_type_t elaborate_type_raw(Design*des, NetScope*scope) const; + NetScope *find_scope(Design* des, NetScope *scope) const; + + std::ostream& debug_dump(std::ostream&out) const; + +private: + PScope *scope; + data_type_t *type; +}; + struct void_type_t : public data_type_t { virtual void pform_dump(std::ostream&out, unsigned indent) const; }; @@ -189,7 +205,7 @@ struct enum_type_t : public data_type_t { SymbolType symbol_type() const; - data_type_t *base_type; + std::unique_ptr base_type; std::unique_ptr< std::list > names; }; @@ -266,7 +282,7 @@ struct array_base_t : public data_type_t { inline explicit array_base_t(data_type_t*btype, std::list*pd) : base_type(btype), dims(pd) { } - data_type_t*base_type; + std::unique_ptr base_type; std::unique_ptr< std::list > dims; }; @@ -319,8 +335,7 @@ struct string_type_t : public data_type_t { struct class_type_t : public data_type_t { - inline explicit class_type_t(perm_string n) - : base_type(0), save_elaborated_type(0) { name = n; } + inline explicit class_type_t(perm_string n) { name = n; } void pform_dump(std::ostream&out, unsigned indent) const; void pform_dump_init(std::ostream&out, unsigned indent) const; @@ -329,15 +344,17 @@ struct class_type_t : public data_type_t { // class that we are extending. This is nil if there is no // hierarchy. If there are arguments to the base class, then // put them in the base_args vector. - data_type_t*base_type; + std::unique_ptr base_type; std::listbase_args; // This is a map of the properties. Map the name to the type. struct prop_info_t : public LineInfo { - inline prop_info_t() : qual(property_qualifier_t::make_none()), type(0) { } + inline prop_info_t() : qual(property_qualifier_t::make_none()) { } inline prop_info_t(property_qualifier_t q, data_type_t*t) : qual(q), type(t) { } + prop_info_t(prop_info_t&&) = default; + prop_info_t& operator=(prop_info_t&&) = default; property_qualifier_t qual; - data_type_t* type; + std::unique_ptr type; }; std::map properties; @@ -352,11 +369,6 @@ struct class_type_t : public data_type_t { std::vector initialize_static; ivl_type_t elaborate_type_raw(Design*, NetScope*) const; - // The save_elaborated_type member must be set to the pointer - // to the netclass_t object that is created to represent this - // type. The elaborate_type_raw() method uses this pointer, - // and it is used in some other situations as well. - netclass_t* save_elaborated_type; virtual SymbolType symbol_type() const; };