Switch to std::round() and a common routine for real to uint64_t
This commit is contained in:
parent
eff75f8209
commit
aad14df3d7
|
|
@ -1727,8 +1727,7 @@ NetECReal* NetESFunc::evaluate_itor_(const NetExpr*arg_) const
|
||||||
return new NetECReal(verireal(0.0));
|
return new NetECReal(verireal(0.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg >= 0.0) arg = floor(arg + 0.5);
|
arg = std::round(arg);
|
||||||
else arg = ceil(arg - 0.5);
|
|
||||||
|
|
||||||
return new NetECReal(verireal(arg));
|
return new NetECReal(verireal(arg));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,7 @@ using namespace std;
|
||||||
*/
|
*/
|
||||||
extern "C" long int lround(double x)
|
extern "C" long int lround(double x)
|
||||||
{
|
{
|
||||||
if (x >= 0.0)
|
return (long)std::round(x);
|
||||||
return (long)floor(x+0.5);
|
|
||||||
else
|
|
||||||
return (long)ceil(x-0.5);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
24
verireal.cc
24
verireal.cc
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com)
|
* Copyright (c) 1999-2025 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
|
||||||
|
|
@ -71,15 +71,8 @@ long verireal::as_long() const
|
||||||
double out = value_;
|
double out = value_;
|
||||||
double outf;
|
double outf;
|
||||||
|
|
||||||
if (out >= 0.0) {
|
outf = std::round(out);
|
||||||
outf = floor(out);
|
|
||||||
if (out >= (outf + 0.5))
|
|
||||||
outf += 1.0;
|
|
||||||
} else {
|
|
||||||
outf = ceil(out);
|
|
||||||
if (out <= (outf - 0.5))
|
|
||||||
outf -= 1.0;
|
|
||||||
}
|
|
||||||
return (long) outf;
|
return (long) outf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,15 +81,8 @@ int64_t verireal::as_long64(int shift) const
|
||||||
double out = value_ * pow(10.0,shift);
|
double out = value_ * pow(10.0,shift);
|
||||||
double outf;
|
double outf;
|
||||||
|
|
||||||
if (out >= 0.0) {
|
outf = std::round(out);
|
||||||
outf = floor(out);
|
|
||||||
if (out >= (outf + 0.5))
|
|
||||||
outf += 1.0;
|
|
||||||
} else {
|
|
||||||
outf = ceil(out);
|
|
||||||
if (out <= (outf - 0.5))
|
|
||||||
outf -= 1.0;
|
|
||||||
}
|
|
||||||
return (int64_t) outf;
|
return (int64_t) outf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,10 +145,7 @@ typedef unsigned long vvp_time64_t;
|
||||||
*/
|
*/
|
||||||
inline long int lround(double x)
|
inline long int lround(double x)
|
||||||
{
|
{
|
||||||
if (x >= 0.0)
|
return (long)std::round(x);
|
||||||
return (long)floor(x+0.5);
|
|
||||||
else
|
|
||||||
return (long)ceil(x-0.5);
|
|
||||||
}
|
}
|
||||||
#endif /* HAVE_LROUND */
|
#endif /* HAVE_LROUND */
|
||||||
|
|
||||||
|
|
@ -160,10 +157,7 @@ inline long int lround(double x)
|
||||||
*/
|
*/
|
||||||
inline int64_t i64round(double x)
|
inline int64_t i64round(double x)
|
||||||
{
|
{
|
||||||
if (x >= 0.0)
|
return (int64_t)std::round(x);
|
||||||
return (int64_t)floor(x+0.5);
|
|
||||||
else
|
|
||||||
return (int64_t)ceil(x-0.5);
|
|
||||||
}
|
}
|
||||||
#else /* HAVE_LLROUND */
|
#else /* HAVE_LLROUND */
|
||||||
# define i64round llround
|
# define i64round llround
|
||||||
|
|
|
||||||
|
|
@ -949,23 +949,6 @@ 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 uint64_t vlg_round_to_u64(double rval)
|
|
||||||
{
|
|
||||||
// Directly casting a negative double to an unsigned integer types is
|
|
||||||
// undefined behavior and behaves differently on different architectures.
|
|
||||||
// Cast to signed integer first to get the behavior we want.
|
|
||||||
return static_cast<uint64_t>(static_cast<int64_t>(vlg_round(rval)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void real_signal_value(struct t_vpi_value*vp, double rval)
|
static void real_signal_value(struct t_vpi_value*vp, double rval)
|
||||||
{
|
{
|
||||||
static const size_t RBUF_SIZE = 64 + 1;
|
static const size_t RBUF_SIZE = 64 + 1;
|
||||||
|
|
@ -984,7 +967,7 @@ 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 {
|
||||||
rval = vlg_round(rval);
|
rval = std::round(rval);
|
||||||
}
|
}
|
||||||
vp->value.integer = (PLI_INT32)rval;
|
vp->value.integer = (PLI_INT32)rval;
|
||||||
break;
|
break;
|
||||||
|
|
@ -993,7 +976,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
|
||||||
if (std::isnan(rval))
|
if (std::isnan(rval))
|
||||||
snprintf(rbuf, RBUF_SIZE, "%s", "nan");
|
snprintf(rbuf, RBUF_SIZE, "%s", "nan");
|
||||||
else
|
else
|
||||||
snprintf(rbuf, RBUF_SIZE, "%0.0f", vlg_round(rval));
|
snprintf(rbuf, RBUF_SIZE, "%0.0f", std::round(rval));
|
||||||
vp->value.str = rbuf;
|
vp->value.str = rbuf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -880,14 +880,7 @@ static PLI_INT32 get_real_as_int(double real)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Round away from zero. */
|
rtn = std::round(real);
|
||||||
if (real >= 0.0) {
|
|
||||||
rtn = floor(real);
|
|
||||||
if (real >= (rtn + 0.5)) rtn += 1.0;
|
|
||||||
} else {
|
|
||||||
rtn = ceil(real);
|
|
||||||
if (real <= (rtn - 0.5)) rtn -= 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (PLI_INT32) rtn;
|
return (PLI_INT32) rtn;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1157,4 +1157,12 @@ extern int vpip_delay_selection;
|
||||||
/* A flag to disable output to MCD bit 0. */
|
/* A flag to disable output to MCD bit 0. */
|
||||||
extern bool vpip_mcd0_disable;
|
extern bool vpip_mcd0_disable;
|
||||||
|
|
||||||
|
inline uint64_t vlg_round_to_u64(double rval)
|
||||||
|
{
|
||||||
|
// Directly casting a negative double to an unsigned integer types is
|
||||||
|
// undefined behavior and behaves differently on different architectures.
|
||||||
|
// Cast to signed integer first to get the behavior we want.
|
||||||
|
return static_cast<uint64_t>(static_cast<int64_t>(std::round(rval)));
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* IVL_vpi_priv_H */
|
#endif /* IVL_vpi_priv_H */
|
||||||
|
|
|
||||||
|
|
@ -87,15 +87,6 @@ static int vthr_word_get(int code, vpiHandle ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static double vlg_round(double rval)
|
|
||||||
{
|
|
||||||
if (rval >= 0.0) {
|
|
||||||
return floor(rval + 0.5);
|
|
||||||
} else {
|
|
||||||
return ceil(rval - 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
|
static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||||
{
|
{
|
||||||
const __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref);
|
const __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref);
|
||||||
|
|
@ -127,7 +118,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||||
if (val != val || (val && (val == 0.5*val))) {
|
if (val != val || (val && (val == 0.5*val))) {
|
||||||
val = 0.0;
|
val = 0.0;
|
||||||
} else {
|
} else {
|
||||||
val = vlg_round(val);
|
val = std::round(val);
|
||||||
}
|
}
|
||||||
vp->value.integer = (PLI_INT32)val;
|
vp->value.integer = (PLI_INT32)val;
|
||||||
break;
|
break;
|
||||||
|
|
@ -136,22 +127,22 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||||
if (std::isnan(val))
|
if (std::isnan(val))
|
||||||
snprintf(rbuf, RBUF_USE_SIZE, "%s", "nan");
|
snprintf(rbuf, RBUF_USE_SIZE, "%s", "nan");
|
||||||
else
|
else
|
||||||
snprintf(rbuf, RBUF_USE_SIZE, "%0.0f", vlg_round(val));
|
snprintf(rbuf, RBUF_USE_SIZE, "%0.0f", std::round(val));
|
||||||
vp->value.str = rbuf;
|
vp->value.str = rbuf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiOctStrVal:
|
case vpiOctStrVal:
|
||||||
snprintf(rbuf, RBUF_USE_SIZE, "%" PRIo64, (uint64_t)vlg_round(val));
|
snprintf(rbuf, RBUF_USE_SIZE, "%" PRIo64, vlg_round_to_u64(val));
|
||||||
vp->value.str = rbuf;
|
vp->value.str = rbuf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiHexStrVal:
|
case vpiHexStrVal:
|
||||||
snprintf(rbuf, RBUF_USE_SIZE, "%" PRIx64, (uint64_t)vlg_round(val));
|
snprintf(rbuf, RBUF_USE_SIZE, "%" PRIx64, vlg_round_to_u64(val));
|
||||||
vp->value.str = rbuf;
|
vp->value.str = rbuf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vpiBinStrVal: {
|
case vpiBinStrVal: {
|
||||||
uint64_t vali = (uint64_t)vlg_round(val);
|
uint64_t vali = vlg_round_to_u64(val);
|
||||||
unsigned len = 0;
|
unsigned len = 0;
|
||||||
|
|
||||||
while (vali > 0) {
|
while (vali > 0) {
|
||||||
|
|
@ -159,7 +150,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||||
vali /= 2;
|
vali /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
vali = (uint64_t)vlg_round(val);
|
vali = vlg_round_to_u64(val);
|
||||||
for (unsigned idx = 0 ; idx < len ; idx += 1) {
|
for (unsigned idx = 0 ; idx < len ; idx += 1) {
|
||||||
rbuf[len-idx-1] = (vali & 1)? '1' : '0';
|
rbuf[len-idx-1] = (vali & 1)? '1' : '0';
|
||||||
vali /= 2;
|
vali /= 2;
|
||||||
|
|
|
||||||
|
|
@ -2380,10 +2380,7 @@ bool of_CVT_SR(vthread_t thr, vvp_code_t cp)
|
||||||
bool of_CVT_UR(vthread_t thr, vvp_code_t cp)
|
bool of_CVT_UR(vthread_t thr, vvp_code_t cp)
|
||||||
{
|
{
|
||||||
double r = thr->pop_real();
|
double r = thr->pop_real();
|
||||||
if (r >= 0.0)
|
thr->words[cp->bit_idx[0]].w_uint = vlg_round_to_u64(r);
|
||||||
thr->words[cp->bit_idx[0]].w_uint = (uint64_t)floor(r+0.5);
|
|
||||||
else
|
|
||||||
thr->words[cp->bit_idx[0]].w_uint = (uint64_t)ceil(r-0.5);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue