Fix for GitHub issue #37 - bug in expression width pruning.

If an expression contains a division, remainder, or right shift operation,
set the expression min_width to UINT_MAX to flag that the expression width
cannot be pruned. Using UINT_MAX ensures that the min_width won't change
as we continue to elaborate the expression.
This commit is contained in:
Martin Whitaker 2014-08-25 20:27:22 +01:00
parent 5de83906f7
commit e5f49baaac
2 changed files with 8 additions and 6 deletions

View File

@ -310,7 +310,7 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
case '%':
case '/':
min_width_ = max(min_width_, expr_width_);
min_width_ = UINT_MAX; // disable width pruning
break;
case 'l': // << Should be handled by PEBShift
@ -816,7 +816,7 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
if (op_ == 'l')
min_width_ = left_->min_width();
else
min_width_ = expr_width_;
min_width_ = UINT_MAX; // disable width pruning
return fix_width_(mode);
}

View File

@ -20,6 +20,7 @@
# include "config.h"
# include <cstdlib>
# include <climits>
# include "netlist.h"
# include "netvector.h"
# include "netmisc.h"
@ -764,12 +765,13 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
// If we can get the same result using a smaller expression
// width, do so.
if ((context_width > 0) && (pe->expr_type() != IVL_VT_REAL)
&& (expr_width > pos_context_width)) {
expr_width = max(pe->min_width(), pos_context_width);
unsigned min_width = pe->min_width();
if ((min_width != UINT_MAX) && (pe->expr_type() != IVL_VT_REAL)
&& (pos_context_width > 0) && (expr_width > pos_context_width)) {
expr_width = max(min_width, pos_context_width);
if (debug_elaborate) {
cerr << pe->get_fileline() << ": "
cerr << pe->get_fileline() << ": : "
<< "pruned to width=" << expr_width << endl;
}
}