diff --git a/elab_sig.cc b/elab_sig.cc index aa84dfe81..0b85f08a7 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -873,28 +873,32 @@ static netclass_t* locate_class_type(Design*, NetScope*scope, return use_class; } -static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope, - struct_type_t*struct_type) +netstruct_t* struct_type_t::elaborate_type(Design*des, NetScope*scope) const { netstruct_t*res = new netstruct_t; - res->packed(struct_type->packed_flag); + res->packed(packed_flag); - for (list::iterator cur = struct_type->members->begin() - ; cur != struct_type->members->end() ; ++ cur) { + if (union_flag) + res->union_flag(true); + + for (list::iterator cur = members->begin() + ; cur != members->end() ; ++ cur) { vectorpacked_dimensions; struct_member_t*curp = *cur; - if (curp->range.get() && ! curp->range->empty()) { + vector_type_t*vecp = dynamic_cast (curp->type.get()); + if (vecp && vecp->pdims.get() && ! vecp->pdims->empty()) { bool bad_range; - bad_range = evaluate_ranges(des, scope, packed_dimensions, *curp->range); + bad_range = evaluate_ranges(des, scope, packed_dimensions, *vecp->pdims); ivl_assert(*curp, !bad_range); } else { packed_dimensions.push_back(netrange_t(0,0)); } - netvector_t*mem_vec = new netvector_t(packed_dimensions, curp->type); + netvector_t*mem_vec = new netvector_t(packed_dimensions, + curp->type->figure_packed_base_type()); for (list::iterator name = curp->names->begin() ; name != curp->names->end() ; ++ name) { @@ -914,7 +918,7 @@ static ivl_type_s*elaborate_type(Design*des, NetScope*scope, data_type_t*pform_type) { if (struct_type_t*struct_type = dynamic_cast(pform_type)) { - netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type); + netstruct_t*use_type = struct_type->elaborate_type(des, scope); return use_type; } @@ -1245,7 +1249,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const } else if (struct_type_t*struct_type = dynamic_cast(set_data_type_)) { // If this is a struct type, then build the net with the // struct type. - netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type); + netstruct_t*use_type = struct_type->elaborate_type(des, scope); if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype; if (use_type->packed()) diff --git a/parse.y b/parse.y index cc5f70052..db6ceb8b4 100644 --- a/parse.y +++ b/parse.y @@ -2259,6 +2259,7 @@ struct_data_type { struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); tmp->packed_flag = $2; + tmp->union_flag = false; tmp->members .reset($4); $$ = tmp; } @@ -2266,28 +2267,34 @@ struct_data_type { struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); tmp->packed_flag = $2; + tmp->union_flag = true; tmp->members .reset($4); $$ = tmp; - yyerror(@4, "sorry: union data type not implemented."); } | K_struct K_packed_opt '{' error '}' - { yyerror(@4, "error: Errors in struct member list."); + { yyerror(@3, "error: Errors in struct member list."); yyerrok; struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); tmp->packed_flag = $2; + tmp->union_flag = false; $$ = tmp; } | K_union K_packed_opt '{' error '}' - { yyerror(@4, "error: Errors in union member list."); + { yyerror(@3, "error: Errors in union member list."); yyerrok; struct_type_t*tmp = new struct_type_t; FILE_NAME(tmp, @1); tmp->packed_flag = $2; + tmp->union_flag = true; $$ = tmp; } ; + /* This is an implementation of the rule snippet: + struct_union_member { struct_union_member } + that is used in the rule matching struct and union types + in IEEE 1800-2012 A.2.2.1. */ struct_union_member_list : struct_union_member_list struct_union_member { list*tmp = $1; @@ -2301,28 +2308,11 @@ struct_union_member_list } ; -struct_union_member - : attribute_list_opt K_bit range_opt list_of_variable_decl_assignments ';' +struct_union_member /* IEEE 1800-2012 A.2.2.1 */ + : attribute_list_opt data_type list_of_variable_decl_assignments ';' { struct_member_t*tmp = new struct_member_t; FILE_NAME(tmp, @2); - tmp->type = IVL_VT_BOOL; - tmp->range .reset($3); - tmp->names .reset($4); - $$ = tmp; - } - | attribute_list_opt K_logic range_opt list_of_variable_decl_assignments ';' - { struct_member_t*tmp = new struct_member_t; - FILE_NAME(tmp, @2); - tmp->type = IVL_VT_LOGIC; - tmp->range .reset($3); - tmp->names .reset($4); - $$ = tmp; - } - | attribute_list_opt atom2_type list_of_variable_decl_assignments ';' - { struct_member_t*tmp = new struct_member_t; - FILE_NAME(tmp, @2); - tmp->type = IVL_VT_BOOL; - tmp->range .reset(make_range_from_width($2)); + tmp->type .reset($2); tmp->names .reset($3); $$ = tmp; } diff --git a/pform_dump.cc b/pform_dump.cc index 26d8c5b98..f9be1e8d2 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -217,7 +217,7 @@ void class_type_t::pform_dump_init(ostream&out, unsigned indent) const void struct_member_t::pform_dump(ostream&out, unsigned indent) const { - out << setw(indent) << "" << type; + out << setw(indent) << "" << (type.get()? typeid(*type).name() : ""); for (list::iterator cur = names->begin() ; cur != names->end() ; ++cur) { decl_assignment_t*curp = *cur; diff --git a/pform_struct_type.cc b/pform_struct_type.cc index b03b45554..60219524b 100644 --- a/pform_struct_type.cc +++ b/pform_struct_type.cc @@ -33,14 +33,21 @@ ivl_variable_type_t struct_type_t::figure_packed_base_type(void) const struct_member_t*tmp = *cur; - if (tmp->type == IVL_VT_BOOL) { + ivl_variable_type_t tmp_type = IVL_VT_NO_TYPE; + if (tmp->type.get()) + tmp_type = tmp->type->figure_packed_base_type(); + + if (tmp_type == IVL_VT_BOOL) { continue; } - if (tmp->type == IVL_VT_LOGIC) { + if (tmp_type == IVL_VT_LOGIC) { base_type = IVL_VT_LOGIC; continue; } + + // Oh no! Member is not a packable type! + return IVL_VT_NO_TYPE; } return base_type; diff --git a/pform_types.h b/pform_types.h index 84700275c..3bd90381f 100644 --- a/pform_types.h +++ b/pform_types.h @@ -24,6 +24,7 @@ # include "LineInfo.h" # include "verinum.h" # include "named.h" +# include "netstruct.h" # include "property_qual.h" # include "ivl_target.h" # include @@ -115,8 +116,7 @@ struct enum_type_t : public data_type_t { }; struct struct_member_t : public LineInfo { - ivl_variable_type_t type; - std::auto_ptr< list > range; + std::auto_ptr type; std::auto_ptr< list > names; void pform_dump(std::ostream&out, unsigned indent) const; }; @@ -124,8 +124,10 @@ 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; bool packed_flag; + bool union_flag; std::auto_ptr< list > members; };