1 /*
2  * Copyright (c) 2004-2020 Stephen Williams (steve@icarus.com)
3  *
4  *    This source code is free software; you can redistribute it
5  *    and/or modify it in source code form under the terms of the GNU
6  *    General Public License as published by the Free Software
7  *    Foundation; either version 2 of the License, or (at your option)
8  *    any later version.
9  *
10  *    This program is distributed in the hope that it will be useful,
11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *    GNU General Public License for more details.
14  *
15  *    You should have received a copy of the GNU General Public License
16  *    along with this program; if not, write to the Free Software
17  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 # include  "event.h"
21 # include  "compile.h"
22 # include  "vthread.h"
23 # include  "schedule.h"
24 # include  "vpi_priv.h"
25 # include  "config.h"
26 # include  <cstring>
27 # include  <cassert>
28 # include  <cstdlib>
29 
30 # include <iostream>
31 
run_waiting_threads_(vthread_t & threads)32 void waitable_hooks_s::run_waiting_threads_(vthread_t&threads)
33 {
34 	// Run the non-blocking event controls.
35       last = &event_ctls;
36       for (evctl*cur = event_ctls; cur != 0;) {
37 	    if (cur->dec_and_run()) {
38 		  evctl*nxt = cur->next;
39 		  delete cur;
40 		  cur = nxt;
41 		  *last = cur;
42 	    } else {
43 		  last = &(cur->next);
44 		  cur = cur->next;
45 	    }
46       }
47 
48       vthread_t tmp = threads;
49       if (tmp == 0) return;
50       threads = 0;
51 
52       vthread_schedule_list(tmp);
53 }
54 
evctl(unsigned long ecount)55 evctl::evctl(unsigned long ecount)
56 {
57       ecount_ = ecount;
58       next = 0;
59 }
60 
dec_and_run()61 bool evctl::dec_and_run()
62 {
63       assert(ecount_ != 0);
64 
65       ecount_ -= 1;
66       if (ecount_ == 0) run_run();
67 
68       return ecount_ == 0;
69 }
70 
evctl_real(__vpiHandle * handle,double value,unsigned long ecount)71 evctl_real::evctl_real(__vpiHandle*handle, double value,
72                        unsigned long ecount)
73 :evctl(ecount)
74 {
75       handle_ = handle;
76       value_ = value;
77 }
78 
run_run()79 void evctl_real::run_run()
80 {
81       t_vpi_value val;
82 
83       val.format = vpiRealVal;
84       val.value.real = value_;
85       vpi_put_value(handle_, &val, 0, vpiNoDelay);
86 }
87 
schedule_evctl(__vpiHandle * handle,double value,vvp_net_t * event,unsigned long ecount)88 void schedule_evctl(__vpiHandle*handle, double value,
89                     vvp_net_t*event, unsigned long ecount)
90 {
91 	// Get the functor we are going to wait on.
92       waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
93       assert(ep);
94 	// Now add this call to the end of the event list.
95       *(ep->last) = new evctl_real(handle, value, ecount);
96       ep->last = &((*(ep->last))->next);
97 }
98 
evctl_vector(vvp_net_ptr_t ptr,const vvp_vector4_t & value,unsigned off,unsigned wid,unsigned long ecount)99 evctl_vector::evctl_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
100                            unsigned off, unsigned wid, unsigned long ecount)
101 :evctl(ecount), ptr_(ptr), value_(value)
102 {
103       off_ = off;
104       wid_ = wid;
105 }
106 
run_run()107 void evctl_vector::run_run()
108 {
109       if (wid_ != 0) {
110 	    vvp_send_vec4_pv(ptr_, value_, off_, value_.size(), wid_, 0);
111       } else {
112 	    vvp_send_vec4(ptr_, value_, 0);
113       }
114 }
115 
schedule_evctl(vvp_net_ptr_t ptr,const vvp_vector4_t & value,unsigned offset,unsigned wid,vvp_net_t * event,unsigned long ecount)116 void schedule_evctl(vvp_net_ptr_t ptr, const vvp_vector4_t&value,
117                     unsigned offset, unsigned wid,
118                     vvp_net_t*event, unsigned long ecount)
119 {
120 	// Get the functor we are going to wait on.
121       waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
122       assert(ep);
123 	// Now add this call to the end of the event list.
124       *(ep->last) = new evctl_vector(ptr, value, offset, wid, ecount);
125       ep->last = &((*(ep->last))->next);
126 }
127 
evctl_array(vvp_array_t memory,unsigned index,const vvp_vector4_t & value,unsigned off,unsigned long ecount)128 evctl_array::evctl_array(vvp_array_t memory, unsigned index,
129                          const vvp_vector4_t&value, unsigned off,
130                          unsigned long ecount)
131 :evctl(ecount), value_(value)
132 {
133       mem_ = memory;
134       idx_ = index;
135       off_ = off;
136 }
137 
run_run()138 void evctl_array::run_run()
139 {
140       mem_->set_word(idx_, off_, value_);
141 }
142 
schedule_evctl(vvp_array_t memory,unsigned index,const vvp_vector4_t & value,unsigned offset,vvp_net_t * event,unsigned long ecount)143 void schedule_evctl(vvp_array_t memory, unsigned index,
144                     const vvp_vector4_t&value, unsigned offset,
145                     vvp_net_t*event, unsigned long ecount)
146 {
147 	// Get the functor we are going to wait on.
148       waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
149       assert(ep);
150 	// Now add this call to the end of the event list.
151       *(ep->last) = new evctl_array(memory, index, value, offset, ecount);
152       ep->last = &((*(ep->last))->next);
153 }
154 
evctl_array_r(vvp_array_t memory,unsigned index,double value,unsigned long ecount)155 evctl_array_r::evctl_array_r(vvp_array_t memory, unsigned index,
156                              double value, unsigned long ecount)
157 :evctl(ecount)
158 {
159       mem_ = memory;
160       idx_ = index;
161       value_ = value;
162 }
163 
run_run()164 void evctl_array_r::run_run()
165 {
166       mem_->set_word(idx_, value_);
167 }
168 
schedule_evctl(vvp_array_t memory,unsigned index,double value,vvp_net_t * event,unsigned long ecount)169 void schedule_evctl(vvp_array_t memory, unsigned index,
170                     double value,
171                     vvp_net_t*event, unsigned long ecount)
172 {
173 	// Get the functor we are going to wait on.
174       waitable_hooks_s*ep = dynamic_cast<waitable_hooks_s*> (event->fun);
175       assert(ep);
176 	// Now add this call to the end of the event list.
177       *(ep->last) = new evctl_array_r(memory, index, value, ecount);
178       ep->last = &((*(ep->last))->next);
179 }
180 
VVP_EDGE(vvp_bit4_t from,vvp_bit4_t to)181 inline vvp_fun_edge::edge_t VVP_EDGE(vvp_bit4_t from, vvp_bit4_t to)
182 {
183       return 1 << ((from << 2) | to);
184 }
185 
186 const vvp_fun_edge::edge_t vvp_edge_posedge
187       = VVP_EDGE(BIT4_0,BIT4_1)
188       | VVP_EDGE(BIT4_0,BIT4_X)
189       | VVP_EDGE(BIT4_0,BIT4_Z)
190       | VVP_EDGE(BIT4_X,BIT4_1)
191       | VVP_EDGE(BIT4_Z,BIT4_1)
192       ;
193 
194 const vvp_fun_edge::edge_t vvp_edge_negedge
195       = VVP_EDGE(BIT4_1,BIT4_0)
196       | VVP_EDGE(BIT4_1,BIT4_X)
197       | VVP_EDGE(BIT4_1,BIT4_Z)
198       | VVP_EDGE(BIT4_X,BIT4_0)
199       | VVP_EDGE(BIT4_Z,BIT4_0)
200       ;
201 
202 const vvp_fun_edge::edge_t vvp_edge_none    = 0;
203 
204 struct vvp_fun_edge_state_s : public waitable_state_s {
vvp_fun_edge_state_svvp_fun_edge_state_s205       vvp_fun_edge_state_s()
206       {
207             for (unsigned idx = 0 ;  idx < 4 ;  idx += 1)
208                   bits[idx] = BIT4_X;
209       }
210 
211       vvp_bit4_t bits[4];
212 };
213 
vvp_fun_edge(edge_t e)214 vvp_fun_edge::vvp_fun_edge(edge_t e)
215 : edge_(e)
216 {
217       for (unsigned idx = 0 ;  idx < 4 ;  idx += 1)
218             bits_[idx] = BIT4_X;
219 }
220 
~vvp_fun_edge()221 vvp_fun_edge::~vvp_fun_edge()
222 {
223 }
224 
recv_vec4_(const vvp_vector4_t & bit,vvp_bit4_t & old_bit,vthread_t & threads)225 bool vvp_fun_edge::recv_vec4_(const vvp_vector4_t&bit,
226                               vvp_bit4_t&old_bit, vthread_t&threads)
227 {
228 	/* See what kind of edge this represents. */
229       edge_t mask = VVP_EDGE(old_bit, bit.value(0));
230 
231 	/* Save the current input for the next time around. */
232       old_bit = bit.value(0);
233 
234       if ((edge_ == vvp_edge_none) || (edge_ & mask)) {
235 	    run_waiting_threads_(threads);
236             return true;
237       }
238       return false;
239 }
240 
vvp_fun_edge_sa(edge_t e)241 vvp_fun_edge_sa::vvp_fun_edge_sa(edge_t e)
242 : vvp_fun_edge(e), threads_(0)
243 {
244 }
245 
~vvp_fun_edge_sa()246 vvp_fun_edge_sa::~vvp_fun_edge_sa()
247 {
248 }
249 
add_waiting_thread(vthread_t thread)250 vthread_t vvp_fun_edge_sa::add_waiting_thread(vthread_t thread)
251 {
252       vthread_t tmp = threads_;
253       threads_ = thread;
254 
255       return tmp;
256 }
257 
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t)258 void vvp_fun_edge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
259                                 vvp_context_t)
260 {
261       if (recv_vec4_(bit, bits_[port.port()], threads_)) {
262 	    vvp_net_t*net = port.ptr();
263 	    net->send_vec4(bit, 0);
264       }
265 }
266 
recv_vec4_pv(vvp_net_ptr_t port,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t)267 void vvp_fun_edge_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
268 				   unsigned base, unsigned wid, unsigned vwid,
269 				   vvp_context_t)
270 {
271       assert(base == 0);
272       if (recv_vec4_(bit, bits_[port.port()], threads_)) {
273 	    vvp_net_t*net = port.ptr();
274 	    net->send_vec4_pv(bit, base, wid, vwid, 0);
275       }
276 }
277 
vvp_fun_edge_aa(edge_t e)278 vvp_fun_edge_aa::vvp_fun_edge_aa(edge_t e)
279 : vvp_fun_edge(e)
280 {
281       context_scope_ = vpip_peek_context_scope();
282       context_idx_ = vpip_add_item_to_context(this, context_scope_);
283 }
284 
~vvp_fun_edge_aa()285 vvp_fun_edge_aa::~vvp_fun_edge_aa()
286 {
287 }
288 
alloc_instance(vvp_context_t context)289 void vvp_fun_edge_aa::alloc_instance(vvp_context_t context)
290 {
291       vvp_set_context_item(context, context_idx_, new vvp_fun_edge_state_s);
292       reset_instance(context);
293 }
294 
reset_instance(vvp_context_t context)295 void vvp_fun_edge_aa::reset_instance(vvp_context_t context)
296 {
297       vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
298             (vvp_get_context_item(context, context_idx_));
299 
300       state->threads = 0;
301       for (unsigned idx = 0 ;  idx < 4 ;  idx += 1)
302             state->bits[idx] = bits_[idx];
303 }
304 
305 #ifdef CHECK_WITH_VALGRIND
free_instance(vvp_context_t context)306 void vvp_fun_edge_aa::free_instance(vvp_context_t context)
307 {
308       vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
309             (vvp_get_context_item(context, context_idx_));
310       delete state;
311 }
312 #endif
313 
add_waiting_thread(vthread_t thread)314 vthread_t vvp_fun_edge_aa::add_waiting_thread(vthread_t thread)
315 {
316       vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
317             (vthread_get_wt_context_item(context_idx_));
318 
319       vthread_t tmp = state->threads;
320       state->threads = thread;
321 
322       return tmp;
323 }
324 
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t context)325 void vvp_fun_edge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
326                                 vvp_context_t context)
327 {
328       if (context) {
329             vvp_fun_edge_state_s*state = static_cast<vvp_fun_edge_state_s*>
330                   (vvp_get_context_item(context, context_idx_));
331 
332             if (recv_vec4_(bit, state->bits[port.port()], state->threads)) {
333                   vvp_net_t*net = port.ptr();
334                   net->send_vec4(bit, context);
335             }
336       } else {
337             context = context_scope_->live_contexts;
338             while (context) {
339                   recv_vec4(port, bit, context);
340                   context = vvp_get_next_context(context);
341             }
342             bits_[port.port()] = bit.value(0);
343       }
344 }
345 
346 class anyedge_value {
347 
348     public:
anyedge_value()349       anyedge_value() {};
~anyedge_value()350       virtual ~anyedge_value() {};
351 
352       virtual void reset() = 0;
353 
354       virtual void duplicate(anyedge_value*&dup) = 0;
355 };
356 
357 class anyedge_vec4_value : public anyedge_value {
358 
359     public:
anyedge_vec4_value()360       anyedge_vec4_value() {};
~anyedge_vec4_value()361       virtual ~anyedge_vec4_value() {};
362 
reset()363       void reset() { old_bits.set_to_x(); }
364 
set(const vvp_vector4_t & bit)365       void set(const vvp_vector4_t&bit) { old_bits = bit; };
366 
367       void duplicate(anyedge_value*&dup);
368 
369       bool recv_vec4(const vvp_vector4_t&bit);
370 
371       bool recv_vec4_pv(const vvp_vector4_t&bit, unsigned base,
372 			unsigned wid, unsigned vwid);
373 
374     private:
375       vvp_vector4_t old_bits;
376 };
377 
get_vec4_value(anyedge_value * & value)378 static anyedge_vec4_value*get_vec4_value(anyedge_value*&value)
379 {
380       anyedge_vec4_value*vec4_value = dynamic_cast<anyedge_vec4_value*>(value);
381       if (!value) {
382 	    vec4_value = new anyedge_vec4_value();
383 	    delete value;
384 	    value = vec4_value;
385       }
386       return vec4_value;
387 }
388 
389 class anyedge_real_value : public anyedge_value {
390 
391     public:
anyedge_real_value()392       anyedge_real_value() : old_bits(0.0) {};
~anyedge_real_value()393       virtual ~anyedge_real_value() {};
394 
reset()395       void reset() { old_bits = 0.0; }
396 
set(double bit)397       void set(double bit) { old_bits = bit; };
398 
399       void duplicate(anyedge_value*&dup);
400 
401       bool recv_real(double bit);
402 
403     private:
404       double old_bits;
405 };
406 
get_real_value(anyedge_value * & value)407 static anyedge_real_value*get_real_value(anyedge_value*&value)
408 {
409       anyedge_real_value*real_value = dynamic_cast<anyedge_real_value*>(value);
410       if (!value) {
411 	    real_value = new anyedge_real_value();
412 	    delete value;
413 	    value = real_value;
414       }
415       return real_value;
416 }
417 
418 class anyedge_string_value : public anyedge_value {
419 
420     public:
anyedge_string_value()421       anyedge_string_value() {};
~anyedge_string_value()422       virtual ~anyedge_string_value() {};
423 
reset()424       void reset() { old_bits.clear(); }
425 
set(const std::string & bit)426       void set(const std::string&bit) { old_bits = bit; };
427 
428       void duplicate(anyedge_value*&dup);
429 
430       bool recv_string(const std::string&bit);
431 
432     private:
433       std::string old_bits;
434 };
435 
get_string_value(anyedge_value * & value)436 static anyedge_string_value*get_string_value(anyedge_value*&value)
437 {
438       anyedge_string_value*string_value = dynamic_cast<anyedge_string_value*>(value);
439       if (!value) {
440 	    string_value = new anyedge_string_value();
441 	    delete value;
442 	    value = string_value;
443       }
444       return string_value;
445 }
446 
447 struct vvp_fun_anyedge_state_s : public waitable_state_s {
vvp_fun_anyedge_state_svvp_fun_anyedge_state_s448       vvp_fun_anyedge_state_s()
449       {
450             for (unsigned idx = 0 ;  idx < 4 ;  idx += 1)
451                   last_value_[idx] = 0;
452       }
453 
~vvp_fun_anyedge_state_svvp_fun_anyedge_state_s454       ~vvp_fun_anyedge_state_s()
455       {
456             for (unsigned idx = 0 ;  idx < 4 ;  idx += 1)
457                   delete last_value_[idx];
458       }
459 
460       anyedge_value *last_value_[4];
461 };
462 
vvp_fun_anyedge()463 vvp_fun_anyedge::vvp_fun_anyedge()
464 {
465       for (unsigned idx = 0 ;  idx < 4 ;  idx += 1)
466 	    last_value_[idx] = 0;
467 }
468 
~vvp_fun_anyedge()469 vvp_fun_anyedge::~vvp_fun_anyedge()
470 {
471       for (unsigned idx = 0 ;  idx < 4 ;  idx += 1)
472 	    delete last_value_[idx];
473 }
474 
duplicate(anyedge_value * & dup)475 void anyedge_vec4_value::duplicate(anyedge_value*&dup)
476 {
477       anyedge_vec4_value*dup_vec4 = get_vec4_value(dup);
478       assert(dup_vec4);
479       dup_vec4->set(old_bits);
480 }
481 
recv_vec4(const vvp_vector4_t & bit)482 bool anyedge_vec4_value::recv_vec4(const vvp_vector4_t&bit)
483 {
484       bool flag = false;
485 
486       if (old_bits.size() != bit.size()) {
487 	    if (old_bits.size() == 0) {
488 		    // Special case: If we've not seen any input yet
489 		    // (old_bits.size()==0) then replace it will a reference
490 		    // vector that is 'bx. Then compare that with the input
491 		    // to see if we are processing a change from 'bx.
492 		  old_bits = vvp_vector4_t(bit.size(), BIT4_X);
493 		  if (old_bits.eeq(bit))
494 			flag = false;
495 		  else
496 			flag = true;
497 
498 	    } else {
499 		  flag = true;
500 	    }
501 
502       } else {
503 	    for (unsigned idx = 0 ;  idx < bit.size() ;  idx += 1) {
504 		  if (old_bits.value(idx) != bit.value(idx)) {
505 			flag = true;
506 			break;
507 		  }
508 	    }
509       }
510 
511       if (flag) {
512 	    old_bits = bit;
513       }
514 
515       return flag;
516 }
517 
recv_vec4_pv(const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid)518 bool anyedge_vec4_value::recv_vec4_pv(const vvp_vector4_t&bit, unsigned base,
519 				      unsigned wid, unsigned vwid)
520 {
521       vvp_vector4_t tmp = old_bits;
522       if (tmp.size() == 0)
523 	    tmp = vvp_vector4_t(vwid, BIT4_Z);
524       assert(wid == bit.size());
525       assert(base+wid <= vwid);
526       assert(tmp.size() == vwid);
527       tmp.set_vec(base, bit);
528 
529       return recv_vec4(tmp);
530 }
531 
duplicate(anyedge_value * & dup)532 void anyedge_real_value::duplicate(anyedge_value*&dup)
533 {
534       anyedge_real_value*dup_real = get_real_value(dup);
535       assert(dup_real);
536       dup_real->set(old_bits);
537 }
538 
recv_real(double bit)539 bool anyedge_real_value::recv_real(double bit)
540 {
541       if (old_bits != bit) {
542 	    old_bits = bit;
543             return true;
544       }
545       return false;
546 }
547 
duplicate(anyedge_value * & dup)548 void anyedge_string_value::duplicate(anyedge_value*&dup)
549 {
550       anyedge_string_value*dup_string = get_string_value(dup);
551       assert(dup_string);
552       dup_string->set(old_bits);
553 }
554 
recv_string(const std::string & bit)555 bool anyedge_string_value::recv_string(const std::string&bit)
556 {
557       if (old_bits != bit) {
558 	    old_bits = bit;
559             return true;
560       }
561       return false;
562 }
563 
vvp_fun_anyedge_sa()564 vvp_fun_anyedge_sa::vvp_fun_anyedge_sa()
565 : threads_(0)
566 {
567 }
568 
~vvp_fun_anyedge_sa()569 vvp_fun_anyedge_sa::~vvp_fun_anyedge_sa()
570 {
571 }
572 
add_waiting_thread(vthread_t thread)573 vthread_t vvp_fun_anyedge_sa::add_waiting_thread(vthread_t thread)
574 {
575       vthread_t tmp = threads_;
576       threads_ = thread;
577 
578       return tmp;
579 }
580 
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t)581 void vvp_fun_anyedge_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
582                                    vvp_context_t)
583 {
584       anyedge_vec4_value*value = get_vec4_value(last_value_[port.port()]);
585       assert(value);
586       if (value->recv_vec4(bit)) {
587 	    run_waiting_threads_(threads_);
588 	    vvp_net_t*net = port.ptr();
589 	    net->send_vec4(bit, 0);
590       }
591 }
592 
recv_vec4_pv(vvp_net_ptr_t port,const vvp_vector4_t & bit,unsigned base,unsigned wid,unsigned vwid,vvp_context_t)593 void vvp_fun_anyedge_sa::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit,
594 				      unsigned base, unsigned wid, unsigned vwid,
595 				      vvp_context_t)
596 {
597       anyedge_vec4_value*value = get_vec4_value(last_value_[port.port()]);
598       assert(value);
599       if (value->recv_vec4_pv(bit, base, wid, vwid)) {
600 	    run_waiting_threads_(threads_);
601 	    vvp_net_t*net = port.ptr();
602 	    net->send_vec4(bit, 0);
603       }
604 }
605 
recv_real(vvp_net_ptr_t port,double bit,vvp_context_t)606 void vvp_fun_anyedge_sa::recv_real(vvp_net_ptr_t port, double bit,
607                                    vvp_context_t)
608 {
609       anyedge_real_value*value = get_real_value(last_value_[port.port()]);
610       assert(value);
611       if (value->recv_real(bit)) {
612 	    run_waiting_threads_(threads_);
613 	    vvp_net_t*net = port.ptr();
614 	    net->send_vec4(vvp_vector4_t(), 0);
615       }
616 }
617 
recv_string(vvp_net_ptr_t port,const std::string & bit,vvp_context_t)618 void vvp_fun_anyedge_sa::recv_string(vvp_net_ptr_t port, const std::string&bit,
619 				     vvp_context_t)
620 {
621       anyedge_string_value*value = get_string_value(last_value_[port.port()]);
622       assert(value);
623       if (value->recv_string(bit)) {
624 	    run_waiting_threads_(threads_);
625 	    vvp_net_t*net = port.ptr();
626 	    net->send_vec4(vvp_vector4_t(), 0);
627       }
628 }
629 
vvp_fun_anyedge_aa()630 vvp_fun_anyedge_aa::vvp_fun_anyedge_aa()
631 {
632       context_scope_ = vpip_peek_context_scope();
633       context_idx_ = vpip_add_item_to_context(this, context_scope_);
634 }
635 
~vvp_fun_anyedge_aa()636 vvp_fun_anyedge_aa::~vvp_fun_anyedge_aa()
637 {
638 }
639 
alloc_instance(vvp_context_t context)640 void vvp_fun_anyedge_aa::alloc_instance(vvp_context_t context)
641 {
642       vvp_set_context_item(context, context_idx_, new vvp_fun_anyedge_state_s);
643       reset_instance(context);
644 }
645 
reset_instance(vvp_context_t context)646 void vvp_fun_anyedge_aa::reset_instance(vvp_context_t context)
647 {
648       vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
649             (vvp_get_context_item(context, context_idx_));
650 
651       state->threads = 0;
652       for (unsigned idx = 0 ;  idx < 4 ;  idx += 1) {
653 	    if (last_value_[idx])
654 	          last_value_[idx]->duplicate(state->last_value_[idx]);
655 	    else if (state->last_value_[idx])
656 		  state->last_value_[idx]->reset();
657       }
658 }
659 
660 #ifdef CHECK_WITH_VALGRIND
free_instance(vvp_context_t context)661 void vvp_fun_anyedge_aa::free_instance(vvp_context_t context)
662 {
663       vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
664             (vvp_get_context_item(context, context_idx_));
665       delete state;
666 }
667 #endif
668 
add_waiting_thread(vthread_t thread)669 vthread_t vvp_fun_anyedge_aa::add_waiting_thread(vthread_t thread)
670 {
671       vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
672             (vthread_get_wt_context_item(context_idx_));
673 
674       vthread_t tmp = state->threads;
675       state->threads = thread;
676 
677       return tmp;
678 }
679 
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t context)680 void vvp_fun_anyedge_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
681                                    vvp_context_t context)
682 {
683       if (context) {
684             vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
685                   (vvp_get_context_item(context, context_idx_));
686 
687             anyedge_vec4_value*value = get_vec4_value(state->last_value_[port.port()]);
688             assert(value);
689             if (value->recv_vec4(bit)) {
690                   run_waiting_threads_(state->threads);
691                   vvp_net_t*net = port.ptr();
692                   net->send_vec4(bit, context);
693             }
694       } else {
695             context = context_scope_->live_contexts;
696             while (context) {
697                   recv_vec4(port, bit, context);
698                   context = vvp_get_next_context(context);
699             }
700             anyedge_vec4_value*value = get_vec4_value(last_value_[port.port()]);
701             assert(value);
702             value->set(bit);
703       }
704 }
705 
recv_real(vvp_net_ptr_t port,double bit,vvp_context_t context)706 void vvp_fun_anyedge_aa::recv_real(vvp_net_ptr_t port, double bit,
707                                    vvp_context_t context)
708 {
709       if (context) {
710             vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
711                   (vvp_get_context_item(context, context_idx_));
712 
713             anyedge_real_value*value = get_real_value(state->last_value_[port.port()]);
714             assert(value);
715             if (value->recv_real(bit)) {
716                   run_waiting_threads_(state->threads);
717                   vvp_net_t*net = port.ptr();
718                   net->send_vec4(vvp_vector4_t(), context);
719             }
720       } else {
721             context = context_scope_->live_contexts;
722             while (context) {
723                   recv_real(port, bit, context);
724                   context = vvp_get_next_context(context);
725             }
726             anyedge_real_value*value = get_real_value(last_value_[port.port()]);
727             assert(value);
728             value->set(bit);
729       }
730 }
731 
recv_string(vvp_net_ptr_t port,const std::string & bit,vvp_context_t context)732 void vvp_fun_anyedge_aa::recv_string(vvp_net_ptr_t port, const std::string&bit,
733 				     vvp_context_t context)
734 {
735       if (context) {
736             vvp_fun_anyedge_state_s*state = static_cast<vvp_fun_anyedge_state_s*>
737                   (vvp_get_context_item(context, context_idx_));
738 
739             anyedge_string_value*value = get_string_value(state->last_value_[port.port()]);
740             assert(value);
741             if (value->recv_string(bit)) {
742                   run_waiting_threads_(state->threads);
743                   vvp_net_t*net = port.ptr();
744                   net->send_vec4(vvp_vector4_t(), context);
745             }
746       } else {
747             context = context_scope_->live_contexts;
748             while (context) {
749                   recv_string(port, bit, context);
750                   context = vvp_get_next_context(context);
751             }
752             anyedge_string_value*value = get_string_value(last_value_[port.port()]);
753             assert(value);
754             value->set(bit);
755       }
756 }
757 
vvp_fun_event_or()758 vvp_fun_event_or::vvp_fun_event_or()
759 {
760 }
761 
~vvp_fun_event_or()762 vvp_fun_event_or::~vvp_fun_event_or()
763 {
764 }
765 
vvp_fun_event_or_sa()766 vvp_fun_event_or_sa::vvp_fun_event_or_sa()
767 : threads_(0)
768 {
769 }
770 
~vvp_fun_event_or_sa()771 vvp_fun_event_or_sa::~vvp_fun_event_or_sa()
772 {
773 }
774 
add_waiting_thread(vthread_t thread)775 vthread_t vvp_fun_event_or_sa::add_waiting_thread(vthread_t thread)
776 {
777       vthread_t tmp = threads_;
778       threads_ = thread;
779 
780       return tmp;
781 }
782 
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t)783 void vvp_fun_event_or_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
784                                     vvp_context_t)
785 {
786       run_waiting_threads_(threads_);
787       vvp_net_t*net = port.ptr();
788       net->send_vec4(bit, 0);
789 }
790 
vvp_fun_event_or_aa()791 vvp_fun_event_or_aa::vvp_fun_event_or_aa()
792 {
793       context_scope_ = vpip_peek_context_scope();
794       context_idx_ = vpip_add_item_to_context(this, context_scope_);
795 }
796 
~vvp_fun_event_or_aa()797 vvp_fun_event_or_aa::~vvp_fun_event_or_aa()
798 {
799 }
800 
alloc_instance(vvp_context_t context)801 void vvp_fun_event_or_aa::alloc_instance(vvp_context_t context)
802 {
803       vvp_set_context_item(context, context_idx_, new waitable_state_s);
804 }
805 
reset_instance(vvp_context_t context)806 void vvp_fun_event_or_aa::reset_instance(vvp_context_t context)
807 {
808       waitable_state_s*state = static_cast<waitable_state_s*>
809             (vvp_get_context_item(context, context_idx_));
810 
811       state->threads = 0;
812 }
813 
814 #ifdef CHECK_WITH_VALGRIND
free_instance(vvp_context_t context)815 void vvp_fun_event_or_aa::free_instance(vvp_context_t context)
816 {
817       waitable_state_s*state = static_cast<waitable_state_s*>
818             (vvp_get_context_item(context, context_idx_));
819       delete state;
820 }
821 #endif
822 
add_waiting_thread(vthread_t thread)823 vthread_t vvp_fun_event_or_aa::add_waiting_thread(vthread_t thread)
824 {
825       waitable_state_s*state = static_cast<waitable_state_s*>
826             (vthread_get_wt_context_item(context_idx_));
827 
828       vthread_t tmp = state->threads;
829       state->threads = thread;
830 
831       return tmp;
832 }
833 
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t context)834 void vvp_fun_event_or_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
835                                     vvp_context_t context)
836 {
837       if (context) {
838             waitable_state_s*state = static_cast<waitable_state_s*>
839                   (vvp_get_context_item(context, context_idx_));
840 
841             run_waiting_threads_(state->threads);
842             vvp_net_t*net = port.ptr();
843             net->send_vec4(bit, context);
844       } else {
845             context = context_scope_->live_contexts;
846             while (context) {
847                   recv_vec4(port, bit, context);
848                   context = vvp_get_next_context(context);
849             }
850       }
851 }
852 
vvp_named_event(__vpiHandle * h)853 vvp_named_event::vvp_named_event(__vpiHandle*h)
854 {
855       handle_ = h;
856 }
857 
~vvp_named_event()858 vvp_named_event::~vvp_named_event()
859 {
860 }
861 
vvp_named_event_sa(__vpiHandle * h)862 vvp_named_event_sa::vvp_named_event_sa(__vpiHandle*h)
863 : vvp_named_event(h), threads_(0)
864 {
865 }
866 
~vvp_named_event_sa()867 vvp_named_event_sa::~vvp_named_event_sa()
868 {
869 }
870 
add_waiting_thread(vthread_t thread)871 vthread_t vvp_named_event_sa::add_waiting_thread(vthread_t thread)
872 {
873       vthread_t tmp = threads_;
874       threads_ = thread;
875 
876       return tmp;
877 }
878 
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t)879 void vvp_named_event_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
880                                    vvp_context_t)
881 {
882       run_waiting_threads_(threads_);
883       vvp_net_t*net = port.ptr();
884       net->send_vec4(bit, 0);
885 
886       __vpiNamedEvent*obj = dynamic_cast<__vpiNamedEvent*>(handle_);
887       assert(obj);
888       obj->run_vpi_callbacks();
889 }
890 
vvp_named_event_aa(__vpiHandle * h)891 vvp_named_event_aa::vvp_named_event_aa(__vpiHandle*h)
892 : vvp_named_event(h)
893 {
894       context_idx_ = vpip_add_item_to_context(this, vpip_peek_context_scope());
895 }
896 
~vvp_named_event_aa()897 vvp_named_event_aa::~vvp_named_event_aa()
898 {
899 }
900 
alloc_instance(vvp_context_t context)901 void vvp_named_event_aa::alloc_instance(vvp_context_t context)
902 {
903       vvp_set_context_item(context, context_idx_, new waitable_state_s);
904 }
905 
reset_instance(vvp_context_t context)906 void vvp_named_event_aa::reset_instance(vvp_context_t context)
907 {
908       waitable_state_s*state = static_cast<waitable_state_s*>
909             (vvp_get_context_item(context, context_idx_));
910 
911       state->threads = 0;
912 }
913 
914 #ifdef CHECK_WITH_VALGRIND
free_instance(vvp_context_t context)915 void vvp_named_event_aa::free_instance(vvp_context_t context)
916 {
917       waitable_state_s*state = static_cast<waitable_state_s*>
918             (vvp_get_context_item(context, context_idx_));
919       delete state;
920 }
921 #endif
922 
add_waiting_thread(vthread_t thread)923 vthread_t vvp_named_event_aa::add_waiting_thread(vthread_t thread)
924 {
925       waitable_state_s*state = static_cast<waitable_state_s*>
926             (vthread_get_wt_context_item(context_idx_));
927 
928       vthread_t tmp = state->threads;
929       state->threads = thread;
930 
931       return tmp;
932 }
933 
recv_vec4(vvp_net_ptr_t port,const vvp_vector4_t & bit,vvp_context_t context)934 void vvp_named_event_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit,
935                                    vvp_context_t context)
936 {
937       assert(context);
938 
939       waitable_state_s*state = static_cast<waitable_state_s*>
940             (vvp_get_context_item(context, context_idx_));
941 
942       run_waiting_threads_(state->threads);
943       vvp_net_t*net = port.ptr();
944       net->send_vec4(bit, context);
945 }
946 
947 /*
948 **  Create an event functor
949 **  edge:  compile_event(label, type, argc, argv, debug_flag)
950 **  or:    compile_event(label, NULL, argc, argv, debug_flag)
951 **
952 **  Named events are handled elsewhere.
953 */
954 
955 static void compile_event_or(char*label, unsigned argc, struct symb_s*argv);
956 
compile_event(char * label,char * type,unsigned argc,struct symb_s * argv)957 void compile_event(char*label, char*type, unsigned argc, struct symb_s*argv)
958 {
959       vvp_net_fun_t*fun = 0;
960 
961       if (type == 0) {
962 	    compile_event_or(label, argc, argv);
963 	    return;
964       }
965 
966       if (strcmp(type,"edge") == 0) {
967 
968 	    free(type);
969 
970             if (vpip_peek_current_scope()->is_automatic()) {
971                   fun = new vvp_fun_anyedge_aa;
972             } else {
973                   fun = new vvp_fun_anyedge_sa;
974             }
975 
976       } else {
977 
978 	    vvp_fun_edge::edge_t edge = vvp_edge_none;
979 
980 	    if (strcmp(type,"posedge") == 0)
981 		  edge = vvp_edge_posedge;
982 	    else if (strcmp(type,"negedge") == 0)
983 		  edge = vvp_edge_negedge;
984 
985 	    assert(argc <= 4);
986 	    free(type);
987 
988             if (vpip_peek_current_scope()->is_automatic()) {
989                   fun = new vvp_fun_edge_aa(edge);
990             } else {
991                   fun = new vvp_fun_edge_sa(edge);
992             }
993 
994       }
995 
996       vvp_net_t* ptr = new vvp_net_t;
997       ptr->fun = fun;
998 
999       define_functor_symbol(label, ptr);
1000       free(label);
1001 
1002       inputs_connect(ptr, argc, argv);
1003       free(argv);
1004 }
1005 
compile_event_or(char * label,unsigned argc,struct symb_s * argv)1006 static void compile_event_or(char*label, unsigned argc, struct symb_s*argv)
1007 {
1008       vvp_net_t* ptr = new vvp_net_t;
1009       if (vpip_peek_current_scope()->is_automatic()) {
1010             ptr->fun = new vvp_fun_event_or_aa;
1011       } else {
1012             ptr->fun = new vvp_fun_event_or_sa;
1013       }
1014       define_functor_symbol(label, ptr);
1015       free(label);
1016 
1017 	/* This is a very special case. Point all the source inputs to
1018 	   the same input. It doesn't matter that the streams get
1019 	   tangled because data values are irrelevant. */
1020       for (unsigned idx = 0 ;  idx < argc ;  idx += 1) {
1021 	    input_connect(ptr, 0, argv[idx].text);
1022       }
1023       free(argv);
1024 }
1025 
1026 /*
1027  * This handles the compile of named events. This functor has no
1028  * inputs, it is only accessed by behavioral trigger statements, which
1029  * in vvp are %set instructions.
1030  */
compile_named_event(char * label,char * name,bool local_flag)1031 void compile_named_event(char*label, char*name, bool local_flag)
1032 {
1033       vvp_net_t*ptr = new vvp_net_t;
1034 
1035       vpiHandle obj = vpip_make_named_event(name, ptr);
1036 
1037       if (vpip_peek_current_scope()->is_automatic()) {
1038             ptr->fun = new vvp_named_event_aa(obj);
1039       } else {
1040             ptr->fun = new vvp_named_event_sa(obj);
1041       }
1042       define_functor_symbol(label, ptr);
1043       compile_vpi_symbol(label, obj);
1044       if (! local_flag) vpip_attach_to_current_scope(obj);
1045 
1046       free(label);
1047       delete[] name;
1048 }
1049 
1050 #ifdef CHECK_WITH_VALGRIND
named_event_delete(__vpiHandle * handle)1051 void named_event_delete(__vpiHandle*handle)
1052 {
1053       delete dynamic_cast<__vpiNamedEvent *>(handle);
1054 }
1055 #endif
1056