Handle ranges of slices.

This commit is contained in:
Stephen Williams 2013-02-13 19:50:05 -08:00
parent 48b186576e
commit 69de1da172
2 changed files with 58 additions and 18 deletions

View File

@ -3668,8 +3668,35 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
tmp->set_line(*this);
return tmp;
}
long sb_lsb = net->sig()->sb_to_idx(prefix_indices, lsv);
long sb_msb = net->sig()->sb_to_idx(prefix_indices, msv);
long sb_lsb, sb_msb;
if (prefix_indices.size()+1 < net->sig()->packed_dims().size()) {
// Here we have a slice that doesn't have enough indices
// to get to a single slice. For example:
// wire [9:0][5:1] foo
// ... foo[4:3] ...
// Make this work by finding the indexed slices and
// creating a generated slice that spans the whole
// range.
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
lrc = net->sig()->sb_to_slice(prefix_indices, lsv, loff, lwid);
lrc = net->sig()->sb_to_slice(prefix_indices, msv, moff, mwid);
if (moff > loff) {
sb_lsb = loff;
sb_msb = moff + mwid - 1;
} else {
sb_lsb = moff;
sb_msb = loff + lwid - 1;
}
} else {
// This case, the prefix indices are enough to index
// down to a single bit/slice.
ivl_assert(*this, prefix_indices.size()+1 == net->sig()->packed_dims().size());
sb_lsb = net->sig()->sb_to_idx(prefix_indices, lsv);
sb_msb = net->sig()->sb_to_idx(prefix_indices, msv);
}
if (sb_msb < sb_lsb) {
cerr << get_fileline() << ": error: part select " << net->name();

View File

@ -560,25 +560,38 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
const vector<netrange_t>&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.
long loff, moff;
long wid;
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;
}
// If there are fewer indices then there are packed
// dimensions, then this is a range of slices. Calculate
// it into a big slice.
bool lrc;
unsigned long tmp_lwid, tmp_mwid;
lrc = reg->sb_to_slice(prefix_indices,lsb, loff, tmp_lwid);
lrc = reg->sb_to_slice(prefix_indices,msb, moff, tmp_mwid);
long loff = reg->sb_to_idx(prefix_indices,lsb);
long moff = reg->sb_to_idx(prefix_indices,msb);
long wid = moff - loff + 1;
if (loff < moff) {
moff = moff + tmp_mwid - 1;
} else {
long ltmp = moff;
moff = loff + tmp_lwid - 1;
loff = ltmp;
}
wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return false;
} else {
loff = reg->sb_to_idx(prefix_indices,lsb);
moff = reg->sb_to_idx(prefix_indices,msb);
wid = moff - loff + 1;
if (moff < loff) {
cerr << get_fileline() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return false;
}
}
// Special case: The range winds up selecting the entire