From 7d7aa0604c49d24b35081e5db571e8e9e86b9a75 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 20 Apr 2021 22:58:40 +0100 Subject: [PATCH] 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. --- elab_expr.cc | 62 ++++++++++++++++++++++++++++++++++++++-------------- elab_lval.cc | 39 +++++++++++++++++++++++++-------- elab_net.cc | 37 ++++++++++++++++++++++++------- 3 files changed, 105 insertions(+), 33 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 200c501f0..c80cf223b 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -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; diff --git a/elab_lval.cc b/elab_lval.cc index 65e32c8fd..d2d3cffdc 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -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); + lrc = reg->sb_to_slice(prefix_indices, lsb, loff, tmp_lwid); + 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) { diff --git a/elab_net.cc b/elab_net.cc index 5ff464096..a4174b719 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -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) {