Make casts from double to unsigned bits portable.

Several places in Icarus Verilog try to get the bits of the integer
part of a double by casting to unsigned or unsigned long. But that
causes some compilers to generate smart code that converts all values
less then 0 to 0, even though we are after the bits, not the math
value. So be careful to do this cast only to non-negative values and
uminus the bits if necessary to get exactly what we want.

Signed-off-by: Stephen Williams <steve@icarus.com>
This commit is contained in:
Stephen Williams 2008-04-27 18:21:32 -07:00
parent 81e12bf7f6
commit c3ac01d31b
2 changed files with 12 additions and 4 deletions

View File

@ -215,7 +215,10 @@ static PLI_INT32 sys_rtoi_calltf(PLI_BYTE8*user)
vpi_get_value(arg, &value);
/* convert */
res.aval = (unsigned)value.value.real;
if (value.value.real >= 0.0)
res.aval = (unsigned)value.value.real;
else
res.aval = - (unsigned)-value.value.real;
res.bval = 0;
value.format = vpiVectorVal;

View File

@ -187,7 +187,7 @@ long rtl_dist_uniform(long *seed, long start, long end)
if (r >= 0) {
i = (unsigned long) r;
} else {
i = (unsigned long) (r - 1);
i = - ( (unsigned long) (-(r - 1)) );
}
if (i < start) i = start;
if (i >= end) i = end - 1;
@ -197,7 +197,7 @@ long rtl_dist_uniform(long *seed, long start, long end)
if (r >= 0) {
i = (unsigned long) r;
} else {
i = (unsigned long) (r - 1);
i = - ( (unsigned long) (-(r - 1)) );
}
if (i <= start) i = start + 1;
if (i > end) i = end;
@ -208,7 +208,12 @@ long rtl_dist_uniform(long *seed, long start, long end)
if (r >= 0) {
i = (unsigned long) r;
} else {
i = (unsigned long) (r - 1);
/* At least some compilers will notice that (r-1)
is <0 when castling to unsigned long and
replace the result with a zero. This causes
much wrongness, so do the casting to the
positive version and invert it back. */
i = - ( (unsigned long) (-(r - 1)) );
}
}