Fix bug in eval of <= compare

The compiler attempts to precalculate the results of <= comparisons.
Fix a few corner cases where the arguments are signed. Also fix the
important test of constant against non-constant where we try to test
if the non-constant value can possibly make the test fail.
This commit is contained in:
Stephen Williams 2008-01-21 22:05:50 -08:00
parent db25bba0d0
commit 5b17f2039a
3 changed files with 38 additions and 5 deletions

View File

@ -1770,6 +1770,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
signed expression and extend it one bit to
accommodate a possible sign bit. */
verinum zero (verinum::V0, val.len()+1, val.has_len());
zero.has_sign(val.has_sign());
verinum nval = zero - val;
if (val.has_len())

View File

@ -447,11 +447,19 @@ NetEConst* NetEBComp::eval_leeq_()
cerr << get_fileline() << ": : " << *this << endl;
}
/* Detect the case where the right side is greater that or
/* Detect the case where the right side is greater than or
equal to the largest value the left side can possibly
have. */
assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width());
if (left_->has_sign() && rv.has_sign()) {
// If the expression is signed, then the largest
// possible value for the left_ needs to have a 0 in the
// sign position.
lv.set(lv.len()-1, verinum::V0);
lv.has_sign(true);
}
if (lv <= rv) {
verinum result(verinum::V1, 1);
return new NetEConst(result);

View File

@ -616,13 +616,25 @@ verinum::V operator == (const verinum&left, const verinum&right)
verinum::V operator <= (const verinum&left, const verinum&right)
{
verinum::V left_pad = verinum::V0;
verinum::V right_pad = verinum::V0;
if (left.has_sign() && right.has_sign()) {
left_pad = left.get(left.len()-1);
right_pad = right.get(right.len()-1);
if (left_pad == verinum::V1 && right_pad == verinum::V0)
return verinum::V1;
if (left_pad == verinum::V0 && right_pad == verinum::V1)
return verinum::V0;
}
unsigned idx;
for (idx = left.len() ; idx > right.len() ; idx -= 1) {
if (left[idx-1] != verinum::V0) return verinum::V0;
if (left[idx-1] != right_pad) return verinum::V0;
}
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
if (right[idx-1] != verinum::V0) return verinum::V1;
if (right[idx-1] != left_pad) return verinum::V1;
}
idx = right.len();
@ -643,13 +655,25 @@ verinum::V operator <= (const verinum&left, const verinum&right)
verinum::V operator < (const verinum&left, const verinum&right)
{
verinum::V left_pad = verinum::V0;
verinum::V right_pad = verinum::V0;
if (left.has_sign() && right.has_sign()) {
left_pad = left.get(left.len()-1);
right_pad = right.get(right.len()-1);
if (left_pad == verinum::V1 && right_pad == verinum::V0)
return verinum::V1;
if (left_pad == verinum::V0 && right_pad == verinum::V1)
return verinum::V0;
}
unsigned idx;
for (idx = left.len() ; idx > right.len() ; idx -= 1) {
if (left[idx-1] != verinum::V0) return verinum::V0;
if (left[idx-1] != right_pad) return verinum::V0;
}
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
if (right[idx-1] != verinum::V0) return verinum::V1;
if (right[idx-1] != left_pad) return verinum::V1;
}
while (idx > 0) {