diff --git a/PWire.cc b/PWire.cc index 945de9be6..56cca4731 100644 --- a/PWire.cc +++ b/PWire.cc @@ -29,7 +29,7 @@ PWire::PWire(perm_string n, : name_(n), type_(t), port_type_(pt), data_type_(dt), signed_(false), isint_(false), port_set_(false), net_set_(false), is_scalar_(false), - error_cnt_(0), enum_type_(0), struct_type_(0), + error_cnt_(0), set_data_type_(0), discipline_(0) { if (t == NetNet::INTEGER) { @@ -253,18 +253,10 @@ void PWire::set_unpacked_idx(const list&ranges) } } -void PWire::set_enumeration(enum_type_t*enum_type) +void PWire::set_packed_type(data_type_t*type) { - assert(enum_type_ == 0); - assert(struct_type_ == 0); - enum_type_ = enum_type; -} - -void PWire::set_struct_type(struct_type_t*type) -{ - assert(enum_type_ == 0); - assert(struct_type_ == 0); - struct_type_ = type; + assert(set_data_type_ == 0); + set_data_type_ = type; } void PWire::set_discipline(ivl_discipline_t d) diff --git a/PWire.h b/PWire.h index 94be9b3da..b0a2e0444 100644 --- a/PWire.h +++ b/PWire.h @@ -81,8 +81,7 @@ class PWire : public LineInfo { void set_unpacked_idx(const std::list&ranges); - void set_enumeration(enum_type_t*enum_type); - void set_struct_type(struct_type_t*type); + void set_packed_type(data_type_t*type); void set_discipline(ivl_discipline_t); ivl_discipline_t get_discipline(void) const; @@ -119,8 +118,7 @@ class PWire : public LineInfo { // me the size and address ranges of the memory. std::listunpacked_; - enum_type_t*enum_type_; - struct_type_t*struct_type_; + data_type_t*set_data_type_; ivl_discipline_t discipline_; diff --git a/elab_sig.cc b/elab_sig.cc index 62da554e6..59e01b3f6 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -892,6 +892,20 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope, return res; } +static netdarray_t* elaborate_parray_type(Design*des, NetScope*scope, + parray_type_t*data_type) +{ + + listpacked_dimensions; + bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims); + ivl_assert(*data_type, bad_range); + + netdarray_t*res = new netdarray_t(packed_dimensions, IVL_VT_NO_TYPE, 0); + //res->set_line(*data_type); + + return res; +} + bool test_ranges_eeq(const list&lef, const list&rig) { if (lef.size() != rig.size()) @@ -1158,8 +1172,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const // If this is a struct type, then build the net with the // struct type. - if (struct_type_) { - netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type_); + if (struct_type_t*struct_type = dynamic_cast(set_data_type_)) { + netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type); if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype; if (use_type->packed()) @@ -1172,10 +1186,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const sig = new NetNet(scope, name_, wtype, use_type); - } else if (enum_type_) { - ivl_assert(*this, struct_type_ == 0); - ivl_assert(*this, ! enum_type_->names->empty()); - list::const_iterator sample_name = enum_type_->names->begin(); + } else if (enum_type_t*enum_type = dynamic_cast(set_data_type_)) { + list::const_iterator sample_name = enum_type->names->begin(); netenum_t*use_enum = scope->enumeration_for_name(sample_name->name); if (debug_elaborate) { @@ -1186,9 +1198,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, use_enum); + } else if (netarray) { - ivl_assert(*this, struct_type_==0); - ivl_assert(*this, enum_type_==0); if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype @@ -1200,6 +1211,15 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const ivl_assert(*this, unpacked_dimensions.empty()); sig = new NetNet(scope, name_, wtype, netarray); + } else if (parray_type_t*parray_type = dynamic_cast(set_data_type_)) { + + netdarray_t*use_type = elaborate_parray_type(des, scope, parray_type); + sig = new NetNet(scope, name_, wtype, use_type); +#if 0 + cerr << get_fileline() << ": sorry: Packed arrays not supported here." << endl; + des->errors += 1; +#endif + } else { if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype; diff --git a/netarray.h b/netarray.h deleted file mode 100644 index cd027bf23..000000000 --- a/netarray.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __netarray_H -#define __netarray_H -/* - * Copyright (c) 2012 Stephen Williams (steve@icarus.com) - * Copyright CERN 2012 / Stephen Williams (steve@icarus.com) - * - * This source code is free software; you can redistribute it - * and/or modify it in source code form under the terms of the GNU - * General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -# include "LineInfo.h" -# include - -class netarray_t : public LineInfo { - - public: - explicit netarray_t(const std::list&packed); - ~netarray_t(); - - unsigned packed_width() const; - - private: - std::list packed_dims_; - -}; - -inline netarray_t::netarray_t(const std::list&packed) -: packed_dims_(packed) -{ -} - -netarray_t::~netarray_t() -{ -} - -#endif diff --git a/netlist.cc b/netlist.cc index 0fbe573fc..ec867f7be 100644 --- a/netlist.cc +++ b/netlist.cc @@ -611,7 +611,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, s->add_signal(this); } -static unsigned calculate_count(netstruct_t*type) +template static unsigned calculate_count(T*type) { long wid = type->packed_width(); if (wid >= 0) diff --git a/parse.y b/parse.y index 2b77f03c9..a3a8919b1 100644 --- a/parse.y +++ b/parse.y @@ -894,7 +894,7 @@ data_type /* IEEE1800-2005: A.2.2.1 */ $$ = tmp; } | TYPE_IDENTIFIER range_opt - { if ($2) $$ = new array_type_t($1, $2); + { if ($2) $$ = new parray_type_t($1, $2); else $$ = $1; } | K_string diff --git a/pform.cc b/pform.cc index 5548d07be..fb6f0012b 100644 --- a/pform.cc +++ b/pform.cc @@ -1591,11 +1591,11 @@ static void pform_set_net_range(perm_string name, pform_bind_attributes(cur->attributes, attr, true); } -void pform_set_net_range(list*names, - list*range, - bool signed_flag, - ivl_variable_type_t dt, - std::list*attr) +static void pform_set_net_range(list*names, + list*range, + bool signed_flag, + ivl_variable_type_t dt, + std::list*attr) { for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur ) { @@ -1997,7 +1997,7 @@ void pform_module_define_port(const struct vlltype&li, } } else if ((struct_type = dynamic_cast(vtype))) { - data_type = figure_struct_base_type(struct_type); + data_type = struct_type->figure_packed_base_type(); signed_flag = false; range = 0; @@ -2017,7 +2017,7 @@ void pform_module_define_port(const struct vlltype&li, cur->set_signed(signed_flag); if (struct_type) { - cur->set_struct_type(struct_type); + cur->set_packed_type(struct_type); } else if (range == 0) { cur->set_range_scalar((type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH); @@ -2790,6 +2790,26 @@ static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list static void pform_set2_data_type(const struct vlltype&li, T*data_type, perm_string name, list*attr) +{ + ivl_variable_type_t base_type = data_type->figure_packed_base_type(); + if (base_type == IVL_VT_NO_TYPE) { + VLerror(li, "Compound type is not PACKED in this context."); + } + + PWire*net = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, base_type); + net->set_packed_type(data_type); + pform_bind_attributes(net->attributes, attr, true); +} + +template static void pform_set2_data_type(const struct vlltype&li, T*data_type, list*names, list*attr) +{ + for (list::iterator cur = names->begin() + ; cur != names->end() ; ++ cur) { + pform_set2_data_type(li, data_type, *cur, attr); + } +} + /* * This function detects the derived class for the given type and * dispatches the type to the proper subtype function. @@ -2828,8 +2848,8 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list (data_type)) { - VLerror(li, "sorry: General array types not supported."); + if (parray_type_t*array_type = dynamic_cast (data_type)) { + pform_set2_data_type(li, array_type, names, attr); return; } @@ -2853,7 +2873,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, assert(enum_type->range.get() != 0); assert(enum_type->range->size() == 1); cur->set_range(*enum_type->range, SR_NET); - cur->set_enumeration(enum_type); + cur->set_packed_type(enum_type); pform_bind_attributes(cur->attributes, attr, true); } diff --git a/pform.h b/pform.h index cd039f105..9fd0a408c 100644 --- a/pform.h +++ b/pform.h @@ -292,11 +292,6 @@ extern void pform_set_port_type(const struct vlltype&li, bool signed_flag, NetNet::PortType); -extern void pform_set_net_range(list*names, - list*, - bool signed_flag, - ivl_variable_type_t, - std::list*attr); extern void pform_set_reg_idx(perm_string name, std::list*indices); extern void pform_set_reg_integer(list*names, list*attr); diff --git a/pform_dump.cc b/pform_dump.cc index 5d9ddad31..e8036ca67 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -391,6 +391,10 @@ void PWire::dump(ostream&out, unsigned ind) const } out << ";" << endl; + if (set_data_type_) { + set_data_type_->pform_dump(out, 8); + } + dump_attributes_map(out, attributes, 8); } diff --git a/pform_struct_type.cc b/pform_struct_type.cc index 9f5089035..eab6dc40f 100644 --- a/pform_struct_type.cc +++ b/pform_struct_type.cc @@ -21,12 +21,15 @@ # include "parse_misc.h" # include "ivl_assert.h" -ivl_variable_type_t figure_struct_base_type(struct_type_t*struct_type) +ivl_variable_type_t struct_type_t::figure_packed_base_type(void) const { + if (! packed_flag) + return IVL_VT_NO_TYPE; + ivl_variable_type_t base_type = IVL_VT_BOOL; - for (list::iterator cur = struct_type->members->begin() - ; cur != struct_type->members->end() ; ++ cur) { + for (list::iterator cur = members->begin() + ; cur != members->end() ; ++ cur) { struct_member_t*tmp = *cur; @@ -50,10 +53,10 @@ ivl_variable_type_t figure_struct_base_type(struct_type_t*struct_type) */ static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name, list*attr) { - ivl_variable_type_t base_type = figure_struct_base_type(struct_type); + ivl_variable_type_t base_type = struct_type->figure_packed_base_type(); PWire*net = pform_get_make_wire_in_scope(name, NetNet::REG, NetNet::NOT_A_PORT, base_type); - net->set_struct_type(struct_type); + net->set_packed_type(struct_type); pform_bind_attributes(net->attributes, attr, true); } @@ -82,11 +85,11 @@ static void pform_makewire(const struct vlltype&li, perm_string name, list*) { - ivl_variable_type_t base_type = figure_struct_base_type(struct_type); + ivl_variable_type_t base_type = struct_type->figure_packed_base_type(); PWire*cur = pform_get_make_wire_in_scope(name, NetNet::WIRE, ptype, base_type); FILE_NAME(cur, li); - cur->set_struct_type(struct_type); + cur->set_packed_type(struct_type); } void pform_makewire(const struct vlltype&li, diff --git a/pform_types.cc b/pform_types.cc index 06b155b78..5a7868bef 100644 --- a/pform_types.cc +++ b/pform_types.cc @@ -27,3 +27,18 @@ data_type_t::~data_type_t() string_type_t::~string_type_t() { } + +ivl_variable_type_t data_type_t::figure_packed_base_type(void) const +{ + return IVL_VT_NO_TYPE; +} + +ivl_variable_type_t parray_type_t::figure_packed_base_type(void) const +{ + return base_type->figure_packed_base_type(); +} + +ivl_variable_type_t vector_type_t::figure_packed_base_type(void) const +{ + return base_type; +} diff --git a/pform_types.h b/pform_types.h index 7c37a4472..80c912fcf 100644 --- a/pform_types.h +++ b/pform_types.h @@ -69,9 +69,12 @@ struct decl_assignment_t { * "data_type" rule in the parse rule. We make the type virtual so * that dynamic types will work. */ -struct data_type_t : public LineInfo { +class data_type_t : public LineInfo { + public: virtual ~data_type_t() = 0; - + // This method is used to figure out the base type of a packed + // compound object. Return IVL_VT_NO_TYPE if the type is not packed. + virtual ivl_variable_type_t figure_packed_base_type(void)const; // This method is used by the pform dumper to diagnostic dump. virtual void pform_dump(std::ostream&out, unsigned indent) const; }; @@ -97,10 +100,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; bool packed_flag; std::auto_ptr< list > members; }; -extern ivl_variable_type_t figure_struct_base_type(struct_type_t*struct_type); struct atom2_type_t : public data_type_t { inline explicit atom2_type_t(int tc, bool flag) @@ -132,6 +135,8 @@ struct vector_type_t : public data_type_t { inline explicit vector_type_t(ivl_variable_type_t bt, bool sf, std::list*pd) : base_type(bt), signed_flag(sf), reg_flag(false), implicit_flag(false), pdims(pd) { } + virtual ivl_variable_type_t figure_packed_base_type(void)const; + ivl_variable_type_t base_type; bool signed_flag; bool reg_flag; // True if "reg" was used @@ -141,11 +146,15 @@ struct vector_type_t : public data_type_t { /* * The array_type_t is a generalization of the vector_type_t in that - * the base type is another general data type. + * the base type is another general data type. Ultimately, the subtype + * must also be packed (as this is a packed array) but that may be + * worked out during elaboration. */ -struct array_type_t : public data_type_t { - inline explicit array_type_t(data_type_t*btype, std::list*pd) +struct parray_type_t : public data_type_t { + inline explicit parray_type_t(data_type_t*btype, std::list*pd) : base_type(btype), packed_dims(pd) { } + virtual ivl_variable_type_t figure_packed_base_type(void)const; + data_type_t*base_type; std::auto_ptr< list > packed_dims; };