1 /*
2  * Copyright (c) 2001-2018 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 /*
21  * Callbacks are objects that carry a function to be called when some
22  * event in the simulation occurs. The VPI code create a __vpiCallback
23  * object, and that object is put in some location that the simulation
24  * can look when the event in question is tripped.
25  */
26 
27 # include  "vpi_user.h"
28 # include  "vpi_priv.h"
29 # include  "vvp_net.h"
30 # include  "schedule.h"
31 # include  "event.h"
32 # include  "vvp_net_sig.h"
33 # include  "config.h"
34 #ifdef CHECK_WITH_VALGRIND
35 #include  "vvp_cleanup.h"
36 #endif
37 # include  <cstdio>
38 # include  <cassert>
39 # include  <cstdlib>
40 /*
41  * Callback handles are created when the VPI function registers a
42  * callback. The handle is stored by the run time, and it triggered
43  * when the run-time thing that it is waiting for happens.
44  *
45  * This is the thing that the VPI code references by the vpiHandle. It
46  * also points to callback data that the caller attached to the event,
47  * as well as the time structure to receive data.
48  *
49  * The cb_sync is a private member that points to the schedulable
50  * event that is triggered when the event happens. The sync_cb class
51  * represents the action to execute when the scheduler gets to this
52  * event. This member is only used for things like cbReadOnlySync.
53  */
54 
55 class sync_callback;
56 
57 struct sync_cb  : public vvp_gen_event_s {
58       sync_callback*handle;
59       bool sync_flag;
60 
~sync_cbsync_cb61       ~sync_cb () { }
62 
63       virtual void run_run();
64 };
65 
__vpiCallback()66 inline __vpiCallback::__vpiCallback()
67 {
68       next = 0;
69 }
70 
~__vpiCallback()71 __vpiCallback::~__vpiCallback()
72 {
73 }
74 
get_type_code(void) const75 int __vpiCallback::get_type_code(void) const
76 { return vpiCallback; }
77 
78 
value_callback(p_cb_data data)79 value_callback::value_callback(p_cb_data data)
80 {
81       cb_data = *data;
82       if (data->time) {
83 	    cb_time = *(data->time);
84       } else {
85 	    cb_time.type = vpiSuppressTime;
86       }
87       cb_data.time = &cb_time;
88       if (data->value) {
89 	    cb_value = *(data->value);
90       } else {
91 	    cb_value.format = vpiSuppressVal;
92       }
93       cb_data.value = &cb_value;
94 }
95 
96 /*
97  * Normally, any assign to a value triggers a value change callback,
98  * so return a constant true here. This is a stub.
99  */
test_value_callback_ready(void)100 bool value_callback::test_value_callback_ready(void)
101 {
102       return true;
103 }
104 
vpip_real_value_change(value_callback * cbh,vpiHandle ref)105 static void vpip_real_value_change(value_callback*cbh, vpiHandle ref)
106 {
107       struct __vpiRealVar*rfp = dynamic_cast<__vpiRealVar*>(ref);
108       assert(rfp);
109       vvp_vpi_callback*obj = dynamic_cast<vvp_vpi_callback*>(rfp->net->fil);
110       assert(obj);
111 
112       obj->add_vpi_callback(cbh);
113 }
114 
115 class value_part_callback : public value_callback {
116     public:
117       explicit value_part_callback(p_cb_data data);
118       ~value_part_callback();
119 
120       bool test_value_callback_ready(void);
121 
122     private:
123       char*value_bits_;
124       size_t value_off_;
125 };
126 
value_part_callback(p_cb_data data)127 inline value_part_callback::value_part_callback(p_cb_data data)
128 : value_callback(data)
129 {
130       struct __vpiPV*pobj = dynamic_cast<__vpiPV*>(data->obj);
131       assert(pobj);
132 
133       vvp_vpi_callback*sig_fil;
134       sig_fil = dynamic_cast<vvp_vpi_callback*>(pobj->net->fil);
135       assert(sig_fil);
136 
137       sig_fil->add_vpi_callback(this);
138 	// Get a reference value that can be used to compare with an
139 	// updated value. Use the filter get_value to get the value,
140 	// and get it in BinStr form so that compares are easy. Note
141 	// that the vpiBinStr format has the MSB first, but the tbase
142 	// is lsb first.
143       s_vpi_value tmp_value;
144       tmp_value.format = vpiBinStrVal;
145       sig_fil->get_value(&tmp_value);
146 
147       value_bits_ = new char[pobj->width+1];
148       value_off_ = pobj->parent->vpi_get(vpiSize) - pobj->width - pobj->tbase;
149 
150       memcpy(value_bits_, tmp_value.value.str + value_off_, pobj->width);
151       value_bits_[pobj->width] = 0;
152 }
153 
~value_part_callback()154 value_part_callback::~value_part_callback()
155 {
156       delete[]value_bits_;
157 }
158 
test_value_callback_ready(void)159 bool value_part_callback::test_value_callback_ready(void)
160 {
161       struct __vpiPV*pobj = dynamic_cast<__vpiPV*>(cb_data.obj);
162       assert(pobj);
163 
164       vvp_vpi_callback*sig_fil;
165       sig_fil = dynamic_cast<vvp_vpi_callback*>(pobj->net->fil);
166       assert(sig_fil);
167 
168 	// Get a reference value that can be used to compare with an
169 	// updated value.
170       s_vpi_value tmp_value;
171       tmp_value.format = vpiBinStrVal;
172       sig_fil->get_value(&tmp_value);
173 
174       if (memcmp(value_bits_, tmp_value.value.str + value_off_, pobj->width) == 0)
175 	    return false;
176 
177       memcpy(value_bits_, tmp_value.value.str + value_off_, pobj->width);
178       return true;
179 }
180 
181 /*
182  * Attach the __vpiCallback to the object that this part select
183  * selects from. The part select itself is not a vvp_vpi_callback
184  * object, but it refers to a net that is a vvp_vpi_callback, so
185  * add the callback to that object.
186  */
make_value_change_part(p_cb_data data)187 static value_callback*make_value_change_part(p_cb_data data)
188 {
189 	/* Attach the __vpiCallback object to the signal. */
190       value_callback*cbh = new value_part_callback(data);
191       return cbh;
192 }
193 
194 /*
195  * A value change callback is tripped when a bit of a signal
196  * changes. This function creates that value change callback and
197  * attaches it to the relevant vpiSignal object. Also, if the signal
198  * does not already have them, create some callback functors to do the
199  * actual value change detection.
200  */
make_value_change(p_cb_data data)201 static value_callback* make_value_change(p_cb_data data)
202 {
203       if (vpi_get(vpiAutomatic, data->obj)) {
204             fprintf(stderr, "vpi error: cannot place value change "
205                             "callback on automatically allocated "
206                             "variable '%s'\n",
207                             vpi_get_str(vpiName, data->obj));
208             return 0;
209       }
210 
211 	// Special case: the target object is a vpiPartSelect
212       if (data->obj->get_type_code() == vpiPartSelect) {
213             if (data->obj->vpi_handle(vpiArray))
214 	        return vpip_array_word_change(data);
215             else
216 	        return make_value_change_part(data);
217       }
218 
219       if (data->obj->get_type_code() == vpiMemoryWord)
220 	    return vpip_array_word_change(data);
221 
222       if (data->obj->get_type_code() == vpiMemory)
223 	    return vpip_array_change(data);
224 
225       value_callback*obj = new value_callback(data);
226 
227       assert(data->obj);
228       switch (data->obj->get_type_code()) {
229 
230 	  case vpiReg:
231 	  case vpiNet:
232 	  case vpiIntegerVar:
233 	  case vpiBitVar:
234 	  case vpiByteVar:
235 	  case vpiShortIntVar:
236 	  case vpiIntVar:
237 	  case vpiLongIntVar:
238 	      /* Attach the callback to the vvp_fun_signal node by
239 		 putting it in the vpi_callbacks list. */
240 	    struct __vpiSignal*sig;
241 	    sig = dynamic_cast<__vpiSignal*>(data->obj);
242 
243 	    vvp_net_fil_t*sig_fil;
244 	    sig_fil = dynamic_cast<vvp_net_fil_t*>(sig->node->fil);
245 	    assert(sig_fil);
246 
247 	      /* Attach the __vpiCallback object to the signal. */
248 	    sig_fil->add_vpi_callback(obj);
249 	    break;
250 
251 	  case vpiRealVar:
252 	    vpip_real_value_change(obj, data->obj);
253 	    break;
254 
255 	  case vpiNamedEvent:
256 	    __vpiNamedEvent*nev;
257 	    nev = dynamic_cast<__vpiNamedEvent*>(data->obj);
258 	    nev->add_vpi_callback(obj);
259 	    break;
260 
261 	  case vpiModule:
262 	  case vpiConstant:
263 	  case vpiParameter:
264 	      /* These are constant, so there are no value change
265 		 lists to put them in. */
266 	    break;
267 
268 	  default:
269 	    fprintf(stderr, "make_value_change: sorry: I cannot callback "
270 		    "values on type code=%d\n",
271 		    data->obj->get_type_code());
272 	    delete obj;
273 	    return 0;
274       }
275 
276       return obj;
277 }
278 
279 class sync_callback : public __vpiCallback {
280     public:
281       explicit sync_callback(p_cb_data data);
282       ~sync_callback();
283 
284     public:
285 	// scheduled event
286       struct sync_cb* cb_sync;
287 	// user supplied callback data
288       struct t_vpi_time cb_time;
289 
290     private:
291 };
292 
sync_callback(p_cb_data data)293 inline sync_callback::sync_callback(p_cb_data data)
294 {
295       cb_sync = 0;
296 
297       cb_data = *data;
298       assert(data->time);
299       cb_time = *(data->time);
300       cb_data.time = &cb_time;
301 }
302 
~sync_callback()303 sync_callback::~sync_callback()
304 {
305       delete cb_sync;
306 }
307 
run_run()308 void sync_cb::run_run()
309 {
310       if (handle == 0)
311 	    return;
312 
313       sync_callback*cur = handle;
314       cur->cb_data.time->type = vpiSimTime;
315       vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
316 
317 	/* Run the callback. If the cb_rtn function pointer is set to
318 	   null, then just skip the whole thing and free it. This is
319 	   the usual way to cancel one-time callbacks of this sort. */
320       if (cur->cb_data.cb_rtn != 0) {
321 	    assert(vpi_mode_flag == VPI_MODE_NONE);
322 	    vpi_mode_flag = sync_flag? VPI_MODE_ROSYNC : VPI_MODE_RWSYNC;
323 	    vpip_cur_task = dynamic_cast<__vpiSysTaskCall*>(cur->cb_data.obj);
324 	    (cur->cb_data.cb_rtn)(&cur->cb_data);
325 	    vpip_cur_task = 0;
326 	    vpi_mode_flag = VPI_MODE_NONE;
327       }
328 
329       delete cur;
330 }
331 
make_sync(p_cb_data data,bool readonly_flag)332 static sync_callback* make_sync(p_cb_data data, bool readonly_flag)
333 {
334       sync_callback*obj = new sync_callback(data);
335 
336       struct sync_cb*cb = new sync_cb;
337       cb->sync_flag = readonly_flag? true : false;
338       cb->handle = obj;
339       obj->cb_sync = cb;
340 
341       vvp_time64_t tv = 0;
342       switch (obj->cb_time.type) {
343 	  case vpiSuppressTime:
344 	    break;
345 
346 	  case vpiSimTime:
347 	    tv = vpip_timestruct_to_time(&obj->cb_time);
348 	    break;
349 
350 	  default:
351 	    fprintf(stderr, "Unsupported time type %d.\n",
352 	            (int)obj->cb_time.type);
353 	    assert(0);
354 	    break;
355       }
356       schedule_generic(cb, tv, true, readonly_flag);
357       return obj;
358 }
359 
make_afterdelay(p_cb_data data)360 static struct __vpiCallback* make_afterdelay(p_cb_data data)
361 {
362       sync_callback*obj = new sync_callback(data);
363       struct sync_cb*cb = new sync_cb;
364       cb->sync_flag = false;
365       cb->handle = obj;
366       obj->cb_sync = cb;
367 
368       vvp_time64_t tv = 0;
369       switch (obj->cb_time.type) {
370 	  case vpiSimTime:
371 	    tv = vpip_timestruct_to_time(&obj->cb_time);
372 	    break;
373 
374 	  default:
375 	    fprintf(stderr, "Unsupported time type %d.\n",
376 	            (int)obj->cb_time.type);
377 	    assert(0);
378 	    break;
379       }
380 
381       schedule_generic(cb, tv, false);
382 
383       return obj;
384 }
385 
make_at_start_of_sim_time(p_cb_data data)386 static struct __vpiCallback* make_at_start_of_sim_time(p_cb_data data)
387 {
388       sync_callback*obj = new sync_callback(data);
389       struct sync_cb*cb = new sync_cb;
390       cb->sync_flag = false;
391       cb->handle = obj;
392       obj->cb_sync = cb;
393 
394       vvp_time64_t tv = 0;
395       switch (obj->cb_time.type) {
396 	  case vpiSimTime:
397 	    tv = vpip_timestruct_to_time(&obj->cb_time);
398 	    break;
399 
400 	  default:
401 	    fprintf(stderr, "Unsupported time type %d.\n",
402 	            (int)obj->cb_time.type);
403 	    assert(0);
404 	    break;
405       }
406 
407       vvp_time64_t cur = schedule_simtime();
408       if (cur > tv) {
409 	    tv = 0;
410 	    assert(0);
411       } else if (cur == tv) {
412 	    tv = 0;
413       } else {
414 	    tv -= cur;
415       }
416       schedule_at_start_of_simtime(cb, tv);
417 
418       return obj;
419 }
420 
make_at_end_of_sim_time(p_cb_data data)421 static struct __vpiCallback* make_at_end_of_sim_time(p_cb_data data)
422 {
423       sync_callback*obj = new sync_callback(data);
424       struct sync_cb*cb = new sync_cb;
425       cb->sync_flag = false;
426       cb->handle = obj;
427       obj->cb_sync = cb;
428 
429       vvp_time64_t tv = 0;
430       switch (obj->cb_time.type) {
431 	  case vpiSimTime:
432 	    tv = vpip_timestruct_to_time(&obj->cb_time);
433 	    break;
434 
435 	  default:
436 	    fprintf(stderr, "Unsupported time type %d.\n",
437 	            (int)obj->cb_time.type);
438 	    assert(0);
439 	    break;
440       }
441 
442       vvp_time64_t cur = schedule_simtime();
443       if (cur > tv) {
444 	    tv = 0;
445 	    assert(0);
446       } else if (cur == tv) {
447 	    tv = 0;
448       } else {
449 	    tv -= cur;
450       }
451       schedule_at_end_of_simtime(cb, tv);
452 
453       return obj;
454 }
455 
456 /*
457  * The following functions are the used for pre and post simulation
458  * callbacks.
459  */
460 
461 class simulator_callback : public __vpiCallback {
462     public:
simulator_callback(struct t_cb_data * data)463       inline explicit simulator_callback(struct t_cb_data*data)
464       { cb_data = *data; }
465 
466     public:
467 };
468 
469 static simulator_callback*NextSimTime = 0;
470 static simulator_callback*EndOfCompile = 0;
471 static simulator_callback*StartOfSimulation = 0;
472 static simulator_callback*EndOfSimulation = 0;
473 
474 #ifdef CHECK_WITH_VALGRIND
475 /* This is really only needed if the simulator aborts before starting the
476  * main event loop. For that reason we can skip the next sim time queue. */
simulator_cb_delete(void)477 void simulator_cb_delete(void)
478 {
479       simulator_callback* cur;
480 
481 	/* Delete all the end of compile callbacks. */
482       while (EndOfCompile) {
483 	    cur = EndOfCompile;
484 	    EndOfCompile = dynamic_cast<simulator_callback*>(cur->next);
485 	    delete cur;
486       }
487 
488 	/* Delete all the start of simulation callbacks. */
489       while (StartOfSimulation) {
490 	    cur = StartOfSimulation;
491 	    StartOfSimulation = dynamic_cast<simulator_callback*>(cur->next);
492 	    delete cur;
493       }
494 
495 	/* Delete all the end of simulation callbacks. */
496       while (EndOfSimulation) {
497 	    cur = EndOfSimulation;
498 	    EndOfSimulation = dynamic_cast<simulator_callback*>(cur->next);
499 	    delete cur;
500       }
501 }
502 #endif
503 
vpiEndOfCompile(void)504 void vpiEndOfCompile(void) {
505       simulator_callback* cur;
506 
507       /*
508        * Walk the list of register callbacks, executing them and
509        * freeing them when done.
510        */
511       assert(vpi_mode_flag == VPI_MODE_NONE);
512       vpi_mode_flag = VPI_MODE_RWSYNC;
513 
514       while (EndOfCompile) {
515 	    cur = EndOfCompile;
516 	    EndOfCompile = dynamic_cast<simulator_callback*>(cur->next);
517 	    (cur->cb_data.cb_rtn)(&cur->cb_data);
518 	    delete cur;
519       }
520 
521       vpi_mode_flag = VPI_MODE_NONE;
522 }
523 
vpiStartOfSim(void)524 void vpiStartOfSim(void) {
525       simulator_callback* cur;
526 
527       /*
528        * Walk the list of register callbacks, executing them and
529        * freeing them when done.
530        */
531       assert(vpi_mode_flag == VPI_MODE_NONE);
532       vpi_mode_flag = VPI_MODE_RWSYNC;
533 
534       while (StartOfSimulation) {
535 	    cur = StartOfSimulation;
536 	    StartOfSimulation = dynamic_cast<simulator_callback*>(cur->next);
537 	    (cur->cb_data.cb_rtn)(&cur->cb_data);
538 	    delete cur;
539       }
540 
541       vpi_mode_flag = VPI_MODE_NONE;
542 }
543 
vpiPostsim(void)544 void vpiPostsim(void) {
545       simulator_callback* cur;
546 
547       /*
548        * Walk the list of register callbacks
549        */
550       assert(vpi_mode_flag == VPI_MODE_NONE);
551       vpi_mode_flag = VPI_MODE_ROSYNC;
552 
553       while (EndOfSimulation) {
554 	    cur = EndOfSimulation;
555 	    EndOfSimulation = dynamic_cast<simulator_callback*>(cur->next);
556 	      /* Only set the time if it is not NULL. */
557 	    if (cur->cb_data.time)
558 	          vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
559 	    (cur->cb_data.cb_rtn)(&cur->cb_data);
560 	    delete cur;
561       }
562 
563       vpi_mode_flag = VPI_MODE_NONE;
564 }
565 
566 /*
567  * The scheduler invokes this to clear out callbacks for the next
568  * simulation time.
569  */
vpiNextSimTime(void)570 void vpiNextSimTime(void)
571 {
572       simulator_callback* cur;
573 
574       assert(vpi_mode_flag == VPI_MODE_NONE);
575       vpi_mode_flag = VPI_MODE_RWSYNC;
576 
577       while (NextSimTime) {
578 	    cur = NextSimTime;
579 	    NextSimTime = dynamic_cast<simulator_callback*>(cur->next);
580 	    (cur->cb_data.cb_rtn)(&cur->cb_data);
581 	    delete cur;
582       }
583 
584       vpi_mode_flag = VPI_MODE_NONE;
585 }
586 
make_prepost(p_cb_data data)587 static simulator_callback* make_prepost(p_cb_data data)
588 {
589       simulator_callback*obj = new simulator_callback(data);
590 
591       /* Insert at head of list */
592       switch (data->reason) {
593 	  case cbEndOfCompile:
594 	    obj->next = EndOfCompile;
595 	    EndOfCompile = obj;
596 	    break;
597 	  case cbStartOfSimulation:
598 	    obj->next = StartOfSimulation;
599 	    StartOfSimulation = obj;
600 	    break;
601 	  case cbEndOfSimulation:
602 	    obj->next = EndOfSimulation;
603 	    EndOfSimulation = obj;
604 	    break;
605 	  case cbNextSimTime:
606 	    obj->next = NextSimTime;
607 	    NextSimTime = obj;
608       }
609 
610       return obj;
611 }
612 
vpi_register_cb(p_cb_data data)613 vpiHandle vpi_register_cb(p_cb_data data)
614 {
615       struct __vpiCallback*obj = 0;
616 
617       assert(data);
618       switch (data->reason) {
619 
620 	  case cbValueChange:
621 	    obj = make_value_change(data);
622 	    break;
623 
624 	  case cbReadOnlySynch:
625 	    obj = make_sync(data, true);
626 	    break;
627 
628 	  case cbReadWriteSynch:
629 	    obj = make_sync(data, false);
630 	    break;
631 
632 	  case cbAtStartOfSimTime:
633 	    obj = make_at_start_of_sim_time(data);
634 	    break;
635 
636 	  case cbAtEndOfSimTime:
637 	    obj = make_at_end_of_sim_time(data);
638 	    break;
639 
640 	  case cbAfterDelay:
641 	    obj = make_afterdelay(data);
642 	    break;
643 
644 	  case cbEndOfCompile:
645 	  case cbStartOfSimulation:
646 	  case cbEndOfSimulation:
647 	  case cbNextSimTime:
648 	    obj = make_prepost(data);
649 	    break;
650 
651 	  default:
652 	    fprintf(stderr, "vpi error: vpi_register_cb invalid or "
653 		    "unsupported callback reason: %d\n",
654 		    (int)data->reason);
655 	    break;
656       }
657 
658       return obj;
659 }
660 
661 /*
662  * Removing a callback doesn't really delete it right away. Instead,
663  * it clears the reference to the user callback function. This causes
664  * the callback to quietly reap itself.
665  */
vpi_remove_cb(vpiHandle ref)666 PLI_INT32 vpi_remove_cb(vpiHandle ref)
667 {
668       struct __vpiCallback*obj = dynamic_cast<__vpiCallback*>(ref);
669       assert(obj);
670       obj->cb_data.cb_rtn = 0;
671 
672       return 1;
673 }
674 
callback_execute(struct __vpiCallback * cur)675 void callback_execute(struct __vpiCallback*cur)
676 {
677       const vpi_mode_t save_mode = vpi_mode_flag;
678       vpi_mode_flag = VPI_MODE_RWSYNC;
679 
680       assert(cur->cb_data.cb_rtn);
681       switch (cur->cb_data.time->type) {
682 	  case vpiSimTime:
683 	    vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
684 	    break;
685 	  case vpiScaledRealTime: {
686 	    cur->cb_data.time->real =
687 	         vpip_time_to_scaled_real(schedule_simtime(),
688 	             (__vpiScope *) vpi_handle(vpiScope, cur->cb_data.obj));
689 	    break;
690 	  }
691 	  case vpiSuppressTime:
692 	    break;
693 	  default:
694 	    fprintf(stderr, "Unsupported time format %d.\n",
695 	            (int)cur->cb_data.time->type);
696 	    assert(0);
697 	    break;
698       }
699       (cur->cb_data.cb_rtn)(&cur->cb_data);
700 
701       vpi_mode_flag = save_mode;
702 }
703 
704 /*
705  * Usually there is at most one array word associated with a vvp signal, but
706  * due to port collapsing, there may be more. Using a linked list to record
707  * the array words minimises memory use for the most common case (no array
708  * words) or next most common case (one array word).
709  */
710 struct __vpi_array_word {
711       struct __vpi_array_word* next;
712       struct __vpiArray* array;
713       unsigned long word;
714 };
715 
vvp_vpi_callback()716 vvp_vpi_callback::vvp_vpi_callback()
717 {
718       vpi_callbacks_ = 0;
719       array_words_ = 0;
720 }
721 
~vvp_vpi_callback()722 vvp_vpi_callback::~vvp_vpi_callback()
723 {
724       assert(vpi_callbacks_ == 0);
725       assert(array_words_ == 0);
726 }
727 
attach_as_word(vvp_array_t arr,unsigned long addr)728 void vvp_vpi_callback::attach_as_word(vvp_array_t arr, unsigned long addr)
729 {
730       struct __vpi_array_word*tmp = new __vpi_array_word;
731       tmp->array = arr;
732       tmp->word = addr;
733       tmp->next = array_words_;
734       array_words_ = tmp;
735 }
736 
add_vpi_callback(value_callback * cb)737 void vvp_vpi_callback::add_vpi_callback(value_callback*cb)
738 {
739       cb->next = vpi_callbacks_;
740       vpi_callbacks_ = cb;
741 }
742 
743 #ifdef CHECK_WITH_VALGRIND
clear_all_callbacks()744 void vvp_vpi_callback::clear_all_callbacks()
745 {
746       while (vpi_callbacks_) {
747 	    value_callback *tmp = dynamic_cast<value_callback*>
748 	                            (vpi_callbacks_->next);
749 	    delete vpi_callbacks_;
750 	    vpi_callbacks_ = tmp;
751       }
752       while (array_words_) {
753 	    struct __vpi_array_word*tmp = array_words_->next;
754 	    delete array_words_;
755 	    array_words_ = tmp;
756       }
757 }
758 #endif
759 
760 /*
761  * A vvp_fun_signal uses this method to run its callbacks whenever it
762  * has a value change. If the cb_rtn is non-nil, then call the
763  * callback function. If the cb_rtn pointer is nil, then the object
764  * has been marked for deletion. Free it.
765  */
run_vpi_callbacks()766 void vvp_vpi_callback::run_vpi_callbacks()
767 {
768       struct __vpi_array_word*array_word = array_words_;
769       while (array_word) {
770 	    array_word->array->word_change(array_word->word);
771 	    array_word = array_word->next;
772       }
773 
774       value_callback *next = vpi_callbacks_;
775       value_callback *prev = 0;
776 
777       while (next) {
778 	    value_callback*cur = next;
779 	    next = dynamic_cast<value_callback*>(cur->next);
780 
781 	    if (cur->cb_data.cb_rtn != 0) {
782 		  if (cur->test_value_callback_ready()) {
783 			if (cur->cb_data.value)
784 			      get_value(cur->cb_data.value);
785 
786 			callback_execute(cur);
787 		  }
788 		  prev = cur;
789 
790 	    } else if (prev == 0) {
791 
792 		  vpi_callbacks_ = next;
793 		  cur->next = 0;
794 		  delete cur;
795 
796 	    } else {
797 		  assert(prev->next == cur);
798 		  prev->next = next;
799 		  cur->next = 0;
800 		  delete cur;
801 	    }
802       }
803 }
804 
get_signal_value(struct t_vpi_value * vp)805 void vvp_signal_value::get_signal_value(struct t_vpi_value*vp)
806 {
807       switch (vp->format) {
808 	  case vpiScalarVal:
809 	    // This works because vvp_bit4_t has the same encoding
810 	    // as a scalar value! See vpip_vec4_get_value() for a
811 	    // more robust method.
812 	    vp->value.scalar = value(0);
813 	    break;
814 
815 	  case vpiBinStrVal:
816 	  case vpiOctStrVal:
817 	  case vpiDecStrVal:
818 	  case vpiHexStrVal:
819 	  case vpiIntVal:
820 	  case vpiVectorVal:
821 	  case vpiStringVal:
822 	  case vpiRealVal: {
823 	    unsigned wid = value_size();
824 	    vvp_vector4_t vec4(wid);
825 	    for (unsigned idx = 0; idx < wid; idx += 1) {
826 		  vec4.set_bit(idx, value(idx));
827 	    }
828 	    vpip_vec4_get_value(vec4, wid, false, vp);
829 	    break;
830 	  }
831 
832 	  case vpiSuppressVal:
833 	    break;
834 
835 	  default:
836 	    fprintf(stderr, "vpi_callback: value "
837 		    "format %d not supported (fun_signal)\n",
838 		    (int)vp->format);
839       }
840 }
841 
vlg_round(double rval)842 static double vlg_round(double rval)
843 {
844       if (rval >= 0.0) {
845             return floor(rval + 0.5);
846       } else {
847             return ceil(rval - 0.5);
848       }
849 }
850 
real_signal_value(struct t_vpi_value * vp,double rval)851 static void real_signal_value(struct t_vpi_value*vp, double rval)
852 {
853       char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL);
854 
855       switch (vp->format) {
856 	  case vpiObjTypeVal:
857 	    vp->format = vpiRealVal;
858 	    // fallthrough
859 	  case vpiRealVal:
860 	    vp->value.real = rval;
861 	    break;
862 
863 	  case vpiIntVal:
864 	      /* NaN or +/- infinity are translated as 0. */
865 	    if (rval != rval || (rval && (rval == 0.5*rval))) {
866 		  rval = 0.0;
867 	    } else {
868 		  rval = vlg_round(rval);
869 	    }
870 	    vp->value.integer = (PLI_INT32)rval;
871 	    break;
872 
873 	  case vpiDecStrVal:
874 	    if (isnan(rval))
875 		  sprintf(rbuf, "%s", "nan");
876 	    else
877 		  sprintf(rbuf, "%0.0f", vlg_round(rval));
878 	    vp->value.str = rbuf;
879 	    break;
880 
881 	  case vpiHexStrVal:
882 	    sprintf(rbuf, "%" PRIx64, (uint64_t)vlg_round(rval));
883 	    vp->value.str = rbuf;
884 	    break;
885 
886 	  case vpiBinStrVal: {
887 		uint64_t val = (uint64_t)vlg_round(rval);
888 		unsigned len = 0;
889 
890 		while (val > 0) {
891 		      len += 1;
892 		      val /= 2;
893 		}
894 
895 		val = (uint64_t)vlg_round(rval);
896 		for (unsigned idx = 0 ;  idx < len ;  idx += 1) {
897 		      rbuf[len-idx-1] = (val & 1)? '1' : '0';
898 		      val /= 2;
899 		}
900 
901 		rbuf[len] = 0;
902 		if (len == 0) {
903 		      rbuf[0] = '0';
904 		      rbuf[1] = 0;
905 		}
906 		vp->value.str = rbuf;
907 		break;
908 	  }
909 
910 	  case vpiSuppressVal:
911 	    break;
912 
913 	  default:
914 	    fprintf(stderr, "vpi_callback: value "
915 		    "format %d not supported (fun_signal_real)\n",
916 		    (int)vp->format);
917       }
918 }
919 
get_signal_value(struct t_vpi_value * vp)920 void vvp_fun_signal_real_aa::get_signal_value(struct t_vpi_value*vp)
921 {
922       real_signal_value(vp, real_value());
923 }
924 
get_signal_value(struct t_vpi_value * vp)925 void vvp_wire_real::get_signal_value(struct t_vpi_value*vp)
926 {
927       real_signal_value(vp, real_value());
928 }
929 
get_signal_value(struct t_vpi_value *)930 void vvp_fun_signal_string_aa::get_signal_value(struct t_vpi_value*)
931 {
932       assert(0);
933 }
934 #if 0
935 void vvp_wire_string::get_signal_value(struct t_vpi_value*vp)
936 {
937       assert(0);
938 }
939 #endif
get_value(struct t_vpi_value * val)940 void vvp_wire_vec4::get_value(struct t_vpi_value*val)
941 {
942       get_signal_value(val);
943 }
944 
get_value(struct t_vpi_value * val)945 void vvp_wire_vec8::get_value(struct t_vpi_value*val)
946 {
947       get_signal_value(val);
948 }
949 
get_value(struct t_vpi_value * val)950 void vvp_wire_real::get_value(struct t_vpi_value*val)
951 {
952       get_signal_value(val);
953 }
954 #if 0
955 void vvp_wire_string::get_value(struct t_vpi_value*val)
956 {
957       assert(0);
958 }
959 #endif
960