This commit is contained in:
Wei Ren 2025-10-29 22:36:53 +01:00 committed by GitHub
commit f786bc8d92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 58 additions and 75 deletions

View File

@ -26,6 +26,7 @@
# include "vpi_user.h"
# include "vpi_priv.h"
# include "vpi_utils.h"
# include "vvp_net.h"
# include "schedule.h"
# include "event.h"
@ -949,23 +950,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 const size_t RBUF_SIZE = 64 + 1;
@ -984,7 +968,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
if (rval != rval || (rval && (rval == 0.5*rval))) {
rval = 0.0;
} else {
rval = vlg_round(rval);
rval = std::round(rval);
}
vp->value.integer = (PLI_INT32)rval;
break;
@ -993,7 +977,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
if (std::isnan(rval))
snprintf(rbuf, RBUF_SIZE, "%s", "nan");
else
snprintf(rbuf, RBUF_SIZE, "%0.0f", vlg_round(rval));
snprintf(rbuf, RBUF_SIZE, "%0.0f", std::round(rval));
vp->value.str = rbuf;
break;
@ -1003,25 +987,23 @@ static void real_signal_value(struct t_vpi_value*vp, double rval)
break;
case vpiBinStrVal: {
uint64_t val = vlg_round_to_u64(rval);
const uint64_t val = vlg_round_to_u64(rval);
unsigned len = 0;
while (val > 0) {
// Compute bitwidth; For val==0, this yields len==1
uint64_t tmp = val;
do {
len += 1;
val /= 2;
tmp /= 2;
} while (tmp > 0);
tmp = val;
for (unsigned idx = 0; idx < len; idx += 1) {
rbuf[len - idx - 1] = (tmp & 1) ? '1' : '0';
tmp /= 2;
}
val = vlg_round_to_u64(rval);
for (unsigned idx = 0 ; idx < len ; idx += 1) {
rbuf[len-idx-1] = (val & 1)? '1' : '0';
val /= 2;
}
rbuf[len] = 0;
if (len == 0) {
rbuf[0] = '0';
rbuf[1] = 0;
}
rbuf[len] = '\0';
vp->value.str = rbuf;
break;
}

15
vvp/vpi_utils.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef IVL_vpi_utils_H
#define IVL_vpi_utils_H
#include <cmath>
#include <cstdint>
static 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::llround(rval)));
}
#endif

View File

@ -24,6 +24,7 @@
*/
# include "vpi_priv.h"
# include "vpi_utils.h"
# include "vthread.h"
# include "config.h"
#ifdef CHECK_WITH_VALGRIND
@ -87,15 +88,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)
{
const __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref);
@ -127,7 +119,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
if (val != val || (val && (val == 0.5*val))) {
val = 0.0;
} else {
val = vlg_round(val);
val = std::round(val);
}
vp->value.integer = (PLI_INT32)val;
break;
@ -136,40 +128,37 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp)
if (std::isnan(val))
snprintf(rbuf, RBUF_USE_SIZE, "%s", "nan");
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;
break;
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;
break;
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;
break;
case vpiBinStrVal: {
uint64_t vali = (uint64_t)vlg_round(val);
const uint64_t vali = vlg_round_to_u64(val);
unsigned len = 0;
while (vali > 0) {
uint64_t tmp = vali;
do {
len += 1;
vali /= 2;
tmp /= 2;
} while (tmp > 0);
tmp = vali;
for (unsigned idx = 0; idx < len; idx += 1) {
rbuf[len - idx - 1] = (tmp & 1) ? '1' : '0';
tmp /= 2;
}
vali = (uint64_t)vlg_round(val);
for (unsigned idx = 0 ; idx < len ; idx += 1) {
rbuf[len-idx-1] = (vali & 1)? '1' : '0';
vali /= 2;
}
rbuf[len] = 0;
if (len == 0) {
rbuf[0] = '0';
rbuf[1] = 0;
}
rbuf[len] = '\0';
vp->value.str = rbuf;
break;
}

View File

@ -24,6 +24,7 @@
# include "ufunc.h"
# include "event.h"
# include "vpi_priv.h"
# include "vpi_utils.h"
# include "vvp_net_sig.h"
# include "vvp_cobject.h"
# include "vvp_darray.h"
@ -2380,11 +2381,7 @@ bool of_CVT_SR(vthread_t thr, vvp_code_t cp)
bool of_CVT_UR(vthread_t thr, vvp_code_t cp)
{
double r = thr->pop_real();
if (r >= 0.0)
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);
thr->words[cp->bit_idx[0]].w_uint = vlg_round_to_u64(r);
return true;
}