From 81e12bf7f605daf0dc0b4835a288fb6e7a389b6f Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 25 Apr 2008 17:17:51 -0700 Subject: [PATCH] Handle multiple active specify delays. Fix handling of cases where multiple specified delays are activated for a given output. Need to apply the standard selection criteria that gets the minimum value. --- vvp/delay.cc | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/vvp/delay.cc b/vvp/delay.cc index 1b4d96aa3..066bfe0f6 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -22,6 +22,7 @@ #include "vpi_priv.h" #include #include +#include #include void vvp_delay_t::calculate_min_delay_() @@ -392,17 +393,24 @@ void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit) if (cur_vec4_.eeq(bit)) return; - /* Select a time delay source that applies. */ - vvp_fun_modpath_src*src = 0; + /* Select a time delay source that applies. Notice that there + may be multiple delay sources that apply, so collect all + the candidates into a list first. */ + listcandidate_list; + vvp_time64_t candidate_wake_time = 0; for (vvp_fun_modpath_src*cur = src_list_ ; cur ; cur=cur->next_) { /* Skip paths that are disabled by conditions. */ if (cur->condition_flag_ == false) continue; - if (src == 0) { - src = cur; - } else if (cur->wake_time_ > src->wake_time_) { - src = cur; + if (candidate_list.empty()) { + candidate_list.push_back(cur); + candidate_wake_time = cur->wake_time_; + } else if (cur->wake_time_ == candidate_wake_time) { + candidate_list.push_back(cur); + } else if (cur->wake_time_ > candidate_wake_time) { + candidate_list.assign(1, cur); + candidate_wake_time = cur->wake_time_; } else { continue; /* Skip this entry. */ } @@ -412,16 +420,24 @@ void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit) match. This may happen, for example, if the set of conditional delays is incomplete, leaving some cases uncovered. In that case, just pass the data without delay */ - if (src == 0) { + if (candidate_list.empty()) { cur_vec4_ = bit; schedule_generic(this, 0, false); return; } - assert(src); - + /* Now given that we have a list of candidate delays, find for + each if the 12 numbers the minimum from all the + candidates. This minimum set becomes the chosen delay to + use. */ vvp_time64_t out_at[12]; vvp_time64_t now = schedule_simtime(); + + typedef list::const_iterator iter_t; + + iter_t cur = candidate_list.begin(); + vvp_fun_modpath_src*src = *cur; + for (unsigned idx = 0 ; idx < 12 ; idx += 1) { out_at[idx] = src->wake_time_ + src->delay_[idx]; if (out_at[idx] <= now) @@ -430,6 +446,19 @@ void vvp_fun_modpath::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit) out_at[idx] -= now; } + for (cur ++ ; cur != candidate_list.end() ; cur ++) { + src = *cur; + for (unsigned idx = 0 ; idx < 12 ; idx += 1) { + vvp_time64_t tmp = src->wake_time_ + src->delay_[idx]; + if (tmp <= now) + tmp = 0; + else + tmp -= now; + if (tmp < out_at[idx]) + out_at[idx] = tmp; + } + } + /* Given the scheduled output time, create an output event. */ vvp_time64_t use_delay = delay_from_edge(cur_vec4_.value(0), bit.value(0),