Fix some bugs with packed array dimensions.
The netparray_t::slice_dimensions bug was the most insidious and caused all manner of confusion. Also fix some other packed array and unpacked array (and mixed) indexing calculations.
This commit is contained in:
parent
df4889ba3d
commit
40b36337e2
50
elab_expr.cc
50
elab_expr.cc
|
|
@ -2832,6 +2832,9 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
}
|
||||
// If we have a net in hand, then we can predict what
|
||||
// the slice width will be. If not, then just guess.
|
||||
if (net == 0)
|
||||
use_width = 1;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -2864,15 +2867,35 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
|||
|
||||
// The width of a signal expression is the width of the signal.
|
||||
if (net != 0) {
|
||||
size_t use_depth = name_tail.index.size();
|
||||
// Account for unpacked dimensions by assuming that the
|
||||
// unpacked dimensions are consumed first, so subtract
|
||||
// the unpacked dimensions from the dimension depth
|
||||
// useable for making the slice.
|
||||
if (use_depth >= net->unpacked_dimensions()) {
|
||||
use_depth -= net->unpacked_dimensions();
|
||||
|
||||
} else {
|
||||
// In this case, we have a slice of an unpacked
|
||||
// array. This likely handled as an array instead
|
||||
// of a slice. Hmm...
|
||||
use_depth = 0;
|
||||
}
|
||||
|
||||
expr_type_ = net->data_type();
|
||||
expr_width_ = net->vector_width();
|
||||
expr_width_ = net->slice_width(use_depth);
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = net->get_signed();
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::test_width: "
|
||||
<< net->name() << " is a net, "
|
||||
<< "type=" << expr_type_
|
||||
<< ", width=" << expr_width_ << endl;
|
||||
<< ", width=" << expr_width_
|
||||
<< ", signed_=" << (signed_flag_?"true":"false")
|
||||
<< ", use_depth=" << use_depth
|
||||
<< ", packed_dimensions=" << net->packed_dimensions()
|
||||
<< ", unpacked_dimensions=" << net->unpacked_dimensions()
|
||||
<< endl;
|
||||
}
|
||||
return expr_width_;
|
||||
}
|
||||
|
|
@ -3228,6 +3251,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
if (!tmp) return 0;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr: "
|
||||
<< "Expression as net. expr_wid=" << expr_wid
|
||||
<< ", tmp->expr_width()=" << tmp->expr_width()
|
||||
<< ", tmp=" << *tmp << endl;
|
||||
}
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
|
|
@ -4445,6 +4475,15 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
// making a mux part in the netlist.
|
||||
if (NetEConst*msc = dynamic_cast<NetEConst*> (mux)) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: "
|
||||
<< "mux is constant=" << *msc
|
||||
<< ", packed_dims()=" << net->sig()->packed_dims()
|
||||
<< ", packed_dims().size()=" << net->sig()->packed_dims().size()
|
||||
<< ", prefix_indices.size()=" << prefix_indices.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Special case: The bit select expression is constant
|
||||
// x/z. The result of the expression is 1'bx.
|
||||
if (! msc->value().is_defined()) {
|
||||
|
|
@ -4462,6 +4501,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
<< endl;
|
||||
}
|
||||
|
||||
// FIXME: Should I be using slice_width() here?
|
||||
NetEConst*tmp = make_const_x(1);
|
||||
tmp->set_line(*this);
|
||||
delete mux;
|
||||
|
|
@ -4553,6 +4593,12 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
if (net->vector_width() == 1)
|
||||
return net;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: "
|
||||
<< "Make bit select idx=" << idx
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Make an expression out of the index
|
||||
NetEConst*idx_c = new NetEConst(verinum(idx));
|
||||
idx_c->set_line(*net);
|
||||
|
|
|
|||
17
elab_net.cc
17
elab_net.cc
|
|
@ -708,6 +708,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
} else if (!path_tail.index.empty()) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
|
||||
<< "path_tail.index.size()=" << path_tail.index.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// There are index expressions on the name, so this is a
|
||||
// bit/slice select of the name. Calculate a canonical
|
||||
// part select.
|
||||
|
||||
if (sig->get_scalar()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "can not select part of ";
|
||||
|
|
@ -739,6 +749,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx, widx_flag? widx : 0)) {
|
||||
cerr << get_fileline() << ": error: Unresolved net/uwire "
|
||||
<< sig->name() << " cannot have multiple drivers." << endl;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": : Overlap in "
|
||||
<< "[" << midx << ":" << lidx << "] (canonical)"
|
||||
<< ", widx=" << (widx_flag? widx : 0)
|
||||
<< ", vector width=" << sig->vector_width()
|
||||
<< endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -762,6 +762,9 @@ const netclass_t* NetNet::class_type(void) const
|
|||
* In this case, slice_width(2) == 1 (slice_width(N) where N is the
|
||||
* number of dimensions will always be 1.) and represents
|
||||
* $bits(foo[a][b]). Then, slice_width(1)==4 ($bits(foo[a]) and slice_width(0)==24.
|
||||
*
|
||||
* NOTE: The caller should already have accounted for unpacked
|
||||
* dimensions. The "depth" is only for the packed dimensions.
|
||||
*/
|
||||
unsigned long NetNet::slice_width(size_t depth) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ vector<netrange_t> netparray_t::slice_dimensions() const
|
|||
vector<netrange_t> res (packed_dims_.size() + elem_dims.size());
|
||||
|
||||
for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1)
|
||||
res[idx] = packed_dims_[0];
|
||||
res[idx] = packed_dims_[idx];
|
||||
for (size_t idx = 0 ; idx < elem_dims.size() ; idx += 1)
|
||||
res[idx+packed_dims_.size()] = elem_dims[idx];
|
||||
|
||||
|
|
|
|||
24
nettypes.cc
24
nettypes.cc
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "nettypes.h"
|
||||
# include <iostream>
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -101,6 +102,12 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
|
|||
{
|
||||
assert(prefix.size() < dims.size());
|
||||
|
||||
// Figure out the width of the slice, given the number of
|
||||
// prefix numbers there are. We don't need to look at the
|
||||
// actual values yet, but we do need to know how many there
|
||||
// are compared to the actual dimensions of the target. So do
|
||||
// this by multiplying the widths of the dims that are NOT
|
||||
// accounted for by the prefix or sb indices.
|
||||
size_t acc_wid = 1;
|
||||
vector<netrange_t>::const_iterator pcur = dims.end();
|
||||
for (size_t idx = prefix.size()+1 ; idx < dims.size() ; idx += 1) {
|
||||
|
|
@ -108,8 +115,12 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
|
|||
acc_wid *= pcur->width();
|
||||
}
|
||||
|
||||
lwid = acc_wid;
|
||||
lwid = acc_wid; // lwid is now the final slice width.
|
||||
|
||||
// pcur is pointing to the dimension AFTER the dimension that
|
||||
// we have an index for, so step back one, then this will be
|
||||
// used with the sb index. Start accumulating in the acc_off
|
||||
// the offset into the n-dimensional vector.
|
||||
-- pcur;
|
||||
if (sb < pcur->get_msb() && sb < pcur->get_lsb())
|
||||
return false;
|
||||
|
|
@ -122,16 +133,18 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
|
|||
else
|
||||
acc_off += (pcur->get_lsb() - sb) * acc_wid;
|
||||
|
||||
// If there are no more prefix items, we are done.
|
||||
if (prefix.empty()) {
|
||||
loff = acc_off;
|
||||
return true;
|
||||
}
|
||||
|
||||
lwid *= pcur->width();
|
||||
|
||||
// Now similarly go through the prefix numbers, working
|
||||
// through the dimensions until we run out. Accumulate a
|
||||
// growing slice width (acc_wid) that is used to caculate the
|
||||
// growing offset (acc_off).
|
||||
list<long>::const_iterator icur = prefix.end();
|
||||
do {
|
||||
-- pcur;
|
||||
-- icur;
|
||||
acc_wid *= pcur->width();
|
||||
if (pcur->get_msb() >= pcur->get_lsb())
|
||||
|
|
@ -139,8 +152,11 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
|
|||
else
|
||||
acc_off += (pcur->get_lsb() - *icur) * acc_wid;
|
||||
|
||||
-- pcur;
|
||||
|
||||
} while (icur != prefix.begin());
|
||||
|
||||
// Got our final offset.
|
||||
loff = acc_off;
|
||||
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue