Variable delays for .delay must be scaled correctly.

A variable that is used to set the delay of a .delay statement
must be scaled to match the local units and for real values
rounded using the precision. This value is then converted to
the simulation precision.
This commit is contained in:
Cary R 2008-09-11 16:50:45 -07:00 committed by Stephen Williams
parent d3d54144ff
commit 441f173ced
4 changed files with 61 additions and 7 deletions

View File

@ -135,6 +135,17 @@ vvp_fun_delay::vvp_fun_delay(vvp_net_t*n, vvp_bit4_t init, const vvp_delay_t&d)
cur_real_ = 0.0;
list_ = 0;
initial_ = true;
// Calculate the values used when converting variable delays
// to simulation time units.
struct __vpiScope*scope = vpip_peek_current_scope();
int pow = scope->time_units - scope->time_precision;
round_ = 1;
for (int lp = 0; lp < pow; lp += 1) round_ *= 10;
pow = scope->time_precision - vpip_get_time_precision();
scale_ = 1;
for (int lp = 0; lp < pow; lp += 1) scale_ *= 10;
}
vvp_fun_delay::~vvp_fun_delay()
@ -176,8 +187,12 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit)
if (port.port() > 0) {
// Get the integer value of the bit vector, or 0 if
// there are X or Z bits.
unsigned long val = 0;
vector4_to_value(bit, val);
vvp_time64_t bval = 0;
// The following does not work correctly for negative values.
// They should be sign extended to 64 bits (1364-2001 9.7.1).
vector4_to_value(bit, bval);
// Integer values do not need to be rounded so just scale them.
vvp_time64_t val = bval * round_ * scale_;
switch (port.port()) {
case 1:
@ -272,9 +287,17 @@ void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit)
if (port.port() > 0) {
/* If the port is not 0, then this is a delay value that
should be rounded and converted to an integer delay. */
unsigned long long val = 0;
if (bit > 0)
val = (unsigned long long) (bit+0.5);
vvp_time64_t val = 0;
if (bit > -0.5) {
val = (vvp_time64_t) (bit * round_ +0.5) * scale_;
} else if (bit != bit) {
// For a NaN we use the default (0).
} else {
vvp_vector4_t vec4(8*sizeof(vvp_time64_t), bit);
vvp_time64_t bval = 0;
vector4_to_value(vec4, bval);
val = bval * round_ * scale_;
}
switch (port.port()) {
case 1:

View File

@ -106,6 +106,7 @@ class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s {
vvp_vector4_t cur_vec4_;
vvp_vector8_t cur_vec8_;
double cur_real_;
vvp_time64_t round_, scale_; // Needed to scale variable time values.
struct event_ *list_;
void enqueue_(struct event_*cur)

View File

@ -1156,7 +1156,9 @@ bool vector4_to_value(const vvp_vector4_t&vec, long&val,
long msk = 1;
bool rc_flag = true;
for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
unsigned size = vec.size();
if (size > 8*sizeof(val)) size = 8*sizeof(val);
for (unsigned idx = 0 ; idx < size ; idx += 1) {
switch (vec.value(idx)) {
case BIT4_0:
break;
@ -1187,7 +1189,34 @@ bool vector4_to_value(const vvp_vector4_t&vec, unsigned long&val)
unsigned long res = 0;
unsigned long msk = 1;
for (unsigned idx = 0 ; idx < vec.size() ; idx += 1) {
unsigned size = vec.size();
if (size > 8*sizeof(val)) size = 8*sizeof(val);
for (unsigned idx = 0 ; idx < size ; idx += 1) {
switch (vec.value(idx)) {
case BIT4_0:
break;
case BIT4_1:
res |= msk;
break;
default:
return false;
}
msk <<= 1UL;
}
val = res;
return true;
}
bool vector4_to_value(const vvp_vector4_t&vec, vvp_time64_t&val)
{
vvp_time64_t res = 0;
vvp_time64_t msk = 1;
unsigned size = vec.size();
if (size > 8*sizeof(val)) size = 8*sizeof(val);
for (unsigned idx = 0 ; idx < size ; idx += 1) {
switch (vec.value(idx)) {
case BIT4_0:
break;

View File

@ -394,6 +394,7 @@ template <class T> extern T coerce_to_width(const T&that, unsigned width);
*/
extern bool vector4_to_value(const vvp_vector4_t&a, long&val, bool is_signed, bool is_arithmetic =true);
extern bool vector4_to_value(const vvp_vector4_t&a, unsigned long&val);
extern bool vector4_to_value(const vvp_vector4_t&a, vvp_time64_t&val);
extern bool vector4_to_value(const vvp_vector4_t&a, double&val, bool is_signed);
/*