Fix br1029 - correct rounding when vpi_get_value converts real to integer string.

(cherry picked from commit 5a4e99b0e8)
This commit is contained in:
Martin Whitaker 2018-05-12 23:40:29 +01:00
parent 0f28b03dd3
commit 24731227b4
1 changed files with 18 additions and 14 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -780,6 +780,15 @@ void vvp_signal_value::get_signal_value(struct t_vpi_value*vp)
} }
} }
static double vlg_round(double rval)
{
if (rval >= 0.0) {
return floor(rval + 0.5);
} else {
return ceil(rval - 0.5);
}
}
static void real_signal_value(struct t_vpi_value*vp, double rval) static void real_signal_value(struct t_vpi_value*vp, double rval)
{ {
char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL); char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL);
@ -797,31 +806,26 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
if (rval != rval || (rval && (rval == 0.5*rval))) { if (rval != rval || (rval && (rval == 0.5*rval))) {
rval = 0.0; rval = 0.0;
} else { } else {
if (rval >= 0.0) rval = floor(rval + 0.5); rval = vlg_round(rval);
else rval = ceil(rval - 0.5);
} }
vp->value.integer = (PLI_INT32)rval; vp->value.integer = (PLI_INT32)rval;
break; break;
case vpiDecStrVal: case vpiDecStrVal:
#if !defined(__GNUC__)
if (isnan(rval)) if (isnan(rval))
sprintf(rbuf, "%s", "nan"); sprintf(rbuf, "%s", "nan");
else else
sprintf(rbuf, "%0.0f", rval); sprintf(rbuf, "%0.0f", vlg_round(rval));
#else
sprintf(rbuf, "%0.0f", rval);
#endif
vp->value.str = rbuf; vp->value.str = rbuf;
break; break;
case vpiHexStrVal: case vpiHexStrVal:
sprintf(rbuf, "%lx", (long)rval); sprintf(rbuf, "%lx", (long)vlg_round(rval));
vp->value.str = rbuf; vp->value.str = rbuf;
break; break;
case vpiBinStrVal: { case vpiBinStrVal: {
unsigned long val = (unsigned long)rval; unsigned long val = (unsigned long)vlg_round(rval);
unsigned len = 0; unsigned len = 0;
while (val > 0) { while (val > 0) {
@ -829,7 +833,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
val /= 2; val /= 2;
} }
val = (unsigned long)rval; val = (unsigned long)vlg_round(rval);
for (unsigned idx = 0 ; idx < len ; idx += 1) { for (unsigned idx = 0 ; idx < len ; idx += 1) {
rbuf[len-idx-1] = (val & 1)? '1' : '0'; rbuf[len-idx-1] = (val & 1)? '1' : '0';
val /= 2; val /= 2;