From bb0502a827f556c245224dbcb8050fa7b99c60fc Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 19:28:21 +0000 Subject: [PATCH] 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. --- ivtest/vpi/nextsimtime_common.c | 2 +- ivtest/vpi_gold/nextsimtime_scaled_time.gold | 7 ++- vvp/vpi_callback.cc | 57 ++++++++++---------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/ivtest/vpi/nextsimtime_common.c b/ivtest/vpi/nextsimtime_common.c index c78fe6a96..525f1a0f9 100644 --- a/ivtest/vpi/nextsimtime_common.c +++ b/ivtest/vpi/nextsimtime_common.c @@ -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); diff --git a/ivtest/vpi_gold/nextsimtime_scaled_time.gold b/ivtest/vpi_gold/nextsimtime_scaled_time.gold index aa9a83eab..1be7a2745 100644 --- a/ivtest/vpi_gold/nextsimtime_scaled_time.gold +++ b/ivtest/vpi_gold/nextsimtime_scaled_time.gold @@ -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 diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index adac89b54..a7bec50a0 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -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(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(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;