Fix for assertion error when expanding macro.
[iverilog.git] / vvp / vpi_callback.cc
blob7f1f12f9ddbda168f1432cd91b3cbd4dd25e7201
1 /*
2 * Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: vpi_callback.cc,v 1.46 2007/04/10 04:32:05 steve Exp $"
21 #endif
24 * Callbacks are objects that carry a function to be called when some
25 * event in the simulation occurs. The VPI code create a __vpiCallback
26 * object, and that object is put in some location that the simulation
27 * can look when the event in question is tripped.
30 # include <vpi_user.h>
31 # include "vpi_priv.h"
32 # include "vvp_net.h"
33 # include "schedule.h"
34 # include "event.h"
35 # include <stdio.h>
36 # include <assert.h>
37 #ifdef HAVE_MALLOC_H
38 # include <malloc.h>
39 #endif
40 # include <stdlib.h>
43 * The vpi_free_object() call to a callback doesn't actually delete
44 * anything, we instead allow the object to run its course and delete
45 * itself. The semantics of vpi_free_object for a callback is that it
46 * deletes the *handle*, and not the object itself, so given the vvp
47 * implementation, there is nothing to do here.
49 static int free_simple_callback(vpiHandle ref)
51 return 1;
54 const struct __vpirt callback_rt = {
55 vpiCallback,
66 &free_simple_callback
70 * Callback handles are created when the VPI function registers a
71 * callback. The handle is stored by the run time, and it triggered
72 * when the run-time thing that it is waiting for happens.
74 * This is the thing that the VPI code references by the vpiHandle. It
75 * also points to callback data that the caller attached to the event,
76 * as well as the time structure to receive data.
78 * The cb_sync is a private member that points to the schedulable
79 * event that is triggered when the event happens. The sync_cb class
80 * represents the action to execute when the scheduler gets to this
81 * event. This member is only used for things like cbReadOnlySync.
84 struct sync_cb : public vvp_gen_event_s {
85 struct __vpiCallback*handle;
86 bool sync_flag;
88 ~sync_cb () { }
90 virtual void run_run();
94 struct __vpiCallback* new_vpi_callback()
96 struct __vpiCallback* obj;
98 obj = new __vpiCallback;
100 obj->base.vpi_type = &callback_rt;
101 obj->cb_sync = 0;
102 obj->next = 0;
103 return obj;
106 static void delete_vpi_callback(struct __vpiCallback* ref)
108 assert(ref);
109 assert(ref->base.vpi_type);
110 assert(ref->base.vpi_type->type_code == vpiCallback);
111 delete ref;
116 * A value change callback is tripped when a bit of a signal
117 * changes. This function creates that value change callback and
118 * attaches it to the relevant vpiSignal object. Also, if the signal
119 * does not already have them, create some callback functors to do the
120 * actual value change detection.
122 static struct __vpiCallback* make_value_change(p_cb_data data)
124 struct __vpiCallback*obj = new_vpi_callback();
125 obj->cb_data = *data;
126 if (data->time) {
127 obj->cb_time = *(data->time);
128 } else {
129 obj->cb_time.type = vpiSuppressTime;
131 obj->cb_data.time = &obj->cb_time;
133 assert(data->obj);
134 assert(data->obj->vpi_type);
136 switch (data->obj->vpi_type->type_code) {
138 case vpiReg:
139 case vpiNet:
140 case vpiIntegerVar:
141 /* Attach the callback to the vvp_fun_signal node by
142 putting it in the vpi_callbacks list. */
143 struct __vpiSignal*sig;
144 sig = reinterpret_cast<__vpiSignal*>(data->obj);
146 vvp_fun_signal_base*sig_fun;
147 sig_fun = dynamic_cast<vvp_fun_signal_base*>(sig->node->fun);
148 assert(sig_fun);
150 /* Attach the __vpiCallback object to the signal. */
151 sig_fun->add_vpi_callback(obj);
152 break;
154 case vpiRealVar:
155 vpip_real_value_change(obj, data->obj);
156 break;
158 case vpiNamedEvent:
159 struct __vpiNamedEvent*nev;
160 nev = reinterpret_cast<__vpiNamedEvent*>(data->obj);
161 obj->next = nev->callbacks;
162 nev->callbacks = obj;
163 break;
165 case vpiMemory:
166 vpip_memory_value_change(obj, data->obj);
167 break;
169 case vpiModule:
170 case vpiConstant:
171 case vpiParameter:
172 /* These are constant, so there are no value change
173 lists to put them in. */
174 break;
176 default:
177 fprintf(stderr, "make_value_change: sorry: I cannot callback "
178 "values on type code=%d\n",
179 data->obj->vpi_type->type_code);
180 delete obj;
181 return 0;
184 return obj;
187 void sync_cb::run_run()
189 if (handle == 0)
190 return;
192 struct __vpiCallback*cur = handle;
193 cur->cb_data.time->type = vpiSimTime;
194 vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
196 /* Run the callback. If the cb_rtn function pointer is set to
197 null, then just skip the whole thing and free it. This is
198 the usual way to cancel one-time callbacks of this sort. */
199 if (cur->cb_data.cb_rtn != 0) {
200 assert(vpi_mode_flag == VPI_MODE_NONE);
201 vpi_mode_flag = sync_flag? VPI_MODE_ROSYNC : VPI_MODE_RWSYNC;
202 (cur->cb_data.cb_rtn)(&cur->cb_data);
203 vpi_mode_flag = VPI_MODE_NONE;
206 delete_vpi_callback(cur);
209 static struct __vpiCallback* make_sync(p_cb_data data, bool readonly_flag)
211 struct __vpiCallback*obj = new_vpi_callback();
212 obj->cb_data = *data;
213 assert(data->time);
214 obj->cb_time = *(data->time);
215 obj->cb_data.time = &obj->cb_time;
217 obj->next = 0;
219 struct sync_cb*cb = new sync_cb;
220 cb->sync_flag = readonly_flag? true : false;
221 cb->handle = obj;
222 obj->cb_sync = cb;
224 switch (obj->cb_time.type) {
225 case vpiSuppressTime:
226 schedule_generic(cb, 0, true, readonly_flag);
227 break;
229 case vpiSimTime:
230 { vvp_time64_t tv = vpip_timestruct_to_time(&obj->cb_time);
231 vvp_time64_t tn = schedule_simtime();
232 if (tv < tn) {
233 schedule_generic(cb, 0, true, readonly_flag);
234 } else {
235 schedule_generic(cb, tv - tn, true, readonly_flag);
237 break;
240 default:
241 fprintf(stderr, "Unsupported time type %d.\n", obj->cb_time.type);
242 assert(0);
243 break;
245 return obj;
248 static struct __vpiCallback* make_afterdelay(p_cb_data data)
250 struct __vpiCallback*obj = new_vpi_callback();
251 obj->cb_data = *data;
252 assert(data->time);
253 obj->cb_time = *(data->time);
254 obj->cb_data.time = &obj->cb_time;
256 obj->next = 0;
258 struct sync_cb*cb = new sync_cb;
259 cb->sync_flag = false;
260 cb->handle = obj;
261 obj->cb_sync = cb;
263 switch (obj->cb_time.type) {
264 case vpiSimTime: {
265 vvp_time64_t tv = vpip_timestruct_to_time(&obj->cb_time);
266 schedule_generic(cb, tv, false);
267 break;
270 default:
271 fprintf(stderr, "Unsupported time type %d.\n", obj->cb_time.type);
272 assert(0);
273 break;
276 return obj;
280 * The following functions are the used for pre and post simulation
281 * callbacks.
284 static struct __vpiCallback*NextSimTime = 0;
285 static struct __vpiCallback*EndOfCompile = NULL;
286 static struct __vpiCallback*StartOfSimulation = NULL;
287 static struct __vpiCallback*EndOfSimulation = NULL;
289 void vpiEndOfCompile(void) {
290 struct __vpiCallback* cur;
293 * Walk the list of register callbacks, executing them and
294 * freeing them when done.
296 assert(vpi_mode_flag == VPI_MODE_NONE);
297 vpi_mode_flag = VPI_MODE_RWSYNC;
299 while (EndOfCompile) {
300 cur = EndOfCompile;
301 EndOfCompile = cur->next;
302 (cur->cb_data.cb_rtn)(&cur->cb_data);
303 delete_vpi_callback(cur);
306 vpi_mode_flag = VPI_MODE_NONE;
309 void vpiStartOfSim(void) {
310 struct __vpiCallback* cur;
313 * Walk the list of register callbacks, executing them and
314 * freeing them when done.
316 assert(vpi_mode_flag == VPI_MODE_NONE);
317 vpi_mode_flag = VPI_MODE_RWSYNC;
319 while (StartOfSimulation) {
320 cur = StartOfSimulation;
321 StartOfSimulation = cur->next;
322 (cur->cb_data.cb_rtn)(&cur->cb_data);
323 delete_vpi_callback(cur);
326 vpi_mode_flag = VPI_MODE_NONE;
329 void vpiPostsim(void) {
330 struct __vpiCallback* cur;
333 * Walk the list of register callbacks
335 assert(vpi_mode_flag == VPI_MODE_NONE);
336 vpi_mode_flag = VPI_MODE_ROSYNC;
338 while (EndOfSimulation) {
339 cur = EndOfSimulation;
340 EndOfSimulation = cur->next;
341 /* Only set the time if it is not NULL. */
342 if (cur->cb_data.time)
343 vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
344 (cur->cb_data.cb_rtn)(&cur->cb_data);
345 delete_vpi_callback(cur);
348 vpi_mode_flag = VPI_MODE_NONE;
352 * The scheduler invokes this to clear out callbacks for the next
353 * simulation time.
355 void vpiNextSimTime(void)
357 struct __vpiCallback* cur;
359 while (NextSimTime) {
360 cur = NextSimTime;
361 NextSimTime = cur->next;
362 (cur->cb_data.cb_rtn)(&cur->cb_data);
363 delete_vpi_callback(cur);
368 static struct __vpiCallback* make_prepost(p_cb_data data)
370 struct __vpiCallback*obj = new_vpi_callback();
371 obj->cb_data = *data;
373 /* Insert at head of list */
374 switch (data->reason) {
375 case cbEndOfCompile:
376 obj->next = EndOfCompile;
377 EndOfCompile = obj;
378 break;
379 case cbStartOfSimulation:
380 obj->next = StartOfSimulation;
381 StartOfSimulation = obj;
382 break;
383 case cbEndOfSimulation:
384 obj->next = EndOfSimulation;
385 EndOfSimulation = obj;
386 break;
387 case cbNextSimTime:
388 obj->next = NextSimTime;
389 NextSimTime = obj;
392 return obj;
395 vpiHandle vpi_register_cb(p_cb_data data)
397 struct __vpiCallback*obj = 0;
399 assert(data);
400 switch (data->reason) {
402 case cbValueChange:
403 obj = make_value_change(data);
404 break;
406 case cbReadOnlySynch:
407 obj = make_sync(data, true);
408 break;
410 case cbReadWriteSynch:
411 obj = make_sync(data, false);
412 break;
414 case cbAfterDelay:
415 obj = make_afterdelay(data);
416 break;
418 case cbEndOfCompile:
419 case cbStartOfSimulation:
420 case cbEndOfSimulation:
421 case cbNextSimTime:
422 obj = make_prepost(data);
423 break;
425 default:
426 fprintf(stderr, "vpi error: vpi_register_cb invalid or "
427 "unsupported callback reason: %d\n",
428 data->reason);
429 break;
432 return obj? &obj->base : 0;
436 * Removing a callback doesn't really delete it right away. Instead,
437 * it clears the reference to the user callback function. This causes
438 * the callback to quietly reap itself.
440 PLI_INT32 vpi_remove_cb(vpiHandle ref)
442 assert(ref);
443 assert(ref->vpi_type);
444 assert(ref->vpi_type->type_code == vpiCallback);
446 struct __vpiCallback*obj = (struct __vpiCallback*)ref;
447 obj->cb_data.cb_rtn = 0;
449 return 1;
452 void callback_execute(struct __vpiCallback*cur)
454 const vpi_mode_t save_mode = vpi_mode_flag;
455 vpi_mode_flag = VPI_MODE_RWSYNC;
457 assert(cur->cb_data.cb_rtn);
458 cur->cb_data.time->type = vpiSimTime;
459 vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
460 (cur->cb_data.cb_rtn)(&cur->cb_data);
462 vpi_mode_flag = save_mode;
465 vvp_vpi_callback::vvp_vpi_callback()
467 vpi_callbacks_ = 0;
468 array_ = 0;
469 array_word_ = 0;
472 vvp_vpi_callback::~vvp_vpi_callback()
474 assert(vpi_callbacks_ == 0);
475 assert(array_ == 0);
478 void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
480 cb->next = vpi_callbacks_;
481 vpi_callbacks_ = cb;
484 void vvp_vpi_callback::attach_as_word(vvp_array_t arr, unsigned long addr)
486 assert(array_ == 0);
487 array_ = arr;
488 array_word_ = addr;
492 * A vvp_fun_signal uses this method to run its callbacks whenever it
493 * has a value change. If the cb_rtn is non-nil, then call the
494 * callback function. If the cb_rtn pointer is nil, then the object
495 * has been marked for deletion. Free it.
497 void vvp_vpi_callback::run_vpi_callbacks()
499 struct __vpiCallback *next = vpi_callbacks_;
500 struct __vpiCallback *prev = 0;
502 if (array_) array_word_change(array_, array_word_);
504 while (next) {
505 struct __vpiCallback*cur = next;
506 next = cur->next;
508 if (cur->cb_data.cb_rtn != 0) {
509 if (cur->cb_data.value)
510 get_value(cur->cb_data.value);
512 callback_execute(cur);
513 prev = cur;
515 } else if (prev == 0) {
517 vpi_callbacks_ = next;
518 cur->next = 0;
519 delete_vpi_callback(cur);
521 } else {
522 assert(prev->next == cur);
523 prev->next = next;
524 cur->next = 0;
525 delete_vpi_callback(cur);
530 void vvp_fun_signal::get_value(struct t_vpi_value*vp)
532 switch (vp->format) {
533 case vpiScalarVal:
534 vp->value.scalar = value(0);
535 break;
536 case vpiSuppressVal:
537 break;
538 default:
539 fprintf(stderr, "vpi_callback: value "
540 "format %d not supported (fun_signal)\n",
541 vp->format);
545 void vvp_fun_signal8::get_value(struct t_vpi_value*vp)
547 switch (vp->format) {
548 case vpiScalarVal:
549 vp->value.scalar = value(0);
550 break;
551 case vpiSuppressVal:
552 break;
553 default:
554 fprintf(stderr, "vpi_callback: value "
555 "format %d not supported (fun_signal8)\n",
556 vp->format);
560 void vvp_fun_signal_real::get_value(struct t_vpi_value*vp)
562 char*rbuf = need_result_buf(64 + 1, RBUF_VAL);
564 switch (vp->format) {
565 case vpiObjTypeVal:
566 vp->format = vpiRealVal;
568 case vpiRealVal:
569 vp->value.real = real_value();
570 break;
572 case vpiIntVal:
573 vp->value.integer = (int)(real_value() + 0.5);
574 break;
576 case vpiDecStrVal:
577 sprintf(rbuf, "%0.0f", real_value());
578 vp->value.str = rbuf;
579 break;
581 case vpiHexStrVal:
582 sprintf(rbuf, "%lx", (long)real_value());
583 vp->value.str = rbuf;
584 break;
586 case vpiBinStrVal: {
587 unsigned long val = (unsigned long)real_value();
588 unsigned len = 0;
590 while (val > 0) {
591 len += 1;
592 val /= 2;
595 val = (unsigned long)real_value();
596 for (unsigned idx = 0 ; idx < len ; idx += 1) {
597 rbuf[len-idx-1] = (val & 1)? '1' : '0';
598 val /= 2;
601 rbuf[len] = 0;
602 if (len == 0) {
603 rbuf[0] = '0';
604 rbuf[1] = 0;
606 vp->value.str = rbuf;
607 break;
610 default:
611 fprintf(stderr, "vpi_callback: value "
612 "format %d not supported (fun_signal_real)\n",
613 vp->format);