Fix problem with enum types in re-used modules

When a module is instantiated multiple times, the enum
types contained within would cause trouble. This fixes
that by elaborating in proper scope context.
This commit is contained in:
Stephen Williams 2013-12-18 08:16:59 +02:00
parent 6ec31517a9
commit fc42f40770
7 changed files with 45 additions and 21 deletions

View File

@ -1313,9 +1313,9 @@ void NetScope::dump(ostream&o) const
o << " enum sets {" << endl; o << " enum sets {" << endl;
/* Dump the enumerations and enum names in this scope. */ /* Dump the enumerations and enum names in this scope. */
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin() for (map<const enum_type_t*,netenum_t*>::const_iterator cur = enum_sets_.begin()
; cur != enum_sets_.end() ; ++ cur) { ; cur != enum_sets_.end() ; ++ cur) {
o << " " << *cur << endl; o << " " << cur->second << endl;
} }
o << " }" << endl; o << " }" << endl;

View File

@ -182,12 +182,9 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
use_enum->set_line(enum_type->li); use_enum->set_line(enum_type->li);
if (scope) if (scope)
scope->add_enumeration_set(use_enum); scope->add_enumeration_set(enum_type, use_enum);
else else
des->add_enumeration_set(use_enum); des->add_enumeration_set(enum_type, use_enum);
ivl_assert(*enum_type, enum_type->net_type == 0);
enum_type->net_type = use_enum;
verinum cur_value (0); verinum cur_value (0);
verinum one_value (1); verinum one_value (1);

View File

@ -80,10 +80,20 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*scope) const
return scope->find_class(name); return scope->find_class(name);
} }
/*
* elaborate_type_raw for enumerations is actually mostly performed
* during scope elaboration so that the enumeration literals are
* available at the right time. At tha time, the netenum_t* object is
* stashed in the scope so that I can retrieve it here.
*/
ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{ {
ivl_assert(*this, net_type); ivl_assert(*this, scope);
return net_type; ivl_type_s*tmp = scope->enumeration_for_key(this);
if (tmp) return tmp;
tmp = des->enumeration_for_key(this);
return tmp;
} }
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const

View File

@ -420,9 +420,9 @@ void NetScope::emit_scope(struct target_t*tgt) const
tgt->class_type(this, cur->second); tgt->class_type(this, cur->second);
} }
for (list<netenum_t*>::const_iterator cur = enum_sets_.begin() for (map<const enum_type_t*,netenum_t*>::const_iterator cur = enum_sets_.begin()
; cur != enum_sets_.end() ; ++cur) ; cur != enum_sets_.end() ; ++cur)
tgt->enumeration(this, *cur); tgt->enumeration(this, cur->second);
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin() for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; cur != children_.end() ; ++ cur ) ; cur != children_.end() ; ++ cur )

View File

@ -38,9 +38,11 @@ Definitions::~Definitions()
{ {
} }
void Definitions::add_enumeration_set(netenum_t*enum_set) void Definitions::add_enumeration_set(const enum_type_t*key, netenum_t*enum_set)
{ {
enum_sets_.push_back(enum_set); netenum_t*&tmp = enum_sets_[key];
assert(tmp == 0);
tmp = enum_set;
} }
bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name) bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name)
@ -57,6 +59,17 @@ bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name)
return cur.second; return cur.second;
} }
netenum_t* Definitions::enumeration_for_key(const enum_type_t*key) const
{
map<const enum_type_t*,netenum_t*>::const_iterator cur;
cur = enum_sets_.find(key);
if (cur != enum_sets_.end())
return cur->second;
else
return 0;
}
/* /*
* This locates the enumeration TYPE for the given enumeration literal. * This locates the enumeration TYPE for the given enumeration literal.
*/ */

View File

@ -76,6 +76,7 @@ class NetEvTrig;
class NetEvWait; class NetEvWait;
class PExpr; class PExpr;
class PFunction; class PFunction;
class enum_type_t;
class netclass_t; class netclass_t;
class netdarray_t; class netdarray_t;
class netparray_t; class netparray_t;
@ -829,13 +830,22 @@ class Definitions {
Definitions(); Definitions();
~Definitions(); ~Definitions();
void add_enumeration_set(netenum_t*enum_set); // Add the enumeration to the set of enumerations in this
// scope. Include a key that the elaboration can use to look
// up this enumeration based on the pform type.
void add_enumeration_set(const enum_type_t*key, netenum_t*enum_set);
bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name); bool add_enumeration_name(netenum_t*enum_set, perm_string enum_name);
// Look up the enumeration literal in this scope. if the name // Look up the enumeration literal in this scope. if the name
// is present, then return the enumeration type that declares it. // is present, then return the enumeration type that declares it.
const netenum_t* enumeration_for_name(perm_string name); const netenum_t* enumeration_for_name(perm_string name);
// Look up the enumeration set that was added with the given
// key. This is used by enum_type_t::elaborate_type to locate
// a previously elaborated enumeration.
netenum_t* enumeration_for_key(const enum_type_t*key) const;
// Look up an enumeration literal in this scope. If the // Look up an enumeration literal in this scope. If the
// literal is present, return the expression that defines its // literal is present, return the expression that defines its
// value. // value.
@ -846,7 +856,7 @@ class Definitions {
// enumerations present in this scope. The enum_names_ is a // enumerations present in this scope. The enum_names_ is a
// map of all the enumeration names back to the sets that // map of all the enumeration names back to the sets that
// contain them. // contain them.
std::list<netenum_t*> enum_sets_; std::map<const enum_type_t*,netenum_t*> enum_sets_;
std::map<perm_string,NetEConstEnum*> enum_names_; std::map<perm_string,NetEConstEnum*> enum_names_;
}; };

View File

@ -116,7 +116,6 @@ struct void_type_t : public data_type_t {
* until it is elaborated in a scope. * until it is elaborated in a scope.
*/ */
struct enum_type_t : public data_type_t { struct enum_type_t : public data_type_t {
inline enum_type_t(void) : net_type(0) { }
// Return the elaborated version of the type. // Return the elaborated version of the type.
virtual ivl_type_s*elaborate_type_raw(Design*des, NetScope*scope) const; virtual ivl_type_s*elaborate_type_raw(Design*des, NetScope*scope) const;
@ -125,11 +124,6 @@ struct enum_type_t : public data_type_t {
std::auto_ptr< list<pform_range_t> > range; std::auto_ptr< list<pform_range_t> > range;
std::auto_ptr< list<named_pexpr_t> > names; std::auto_ptr< list<named_pexpr_t> > names;
LineInfo li; LineInfo li;
// This is the elaborated type. The enumeration type is
// elaborated early so that names can be placed in the scope,
// but that means the result needs to be saved for the actual
// elaborate_type method to use.
netenum_t*net_type;
}; };
struct struct_member_t : public LineInfo { struct struct_member_t : public LineInfo {