Properly report errors for out-of-bounds constant indexed part selects.

(replacing assertions)

The IEEE standard either requires out-of-bounds bits to be ignored on
write, returned as 1'bx on read, or requires a compile-time error message.
The latter is easier to implement.
This commit is contained in:
Martin Whitaker 2021-04-20 22:58:40 +01:00
parent 4af830187e
commit 7d7aa0604c
3 changed files with 105 additions and 33 deletions

View File

@ -5725,11 +5725,19 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
// range.
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
bool lrc, mrc;
lrc = net->sig()->sb_to_slice(prefix_indices, lsv, loff, lwid);
ivl_assert(*this, lrc);
lrc = net->sig()->sb_to_slice(prefix_indices, msv, moff, mwid);
ivl_assert(*this, lrc);
mrc = net->sig()->sb_to_slice(prefix_indices, msv, moff, mwid);
if (!mrc || !lrc) {
cerr << get_fileline() << ": error: ";
cerr << "Part-select [" << msv << ":" << lsv;
cerr << "] exceeds the declared bounds for ";
cerr << net->sig()->name();
if (net->sig()->unpacked_dimensions() > 0) cerr << "[]";
cerr << "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, lwid == mwid);
if (moff > loff) {
@ -5842,14 +5850,25 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
// Here we are selecting one or more sub-arrays.
// Make this work by finding the indexed sub-arrays and
// creating a generated slice that spans the whole range.
unsigned long swid = net->sig()->slice_width(prefix_indices.size()+1);
ivl_assert(*this, swid > 0);
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
lrc = net->sig()->sb_to_slice(prefix_indices, lsv, moff, mwid);
ivl_assert(*this, lrc);
lrc = net->sig()->sb_to_slice(prefix_indices, lsv+(wid/mwid)-1, loff, lwid);
ivl_assert(*this, lrc);
ivl_assert(*this, lwid == mwid);
bool lrc, mrc;
mrc = net->sig()->sb_to_slice(prefix_indices, lsv, moff, mwid);
lrc = net->sig()->sb_to_slice(prefix_indices, lsv+(wid/swid)-1, loff, lwid);
if (!mrc || !lrc) {
cerr << get_fileline() << ": error: ";
cerr << "Part-select [" << lsv << "+:" << (wid/swid);
cerr << "] exceeds the declared bounds for ";
cerr << net->sig()->name();
if (net->sig()->unpacked_dimensions() > 0) cerr << "[]";
cerr << "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, mwid == swid);
ivl_assert(*this, lwid == swid);
if (moff > loff) {
rel_base = loff;
@ -5963,14 +5982,25 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
// Here we are selecting one or more sub-arrays.
// Make this work by finding the indexed sub-arrays and
// creating a generated slice that spans the whole range.
unsigned long swid = net->sig()->slice_width(prefix_indices.size()+1);
ivl_assert(*this, swid > 0);
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
lrc = net->sig()->sb_to_slice(prefix_indices, lsv, moff, mwid);
ivl_assert(*this, lrc);
lrc = net->sig()->sb_to_slice(prefix_indices, lsv-(wid/mwid)+1, loff, lwid);
ivl_assert(*this, lrc);
ivl_assert(*this, lwid == mwid);
bool lrc, mrc;
mrc = net->sig()->sb_to_slice(prefix_indices, lsv, moff, mwid);
lrc = net->sig()->sb_to_slice(prefix_indices, lsv-(wid/swid)+1, loff, lwid);
if (!mrc || !lrc) {
cerr << get_fileline() << ": error: ";
cerr << "Part-select [" << lsv << "-:" << (wid/swid);
cerr << "] exceeds the declared bounds for ";
cerr << net->sig()->name();
if (net->sig()->unpacked_dimensions() > 0) cerr << "[]";
cerr << "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, mwid == swid);
ivl_assert(*this, lwid == swid);
if (moff > loff) {
rel_base = loff;

View File

@ -863,12 +863,20 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
// 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;
bool lrc, mrc;
unsigned long tmp_lwid, tmp_mwid;
lrc = reg->sb_to_slice(prefix_indices, lsb, loff, tmp_lwid);
ivl_assert(*this, lrc);
lrc = reg->sb_to_slice(prefix_indices,msb, moff, tmp_mwid);
ivl_assert(*this, lrc);
mrc = reg->sb_to_slice(prefix_indices, msb, moff, tmp_mwid);
if (!mrc || !lrc) {
cerr << get_fileline() << ": error: ";
cerr << "Part-select [" << msb << ":" << lsb;
cerr << "] exceeds the declared bounds for ";
cerr << reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "." << endl;
des->errors += 1;
return 0;
}
if (loff < moff) {
moff = moff + tmp_mwid - 1;
@ -957,14 +965,27 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
// creating a generated slice that spans the whole range.
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
lrc = reg->sb_to_slice(prefix_indices, lsv, moff, mwid);
ivl_assert(*this, lrc);
bool lrc, mrc;
mrc = reg->sb_to_slice(prefix_indices, lsv, moff, mwid);
if (use_sel == index_component_t::SEL_IDX_UP)
lrc = reg->sb_to_slice(prefix_indices, lsv+wid-1, loff, lwid);
else
lrc = reg->sb_to_slice(prefix_indices, lsv-wid+1, loff, lwid);
ivl_assert(*this, lrc);
if (!mrc || !lrc) {
cerr << get_fileline() << ": error: ";
cerr << "Part-select [" << lsv;
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] exceeds the declared bounds for ";
cerr << reg->name();
if (reg->unpacked_dimensions() > 0) cerr << "[]";
cerr << "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, lwid == mwid);
if (moff > loff) {

View File

@ -270,14 +270,27 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
// creating a generated slice that spans the whole range.
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
lrc = sig->sb_to_slice(prefix_indices, midx_val, moff, mwid);
ivl_assert(*this, lrc);
bool mrc, lrc;
mrc = sig->sb_to_slice(prefix_indices, midx_val, moff, mwid);
if (index_tail.sel == index_component_t::SEL_IDX_UP)
lrc = sig->sb_to_slice(prefix_indices, midx_val+wid-1, loff, lwid);
else
lrc = sig->sb_to_slice(prefix_indices, midx_val-wid+1, loff, lwid);
ivl_assert(*this, lrc);
if (!mrc || !lrc) {
cerr << get_fileline() << ": error: ";
cerr << "Part-select [" << midx_val;
if (index_tail.sel == index_component_t::SEL_IDX_UP) {
cerr << "+:";
} else {
cerr << "-:";
}
cerr << wid << "] exceeds the declared bounds for ";
cerr << sig->name();
if (sig->unpacked_dimensions() > 0) cerr << "[]";
cerr << "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, lwid == mwid);
if (moff > loff) {
@ -364,11 +377,19 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
// range.
long loff, moff;
unsigned long lwid, mwid;
bool lrc;
bool lrc, mrc;
lrc = sig->sb_to_slice(prefix_indices, lsb, loff, lwid);
ivl_assert(*this, lrc);
lrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
ivl_assert(*this, lrc);
mrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
if (!mrc || !lrc) {
cerr << get_fileline() << ": error: ";
cerr << "Part-select [" << msb << ":" << lsb;
cerr << "] exceeds the declared bounds for ";
cerr << sig->name();
if (sig->unpacked_dimensions() > 0) cerr << "[]";
cerr << "." << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, lwid == mwid);
if (moff > loff) {