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