diff --git a/elab_scope.cc b/elab_scope.cc index 54f04bceb..3ffb8a2a2 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -490,6 +490,8 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) use_class->set_definition_scope(scope); set_scope_timescale(des, class_scope, pclass); + class_scope->add_typedefs(&pclass->typedefs); + // Elaborate enum types declared in the class. We need these // now because enumeration constants can be used during scope // elaboration. @@ -708,6 +710,8 @@ bool PPackage::elaborate_scope(Design*des, NetScope*scope) << "Elaborate package " << scope_path(scope) << "." << endl; } + scope->add_typedefs(&typedefs); + collect_scope_parameters_(des, scope, parameters); collect_scope_localparams_(des, scope, localparams); @@ -734,6 +738,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope, << "Elaborate " << scope_path(scope) << "." << endl; } + scope->add_typedefs(&typedefs); + // Add the genvars to the scope. typedef map::const_iterator genvar_it_t; for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) { @@ -1192,6 +1198,8 @@ void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope) void PGenerate::elaborate_subscope_(Design*des, NetScope*scope) { + scope->add_typedefs(&typedefs); + // Add the genvars to this scope. typedef map::const_iterator genvar_it_t; for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) { @@ -1545,6 +1553,8 @@ void PFunction::elaborate_scope(Design*des, NetScope*scope) const // find otherwise. scope->is_const_func(true); + scope->add_typedefs(&typedefs); + // Scan the parameters in the function, and store the information // needed to evaluate the parameter expressions. @@ -1563,6 +1573,8 @@ void PTask::elaborate_scope(Design*des, NetScope*scope) const { assert(scope->type() == NetScope::TASK); + scope->add_typedefs(&typedefs); + // Scan the parameters in the task, and store the information // needed to evaluate the parameter expressions. @@ -1611,6 +1623,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const my_scope->set_line(get_file(), get_lineno()); my_scope->is_auto(scope->is_auto()); my_scope->add_imports(&explicit_imports); + my_scope->add_typedefs(&typedefs); // Scan the parameters in the scope, and store the information // needed to evaluate the parameter expressions. diff --git a/elab_sig.cc b/elab_sig.cc index 8815ebded..c315efba7 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -955,6 +955,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const unsigned wid = 1; vectorpacked_dimensions; + NetScope*base_type_scope = scope; + if (set_data_type_ && !set_data_type_->name.nil()) + base_type_scope = scope->find_typedef_scope(des, set_data_type_); + des->errors += error_cnt_; if (port_set_ || net_set_) { @@ -997,7 +1001,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, scope, this, nlist, net_); + dimensions_ok &= evaluate_ranges(des, base_type_scope, this, nlist, net_); } assert(net_set_ || net_.empty()); @@ -1068,6 +1072,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const listunpacked_dimensions; netdarray_t*netdarray = 0; + NetScope*array_type_scope = scope; + if (uarray_type_ && !uarray_type_->name.nil()) + array_type_scope = scope->find_typedef_scope(des, uarray_type_); + for (list::const_iterator cur = unpacked_.begin() ; cur != unpacked_.end() ; ++cur) { PExpr*use_lidx = cur->first; @@ -1100,7 +1108,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const ivl_assert(*this, netdarray==0); long index_l, index_r; - evaluate_range(des, scope, this, *cur, index_l, index_r); + evaluate_range(des, array_type_scope, this, *cur, index_l, index_r); if (abs(index_r - index_l) > warn_dimension_size) { cerr << get_fileline() << ": warning: Array dimension " @@ -1191,7 +1199,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const } else if (enum_type_t*enum_type = dynamic_cast(set_data_type_)) { list::const_iterator sample_name = enum_type->names->begin(); - const netenum_t*use_enum = scope->find_enumeration_for_name(des, sample_name->name); + const netenum_t*use_enum = base_type_scope->find_enumeration_for_name(des, sample_name->name); if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype diff --git a/elab_type.cc b/elab_type.cc index 072d1e723..f193945ad 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -78,6 +78,11 @@ static void elaborate_array_ranges(Design*des, NetScope*scope, */ ivl_type_s* 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); + ivl_assert(*this, scope); Definitions*use_definitions = scope; diff --git a/net_scope.cc b/net_scope.cc index 986bb3c5f..31225eb92 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -119,6 +119,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_u is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up) { imports_ = 0; + typedefs_ = 0; events_ = 0; lcounter_ = 0; is_auto_ = false; @@ -224,6 +225,35 @@ NetScope*NetScope::find_import(const Design*des, perm_string name) return 0; } +void NetScope::add_typedefs(const map*typedefs) +{ + if (!typedefs->empty()) + typedefs_ = typedefs; +} + +NetScope*NetScope::find_typedef_scope(const Design*des, data_type_t*type) +{ + assert(type); + + NetScope *cur_scope = this; + while (cur_scope) { + if (cur_scope->typedefs_ && cur_scope->typedefs_->find(type->name) != cur_scope->typedefs_->end()) + return cur_scope; + NetScope*import_scope = cur_scope->find_import(des, type->name); + if (import_scope) + cur_scope = import_scope; + else if (cur_scope == unit_) + return 0; + else + cur_scope = cur_scope->parent(); + + if (cur_scope == 0) + cur_scope = unit_; + } + + return 0; +} + /* * Look for the enumeration in the current scope and any parent scopes. */ @@ -235,9 +265,12 @@ const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_strin if (tmp) break; NetScope*import_scope = cur_scope->find_import(des, name); if (import_scope) - cur_scope = import_scope; + cur_scope = import_scope; + else if (cur_scope == unit_) + return 0; else - cur_scope = cur_scope->parent(); + cur_scope = cur_scope->parent(); + if (cur_scope == 0) cur_scope = unit_; } diff --git a/netlist.h b/netlist.h index 66eb0890e..441aaeb9f 100644 --- a/netlist.h +++ b/netlist.h @@ -946,6 +946,11 @@ class NetScope : public Definitions, public Attrib { void add_imports(const map*imports); NetScope*find_import(const Design*des, perm_string name); + void add_typedefs(const map*typedefs); + + /* Search the scope hierarchy for the scope where 'type' was defined. */ + NetScope*find_typedef_scope(const Design*des, data_type_t*type); + /* Routine to search for the enumeration given a name. It basically * does what enumeration_for_name() does but searched the hierarchy. */ const netenum_t*find_enumeration_for_name(const Design*des, perm_string name); @@ -1275,6 +1280,8 @@ class NetScope : public Definitions, public Attrib { const map*imports_; + const map*typedefs_; + NetEvent *events_; map genvars_; diff --git a/pform.cc b/pform.cc index 38ce6c3d9..121f21586 100644 --- a/pform.cc +++ b/pform.cc @@ -3520,8 +3520,9 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, // Add the file and line information to the enumeration type. FILE_NAME(&(enum_type->li), li); - // Attach the enumeration to the current scope. - pform_put_enum_type_in_scope(enum_type); + // If this is an anonymous enumeration, attach it to the current scope. + if (enum_type->name.nil()) + pform_put_enum_type_in_scope(enum_type); // Now apply the checked enumeration type to the variables // that are being declared with this type.