From c3ac01d31befb320e4313eb97855fc5a95480095 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 27 Apr 2008 18:21:32 -0700 Subject: [PATCH] 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 --- vpi/sys_convert.c | 5 ++++- vpi/sys_random.c | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/vpi/sys_convert.c b/vpi/sys_convert.c index 4b6ce77f3..9c387aabd 100644 --- a/vpi/sys_convert.c +++ b/vpi/sys_convert.c @@ -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; diff --git a/vpi/sys_random.c b/vpi/sys_random.c index b152a4ed8..d0a3cb251 100644 --- a/vpi/sys_random.c +++ b/vpi/sys_random.c @@ -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)) ); } }