From 0cc8285a019965de1e1297e52541aeffc9af9379 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 23 Nov 2009 18:27:14 -0800 Subject: [PATCH] Handle case that delay output is pending when new event arrives If the delay has an event pending for the current time, then use that as a reference for calculating the next delay. If that is not done, then the delay calculated against the wrong reference might result in zero, and bad results. (cherry picked from commit f07577db1136c2b0a23d3c115cd2def7cf8cac30) --- vvp/delay.cc | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/vvp/delay.cc b/vvp/delay.cc index 53330868d..3d123fc27 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -269,17 +269,23 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, } else { assert(type_ == VEC4_DELAY); + // Use as a reference for calculating the delay the + // current value of the output. Detect and handle the + // special case that the event list contains the current + // value as a zero-delay-remaining event. + const vvp_vector4_t&use_vec4 = (list_ && list_->next->sim_time == schedule_simtime())? list_->next->ptr_vec4 : cur_vec4_; + /* How many bits to compare? */ - unsigned use_wid = cur_vec4_.size(); + unsigned use_wid = use_vec4.size(); if (bit.size() < use_wid) use_wid = bit.size(); /* Scan the vectors looking for delays. Select the maximum delay encountered. */ - use_delay = delay_.get_delay(cur_vec4_.value(0), bit.value(0)); + use_delay = delay_.get_delay(use_vec4.value(0), bit.value(0)); for (unsigned idx = 1 ; idx < use_wid ; idx += 1) { vvp_time64_t tmp; - tmp = delay_.get_delay(cur_vec4_.value(idx), bit.value(idx)); + tmp = delay_.get_delay(use_vec4.value(idx), bit.value(idx)); if (tmp > use_delay) use_delay = tmp; } } @@ -292,7 +298,7 @@ void vvp_fun_delay::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, vvp_time64_t use_simtime = schedule_simtime() + use_delay; /* And propagate it. */ - if (use_delay == 0) { + if (use_delay == 0 && list_ == 0) { cur_vec4_ = bit; initial_ = false; vvp_send_vec4(net_->out, cur_vec4_, 0); @@ -325,18 +331,24 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit) } else { assert(type_ == VEC8_DELAY); + // Use as a reference for calculating the delay the + // current value of the output. Detect and handle the + // special case that the event list contains the current + // value as a zero-delay-remaining event. + const vvp_vector8_t&use_vec8 = (list_ && list_->next->sim_time == schedule_simtime())? list_->next->ptr_vec8 : cur_vec8_; + /* How many bits to compare? */ - unsigned use_wid = cur_vec8_.size(); + unsigned use_wid = use_vec8.size(); if (bit.size() < use_wid) use_wid = bit.size(); /* Scan the vectors looking for delays. Select the maximum delay encountered. */ - use_delay = delay_.get_delay(cur_vec8_.value(0).value(), + use_delay = delay_.get_delay(use_vec8.value(0).value(), bit.value(0).value()); for (unsigned idx = 1 ; idx < use_wid ; idx += 1) { vvp_time64_t tmp; - tmp = delay_.get_delay(cur_vec8_.value(idx).value(), + tmp = delay_.get_delay(use_vec8.value(idx).value(), bit.value(idx).value()); if (tmp > use_delay) use_delay = tmp; } @@ -350,7 +362,7 @@ void vvp_fun_delay::recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit) vvp_time64_t use_simtime = schedule_simtime() + use_delay; /* And propagate it. */ - if (use_delay == 0) { + if (use_delay == 0 && list_ == 0) { cur_vec8_ = bit; initial_ = false; vvp_send_vec8(net_->out, cur_vec8_); @@ -409,7 +421,7 @@ void vvp_fun_delay::recv_real(vvp_net_ptr_t port, double bit, vvp_time64_t use_simtime = schedule_simtime() + use_delay; - if (use_delay == 0) { + if (use_delay == 0 && list_ == 0) { cur_real_ = bit; initial_ = false; vvp_send_real(net_->out, cur_real_, 0);