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 '%':
case '/': case '/':
min_width_ = max(min_width_, expr_width_); min_width_ = UINT_MAX; // disable width pruning
break; break;
case 'l': // << Should be handled by PEBShift 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') if (op_ == 'l')
min_width_ = left_->min_width(); min_width_ = left_->min_width();
else else
min_width_ = expr_width_; min_width_ = UINT_MAX; // disable width pruning
return fix_width_(mode); return fix_width_(mode);
} }

View File

@ -20,6 +20,7 @@
# include "config.h" # include "config.h"
# include <cstdlib> # include <cstdlib>
# include <climits>
# include "netlist.h" # include "netlist.h"
# include "netvector.h" # include "netvector.h"
# include "netmisc.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 // If we can get the same result using a smaller expression
// width, do so. // width, do so.
if ((context_width > 0) && (pe->expr_type() != IVL_VT_REAL) unsigned min_width = pe->min_width();
&& (expr_width > pos_context_width)) { if ((min_width != UINT_MAX) && (pe->expr_type() != IVL_VT_REAL)
expr_width = max(pe->min_width(), pos_context_width); && (pos_context_width > 0) && (expr_width > pos_context_width)) {
expr_width = max(min_width, pos_context_width);
if (debug_elaborate) { if (debug_elaborate) {
cerr << pe->get_fileline() << ": " cerr << pe->get_fileline() << ": : "
<< "pruned to width=" << expr_width << endl; << "pruned to width=" << expr_width << endl;
} }
} }