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;
/* 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) {
o << " " << *cur << endl;
o << " " << cur->second << 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);
if (scope)
scope->add_enumeration_set(use_enum);
scope->add_enumeration_set(enum_type, use_enum);
else
des->add_enumeration_set(use_enum);
ivl_assert(*enum_type, enum_type->net_type == 0);
enum_type->net_type = use_enum;
des->add_enumeration_set(enum_type, use_enum);
verinum cur_value (0);
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);
}
/*
* 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_assert(*this, net_type);
return net_type;
ivl_assert(*this, scope);
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

View File

@ -420,9 +420,9 @@ void NetScope::emit_scope(struct target_t*tgt) const
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)
tgt->enumeration(this, *cur);
tgt->enumeration(this, cur->second);
for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
; 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)
@ -57,6 +59,17 @@ bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name)
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.
*/

View File

@ -76,6 +76,7 @@ class NetEvTrig;
class NetEvWait;
class PExpr;
class PFunction;
class enum_type_t;
class netclass_t;
class netdarray_t;
class netparray_t;
@ -829,13 +830,22 @@ class 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);
// Look up the enumeration literal in this scope. if the name
// is present, then return the enumeration type that declares it.
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
// literal is present, return the expression that defines its
// value.
@ -846,7 +856,7 @@ class Definitions {
// enumerations present in this scope. The enum_names_ is a
// map of all the enumeration names back to the sets that
// 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_;
};

View File

@ -116,7 +116,6 @@ struct void_type_t : public data_type_t {
* until it is elaborated in a scope.
*/
struct enum_type_t : public data_type_t {
inline enum_type_t(void) : net_type(0) { }
// Return the elaborated version of the type.
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<named_pexpr_t> > names;
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 {