Fix implicit casts in assignments (part 4).

This patch fixes a few issues/bugs that showed up when testing the
fixes for implicit casts:

1. Make the compile-time implementation of $abs, $min, and $max match
   the run-time behaviour (system functions can't be polymorphic).

2. Correctly set the type (signed/unsigned) of the result of an
   assignment inside a constant user function (the LHS should not
   inherit the type of the RHS).

3. Fix a bug in the verinum(double) constructor (insufficient bits
   were allocated in the case where the double value rounded up to
   the next power of two).
This commit is contained in:
Martin Whitaker 2013-02-26 22:39:04 +00:00 committed by Stephen Williams
parent faece5816c
commit e8d4039175
3 changed files with 16 additions and 32 deletions

View File

@ -1812,23 +1812,19 @@ NetExpr* NetESFunc::evaluate_abs_(const NetExpr*arg_) const
NetExpr*res = 0;
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg_);
if (tmpi) {
verinum arg = tmpi->value();
if (arg.is_negative()) {
arg = v_not(arg) + verinum(1);
}
res = new NetEConst(arg);
ivl_assert(*this, res);
}
const NetECReal*tmpr = dynamic_cast<const NetECReal*>(arg_);
if (tmpr) {
double arg = tmpr->value().as_double();
if (tmpi || tmpr) {
double arg;
if (tmpi) {
arg = tmpi->value().as_double();
} else {
arg = tmpr->value().as_double();
}
res = new NetECReal(verireal(fabs(arg)));
ivl_assert(*this, res);
}
eval_debug(this, res, tmpr != 0);
eval_debug(this, res, true);
return res;
}
@ -1842,23 +1838,7 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
NetExpr*res = 0;
if (tmpi0 && tmpi1) {
verinum arg0 = tmpi0->value();
verinum arg1 = tmpi1->value();
switch (id) {
case MIN:
res = new NetEConst( arg0 < arg1 ? arg0 : arg1);
break;
case MAX:
res = new NetEConst( arg0 < arg1 ? arg1 : arg0);
break;
default:
ivl_assert(*this, 0);
break;
}
ivl_assert(*this, res);
} else if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
if ((tmpi0 || tmpr0) && (tmpi1 || tmpr1)) {
double arg0, arg1;
if (tmpi0) {
arg0 = tmpi0->value().as_double();
@ -1884,7 +1864,7 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
ivl_assert(*this, res);
}
eval_debug(this, res, tmpr0 || tmpr1);
eval_debug(this, res, true);
return res;
}

View File

@ -170,6 +170,8 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
delete base_result;
delete rval_result;
rval_result = new NetEConst(lval_v);
} else {
rval_result->cast_signed(lval->sig()->get_signed());
}
if (ptr->second)

View File

@ -192,6 +192,10 @@ verinum::verinum(double val, bool)
val = -val;
}
/* Round to the nearest integer now, as this may increase the
number of bits we need to allocate. */
val = round(val);
/* Get the exponent and fractional part of the number. */
fraction = frexp(val, &exponent);
nbits_ = exponent+1;
@ -222,7 +226,6 @@ verinum::verinum(double val, bool)
bits_[idx] = (bits&1) ? V1 : V0;
bits >>= 1;
}
if (fraction >= 0.5) *this = *this + const_one;
} else {
for (int wd = nwords; wd >= 0; wd -= 1) {
unsigned long bits = (unsigned long) fraction;
@ -235,7 +238,6 @@ verinum::verinum(double val, bool)
}
fraction = ldexp(fraction, BITS_IN_LONG);
}
if (fraction >= ldexp(0.5, BITS_IN_LONG)) *this = *this + const_one;
}
/* Convert a negative number if needed. */