Fix the debugger to finish correctly.
[iverilog.git] / vvp / vpi_callback.cc
blobaadcebf377c939bc205ecab230a907ed7d99bcf1
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 vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
342 (cur->cb_data.cb_rtn)(&cur->cb_data);
343 delete_vpi_callback(cur);
346 vpi_mode_flag = VPI_MODE_NONE;
350 * The scheduler invokes this to clear out callbacks for the next
351 * simulation time.
353 void vpiNextSimTime(void)
355 struct __vpiCallback* cur;
357 while (NextSimTime) {
358 cur = NextSimTime;
359 NextSimTime = cur->next;
360 (cur->cb_data.cb_rtn)(&cur->cb_data);
361 delete_vpi_callback(cur);
366 static struct __vpiCallback* make_prepost(p_cb_data data)
368 struct __vpiCallback*obj = new_vpi_callback();
369 obj->cb_data = *data;
371 /* Insert at head of list */
372 switch (data->reason) {
373 case cbEndOfCompile:
374 obj->next = EndOfCompile;
375 EndOfCompile = obj;
376 break;
377 case cbStartOfSimulation:
378 obj->next = StartOfSimulation;
379 StartOfSimulation = obj;
380 break;
381 case cbEndOfSimulation:
382 obj->next = EndOfSimulation;
383 EndOfSimulation = obj;
384 break;
385 case cbNextSimTime:
386 obj->next = NextSimTime;
387 NextSimTime = obj;
390 return obj;
393 vpiHandle vpi_register_cb(p_cb_data data)
395 struct __vpiCallback*obj = 0;
397 assert(data);
398 switch (data->reason) {
400 case cbValueChange:
401 obj = make_value_change(data);
402 break;
404 case cbReadOnlySynch:
405 obj = make_sync(data, true);
406 break;
408 case cbReadWriteSynch:
409 obj = make_sync(data, false);
410 break;
412 case cbAfterDelay:
413 obj = make_afterdelay(data);
414 break;
416 case cbEndOfCompile:
417 case cbStartOfSimulation:
418 case cbEndOfSimulation:
419 case cbNextSimTime:
420 obj = make_prepost(data);
421 break;
423 default:
424 fprintf(stderr, "vpi error: vpi_register_cb invalid or "
425 "unsupported callback reason: %d\n",
426 data->reason);
427 break;
430 return obj? &obj->base : 0;
434 * Removing a callback doesn't really delete it right away. Instead,
435 * it clears the reference to the user callback function. This causes
436 * the callback to quietly reap itself.
438 PLI_INT32 vpi_remove_cb(vpiHandle ref)
440 assert(ref);
441 assert(ref->vpi_type);
442 assert(ref->vpi_type->type_code == vpiCallback);
444 struct __vpiCallback*obj = (struct __vpiCallback*)ref;
445 obj->cb_data.cb_rtn = 0;
447 return 1;
450 void callback_execute(struct __vpiCallback*cur)
452 const vpi_mode_t save_mode = vpi_mode_flag;
453 vpi_mode_flag = VPI_MODE_RWSYNC;
455 assert(cur->cb_data.cb_rtn);
456 cur->cb_data.time->type = vpiSimTime;
457 vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
458 (cur->cb_data.cb_rtn)(&cur->cb_data);
460 vpi_mode_flag = save_mode;
463 vvp_vpi_callback::vvp_vpi_callback()
465 vpi_callbacks_ = 0;
466 array_ = 0;
467 array_word_ = 0;
470 vvp_vpi_callback::~vvp_vpi_callback()
472 assert(vpi_callbacks_ == 0);
473 assert(array_ == 0);
476 void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
478 cb->next = vpi_callbacks_;
479 vpi_callbacks_ = cb;
482 void vvp_vpi_callback::attach_as_word(vvp_array_t arr, unsigned long addr)
484 assert(array_ == 0);
485 array_ = arr;
486 array_word_ = addr;
490 * A vvp_fun_signal uses this method to run its callbacks whenever it
491 * has a value change. If the cb_rtn is non-nil, then call the
492 * callback function. If the cb_rtn pointer is nil, then the object
493 * has been marked for deletion. Free it.
495 void vvp_vpi_callback::run_vpi_callbacks()
497 struct __vpiCallback *next = vpi_callbacks_;
498 struct __vpiCallback *prev = 0;
500 if (array_) array_word_change(array_, array_word_);
502 while (next) {
503 struct __vpiCallback*cur = next;
504 next = cur->next;
506 if (cur->cb_data.cb_rtn != 0) {
507 if (cur->cb_data.value)
508 get_value(cur->cb_data.value);
510 callback_execute(cur);
511 prev = cur;
513 } else if (prev == 0) {
515 vpi_callbacks_ = next;
516 cur->next = 0;
517 delete_vpi_callback(cur);
519 } else {
520 assert(prev->next == cur);
521 prev->next = next;
522 cur->next = 0;
523 delete_vpi_callback(cur);
528 void vvp_fun_signal::get_value(struct t_vpi_value*vp)
530 switch (vp->format) {
531 case vpiScalarVal:
532 vp->value.scalar = value(0);
533 break;
534 case vpiSuppressVal:
535 break;
536 default:
537 fprintf(stderr, "vpi_callback: value "
538 "format %d not supported (fun_signal)\n",
539 vp->format);
543 void vvp_fun_signal8::get_value(struct t_vpi_value*vp)
545 switch (vp->format) {
546 case vpiScalarVal:
547 vp->value.scalar = value(0);
548 break;
549 case vpiSuppressVal:
550 break;
551 default:
552 fprintf(stderr, "vpi_callback: value "
553 "format %d not supported (fun_signal8)\n",
554 vp->format);
558 void vvp_fun_signal_real::get_value(struct t_vpi_value*vp)
560 char*rbuf = need_result_buf(64 + 1, RBUF_VAL);
562 switch (vp->format) {
563 case vpiObjTypeVal:
564 vp->format = vpiRealVal;
566 case vpiRealVal:
567 vp->value.real = real_value();
568 break;
570 case vpiIntVal:
571 vp->value.integer = (int)(real_value() + 0.5);
572 break;
574 case vpiDecStrVal:
575 sprintf(rbuf, "%0.0f", real_value());
576 vp->value.str = rbuf;
577 break;
579 case vpiHexStrVal:
580 sprintf(rbuf, "%lx", (long)real_value());
581 vp->value.str = rbuf;
582 break;
584 case vpiBinStrVal: {
585 unsigned long val = (unsigned long)real_value();
586 unsigned len = 0;
588 while (val > 0) {
589 len += 1;
590 val /= 2;
593 val = (unsigned long)real_value();
594 for (unsigned idx = 0 ; idx < len ; idx += 1) {
595 rbuf[len-idx-1] = (val & 1)? '1' : '0';
596 val /= 2;
599 rbuf[len] = 0;
600 if (len == 0) {
601 rbuf[0] = '0';
602 rbuf[1] = 0;
604 vp->value.str = rbuf;
605 break;
608 default:
609 fprintf(stderr, "vpi_callback: value "
610 "format %d not supported (fun_signal_real)\n",
611 vp->format);