diff --git a/Makefile.in b/Makefile.in index 9bcd535f4..a38278bb1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -108,7 +108,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \ net_design.o netdarray.o \ - netenum.o netstruct.o netvector.o net_event.o net_expr.o net_func.o \ + netenum.o netparray.o netstruct.o netvector.o net_event.o net_expr.o net_func.o \ net_func_eval.o net_link.o net_modulo.o \ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \ net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \ diff --git a/design_dump.cc b/design_dump.cc index 1aed8c1ef..993323eb9 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -249,8 +249,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const { o << setw(ind) << "" << type() << ": " << name() << unpacked_dims_ << " unpacked dims=" << unpacked_dimensions(); - if (!packed_dims_.empty()) - o << " packed dims=" << packed_dims_; o << " pin_count=" << pin_count(); if (local_flag_) o << " (local)"; @@ -1107,7 +1105,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const if (result_sig_) { o << setw(ind+2) << "" << "Return signal: "; if (result_sig_->get_signed()) o << "+"; - o << result_sig_->name() << result_sig_->packed_dims() << endl; + o << result_sig_->name() << endl; } o << setw(ind+2) << "" << "Arguments: "; if (port_count() == 0) o << ""; @@ -1129,7 +1127,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const break; } if (port(idx)->get_signed()) o << "+"; - o << port(idx)->name() << port(idx)->packed_dims() << endl; + o << port(idx)->name() << endl; } if (statement_) statement_->dump(o, ind+2); @@ -1548,7 +1546,8 @@ void NetESignal::dump(ostream&o) const o << "+"; o << name(); if (word_) o << "[word=" << *word_ << "]"; - o << sig()->packed_dims(); + vectortmp = net_->net_type()->slice_dimensions(); + o << tmp; } void NetETernary::dump(ostream&o) const diff --git a/elab_expr.cc b/elab_expr.cc index c027cc9c3..3e937cc25 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1481,7 +1481,7 @@ static const netstruct_t::member_t*get_struct_member(const LineInfo*li, perm_string method_name, unsigned long&off) { - netstruct_t*type = net->struct_type(); + const netstruct_t*type = net->struct_type(); ivl_assert(*li, type); if (! type->packed()) { @@ -3555,7 +3555,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope, long lsv = base_c->value().as_long(); long offset = 0; // Get the signal range. - const list&packed = net->sig()->packed_dims(); + const vector&packed = net->sig()->packed_dims(); ivl_assert(*this, packed.size() == prefix_indices.size()+1); // We want the last range, which is where we work. @@ -3784,7 +3784,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, long msv = msc->value().as_long(); - const list& sig_packed = net->sig()->packed_dims(); + const vector& sig_packed = net->sig()->packed_dims(); if (prefix_indices.size()+2 <= sig_packed.size()) { // Special case: this is a slice of a multi-dimensional // packed array. For example: @@ -3877,7 +3877,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, return res; } - const list& sig_packed = net->sig()->packed_dims(); + const vector& sig_packed = net->sig()->packed_dims(); if (prefix_indices.size()+2 <= sig_packed.size()) { // Special case: this is a slice of a multi-dimensional // packed array. For example: diff --git a/elab_lval.cc b/elab_lval.cc index 2db622e9c..d5119e0fc 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -507,7 +507,7 @@ bool PEIdent::elaborate_lval_net_part_(Design*des, NetNet*reg = lv->sig(); ivl_assert(*this, reg); - const list&packed = reg->packed_dims(); + const vector&packed = reg->packed_dims(); // Part selects cannot select slices. So there must be enough // prefix_indices to get all the way to the final dimension. @@ -596,7 +596,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des, long lsv = base_c->value().as_long(); long offset = 0; // Get the signal range. - const list&packed = reg->packed_dims(); + const vector&packed = reg->packed_dims(); ivl_assert(*this, packed.size() == prefix_indices.size()+1); // We want the last range, which is where we work. @@ -680,7 +680,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, NetNet*reg = lv->sig(); ivl_assert(*this, reg); - netstruct_t*struct_type = reg->struct_type(); + const netstruct_t*struct_type = reg->struct_type(); ivl_assert(*this, struct_type); if (debug_elaborate) { diff --git a/elab_net.cc b/elab_net.cc index 465a6de4b..abd98a62e 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -430,11 +430,18 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, remove the member and store it into method_name, and retry the search with "a.b". */ if (sig == 0 && path_.size() >= 2) { + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " + "Symbol not found, try again with path_prefix=" << path_prefix + << " and method_name=" << path_tail.name << endl; + } method_name = path_tail.name; symbol_search(this, des, scope, path_prefix, sig, par, eve); // Whoops, not a struct signal, so give up on this avenue. if (sig && sig->struct_type() == 0) { + cerr << get_fileline() << ": XXXXX: sig=" << sig->name() + << " is found, but not a struct with member " << method_name << endl; method_name = perm_string(); sig = 0; } @@ -474,7 +481,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, list unpacked_indices_const; - netstruct_t*struct_type = 0; + const netstruct_t*struct_type = 0; if ((struct_type = sig->struct_type()) && !method_name.nil()) { // Detect the variable is a structure and there was a diff --git a/elab_sig.cc b/elab_sig.cc index c01323f1c..9cc281518 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -522,7 +522,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const des->errors += 1; } - list packed; + vector packed; packed.push_back(netrange_t(mnum, lnum)); ret_vec = new netvector_t(packed, IVL_VT_LOGIC); ret_vec->set_signed(return_type_.type == PTF_REG_S); @@ -823,7 +823,7 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const } static bool evaluate_ranges(Design*des, NetScope*scope, - list&llist, + vector&llist, const list&rlist) { bool bad_msb = false, bad_lsb = false; @@ -874,7 +874,7 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope, for (list::iterator cur = struct_type->members->begin() ; cur != struct_type->members->end() ; ++ cur) { - listpacked_dimensions; + vectorpacked_dimensions; struct_member_t*curp = *cur; if (curp->range.get() && ! curp->range->empty()) { @@ -900,20 +900,6 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope, return res; } -static netparray_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); - - netparray_t*res = new netparray_t(packed_dimensions); - //res->set_line(*data_type); - - return res; -} - static ivl_type_s*elaborate_type(Design*des, NetScope*scope, data_type_t*pform_type) { @@ -929,13 +915,29 @@ static ivl_type_s*elaborate_type(Design*des, NetScope*scope, return 0; } -bool test_ranges_eeq(const list&lef, const list&rig) +static netparray_t* elaborate_parray_type(Design*des, NetScope*scope, + parray_type_t*data_type) +{ + + vectorpacked_dimensions; + bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims); + ivl_assert(*data_type, !bad_range); + + ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type); + + netparray_t*res = new netparray_t(packed_dimensions, element_type); + //res->set_line(*data_type); + + return res; +} + +bool test_ranges_eeq(const vector&lef, const vector&rig) { if (lef.size() != rig.size()) return false; - list::const_iterator lcur = lef.begin(); - list::const_iterator rcur = rig.begin(); + vector::const_iterator lcur = lef.begin(); + vector::const_iterator rcur = rig.begin(); while (lcur != lef.end()) { if (lcur->get_msb() != rcur->get_msb()) return false; @@ -970,7 +972,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const } unsigned wid = 1; - listpacked_dimensions; + vectorpacked_dimensions; des->errors += error_cnt_; @@ -1011,7 +1013,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const if (port_set_ || net_set_) { bool bad_range = false; - list plist, nlist; + vector plist, nlist; /* If they exist get the port definition MSB and LSB */ if (port_set_ && !port_.empty()) { bad_range |= evaluate_ranges(des, scope, plist, port_); @@ -1222,7 +1224,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const << " and packed_width=" << use_enum->packed_width() << endl; } - sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, use_enum); + ivl_assert(*this, packed_dimensions.empty()); + sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum); } else if (netarray) { @@ -1256,14 +1259,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const << " in scope " << scope_path(scope) << endl; } - ivl_type_s*base_type = elaborate_type(des, scope, parray_type->base_type); -#if 0 - cerr << get_fileline() << ": sorry: Packed array of " - << typeid(*parray_type->base_type).name() - << " not supported." << endl; - des->errors += 1; -#endif - sig = new NetNet(scope, name_, wtype, use_type->packed_dimensions(), unpacked_dimensions, base_type); + sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type); } else { @@ -1293,7 +1289,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const if (is_implicit_scalar) vec->set_scalar(true); else vec->set_scalar(get_scalar()); packed_dimensions.clear(); - sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, vec); + sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec); } diff --git a/elaborate.cc b/elaborate.cc index 611951452..770193866 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -998,8 +998,9 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope, ivl_assert(*this, dir != NetNet::NOT_A_PORT); ivl_assert(*this, dir != NetNet::PIMPLICIT); + netvector_t*tmp_type = new netvector_t(IVL_VT_LOGIC, port_wid-1, 0); NetNet*tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, port_wid); + NetNet::WIRE, tmp_type); tmp->local_flag(true); tmp->set_line(*this); @@ -1417,6 +1418,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const << "too complicated for elaboration." << endl; continue; } + + if (debug_elaborate) { + cerr << get_fileline() << ": debug: " + << "Elaborating INPUT port expression: " << *tmp_expr << endl; + } + sig = tmp_expr->synthesize(des, scope, tmp_expr); if (sig == 0) { cerr << pins[idx]->get_fileline() diff --git a/netenum.cc b/netenum.cc index 689a47418..614a9618a 100644 --- a/netenum.cc +++ b/netenum.cc @@ -21,6 +21,8 @@ # include "compiler.h" # include +using namespace std; + netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag, long msb, long lsb, size_t name_count) : base_type_(btype), signed_flag_(signed_flag), msb_(msb), lsb_(lsb), @@ -45,6 +47,14 @@ long netenum_t::packed_width() const return lsb_ - msb_ + 1; } +vector netenum_t::slice_dimensions() const +{ + vector tmp (1); + tmp[0] = netrange_t(msb_, lsb_); + return tmp; +} + + bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val) { std::pair::iterator, bool> res; diff --git a/netenum.h b/netenum.h index a0f3b5373..80704bd0c 100644 --- a/netenum.h +++ b/netenum.h @@ -38,6 +38,7 @@ class netenum_t : public LineInfo, public ivl_type_s { ivl_variable_type_t base_type() const; long packed_width() const; + std::vector slice_dimensions() const; bool get_signed() const; // The size() is the number of enumeration literals. diff --git a/netlist.cc b/netlist.cc index a51fb9c37..bdf9fe5c8 100644 --- a/netlist.cc +++ b/netlist.cc @@ -29,6 +29,7 @@ # include "netmisc.h" # include "netdarray.h" # include "netenum.h" +# include "netparray.h" # include "netstruct.h" # include "netvector.h" # include "ivl_assert.h" @@ -464,44 +465,6 @@ PortType::Enum PortType::merged( Enum lhs, Enum rhs ) return PINOUT; } -NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) -: NetObj(s, n, 1), - type_(t), port_type_(NOT_A_PORT), - local_flag_(false), - net_type_(0), discipline_(0), - eref_count_(0), lref_count_(0), - port_index_(-1) -{ - assert(s); - assert(npins>0); - - // Synthesize a single range to describe this canonical vector. - packed_dims_.push_back(netrange_t(npins-1, 0)); - calculate_slice_widths_from_packed_dims_(); - - Link::DIR dir = Link::PASSIVE; - - switch (t) { - case REG: - case INTEGER: - case IMPLICIT_REG: - dir = Link::OUTPUT; - break; - case SUPPLY0: - dir = Link::OUTPUT; - break; - case SUPPLY1: - dir = Link::OUTPUT; - break; - default: - break; - } - - pin(0).set_dir(dir); - - s->add_signal(this); -} - void NetNet::initialize_dir_(Link::DIR dir) { if (pins_are_virtual()) { @@ -544,47 +507,35 @@ template static unsigned calculate_count(T*type) void NetNet::calculate_slice_widths_from_packed_dims_(void) { - netvector_t*vec = dynamic_cast (net_type_); - ivl_assert(*this, vec==0 || packed_dims_.empty()); + ivl_assert(*this, net_type_); + slice_dims_ = net_type_->slice_dimensions(); - const std::list&use_packed = vec? vec->packed_dims() : packed_dims_; - if (use_packed.empty()) { - slice_wids_.clear(); + // Special case: There are no actual packed dimensions, so + // build up a fake dimension of "1". + if (slice_dims_.size() == 0) { + slice_wids_.resize(1); + slice_wids_[0] = net_type_->packed_width(); return; } - slice_wids_.resize(use_packed.size()); + slice_wids_.resize(slice_dims_.size()); - slice_wids_[0] = netrange_width(use_packed); - list::const_iterator cur = use_packed.begin(); + ivl_assert(*this, slice_wids_.size() >= 1); + slice_wids_[0] = netrange_width(slice_dims_); + vector::const_iterator cur = slice_dims_.begin(); for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) { slice_wids_[idx] = slice_wids_[idx-1] / cur->width(); } - } NetNet::NetNet(NetScope*s, perm_string n, Type t, - const list&packed, - const list&unpacked, - ivl_type_s*use_net_type) + const list&unpacked, ivl_type_s*use_net_type) : NetObj(s, n, calculate_count(unpacked)), type_(t), port_type_(NOT_A_PORT), local_flag_(false), net_type_(use_net_type), discipline_(0), unpacked_dims_(unpacked.size()), eref_count_(0), lref_count_(0) { - packed_dims_ = packed; - // Special case: This is an enum, so it is its own packed vector. - if (netenum_t*et = dynamic_cast(use_net_type)) { - ivl_assert(*this, packed_dims_.empty()); - packed_dims_.push_back(netrange_t(calculate_count(et)-1, 0)); - } - // Special case: netstruct types are like another packed - // dimension. - if (netstruct_t*st = dynamic_cast(use_net_type)) { - packed_dims_.push_back(netrange_t(calculate_count(st)-1, 0)); - } - calculate_slice_widths_from_packed_dims_(); size_t idx = 0; for (list::const_iterator cur = unpacked.begin() @@ -633,7 +584,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty) discipline_(0), eref_count_(0), lref_count_(0) { - packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0)); + //XXXX packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0)); calculate_slice_widths_from_packed_dims_(); Link::DIR dir = Link::PASSIVE; @@ -792,16 +743,6 @@ void NetNet::set_module_port_index(unsigned idx) assert( port_index_ >= 0 ); } -const std::list& NetNet::packed_dims() const -{ - if (netvector_t*vec = dynamic_cast (net_type_)) { - ivl_assert(*this, packed_dims_.empty()); - return vec->packed_dims(); - } - - return packed_dims_; -} - ivl_variable_type_t NetNet::data_type() const { if (net_type_==0) @@ -839,9 +780,26 @@ netenum_t*NetNet::enumeration(void) const return dynamic_cast (net_type_); } -netstruct_t*NetNet::struct_type(void) const +const netstruct_t*NetNet::struct_type(void) const { - return dynamic_cast (net_type_); + const ivl_type_s*cur_type = net_type_; + while (cur_type) { + if (const netdarray_t*da = dynamic_cast (cur_type)) { + cur_type = da->element_type(); + continue; + } + if (const netparray_t*da = dynamic_cast (cur_type)) { + cur_type = da->element_type(); + continue; + } + if (const netstruct_t*st = dynamic_cast (cur_type)) + return st; + else + return 0; + } + + assert(0); + return 0; } netdarray_t* NetNet::darray_type(void) const @@ -894,7 +852,7 @@ long NetNet::sb_to_idx(const list&indices, long sb) const { ivl_assert(*this, indices.size()+1 == packed_dims().size()); - list::const_iterator pcur = packed_dims().end(); + vector::const_iterator pcur = packed_dims().end(); -- pcur; long acc_off; @@ -2486,14 +2444,14 @@ NetNet* NetESignal::sig() */ long NetESignal::lsi() const { - const list&packed = net_->packed_dims(); + const vector&packed = net_->packed_dims(); ivl_assert(*this, packed.size() == 1); return packed.back().get_lsb(); } long NetESignal::msi() const { - const list&packed = net_->packed_dims(); + const vector&packed = net_->packed_dims(); ivl_assert(*this, packed.size() == 1); return packed.back().get_msb(); } diff --git a/netlist.h b/netlist.h index a8897fe3e..0728a228a 100644 --- a/netlist.h +++ b/netlist.h @@ -597,21 +597,15 @@ class NetNet : public NetObj, public PortType { typedef PortType::Enum PortType; public: - // The width in this case is a shorthand for ms=width-1 and - // ls=0. Only one pin is created, the width is of the vector - // that passed through. - explicit NetNet(NetScope*s, perm_string n, Type t, unsigned width =1); - - // This form supports an array of vectors. The [ms:ls] define - // the base vector, and the [s0:e0] define the array - // dimensions. If s0==e0, then this is not an array after - // all. + // This form is the more generic form of the constructor. For + // now, the unpacked type is not burried into an ivl_type_s object. explicit NetNet(NetScope*s, perm_string n, Type t, - const std::list&packed, const std::list&unpacked, ivl_type_s*type =0); - // This form builds a NetNet from its record/enum definition. + // This form builds a NetNet from its record/enum/darray + // definition. They should probably be replaced with a single + // version that takes an ivl_type_s* base. explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type); explicit NetNet(NetScope*s, perm_string n, Type t, netdarray_t*type); explicit NetNet(NetScope*s, perm_string n, Type t, netvector_t*type); @@ -643,7 +637,7 @@ class NetNet : public NetObj, public PortType { inline const ivl_type_s* net_type(void) const { return net_type_; } netenum_t*enumeration(void) const; - netstruct_t*struct_type(void) const; + const netstruct_t*struct_type(void) const; netdarray_t*darray_type(void) const; /* Attach a discipline to the net. */ @@ -653,8 +647,9 @@ class NetNet : public NetObj, public PortType { /* This method returns a reference to the packed dimensions for the vector. These are arranged as a list where the first range in the list (front) is the left-most range in - the verilog declaration. */ - const std::list& packed_dims() const; + the verilog declaration. These packed dims are compressed + to represent the dimensions of all the subtypes. */ + const std::vector& packed_dims() const { return slice_dims_; } const std::vector& unpacked_dims() const { return unpacked_dims_; } @@ -694,7 +689,7 @@ class NetNet : public NetObj, public PortType { /* This methor returns 0 for scalars, but vectors and other PACKED arrays have packed dimensions. */ - inline size_t packed_dimensions() const { return packed_dims_.size(); } + inline size_t packed_dimensions() const { return slice_dims_.size(); } // This is the number of array elements. unsigned unpacked_count() const; @@ -733,7 +728,6 @@ class NetNet : public NetObj, public PortType { ivl_type_s*net_type_; ivl_discipline_t discipline_; - std::list packed_dims_; std::vector unpacked_dims_; // These are the widths of the various slice depths. There is @@ -742,6 +736,7 @@ class NetNet : public NetObj, public PortType { // // For example: slice_wids_[0] is vector_width(). void calculate_slice_widths_from_packed_dims_(void); + std::vector slice_dims_; std::vector slice_wids_; unsigned eref_count_; @@ -756,7 +751,6 @@ class NetNet : public NetObj, public PortType { int port_index_; }; -extern std::ostream&operator << (std::ostream&out, const std::list&rlist); /* * This object type is used to contain a logical scope within a diff --git a/netmisc.cc b/netmisc.cc index b63fb445a..ee85a9104 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -353,7 +353,7 @@ NetExpr *normalize_variable_base(NetExpr *base, NetExpr *normalize_variable_bit_base(const list&indices, NetExpr*base, const NetNet*reg) { - const list&packed_dims = reg->packed_dims(); + const vector&packed_dims = reg->packed_dims(); ivl_assert(*base, indices.size()+1 == packed_dims.size()); // Get the canonical offset of the slice within which we are @@ -369,7 +369,7 @@ NetExpr *normalize_variable_part_base(const list&indices, NetExpr*base, const NetNet*reg, unsigned long wid, bool is_up) { - const list&packed_dims = reg->packed_dims(); + const vector&packed_dims = reg->packed_dims(); ivl_assert(*base, indices.size()+1 == packed_dims.size()); // Get the canonical offset of the slice within which we are @@ -384,10 +384,10 @@ NetExpr *normalize_variable_part_base(const list&indices, NetExpr*base, NetExpr *normalize_variable_slice_base(const list&indices, NetExpr*base, const NetNet*reg, unsigned long&lwid) { - const list&packed_dims = reg->packed_dims(); + const vector&packed_dims = reg->packed_dims(); ivl_assert(*base, indices.size() < packed_dims.size()); - list::const_iterator pcur = packed_dims.end(); + vector::const_iterator pcur = packed_dims.end(); for (size_t idx = indices.size() ; idx < packed_dims.size(); idx += 1) { -- pcur; } @@ -1182,8 +1182,8 @@ NetExpr*collapse_array_exprs(Design*des, NetScope*scope, return *exprs.begin(); } - const std::list&pdims = net->packed_dims(); - std::list::const_iterator pcur = pdims.begin(); + const std::vector&pdims = net->packed_dims(); + std::vector::const_iterator pcur = pdims.begin(); list::iterator ecur = exprs.begin(); NetExpr* base = 0; diff --git a/netparray.cc b/netparray.cc new file mode 100644 index 000000000..31f1274b7 --- /dev/null +++ b/netparray.cc @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012 Picture Elements, Inc. + * 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 "netparray.h" + +using namespace std; + +/* + * The packed width of a packed array is the packed width of the + * element times the dimension width of the array itself. + */ +long netparray_t::packed_width(void) const +{ + long cur_width = element_type_->packed_width(); + + for (vector::const_iterator cur = packed_dims_.begin() + ; cur != packed_dims_.end() ; ++cur) { + cur_width *= cur->width(); + } + + return cur_width; +} + +vector netparray_t::slice_dimensions() const +{ + vector elem_dims = element_type_->slice_dimensions(); + + vector res (packed_dims_.size() + elem_dims.size()); + + for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1) + res[idx] = packed_dims_[0]; + for (size_t idx = 0 ; idx < elem_dims.size() ; idx += 1) + res[idx+packed_dims_.size()] = elem_dims[idx]; + + return res; +} + +ivl_variable_type_t netparray_t::base_type() const +{ + return element_type_->base_type(); +} diff --git a/netparray.h b/netparray.h index ca3f10cfa..325437645 100644 --- a/netparray.h +++ b/netparray.h @@ -20,29 +20,40 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -# include "LineInfo.h" # include "nettypes.h" # include /* * Packed arrays. */ -class netparray_t : public ivl_type_s, public LineInfo { +class netparray_t : public ivl_type_s { public: - explicit netparray_t(const std::list&packed); + explicit netparray_t(const std::vector&packed, + ivl_type_t etype); ~netparray_t(); - inline const std::list& packed_dimensions() const + public: + // Virtual methods from the ivl_type_s type... + long packed_width(void) const; + std::vector slice_dimensions() const; + ivl_variable_type_t base_type() const; + + public: + inline const ivl_type_s* element_type() const { return element_type_; } + + inline const std::vector& packed_dimensions() const { return packed_dims_; } private: - std::list packed_dims_; + std::vector packed_dims_; + ivl_type_t element_type_; }; -inline netparray_t::netparray_t(const std::list&packed) -: packed_dims_(packed) +inline netparray_t::netparray_t(const std::vector&packed, + ivl_type_t etype) +: packed_dims_(packed), element_type_(etype) { } diff --git a/netstruct.cc b/netstruct.cc index 0f6982a78..b4c372599 100644 --- a/netstruct.cc +++ b/netstruct.cc @@ -67,6 +67,13 @@ long netstruct_t::packed_width(void) const return res; } +vector netstruct_t::slice_dimensions() const +{ + vector tmp; + tmp .push_back(netrange_t(packed_width()-1, 0)); + return tmp; +} + ivl_variable_type_t netstruct_t::base_type() const { if (! packed_) diff --git a/netstruct.h b/netstruct.h index 592fff8cf..9d971961e 100644 --- a/netstruct.h +++ b/netstruct.h @@ -20,7 +20,7 @@ */ # include "LineInfo.h" -# include +# include # include "ivl_target.h" # include "nettypes.h" @@ -30,7 +30,7 @@ class netstruct_t : public LineInfo, public ivl_type_s { struct member_t { perm_string name; ivl_variable_type_t type; - list packed_dims; + std::vector packed_dims; long width() const; ivl_variable_type_t data_type() const { return type; }; // We need to keep the individual element sign information. @@ -54,6 +54,7 @@ class netstruct_t : public LineInfo, public ivl_type_s { // Return the width (in bits) of the packed record, or -1 if // the record is not packed. long packed_width() const; + std::vector slice_dimensions() const; // Return the base type of the packed record, or // IVL_VT_NO_TYPE if the record is not packed. diff --git a/nettypes.cc b/nettypes.cc index 46e49db5a..215e5e3f1 100644 --- a/nettypes.cc +++ b/nettypes.cc @@ -31,6 +31,11 @@ long ivl_type_s::packed_width(void) const return 1; } +vector ivl_type_s::slice_dimensions() const +{ + return vector(); +} + ivl_variable_type_t ivl_type_s::base_type() const { return IVL_VT_NO_TYPE; @@ -41,10 +46,10 @@ bool ivl_type_s::get_signed() const return false; } -unsigned long netrange_width(const list&packed) +unsigned long netrange_width(const vector&packed) { unsigned wid = 1; - for (list::const_iterator cur = packed.begin() + for (vector::const_iterator cur = packed.begin() ; cur != packed.end() ; ++cur) { unsigned use_wid = cur->width(); wid *= use_wid; @@ -59,14 +64,14 @@ unsigned long netrange_width(const list&packed) * and width of the resulting slice. In this case, the "sb" argument * is an extra index of the prefix. */ -bool prefix_to_slice(const std::list&dims, +bool prefix_to_slice(const std::vector&dims, const std::list&prefix, long sb, long&loff, unsigned long&lwid) { assert(prefix.size() < dims.size()); size_t acc_wid = 1; - list::const_iterator pcur = dims.end(); + vector::const_iterator pcur = dims.end(); for (size_t idx = prefix.size()+1 ; idx < dims.size() ; idx += 1) { -- pcur; acc_wid *= pcur->width(); diff --git a/nettypes.h b/nettypes.h index cbf759e48..983425e48 100644 --- a/nettypes.h +++ b/nettypes.h @@ -20,10 +20,13 @@ */ # include "ivl_target.h" -# include -# include -# include -# include +# include +# include +# include +# include +# include + +class netrange_t; /* * This is a fully abstract type that is a type that can be attached @@ -33,6 +36,7 @@ class ivl_type_s { public: virtual ~ivl_type_s() =0; virtual long packed_width(void) const; + virtual std::vector slice_dimensions() const; // Some types have a base variable type. virtual ivl_variable_type_t base_type() const; @@ -78,14 +82,17 @@ class netrange_t { long lsb_; }; -extern unsigned long netrange_width(const std::list&dims); +extern std::ostream&operator << (std::ostream&out, const std::list&rlist); +extern std::ostream&operator << (std::ostream&out, const std::vector&rlist); + +extern unsigned long netrange_width(const std::vector&dims); /* * Take as input a list of packed dimensions and a list of prefix * indices, and calculate the offset/width of the resulting slice into * the packed array. */ -extern bool prefix_to_slice(const std::list&dims, +extern bool prefix_to_slice(const std::vector&dims, const std::list&prefix, long sb, long&loff, unsigned long&lwid); diff --git a/netvector.cc b/netvector.cc index 259ba532f..859b76110 100644 --- a/netvector.cc +++ b/netvector.cc @@ -19,6 +19,8 @@ # include "netvector.h" +using namespace std; + netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb) : type_(type), signed_(false) { @@ -43,3 +45,8 @@ long netvector_t::packed_width() const { return netrange_width(packed_dims_); } + +vector netvector_t::slice_dimensions() const +{ + return packed_dims_; +} diff --git a/netvector.h b/netvector.h index ede35cee4..770ac22d8 100644 --- a/netvector.h +++ b/netvector.h @@ -26,6 +26,12 @@ class netvector_t : public ivl_type_s { public: + explicit netvector_t(const std::vector&packed, + ivl_variable_type_t type); + + // This is a variant of the vector form. Some code processes + // the list of packed ranges as a list, but we will store them + // as a vector in this constructor. explicit netvector_t(const std::list&packed, ivl_variable_type_t type); @@ -51,27 +57,28 @@ class netvector_t : public ivl_type_s { inline bool get_scalar(void) const { return is_scalar_; } ivl_variable_type_t base_type() const; - const std::list&packed_dims() const; + const std::vector&packed_dims() const; long packed_width() const; + std::vector slice_dimensions() const; std::ostream& debug_dump(std::ostream&) const; private: - std::list packed_dims_; + std::vector packed_dims_; ivl_variable_type_t type_; bool signed_ : 1; bool isint_ : 1; // original type of integer bool is_scalar_ : 1; }; -inline netvector_t::netvector_t(const std::list&packed, +inline netvector_t::netvector_t(const std::vector&packed, ivl_variable_type_t type) : packed_dims_(packed), type_(type), signed_(false) { } -inline const std::list& netvector_t::packed_dims() const +inline const std::vector& netvector_t::packed_dims() const { return packed_dims_; } diff --git a/t-dll.cc b/t-dll.cc index 4a4a7cc23..8b620a5e7 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -2374,7 +2374,7 @@ void dll_target::signal(const NetNet*net) ivl_signal_t object. */ { size_t idx = 0; - list::const_iterator cur; + vector::const_iterator cur; obj->packed_dims.resize(net->packed_dims().size()); for (cur = net->packed_dims().begin(), idx = 0 ; cur != net->packed_dims().end() ; ++cur, idx += 1) {