Trim results of unsized constant add to prevent width expansion
When constant values are added to get another constant value, and the expression is not otherwise a fixed size, then trim the result to prevent unbounded expansion of unsized expression with. In the process, find and fix a bug in the vtrim function that caused an assert if trimming were not possible for an unsigned value.
This commit is contained in:
parent
bfb33230aa
commit
dffe1be819
14
eval_tree.cc
14
eval_tree.cc
|
|
@ -95,12 +95,14 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debug_eval_tree) {
|
||||||
|
cerr << get_fileline() << ": debug: Evaluate expr=" << *this
|
||||||
|
<< " --- prune=" << prune_to_width
|
||||||
|
<< " has_width=" << (has_width()? "true" : "false") << endl;
|
||||||
|
}
|
||||||
|
|
||||||
/* Result might have known width. */
|
/* Result might have known width. */
|
||||||
if (has_width()) {
|
if (has_width()) {
|
||||||
if (debug_eval_tree) {
|
|
||||||
cerr << get_fileline() << ": debug: Evaluate expr=" << *this
|
|
||||||
<< " --- prune=" << prune_to_width << endl;
|
|
||||||
}
|
|
||||||
unsigned lwid = lc->expr_width();
|
unsigned lwid = lc->expr_width();
|
||||||
unsigned rwid = rc->expr_width();
|
unsigned rwid = rc->expr_width();
|
||||||
unsigned wid = (rwid > lwid) ? rwid : lwid;
|
unsigned wid = (rwid > lwid) ? rwid : lwid;
|
||||||
|
|
@ -108,6 +110,10 @@ NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||||
wid += 1;
|
wid += 1;
|
||||||
verinum val2=verinum(val,wid);
|
verinum val2=verinum(val,wid);
|
||||||
val=val2;
|
val=val2;
|
||||||
|
} else {
|
||||||
|
/* No fixed width, so trim the bits losslessly. */
|
||||||
|
verinum val2 = trim_vnum(val);
|
||||||
|
val = val2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NetEConst(val);
|
return new NetEConst(val);
|
||||||
|
|
|
||||||
10
verinum.cc
10
verinum.cc
|
|
@ -505,12 +505,20 @@ verinum trim_vnum(const verinum&that)
|
||||||
unsigned top = that.len()-1;
|
unsigned top = that.len()-1;
|
||||||
while ((top > 0) && (that.get(top) == verinum::V0))
|
while ((top > 0) && (that.get(top) == verinum::V0))
|
||||||
top -= 1;
|
top -= 1;
|
||||||
|
|
||||||
|
/* Now top is the index of the highest non-zero bit. If
|
||||||
|
that turns out to the highest bit in the vector, then
|
||||||
|
tere is no trimming possible. */
|
||||||
|
if (top+1 == that.len())
|
||||||
|
return that;
|
||||||
|
|
||||||
|
/* Make tlen wide enough to include the highest non-zero
|
||||||
|
bit, plus one extra 0 bit. */
|
||||||
tlen = top+2;
|
tlen = top+2;
|
||||||
|
|
||||||
/* This can only happen when the verinum is all zeros,
|
/* This can only happen when the verinum is all zeros,
|
||||||
so make it a single bit wide. */
|
so make it a single bit wide. */
|
||||||
if (that.get(top) == verinum::V0) tlen -= 1;
|
if (that.get(top) == verinum::V0) tlen -= 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
verinum tmp (verinum::V0, tlen, false);
|
verinum tmp (verinum::V0, tlen, false);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue