diff --git a/elab_expr.cc b/elab_expr.cc index f380659aa..015a6f61d 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -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()) diff --git a/eval_tree.cc b/eval_tree.cc index 450de5e49..520dc894b 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -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); diff --git a/verinum.cc b/verinum.cc index 98ecae9d6..2f48fbb8f 100644 --- a/verinum.cc +++ b/verinum.cc @@ -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) {