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