diff --git a/PScope.h b/PScope.h index f450c9c64..279ca6e6c 100644 --- a/PScope.h +++ b/PScope.h @@ -24,6 +24,7 @@ # include "pform_types.h" # include "ivl_target.h" # include +# include # include class PEvent; @@ -112,7 +113,7 @@ class LexicalScope { list analog_behaviors; // Enumeration sets. - list enum_sets; + std::set enum_sets; LexicalScope* parent_scope() const { return parent_; } diff --git a/elab_scope.cc b/elab_scope.cc index d8072ec04..eb0028ee8 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -178,6 +178,9 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, use_enum->set_line(enum_type->li); scope->add_enumeration_set(use_enum); + ivl_assert(*enum_type, enum_type->net_type == 0); + enum_type->net_type = use_enum; + verinum cur_value (0); verinum one_value (1); size_t name_idx = 0; @@ -285,11 +288,12 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, } static void elaborate_scope_enumerations(Design*des, NetScope*scope, - const list&enum_types) + const set&enum_types) { - for (list::const_iterator cur = enum_types.begin() + for (set::const_iterator cur = enum_types.begin() ; cur != enum_types.end() ; ++ cur) { - elaborate_scope_enumeration(des, scope, *cur); + enum_type_t*curp = *cur; + elaborate_scope_enumeration(des, scope, curp); } } diff --git a/elab_type.cc b/elab_type.cc index f9c17bba5..997069ea0 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -21,6 +21,7 @@ # include "netlist.h" # include "netclass.h" # include "netdarray.h" +# include "netenum.h" # include "netscalar.h" # include "netstruct.h" # include "netvector.h" @@ -79,6 +80,12 @@ ivl_type_s* class_type_t::elaborate_type(Design*, NetScope*scope) const return scope->find_class(name); } +ivl_type_s* enum_type_t::elaborate_type(Design*des, NetScope*scope) const +{ + ivl_assert(*this, net_type); + return net_type; +} + ivl_type_s* vector_type_t::elaborate_type(Design*des, NetScope*scope) const { vector packed; @@ -146,6 +153,8 @@ netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const // Elaborate the type of the member. struct_member_t*curp = *cur; ivl_type_t mem_vec = curp->type->elaborate_type(des, scope); + if (mem_vec == 0) + continue; // There may be several names that are the same type: // name1, name2, ...; diff --git a/netenum.cc b/netenum.cc index 24dc1d3f0..1b8f4441b 100644 --- a/netenum.cc +++ b/netenum.cc @@ -39,6 +39,14 @@ bool netenum_t::get_signed() const return signed_flag_; } +/* + * Enumerations are by definition always packed. + */ +bool netenum_t::packed() const +{ + return true; +} + long netenum_t::packed_width() const { if (msb_ >= lsb_) diff --git a/netenum.h b/netenum.h index a768d02c4..a66fbc237 100644 --- a/netenum.h +++ b/netenum.h @@ -36,8 +36,9 @@ class netenum_t : public LineInfo, public ivl_type_s { long msb, long lsb, size_t name_count); ~netenum_t(); - ivl_variable_type_t base_type() const; - long packed_width() const; + virtual ivl_variable_type_t base_type() const; + virtual bool packed() const; + virtual long packed_width() const; std::vector slice_dimensions() const; bool get_signed() const; diff --git a/netstruct.cc b/netstruct.cc index a2182e671..e56b333a7 100644 --- a/netstruct.cc +++ b/netstruct.cc @@ -52,6 +52,8 @@ void netstruct_t::packed(bool flag) void netstruct_t::append_member(Design*des, const netstruct_t::member_t&val) { + ivl_assert(*this, val.net_type); + members_.push_back(val); if (packed_) { if (! members_.back().net_type->packed()) { diff --git a/pform.cc b/pform.cc index 4c595f27b..4d2a03737 100644 --- a/pform.cc +++ b/pform.cc @@ -484,7 +484,7 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net) static void pform_put_enum_type_in_scope(enum_type_t*enum_set) { - lexical_scope->enum_sets.push_back(enum_set); + lexical_scope->enum_sets.insert(enum_set); } PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type) @@ -508,6 +508,10 @@ void pform_set_typedef(perm_string name, data_type_t*data_type) data_type_t*&ref = lexical_scope->typedefs[name]; ivl_assert(*data_type, ref == 0); ref = data_type; + + if (enum_type_t*enum_type = dynamic_cast(data_type)) { + pform_put_enum_type_in_scope(enum_type); + } } data_type_t* pform_test_type_identifier(const char*txt) diff --git a/pform_dump.cc b/pform_dump.cc index f9be1e8d2..fb2882123 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1328,7 +1328,7 @@ void LexicalScope::dump_localparams_(ostream&out, unsigned indent) const void LexicalScope::dump_enumerations_(ostream&out, unsigned indent) const { - for (list::const_iterator cur = enum_sets.begin() + for (set::const_iterator cur = enum_sets.begin() ; cur != enum_sets.end() ; ++ cur) { out << setw(indent) << "" << "enum {" << endl; diff --git a/pform_types.h b/pform_types.h index 3bd90381f..207e47700 100644 --- a/pform_types.h +++ b/pform_types.h @@ -43,6 +43,7 @@ class PExpr; class PWire; class Statement; class ivl_type_s; +class netenum_t; typedef named named_number_t; typedef named named_pexpr_t; typedef std::pair pform_range_t; @@ -104,15 +105,24 @@ struct void_type_t : public data_type_t { /* * The enum_type_t holds the parsed declaration to represent an * enumeration. Since this is in the pform, it represents the type - * before elaboration to the range, for example, man not be complete + * before elaboration so the range, for example, may not be complete * 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(Design*des, NetScope*scope) const; + ivl_variable_type_t base_type; bool signed_flag; std::auto_ptr< list > range; std::auto_ptr< list > 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 { @@ -124,7 +134,7 @@ struct struct_member_t : public LineInfo { struct struct_type_t : public data_type_t { virtual ivl_variable_type_t figure_packed_base_type(void)const; virtual void pform_dump(std::ostream&out, unsigned indent) const; - netstruct_t* elaborate_type(Design*des, NetScope*scope) const; + virtual netstruct_t* elaborate_type(Design*des, NetScope*scope) const; bool packed_flag; bool union_flag;