1 #ifndef IVL_delay_H 2 #define IVL_delay_H 3 /* 4 * Copyright 2005-2016 Stephen Williams 5 * 6 * This source code is free software; you can redistribute it 7 * and/or modify it in source code form under the terms of the GNU 8 * General Public License as published by the Free Software 9 * Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 */ 21 22 # include <stddef.h> 23 # include "vvp_net.h" 24 # include "schedule.h" 25 26 enum delay_edge_t { 27 DELAY_EDGE_01 = 0, DELAY_EDGE_10, DELAY_EDGE_0z, 28 DELAY_EDGE_z1, DELAY_EDGE_1z, DELAY_EDGE_z0, 29 DELAY_EDGE_0x, DELAY_EDGE_x1, DELAY_EDGE_1x, 30 DELAY_EDGE_x0, DELAY_EDGE_xz, DELAY_EDGE_zx, 31 DELAY_EDGE_COUNT 32 }; 33 34 /* 35 * Instances of this object are functions that calculate the delay for 36 * the transition from the source vvp_bit4_t value to the destination 37 * value. 38 */ 39 class vvp_delay_t { 40 41 public: 42 vvp_delay_t(vvp_time64_t rise, vvp_time64_t fall); 43 vvp_delay_t(vvp_time64_t rise, vvp_time64_t fall, vvp_time64_t decay); 44 ~vvp_delay_t(); 45 46 vvp_time64_t get_delay(vvp_bit4_t from, vvp_bit4_t to); 47 vvp_time64_t get_min_delay() const; 48 49 void set_rise(vvp_time64_t val); 50 void set_fall(vvp_time64_t val); 51 void set_decay(vvp_time64_t val); 52 void set_ignore_decay(); 53 54 private: 55 vvp_time64_t rise_, fall_, decay_; 56 vvp_time64_t min_delay_; 57 bool ignore_decay_; 58 59 void calculate_min_delay_(); 60 }; 61 62 /* vvp_fun_delay 63 * This is a lighter weight version of vvp_fun_drive, that only 64 * carries delays. The output that it propagates is vvp_vector4_t so 65 * drive strengths are lost, but then again it doesn't go through the 66 * effort of calculating strength values either. 67 * 68 * The node needs a pointer to the vvp_net_t input so that it knows 69 * how to find its output when propagating delayed output. 70 * 71 * NOTE: This node supports vec4 and real by repeating whatever was 72 * input. This is a bit of a hack, as it may be more efficient to 73 * create the right type of vvp_fun_delay_real. 74 */ 75 class vvp_fun_delay : public vvp_net_fun_t, private vvp_gen_event_s { 76 77 enum delay_type_t {UNKNOWN_DELAY, VEC4_DELAY, VEC8_DELAY, REAL_DELAY}; 78 struct event_ { event_event_79 explicit event_(vvp_time64_t s) : sim_time(s) { 80 ptr_real = 0.0; 81 next = NULL; 82 } 83 void (vvp_fun_delay::*run_run_ptr)(struct vvp_fun_delay::event_*cur); 84 const vvp_time64_t sim_time; 85 vvp_vector4_t ptr_vec4; 86 vvp_vector8_t ptr_vec8; 87 double ptr_real; 88 struct event_*next; 89 }; 90 91 public: 92 vvp_fun_delay(vvp_net_t*net, unsigned width, const vvp_delay_t&d); 93 ~vvp_fun_delay(); 94 95 void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, 96 vvp_context_t); 97 void recv_vec8(vvp_net_ptr_t port, const vvp_vector8_t&bit); 98 void recv_real(vvp_net_ptr_t port, double bit, 99 vvp_context_t); 100 //void recv_long(vvp_net_ptr_t port, long bit); 101 102 void recv_vec4_pv(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, 103 unsigned base, unsigned wid, unsigned vwid, 104 vvp_context_t ctx); 105 void recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit, 106 unsigned base, unsigned wid, unsigned vwid); 107 108 private: 109 virtual void run_run(); 110 111 112 void run_run_vec4_(struct vvp_fun_delay::event_*cur); 113 void run_run_vec8_(struct vvp_fun_delay::event_*cur); 114 void run_run_real_(struct vvp_fun_delay::event_*cur); 115 116 private: 117 vvp_net_t*net_; 118 vvp_delay_t delay_; 119 delay_type_t type_; 120 bool initial_; // Indicates if the value is still the initial value. 121 122 vvp_vector4_t cur_vec4_; 123 vvp_vector8_t cur_vec8_; 124 double cur_real_; 125 vvp_time64_t round_, scale_; // Needed to scale variable time values. 126 127 struct event_ *list_; enqueue_(struct event_ * cur)128 void enqueue_(struct event_*cur) 129 { 130 if (list_) { 131 cur->next = list_->next; 132 list_->next = cur; 133 list_ = cur; 134 } else { 135 cur->next = cur; 136 list_ = cur; 137 } 138 } dequeue_(void)139 struct event_* dequeue_(void) 140 { 141 if (list_ == 0) 142 return 0; 143 struct event_*cur = list_->next; 144 if (list_ == cur) 145 list_ = 0; 146 else 147 list_->next = cur->next; 148 return cur; 149 } 150 bool clean_pulse_events_(vvp_time64_t use_delay, const vvp_vector4_t&bit); 151 bool clean_pulse_events_(vvp_time64_t use_delay, const vvp_vector8_t&bit); 152 bool clean_pulse_events_(vvp_time64_t use_delay, double bit); 153 // Delete this when done! 154 void clean_pulse_events_(vvp_time64_t use_delay); 155 }; 156 157 /* 158 * These objects implement module delay paths. The fun_modpath functor 159 * is the output of the modpath, and the vvp_fun_modpath_src is the 160 * source of the modpath. The modpath source tracks events on the 161 * inputs to enable delays, and the vvp_fun_modpath, when it's time to 162 * schedule, looks at the associated modpath_src objects for which 163 * paths are active. 164 */ 165 class vvp_fun_modpath; 166 class vvp_fun_modpath_src; 167 168 class vvp_fun_modpath : public vvp_net_fun_t, private vvp_gen_event_s { 169 170 public: 171 vvp_fun_modpath(vvp_net_t*net, unsigned width); 172 ~vvp_fun_modpath(); 173 174 void add_modpath_src(vvp_fun_modpath_src*that, bool ifnone); 175 176 void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, 177 vvp_context_t); 178 179 private: 180 virtual void run_run(); 181 182 private: 183 vvp_net_t*net_; 184 185 vvp_vector4_t cur_vec4_; 186 187 vvp_fun_modpath_src*src_list_; 188 vvp_fun_modpath_src*ifnone_list_; 189 190 private: // not implemented 191 vvp_fun_modpath(const vvp_fun_modpath&); 192 vvp_fun_modpath& operator= (const vvp_fun_modpath&); 193 }; 194 195 class vvp_fun_modpath_src : public vvp_net_fun_t { 196 197 friend class vvp_fun_modpath; 198 199 public: 200 explicit vvp_fun_modpath_src(vvp_time64_t d[12]); 201 protected: 202 ~vvp_fun_modpath_src(); 203 204 public: 205 void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, 206 vvp_context_t); 207 virtual bool test_vec4(const vvp_vector4_t&bit); 208 209 void get_delay12(vvp_time64_t out[12]) const; 210 void put_delay12(const vvp_time64_t in[12]); 211 212 private: 213 // FIXME: Needs to be a 12-value array 214 vvp_time64_t delay_[12]; 215 // Used by vvp_fun_modpath to keep a list of modpath_src objects. 216 vvp_fun_modpath_src*next_; 217 218 vvp_time64_t wake_time_; 219 bool condition_flag_; 220 221 private: 222 vvp_fun_modpath_src(const vvp_fun_modpath_src&); 223 vvp_fun_modpath_src& operator = (const vvp_fun_modpath_src&); 224 }; 225 226 class vvp_fun_modpath_edge : public vvp_fun_modpath_src { 227 228 public: 229 vvp_fun_modpath_edge(vvp_time64_t del[12], bool pos, bool neg); 230 231 bool test_vec4(const vvp_vector4_t&bit); 232 233 private: 234 vvp_bit4_t old_value_; 235 bool posedge_; 236 bool negedge_; 237 }; 238 239 #endif /* IVL_delay_H */ 240