vvp: Factor out common code for returning the time of a VPI callback.

This adds support for vpiScaledRealTime in various callbacks where it
wasn't previously supported. However this doesn't work properly when
the cb_data.obj field references a scope handle.
This commit is contained in:
Martin Whitaker 2024-02-05 19:28:21 +00:00
parent 5d40f6ecb2
commit bb0502a827
3 changed files with 34 additions and 32 deletions

View File

@ -42,7 +42,7 @@ static PLI_INT32 nextsimtime_cb(struct t_cb_data* cb) {
#else
timerec.type = vpiSimTime;
#endif
vpi_get_time(NULL, &timerec);
vpi_get_time(vpi_handle_by_name("main", NULL), &timerec);
#ifdef TEST_SCALED_TIME
vpi_printf("nextsimtime: %f vpi_get_time: %f\n",
cb->time->real, timerec.real);

View File

@ -1,3 +1,8 @@
Compiling vpi/nextsimtime_scaled_time.c...
Making nextsimtime_scaled_time.vpi from nextsimtime_scaled_time.o...
ERROR: VPI: cbNextSimTime time type vpiScaledRealTime is not implemented.
time 0: 0
nextsimtime: 1.000000 vpi_get_time: 1.000000
time 1: 1
nextsimtime: 4.000000 vpi_get_time: 4.000000
time 4: 4
nextsimtime: 5.000000 vpi_get_time: 5.000000

View File

@ -40,6 +40,29 @@
using namespace std;
static void set_callback_time(p_cb_data data)
{
assert(data && data->time);
data->time->low = 0;
data->time->high = 0;
data->time->real = 0.0;
switch (data->time->type) {
case vpiSimTime:
vpip_time_to_timestruct(data->time, schedule_simtime());
break;
case vpiScaledRealTime:
data->time->real =
vpip_time_to_scaled_real(schedule_simtime(),
data->obj ? static_cast<__vpiScope *>(vpi_handle(vpiScope, data->obj)) : 0);
break;
case vpiSuppressTime:
break;
default:
assert(0);
break;
}
}
/*
* Callback handles are created when the VPI function registers a
* callback. The handle is stored by the run time, and it triggered
@ -314,13 +337,12 @@ void sync_cb::run_run()
return;
sync_callback*cur = handle;
cur->cb_data.time->type = vpiSimTime;
vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
/* Run the callback. If the cb_rtn function pointer is set to
null, then just skip the whole thing and free it. This is
the usual way to cancel one-time callbacks of this sort. */
if (cur->cb_data.cb_rtn != 0) {
set_callback_time(&cur->cb_data);
assert(vpi_mode_flag == VPI_MODE_NONE);
vpi_mode_flag = sync_flag? VPI_MODE_ROSYNC : VPI_MODE_RWSYNC;
(cur->cb_data.cb_rtn)(&cur->cb_data);
@ -572,8 +594,7 @@ void vpiPostsim(void) {
cur = EndOfSimulation;
EndOfSimulation = dynamic_cast<simulator_callback*>(cur->next);
if (cur->cb_data.cb_rtn != 0) {
assert(cur->cb_data.time);
vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
set_callback_time(&cur->cb_data);
(cur->cb_data.cb_rtn)(&cur->cb_data);
}
delete cur;
@ -599,8 +620,7 @@ void vpiNextSimTime(void)
cur = next;
next = dynamic_cast<simulator_callback*>(cur->next);
if (cur->cb_data.cb_rtn != 0) {
// only vpiSimTime implemented right now
vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
set_callback_time(&cur->cb_data);
(cur->cb_data.cb_rtn)(&cur->cb_data);
}
delete cur;
@ -638,11 +658,6 @@ static simulator_callback* make_prepost(p_cb_data data)
vpi_control(vpiFinish, 1);
break;
}
if (data->time->type == vpiScaledRealTime) {
vpi_printf("ERROR: VPI: cbNextSimTime time type vpiScaledRealTime is not implemented.\n");
vpi_control(vpiFinish, 1);
break;
}
obj->next = NextSimTime;
NextSimTime = obj;
break;
@ -719,25 +734,7 @@ void callback_execute(struct __vpiCallback*cur)
vpi_mode_flag = VPI_MODE_RWSYNC;
assert(cur->cb_data.cb_rtn);
switch (cur->cb_data.time->type) {
case vpiSimTime:
vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
break;
case vpiScaledRealTime: {
cur->cb_data.time->real =
vpip_time_to_scaled_real(schedule_simtime(),
static_cast<__vpiScope *>(vpi_handle(vpiScope,
cur->cb_data.obj)));
break;
}
case vpiSuppressTime:
break;
default:
fprintf(stderr, "Unsupported time format %d.\n",
(int)cur->cb_data.time->type);
assert(0);
break;
}
set_callback_time(&cur->cb_data);
(cur->cb_data.cb_rtn)(&cur->cb_data);
vpi_mode_flag = save_mode;