Pass local scope precision from compiler to vvp/etc.
[iverilog.git] / vvp / vpi_callback.cc
blob7f7dccbd78e544f99e20ebb3e91bc323bd807363
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 (cur->cb_data.cb_rtn)(&cur->cb_data);
342 delete_vpi_callback(cur);
345 vpi_mode_flag = VPI_MODE_NONE;
349 * The scheduler invokes this to clear out callbacks for the next
350 * simulation time.
352 void vpiNextSimTime(void)
354 struct __vpiCallback* cur;
356 while (NextSimTime) {
357 cur = NextSimTime;
358 NextSimTime = cur->next;
359 (cur->cb_data.cb_rtn)(&cur->cb_data);
360 delete_vpi_callback(cur);
365 static struct __vpiCallback* make_prepost(p_cb_data data)
367 struct __vpiCallback*obj = new_vpi_callback();
368 obj->cb_data = *data;
370 /* Insert at head of list */
371 switch (data->reason) {
372 case cbEndOfCompile:
373 obj->next = EndOfCompile;
374 EndOfCompile = obj;
375 break;
376 case cbStartOfSimulation:
377 obj->next = StartOfSimulation;
378 StartOfSimulation = obj;
379 break;
380 case cbEndOfSimulation:
381 obj->next = EndOfSimulation;
382 EndOfSimulation = obj;
383 break;
384 case cbNextSimTime:
385 obj->next = NextSimTime;
386 NextSimTime = obj;
389 return obj;
392 vpiHandle vpi_register_cb(p_cb_data data)
394 struct __vpiCallback*obj = 0;
396 assert(data);
397 switch (data->reason) {
399 case cbValueChange:
400 obj = make_value_change(data);
401 break;
403 case cbReadOnlySynch:
404 obj = make_sync(data, true);
405 break;
407 case cbReadWriteSynch:
408 obj = make_sync(data, false);
409 break;
411 case cbAfterDelay:
412 obj = make_afterdelay(data);
413 break;
415 case cbEndOfCompile:
416 case cbStartOfSimulation:
417 case cbEndOfSimulation:
418 case cbNextSimTime:
419 obj = make_prepost(data);
420 break;
422 default:
423 fprintf(stderr, "vpi error: vpi_register_cb invalid or "
424 "unsupported callback reason: %d\n",
425 data->reason);
426 break;
429 return obj? &obj->base : 0;
433 * Removing a callback doesn't really delete it right away. Instead,
434 * it clears the reference to the user callback function. This causes
435 * the callback to quietly reap itself.
437 PLI_INT32 vpi_remove_cb(vpiHandle ref)
439 assert(ref);
440 assert(ref->vpi_type);
441 assert(ref->vpi_type->type_code == vpiCallback);
443 struct __vpiCallback*obj = (struct __vpiCallback*)ref;
444 obj->cb_data.cb_rtn = 0;
446 return 1;
449 void callback_execute(struct __vpiCallback*cur)
451 const vpi_mode_t save_mode = vpi_mode_flag;
452 vpi_mode_flag = VPI_MODE_RWSYNC;
454 assert(cur->cb_data.cb_rtn);
455 cur->cb_data.time->type = vpiSimTime;
456 vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
457 (cur->cb_data.cb_rtn)(&cur->cb_data);
459 vpi_mode_flag = save_mode;
462 vvp_vpi_callback::vvp_vpi_callback()
464 vpi_callbacks_ = 0;
465 array_ = 0;
466 array_word_ = 0;
469 vvp_vpi_callback::~vvp_vpi_callback()
471 assert(vpi_callbacks_ == 0);
472 assert(array_ == 0);
475 void vvp_vpi_callback::add_vpi_callback(__vpiCallback*cb)
477 cb->next = vpi_callbacks_;
478 vpi_callbacks_ = cb;
481 void vvp_vpi_callback::attach_as_word(vvp_array_t arr, unsigned long addr)
483 assert(array_ == 0);
484 array_ = arr;
485 array_word_ = addr;
489 * A vvp_fun_signal uses this method to run its callbacks whenever it
490 * has a value change. If the cb_rtn is non-nil, then call the
491 * callback function. If the cb_rtn pointer is nil, then the object
492 * has been marked for deletion. Free it.
494 void vvp_vpi_callback::run_vpi_callbacks()
496 struct __vpiCallback *next = vpi_callbacks_;
497 struct __vpiCallback *prev = 0;
499 if (array_) array_word_change(array_, array_word_);
501 while (next) {
502 struct __vpiCallback*cur = next;
503 next = cur->next;
505 if (cur->cb_data.cb_rtn != 0) {
506 if (cur->cb_data.value)
507 get_value(cur->cb_data.value);
509 callback_execute(cur);
510 prev = cur;
512 } else if (prev == 0) {
514 vpi_callbacks_ = next;
515 cur->next = 0;
516 delete_vpi_callback(cur);
518 } else {
519 assert(prev->next == cur);
520 prev->next = next;
521 cur->next = 0;
522 delete_vpi_callback(cur);
527 void vvp_fun_signal::get_value(struct t_vpi_value*vp)
529 switch (vp->format) {
530 case vpiScalarVal:
531 vp->value.scalar = value(0);
532 break;
533 case vpiSuppressVal:
534 break;
535 default:
536 fprintf(stderr, "vpi_callback: value "
537 "format %d not supported (fun_signal)\n",
538 vp->format);
542 void vvp_fun_signal8::get_value(struct t_vpi_value*vp)
544 switch (vp->format) {
545 case vpiScalarVal:
546 vp->value.scalar = value(0);
547 break;
548 case vpiSuppressVal:
549 break;
550 default:
551 fprintf(stderr, "vpi_callback: value "
552 "format %d not supported (fun_signal8)\n",
553 vp->format);
557 void vvp_fun_signal_real::get_value(struct t_vpi_value*vp)
559 char*rbuf = need_result_buf(64 + 1, RBUF_VAL);
561 switch (vp->format) {
562 case vpiObjTypeVal:
563 vp->format = vpiRealVal;
565 case vpiRealVal:
566 vp->value.real = real_value();
567 break;
569 case vpiIntVal:
570 vp->value.integer = (int)(real_value() + 0.5);
571 break;
573 case vpiDecStrVal:
574 sprintf(rbuf, "%0.0f", real_value());
575 vp->value.str = rbuf;
576 break;
578 case vpiHexStrVal:
579 sprintf(rbuf, "%lx", (long)real_value());
580 vp->value.str = rbuf;
581 break;
583 case vpiBinStrVal: {
584 unsigned long val = (unsigned long)real_value();
585 unsigned len = 0;
587 while (val > 0) {
588 len += 1;
589 val /= 2;
592 val = (unsigned long)real_value();
593 for (unsigned idx = 0 ; idx < len ; idx += 1) {
594 rbuf[len-idx-1] = (val & 1)? '1' : '0';
595 val /= 2;
598 rbuf[len] = 0;
599 if (len == 0) {
600 rbuf[0] = '0';
601 rbuf[1] = 0;
603 vp->value.str = rbuf;
604 break;
607 default:
608 fprintf(stderr, "vpi_callback: value "
609 "format %d not supported (fun_signal_real)\n",
610 vp->format);