diff --git a/elab_lval.cc b/elab_lval.cc index ce887fff6..cf1aecb8b 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -456,42 +456,47 @@ bool PEIdent::elaborate_lval_net_part_(Design*des, ivl_assert(*this, reg); const list&packed = reg->packed_dims(); - ivl_assert(*this, packed.size() == 1); - const NetNet::range_t&rng = packed.back(); - if (msb == rng.msb && lsb == rng.lsb) { - - /* Part select covers the entire vector. Simplest case. */ - - } else { - - /* Get the canonical offsets into the vector. */ - long loff = reg->sb_to_idx(prefix_indices,lsb); - long moff = reg->sb_to_idx(prefix_indices,msb); - long wid = moff - loff + 1; - - if (moff < loff) { - cerr << get_fileline() << ": error: part select " - << reg->name() << "[" << msb<<":"<errors += 1; - return false; - } - - /* If the part select extends beyond the extremes of the - variable, then report an error. Note that loff is - converted to normalized form so is relative the - variable pins. */ - - if (loff < 0 || moff >= (signed)reg->vector_width()) { - cerr << get_fileline() << ": warning: Part select " - << reg->name() << "[" << msb<<":"<set_part(new NetEConst(verinum(loff)), wid); + // Part selects cannot select slices. So there must be enough + // prefix_indices to get all the way to the final dimension. + if (prefix_indices.size()+1 < packed.size()) { + cerr << get_fileline() << ": error: Cannot select a range " + << "of slices from a packed array." << endl; + des->errors += 1; + return false; } + long loff = reg->sb_to_idx(prefix_indices,lsb); + long moff = reg->sb_to_idx(prefix_indices,msb); + long wid = moff - loff + 1; + + if (moff < loff) { + cerr << get_fileline() << ": error: part select " + << reg->name() << "[" << msb<<":"<errors += 1; + return false; + } + + // Special case: The range winds up selecting the entire + // vector. Treat this as no part select at all. + if (loff == 0 && moff == (reg->vector_width()-1)) { + return true; + } + + /* If the part select extends beyond the extremes of the + variable, then report an error. Note that loff is + converted to normalized form so is relative the + variable pins. */ + + if (loff < 0 || moff >= (signed)reg->vector_width()) { + cerr << get_fileline() << ": warning: Part select " + << reg->name() << "[" << msb<<":"<set_part(new NetEConst(verinum(loff)), wid); + return true; } diff --git a/netlist.cc b/netlist.cc index 922f6f2bb..ef0b6c1a6 100644 --- a/netlist.cc +++ b/netlist.cc @@ -794,12 +794,39 @@ bool NetNet::sb_is_valid(const list&indices, long sb) const long NetNet::sb_to_idx(const list&indices, long sb) const { ivl_assert(*this, indices.size()+1 == packed_dims_.size()); - assert(packed_dims_.size() == 1); - const range_t&rng = packed_dims_.back(); - if (rng.msb >= rng.lsb) - return sb - rng.lsb; + + list::const_iterator pcur = packed_dims_.end(); + -- pcur; + + long acc_off; + long acc_wid = pcur->width(); + if (pcur->msb >= pcur->lsb) + acc_off = sb - pcur->lsb; else - return rng.lsb - sb; + acc_off = pcur->lsb - sb; + + // The acc_off is the possition within the innermost + // dimension. If this is a multi-dimension packed array then + // we need to add in the canonical address of the current slice. + if (indices.size() >= 1) { + list::const_iterator icur = indices.end(); + do { + -- icur; + -- pcur; + + long tmp_off; + if (pcur->msb >= pcur->lsb) + tmp_off = *icur - pcur->lsb; + else + tmp_off = pcur->lsb - *icur; + + acc_off += tmp_off * acc_wid; + acc_wid *= pcur->width(); + + } while (icur != indices.begin()); + } + + return acc_off; } bool NetNet::sb_to_slice(const list&indices, long sb, long&loff, unsigned long&lwid) const diff --git a/netlist.h b/netlist.h index 42f31050e..36f531dac 100644 --- a/netlist.h +++ b/netlist.h @@ -653,7 +653,7 @@ class NetNet : public NetObj { reg/wire/whatever. Note that a canonical index of a multi-dimensioned packed array is a single dimension. For example, "reg [4:1][3:0]..." has the canonical dimension - [15:0] and the sb_to_idx) method will convert [2][2] to + [15:0] and the sb_to_idx() method will convert [2][2] to the canonical index [6]. */ long sb_to_idx(const std::list&prefix, long sb) const; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 24fd5bdb4..3cddd2ab6 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -1288,11 +1288,14 @@ static void show_signal(ivl_signal_t net) for (idx = 0 ; idx < ivl_signal_array_count(net) ; idx += 1) { ivl_nexus_t nex = ivl_signal_nex(net, idx); + unsigned dim; - fprintf(out, " %s %s %s%s[%d:%d] %s[word=%u, adr=%d] " - " ", - type, sign, port, data_type, - ivl_signal_msb(net), ivl_signal_lsb(net), + fprintf(out, " %s %s %s%s", type, sign, port, data_type); + for (dim = 0 ; dim < ivl_signal_packed_dimensions(net) ; dim += 1) { + fprintf(out, "[%d:%d]", ivl_signal_packed_msb(net,dim), + ivl_signal_packed_lsb(net,dim)); + } + fprintf(out, " %s[word=%u, adr=%d] ", ivl_signal_basename(net), idx, ivl_signal_array_base(net)+idx, ivl_signal_width(net), diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 24b0e98dc..edb29b5e7 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -425,8 +425,17 @@ const char*draw_input_from_net(ivl_nexus_t nex) */ static void draw_reg_in_scope(ivl_signal_t sig) { - int msb = ivl_signal_msb(sig); - int lsb = ivl_signal_lsb(sig); + int msb; + int lsb; + if (ivl_signal_packed_dimensions(sig) > 1) { + // FIX ME: Improve this when vvp becomes aware of packed + // arrays. + msb = ivl_signal_width(sig) - 1; + lsb = 0; + } else { + msb = ivl_signal_msb(sig); + lsb = ivl_signal_lsb(sig); + } const char*datatype_flag = ivl_signal_integer(sig) ? "/i" : ivl_signal_signed(sig)? "/s" : "";