From 53e8a139b01a65d587b1cf1de6b6cfb25ea23cb2 Mon Sep 17 00:00:00 2001 From: Jevin Sweval Date: Tue, 5 Jul 2022 12:24:43 -0700 Subject: [PATCH 01/19] VPI cbNextSimTime: Fill out time and don't call newly generated CBs Fill out cb_data.time and require it is non-NULL. Record the last NextSimTime CB so we don't call CBs added during this timestep. (cherry picked from PR #740) --- ivtest/vpi/nextsimtime_errors.c | 63 ++++++++++++++++ ivtest/vpi/nextsimtime_fill_time.c | 62 ++++++++++++++++ ivtest/vpi/nextsimtime_fill_time.v | 29 ++++++++ ivtest/vpi/nextsimtime_null_time.c | 2 + ivtest/vpi/nextsimtime_null_time.v | 1 + ivtest/vpi/nextsimtime_scaled_time.c | 2 + ivtest/vpi/nextsimtime_scaled_time.v | 1 + ivtest/vpi/nextsimtime_suppress_time.c | 2 + ivtest/vpi/nextsimtime_suppress_time.v | 1 + ivtest/vpi/pr686.c | 2 + ivtest/vpi_gold/nextsimtime_fill_time.gold | 8 +++ ivtest/vpi_gold/nextsimtime_null_time.gold | 3 + ivtest/vpi_gold/nextsimtime_scaled_time.gold | 3 + .../vpi_gold/nextsimtime_suppress_time.gold | 3 + ivtest/vpi_regress.list | 4 ++ vvp/vpi_callback.cc | 71 +++++++++++++------ 16 files changed, 236 insertions(+), 21 deletions(-) create mode 100644 ivtest/vpi/nextsimtime_errors.c create mode 100644 ivtest/vpi/nextsimtime_fill_time.c create mode 100644 ivtest/vpi/nextsimtime_fill_time.v create mode 100644 ivtest/vpi/nextsimtime_null_time.c create mode 100644 ivtest/vpi/nextsimtime_null_time.v create mode 100644 ivtest/vpi/nextsimtime_scaled_time.c create mode 100644 ivtest/vpi/nextsimtime_scaled_time.v create mode 100644 ivtest/vpi/nextsimtime_suppress_time.c create mode 100644 ivtest/vpi/nextsimtime_suppress_time.v create mode 100644 ivtest/vpi_gold/nextsimtime_fill_time.gold create mode 100644 ivtest/vpi_gold/nextsimtime_null_time.gold create mode 100644 ivtest/vpi_gold/nextsimtime_scaled_time.gold create mode 100644 ivtest/vpi_gold/nextsimtime_suppress_time.gold diff --git a/ivtest/vpi/nextsimtime_errors.c b/ivtest/vpi/nextsimtime_errors.c new file mode 100644 index 000000000..9b7256fdd --- /dev/null +++ b/ivtest/vpi/nextsimtime_errors.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 Jevin Sweval (jevinsweval@gmail.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "vpi_user.h" +# include + +#if defined(TEST_SCALED) || defined(TEST_SUPPRESS) +#if defined(TEST_SCALED) +#define TIME_TYPE vpiScaledRealTime +#elif defined(TEST_SUPPRESS) +#define TIME_TYPE vpiSuppressTime +#endif +static s_vpi_time cb_timerec = {TIME_TYPE, 0, 0, 0}; +#endif + +static PLI_INT32 dummy_cb(struct t_cb_data* cb) { + (void)cb; /* unused */ + return 0; +} + +static PLI_INT32 register_nextsimtime(struct t_cb_data* cb) { + (void)cb; /* unused */ + s_cb_data cb_data; +#if defined(TEST_SCALED) || defined(TEST_SUPPRESS) + cb_data.time = &cb_timerec; +#elif defined(TEST_NULL) + cb_data.time = NULL; +#endif + cb_data.reason = cbNextSimTime; + cb_data.cb_rtn = dummy_cb; + vpiHandle hndl = NULL; + assert((hndl = vpi_register_cb(&cb_data)) && vpi_free_object(hndl)); + return 0; +} + +static void register_functions(void) +{ + s_cb_data cb_data; + cb_data.reason = cbEndOfCompile; + cb_data.cb_rtn = register_nextsimtime; + vpi_register_cb(&cb_data); +} + +void (*vlog_startup_routines[])(void) = { + register_functions, + NULL +}; diff --git a/ivtest/vpi/nextsimtime_fill_time.c b/ivtest/vpi/nextsimtime_fill_time.c new file mode 100644 index 000000000..e51f5f4f9 --- /dev/null +++ b/ivtest/vpi/nextsimtime_fill_time.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022 Jevin Sweval (jevinsweval@gmail.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "vpi_user.h" +# include + + +static s_vpi_time cb_timerec = {vpiSimTime, 0, 0, 0}; + +static PLI_INT32 register_nextsimtime(struct t_cb_data* cb); + +static PLI_INT32 nextsimtime_cb(struct t_cb_data* cb) { + uint64_t nextsimtime = ((uint64_t)cb->time->high << 32) | cb->time->low; + s_vpi_time timerec; + timerec.type = vpiSimTime; + vpi_get_time(NULL, &timerec); + uint64_t time = ((uint64_t)timerec.high << 32) | timerec.low; + vpi_printf("nextsimtime: %" PLI_UINT64_FMT " vpi_get_time: %" PLI_UINT64_FMT "\n", + nextsimtime, time); + register_nextsimtime(NULL); + return 0; +} + +static PLI_INT32 register_nextsimtime(struct t_cb_data* cb) { + (void)cb; /* unused */ + s_cb_data cb_data; + cb_data.time = &cb_timerec; + cb_data.reason = cbNextSimTime; + cb_data.cb_rtn = nextsimtime_cb; + vpiHandle hndl = NULL; + assert((hndl = vpi_register_cb(&cb_data)) && vpi_free_object(hndl)); + return 0; +} + +static void register_functions(void) +{ + s_cb_data cb_data; + cb_data.reason = cbEndOfCompile; + cb_data.cb_rtn = register_nextsimtime; + vpi_register_cb(&cb_data); +} + +void (*vlog_startup_routines[])(void) = { + register_functions, + NULL +}; diff --git a/ivtest/vpi/nextsimtime_fill_time.v b/ivtest/vpi/nextsimtime_fill_time.v new file mode 100644 index 000000000..ca112edcc --- /dev/null +++ b/ivtest/vpi/nextsimtime_fill_time.v @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 Jevin Sweval (jevinsweval@gmail.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +module main; + + initial begin + $display("time 0: %0d", $time); + #1 $display("time 1: %0d", $time); + #3 $display("time 4: %0d", $time); + #1; + end + +endmodule // main diff --git a/ivtest/vpi/nextsimtime_null_time.c b/ivtest/vpi/nextsimtime_null_time.c new file mode 100644 index 000000000..23f7cfd83 --- /dev/null +++ b/ivtest/vpi/nextsimtime_null_time.c @@ -0,0 +1,2 @@ +#define TEST_NULL +#include "nextsimtime_errors.c" diff --git a/ivtest/vpi/nextsimtime_null_time.v b/ivtest/vpi/nextsimtime_null_time.v new file mode 100644 index 000000000..92a807d86 --- /dev/null +++ b/ivtest/vpi/nextsimtime_null_time.v @@ -0,0 +1 @@ +`include "vpi/nextsimtime_fill_time.v" diff --git a/ivtest/vpi/nextsimtime_scaled_time.c b/ivtest/vpi/nextsimtime_scaled_time.c new file mode 100644 index 000000000..1a1d76608 --- /dev/null +++ b/ivtest/vpi/nextsimtime_scaled_time.c @@ -0,0 +1,2 @@ +#define TEST_SCALED +#include "nextsimtime_errors.c" diff --git a/ivtest/vpi/nextsimtime_scaled_time.v b/ivtest/vpi/nextsimtime_scaled_time.v new file mode 100644 index 000000000..92a807d86 --- /dev/null +++ b/ivtest/vpi/nextsimtime_scaled_time.v @@ -0,0 +1 @@ +`include "vpi/nextsimtime_fill_time.v" diff --git a/ivtest/vpi/nextsimtime_suppress_time.c b/ivtest/vpi/nextsimtime_suppress_time.c new file mode 100644 index 000000000..ca8151bb6 --- /dev/null +++ b/ivtest/vpi/nextsimtime_suppress_time.c @@ -0,0 +1,2 @@ +#define TEST_SUPPRESS +#include "nextsimtime_errors.c" diff --git a/ivtest/vpi/nextsimtime_suppress_time.v b/ivtest/vpi/nextsimtime_suppress_time.v new file mode 100644 index 000000000..92a807d86 --- /dev/null +++ b/ivtest/vpi/nextsimtime_suppress_time.v @@ -0,0 +1 @@ +`include "vpi/nextsimtime_fill_time.v" diff --git a/ivtest/vpi/pr686.c b/ivtest/vpi/pr686.c index dc68db901..720ef01f0 100644 --- a/ivtest/vpi/pr686.c +++ b/ivtest/vpi/pr686.c @@ -47,6 +47,7 @@ static PLI_INT32 test_next_compiletf(PLI_BYTE8 *name) static PLI_INT32 test_next_calltf(PLI_BYTE8 *name) { vpiHandle sys, argv, value; + static s_vpi_time dummy_time = {vpiSimTime, 0, 0, 0}; (void)name; /* Parameter is not used. */ @@ -59,6 +60,7 @@ static PLI_INT32 test_next_calltf(PLI_BYTE8 *name) for (value = vpi_scan(argv) ; value ; value = vpi_scan(argv)) { s_cb_data cb; cb.reason = cbNextSimTime; + cb.time = &dummy_time; cb.cb_rtn = next_sim_time_callback; cb.user_data = (char*)value; vpi_register_cb(&cb); diff --git a/ivtest/vpi_gold/nextsimtime_fill_time.gold b/ivtest/vpi_gold/nextsimtime_fill_time.gold new file mode 100644 index 000000000..69d8e699f --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_fill_time.gold @@ -0,0 +1,8 @@ +Compiling vpi/nextsimtime_fill_time.c... +Making nextsimtime_fill_time.vpi from nextsimtime_fill_time.o... +time 0: 0 +nextsimtime: 1 vpi_get_time: 1 +time 1: 1 +nextsimtime: 4 vpi_get_time: 4 +time 4: 4 +nextsimtime: 5 vpi_get_time: 5 diff --git a/ivtest/vpi_gold/nextsimtime_null_time.gold b/ivtest/vpi_gold/nextsimtime_null_time.gold new file mode 100644 index 000000000..020526985 --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_null_time.gold @@ -0,0 +1,3 @@ +Compiling vpi/nextsimtime_null_time.c... +Making nextsimtime_null_time.vpi from nextsimtime_null_time.o... +ERROR: VPI: cbNextSimTime time pointer must be valid. diff --git a/ivtest/vpi_gold/nextsimtime_scaled_time.gold b/ivtest/vpi_gold/nextsimtime_scaled_time.gold new file mode 100644 index 000000000..aa9a83eab --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_scaled_time.gold @@ -0,0 +1,3 @@ +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. diff --git a/ivtest/vpi_gold/nextsimtime_suppress_time.gold b/ivtest/vpi_gold/nextsimtime_suppress_time.gold new file mode 100644 index 000000000..2906f3736 --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_suppress_time.gold @@ -0,0 +1,3 @@ +Compiling vpi/nextsimtime_suppress_time.c... +Making nextsimtime_suppress_time.vpi from nextsimtime_suppress_time.o... +ERROR: VPI: cbNextSimTime time type cannot be vpiSuppressTime. diff --git a/ivtest/vpi_regress.list b/ivtest/vpi_regress.list index 4d9d5c951..37d1571b0 100644 --- a/ivtest/vpi_regress.list +++ b/ivtest/vpi_regress.list @@ -99,6 +99,10 @@ hello_tf normal hello_tf.c hello_tf.log hello_vpi normal hello_vpi.c hello.log hello_vpi2 normal hello_vpi2.c hello2.log vpi/hello_vpi1.c listparams normal listparams.c listparams.log +nextsimtime_fill_time normal nextsimtime_fill_time.c nextsimtime_fill_time.gold +nextsimtime_null_time normal nextsimtime_null_time.c nextsimtime_null_time.gold +nextsimtime_scaled_time normal nextsimtime_scaled_time.c nextsimtime_scaled_time.gold +nextsimtime_suppress_time normal nextsimtime_suppress_time.c nextsimtime_suppress_time.gold memmon normal,-g1995 memmon.c memmon.log memwide normal memwide.cc memwide.log mipname normal mipname.c mipname.log diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 3427f32f6..de255c05d 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -577,17 +577,30 @@ void vpiPostsim(void) { void vpiNextSimTime(void) { simulator_callback* cur; + simulator_callback* last_cb = NextSimTime; assert(vpi_mode_flag == VPI_MODE_NONE); vpi_mode_flag = VPI_MODE_RWSYNC; + /* Find the last event currently in the list. Remember this callback so + * we don't call additional NextSimTime CB's generated during this timestep. + */ + while (last_cb && last_cb->next) { + last_cb = dynamic_cast(last_cb->next); + } + while (NextSimTime) { - cur = NextSimTime; - NextSimTime = dynamic_cast(cur->next); - if (cur->cb_data.cb_rtn != 0) { - (cur->cb_data.cb_rtn)(&cur->cb_data); - } - delete cur; + cur = NextSimTime; + NextSimTime = 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()); + (cur->cb_data.cb_rtn)(&cur->cb_data); + } + delete cur; + if (cur == last_cb) { + break; + } } vpi_mode_flag = VPI_MODE_NONE; @@ -599,21 +612,37 @@ static simulator_callback* make_prepost(p_cb_data data) /* Insert at head of list */ switch (data->reason) { - case cbEndOfCompile: - obj->next = EndOfCompile; - EndOfCompile = obj; - break; - case cbStartOfSimulation: - obj->next = StartOfSimulation; - StartOfSimulation = obj; - break; - case cbEndOfSimulation: - obj->next = EndOfSimulation; - EndOfSimulation = obj; - break; - case cbNextSimTime: - obj->next = NextSimTime; - NextSimTime = obj; + case cbEndOfCompile: + obj->next = EndOfCompile; + EndOfCompile = obj; + break; + case cbStartOfSimulation: + obj->next = StartOfSimulation; + StartOfSimulation = obj; + break; + case cbEndOfSimulation: + obj->next = EndOfSimulation; + EndOfSimulation = obj; + break; + case cbNextSimTime: + if (!data->time) { + vpi_printf("ERROR: VPI: cbNextSimTime time pointer must be valid.\n"); + vpi_control(vpiFinish, 1); + break; + } + if (data->time->type == vpiSuppressTime) { + vpi_printf("ERROR: VPI: cbNextSimTime time type cannot be vpiSuppressTime.\n"); + 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; } return obj; From d364c5e90353e74219674df12c39f726bafa1018 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 08:42:32 +0000 Subject: [PATCH 02/19] Fix indentation and white space. --- vvp/vpi_callback.cc | 76 ++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index de255c05d..c37a0f113 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -516,7 +516,7 @@ void vpiEndOfCompile(void) { cur = EndOfCompile; EndOfCompile = dynamic_cast(cur->next); if (cur->cb_data.cb_rtn != 0) { - (cur->cb_data.cb_rtn)(&cur->cb_data); + (cur->cb_data.cb_rtn)(&cur->cb_data); } delete cur; } @@ -538,7 +538,7 @@ void vpiStartOfSim(void) { cur = StartOfSimulation; StartOfSimulation = dynamic_cast(cur->next); if (cur->cb_data.cb_rtn != 0) { - (cur->cb_data.cb_rtn)(&cur->cb_data); + (cur->cb_data.cb_rtn)(&cur->cb_data); } delete cur; } @@ -559,10 +559,10 @@ void vpiPostsim(void) { cur = EndOfSimulation; EndOfSimulation = dynamic_cast(cur->next); if (cur->cb_data.cb_rtn != 0) { - /* Only set the time if it is not NULL. */ - if (cur->cb_data.time) - vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime()); - (cur->cb_data.cb_rtn)(&cur->cb_data); + /* Only set the time if it is not NULL. */ + if (cur->cb_data.time) + vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime()); + (cur->cb_data.cb_rtn)(&cur->cb_data); } delete cur; } @@ -583,7 +583,7 @@ void vpiNextSimTime(void) vpi_mode_flag = VPI_MODE_RWSYNC; /* Find the last event currently in the list. Remember this callback so - * we don't call additional NextSimTime CB's generated during this timestep. + * we don't call additional NextSimTime CB's generated during this timestep. */ while (last_cb && last_cb->next) { last_cb = dynamic_cast(last_cb->next); @@ -612,37 +612,37 @@ static simulator_callback* make_prepost(p_cb_data data) /* Insert at head of list */ switch (data->reason) { - case cbEndOfCompile: - obj->next = EndOfCompile; - EndOfCompile = obj; - break; - case cbStartOfSimulation: - obj->next = StartOfSimulation; - StartOfSimulation = obj; - break; - case cbEndOfSimulation: - obj->next = EndOfSimulation; - EndOfSimulation = obj; - break; - case cbNextSimTime: - if (!data->time) { - vpi_printf("ERROR: VPI: cbNextSimTime time pointer must be valid.\n"); - vpi_control(vpiFinish, 1); - break; - } - if (data->time->type == vpiSuppressTime) { - vpi_printf("ERROR: VPI: cbNextSimTime time type cannot be vpiSuppressTime.\n"); - 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; + case cbEndOfCompile: + obj->next = EndOfCompile; + EndOfCompile = obj; + break; + case cbStartOfSimulation: + obj->next = StartOfSimulation; + StartOfSimulation = obj; + break; + case cbEndOfSimulation: + obj->next = EndOfSimulation; + EndOfSimulation = obj; + break; + case cbNextSimTime: + if (!data->time) { + vpi_printf("ERROR: VPI: cbNextSimTime time pointer must be valid.\n"); + vpi_control(vpiFinish, 1); + break; + } + if (data->time->type == vpiSuppressTime) { + vpi_printf("ERROR: VPI: cbNextSimTime time type cannot be vpiSuppressTime.\n"); + 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; } return obj; From c0e9b73d1cbe3e84282146f3acae4bad350bd896 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 09:21:01 +0000 Subject: [PATCH 03/19] vvp: Allocate time structures for cbNextSimTime and cbEndOfSimulation. Previously they were reusing the pointer supplied when the callback was registered, which is not guaranteed to still be valid. Note that the IEEE standard states: The only fields in the s_cb_data structure that shall need to be set up for simulation action or feature callbacks are the reason, cb_rtn, and user_data (if desired) fields. so for cbEndOfSimulation callbacks we cannot rely on the time pointer being either valid or null. The standard does not require that the time structure should be filled in when the callback occurs, but for backwards compatibility continue to do so, returning a vpiSimTime value. --- vvp/vpi_callback.cc | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index c37a0f113..f25e80b0c 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2022 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -461,12 +461,25 @@ static struct __vpiCallback* make_at_end_of_sim_time(p_cb_data data) class simulator_callback : public __vpiCallback { public: - inline explicit simulator_callback(const struct t_cb_data*data) - { cb_data = *data; } + explicit simulator_callback(const struct t_cb_data*data); public: + struct t_vpi_time cb_time; }; +inline simulator_callback::simulator_callback(const struct t_cb_data*data) +{ + cb_data = *data; + if ((data->reason == cbNextSimTime) && data->time) { + cb_time = *(data->time); + } else if (data->reason == cbEndOfSimulation) { + cb_time.type = vpiSimTime; + } else { + cb_time.type = vpiSuppressTime; + } + cb_data.time = &cb_time; +} + static simulator_callback*NextSimTime = 0; static simulator_callback*EndOfCompile = 0; static simulator_callback*StartOfSimulation = 0; @@ -559,9 +572,8 @@ void vpiPostsim(void) { cur = EndOfSimulation; EndOfSimulation = dynamic_cast(cur->next); if (cur->cb_data.cb_rtn != 0) { - /* Only set the time if it is not NULL. */ - if (cur->cb_data.time) - vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime()); + assert(cur->cb_data.time); + vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime()); (cur->cb_data.cb_rtn)(&cur->cb_data); } delete cur; From cae337231c515031148a42bebe51ac5fb5f6458a Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 17:53:01 +0000 Subject: [PATCH 04/19] vvp: Optimise the code for walking the NextSimTime callback list. --- vvp/vpi_callback.cc | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index f25e80b0c..adac89b54 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -589,30 +589,21 @@ void vpiPostsim(void) { void vpiNextSimTime(void) { simulator_callback* cur; - simulator_callback* last_cb = NextSimTime; + simulator_callback* next = NextSimTime; + NextSimTime = 0; assert(vpi_mode_flag == VPI_MODE_NONE); vpi_mode_flag = VPI_MODE_RWSYNC; - /* Find the last event currently in the list. Remember this callback so - * we don't call additional NextSimTime CB's generated during this timestep. - */ - while (last_cb && last_cb->next) { - last_cb = dynamic_cast(last_cb->next); - } - - while (NextSimTime) { - cur = NextSimTime; - NextSimTime = dynamic_cast(cur->next); + while (next) { + 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()); (cur->cb_data.cb_rtn)(&cur->cb_data); } delete cur; - if (cur == last_cb) { - break; - } } vpi_mode_flag = VPI_MODE_NONE; From 5d40f6ecb22cdc60196b9cc7446167b51e7838c9 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 18:17:53 +0000 Subject: [PATCH 05/19] Restructure and simplify the nextsimtime VPI tests. Add support for properly testing the vpiScaledRealTime time type for when it's implemented. --- ...mtime_fill_time.c => nextsimtime_common.c} | 32 +++++++++- ...mtime_fill_time.v => nextsimtime_common.v} | 2 + ivtest/vpi/nextsimtime_errors.c | 63 ------------------- ivtest/vpi/nextsimtime_null_time.c | 4 +- ivtest/vpi/nextsimtime_null_time.v | 2 +- ivtest/vpi/nextsimtime_scaled_time.c | 4 +- ivtest/vpi/nextsimtime_scaled_time.v | 2 +- ivtest/vpi/nextsimtime_sim_time.c | 2 + ivtest/vpi/nextsimtime_sim_time.v | 1 + ivtest/vpi/nextsimtime_suppress_time.c | 4 +- ivtest/vpi/nextsimtime_suppress_time.v | 2 +- ivtest/vpi_gold/nextsimtime_fill_time.gold | 8 --- ivtest/vpi_gold/nextsimtime_sim_time.gold | 8 +++ ivtest/vpi_regress.list | 8 +-- 14 files changed, 56 insertions(+), 86 deletions(-) rename ivtest/vpi/{nextsimtime_fill_time.c => nextsimtime_common.c} (75%) rename ivtest/vpi/{nextsimtime_fill_time.v => nextsimtime_common.v} (98%) delete mode 100644 ivtest/vpi/nextsimtime_errors.c create mode 100644 ivtest/vpi/nextsimtime_sim_time.c create mode 100644 ivtest/vpi/nextsimtime_sim_time.v delete mode 100644 ivtest/vpi_gold/nextsimtime_fill_time.gold create mode 100644 ivtest/vpi_gold/nextsimtime_sim_time.gold diff --git a/ivtest/vpi/nextsimtime_fill_time.c b/ivtest/vpi/nextsimtime_common.c similarity index 75% rename from ivtest/vpi/nextsimtime_fill_time.c rename to ivtest/vpi/nextsimtime_common.c index e51f5f4f9..c78fe6a96 100644 --- a/ivtest/vpi/nextsimtime_fill_time.c +++ b/ivtest/vpi/nextsimtime_common.c @@ -20,19 +20,38 @@ # include "vpi_user.h" # include +#if defined(TEST_SIM_TIME) +#define TIME_TYPE vpiSimTime +#elif defined(TEST_SCALED_TIME) +#define TIME_TYPE vpiScaledRealTime +#else +#define TIME_TYPE vpiSuppressTime +#endif -static s_vpi_time cb_timerec = {vpiSimTime, 0, 0, 0}; +#ifndef TEST_NULL_TIME +static s_vpi_time cb_timerec = {TIME_TYPE, 0, 0, 0}; +#endif static PLI_INT32 register_nextsimtime(struct t_cb_data* cb); + static PLI_INT32 nextsimtime_cb(struct t_cb_data* cb) { - uint64_t nextsimtime = ((uint64_t)cb->time->high << 32) | cb->time->low; s_vpi_time timerec; +#ifdef TEST_SCALED_TIME + timerec.type = vpiScaledRealTime; +#else timerec.type = vpiSimTime; +#endif vpi_get_time(NULL, &timerec); +#ifdef TEST_SCALED_TIME + vpi_printf("nextsimtime: %f vpi_get_time: %f\n", + cb->time->real, timerec.real); +#else + uint64_t nextsimtime = ((uint64_t)cb->time->high << 32) | cb->time->low; uint64_t time = ((uint64_t)timerec.high << 32) | timerec.low; vpi_printf("nextsimtime: %" PLI_UINT64_FMT " vpi_get_time: %" PLI_UINT64_FMT "\n", nextsimtime, time); +#endif register_nextsimtime(NULL); return 0; } @@ -40,7 +59,16 @@ static PLI_INT32 nextsimtime_cb(struct t_cb_data* cb) { static PLI_INT32 register_nextsimtime(struct t_cb_data* cb) { (void)cb; /* unused */ s_cb_data cb_data; +#ifdef TEST_NULL_TIME + cb_data.time = 0; +#else cb_data.time = &cb_timerec; +#endif +#ifdef TEST_SCALED_TIME + cb_data.obj = vpi_handle_by_name("main", NULL); +#else + cb_data.obj = 0; +#endif cb_data.reason = cbNextSimTime; cb_data.cb_rtn = nextsimtime_cb; vpiHandle hndl = NULL; diff --git a/ivtest/vpi/nextsimtime_fill_time.v b/ivtest/vpi/nextsimtime_common.v similarity index 98% rename from ivtest/vpi/nextsimtime_fill_time.v rename to ivtest/vpi/nextsimtime_common.v index ca112edcc..aec944aaa 100644 --- a/ivtest/vpi/nextsimtime_fill_time.v +++ b/ivtest/vpi/nextsimtime_common.v @@ -17,6 +17,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ +`timescale 1s/1ms + module main; initial begin diff --git a/ivtest/vpi/nextsimtime_errors.c b/ivtest/vpi/nextsimtime_errors.c deleted file mode 100644 index 9b7256fdd..000000000 --- a/ivtest/vpi/nextsimtime_errors.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2022 Jevin Sweval (jevinsweval@gmail.com) - * - * This source code is free software; you can redistribute it - * and/or modify it in source code form under the terms of the GNU - * General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -# include "vpi_user.h" -# include - -#if defined(TEST_SCALED) || defined(TEST_SUPPRESS) -#if defined(TEST_SCALED) -#define TIME_TYPE vpiScaledRealTime -#elif defined(TEST_SUPPRESS) -#define TIME_TYPE vpiSuppressTime -#endif -static s_vpi_time cb_timerec = {TIME_TYPE, 0, 0, 0}; -#endif - -static PLI_INT32 dummy_cb(struct t_cb_data* cb) { - (void)cb; /* unused */ - return 0; -} - -static PLI_INT32 register_nextsimtime(struct t_cb_data* cb) { - (void)cb; /* unused */ - s_cb_data cb_data; -#if defined(TEST_SCALED) || defined(TEST_SUPPRESS) - cb_data.time = &cb_timerec; -#elif defined(TEST_NULL) - cb_data.time = NULL; -#endif - cb_data.reason = cbNextSimTime; - cb_data.cb_rtn = dummy_cb; - vpiHandle hndl = NULL; - assert((hndl = vpi_register_cb(&cb_data)) && vpi_free_object(hndl)); - return 0; -} - -static void register_functions(void) -{ - s_cb_data cb_data; - cb_data.reason = cbEndOfCompile; - cb_data.cb_rtn = register_nextsimtime; - vpi_register_cb(&cb_data); -} - -void (*vlog_startup_routines[])(void) = { - register_functions, - NULL -}; diff --git a/ivtest/vpi/nextsimtime_null_time.c b/ivtest/vpi/nextsimtime_null_time.c index 23f7cfd83..3a61905f6 100644 --- a/ivtest/vpi/nextsimtime_null_time.c +++ b/ivtest/vpi/nextsimtime_null_time.c @@ -1,2 +1,2 @@ -#define TEST_NULL -#include "nextsimtime_errors.c" +#define TEST_NULL_TIME +#include "nextsimtime_common.c" diff --git a/ivtest/vpi/nextsimtime_null_time.v b/ivtest/vpi/nextsimtime_null_time.v index 92a807d86..4d31b0d01 100644 --- a/ivtest/vpi/nextsimtime_null_time.v +++ b/ivtest/vpi/nextsimtime_null_time.v @@ -1 +1 @@ -`include "vpi/nextsimtime_fill_time.v" +`include "vpi/nextsimtime_common.v" diff --git a/ivtest/vpi/nextsimtime_scaled_time.c b/ivtest/vpi/nextsimtime_scaled_time.c index 1a1d76608..a33a17d6e 100644 --- a/ivtest/vpi/nextsimtime_scaled_time.c +++ b/ivtest/vpi/nextsimtime_scaled_time.c @@ -1,2 +1,2 @@ -#define TEST_SCALED -#include "nextsimtime_errors.c" +#define TEST_SCALED_TIME +#include "nextsimtime_common.c" diff --git a/ivtest/vpi/nextsimtime_scaled_time.v b/ivtest/vpi/nextsimtime_scaled_time.v index 92a807d86..4d31b0d01 100644 --- a/ivtest/vpi/nextsimtime_scaled_time.v +++ b/ivtest/vpi/nextsimtime_scaled_time.v @@ -1 +1 @@ -`include "vpi/nextsimtime_fill_time.v" +`include "vpi/nextsimtime_common.v" diff --git a/ivtest/vpi/nextsimtime_sim_time.c b/ivtest/vpi/nextsimtime_sim_time.c new file mode 100644 index 000000000..3c4b79e39 --- /dev/null +++ b/ivtest/vpi/nextsimtime_sim_time.c @@ -0,0 +1,2 @@ +#define TEST_SIM_TIME +#include "nextsimtime_common.c" diff --git a/ivtest/vpi/nextsimtime_sim_time.v b/ivtest/vpi/nextsimtime_sim_time.v new file mode 100644 index 000000000..4d31b0d01 --- /dev/null +++ b/ivtest/vpi/nextsimtime_sim_time.v @@ -0,0 +1 @@ +`include "vpi/nextsimtime_common.v" diff --git a/ivtest/vpi/nextsimtime_suppress_time.c b/ivtest/vpi/nextsimtime_suppress_time.c index ca8151bb6..14ba3e786 100644 --- a/ivtest/vpi/nextsimtime_suppress_time.c +++ b/ivtest/vpi/nextsimtime_suppress_time.c @@ -1,2 +1,2 @@ -#define TEST_SUPPRESS -#include "nextsimtime_errors.c" +#define TEST_SUPPRESS_TIME +#include "nextsimtime_common.c" diff --git a/ivtest/vpi/nextsimtime_suppress_time.v b/ivtest/vpi/nextsimtime_suppress_time.v index 92a807d86..4d31b0d01 100644 --- a/ivtest/vpi/nextsimtime_suppress_time.v +++ b/ivtest/vpi/nextsimtime_suppress_time.v @@ -1 +1 @@ -`include "vpi/nextsimtime_fill_time.v" +`include "vpi/nextsimtime_common.v" diff --git a/ivtest/vpi_gold/nextsimtime_fill_time.gold b/ivtest/vpi_gold/nextsimtime_fill_time.gold deleted file mode 100644 index 69d8e699f..000000000 --- a/ivtest/vpi_gold/nextsimtime_fill_time.gold +++ /dev/null @@ -1,8 +0,0 @@ -Compiling vpi/nextsimtime_fill_time.c... -Making nextsimtime_fill_time.vpi from nextsimtime_fill_time.o... -time 0: 0 -nextsimtime: 1 vpi_get_time: 1 -time 1: 1 -nextsimtime: 4 vpi_get_time: 4 -time 4: 4 -nextsimtime: 5 vpi_get_time: 5 diff --git a/ivtest/vpi_gold/nextsimtime_sim_time.gold b/ivtest/vpi_gold/nextsimtime_sim_time.gold new file mode 100644 index 000000000..ad034a206 --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_sim_time.gold @@ -0,0 +1,8 @@ +Compiling vpi/nextsimtime_sim_time.c... +Making nextsimtime_sim_time.vpi from nextsimtime_sim_time.o... +time 0: 0 +nextsimtime: 1000 vpi_get_time: 1000 +time 1: 1 +nextsimtime: 4000 vpi_get_time: 4000 +time 4: 4 +nextsimtime: 5000 vpi_get_time: 5000 diff --git a/ivtest/vpi_regress.list b/ivtest/vpi_regress.list index 37d1571b0..2945bb4bf 100644 --- a/ivtest/vpi_regress.list +++ b/ivtest/vpi_regress.list @@ -99,10 +99,10 @@ hello_tf normal hello_tf.c hello_tf.log hello_vpi normal hello_vpi.c hello.log hello_vpi2 normal hello_vpi2.c hello2.log vpi/hello_vpi1.c listparams normal listparams.c listparams.log -nextsimtime_fill_time normal nextsimtime_fill_time.c nextsimtime_fill_time.gold -nextsimtime_null_time normal nextsimtime_null_time.c nextsimtime_null_time.gold -nextsimtime_scaled_time normal nextsimtime_scaled_time.c nextsimtime_scaled_time.gold -nextsimtime_suppress_time normal nextsimtime_suppress_time.c nextsimtime_suppress_time.gold +nextsimtime_null_time normal nextsimtime_null_time.c nextsimtime_null_time.gold +nextsimtime_scaled_time normal nextsimtime_scaled_time.c nextsimtime_scaled_time.gold +nextsimtime_sim_time normal nextsimtime_sim_time.c nextsimtime_sim_time.gold +nextsimtime_suppress_time normal nextsimtime_suppress_time.c nextsimtime_suppress_time.gold memmon normal,-g1995 memmon.c memmon.log memwide normal memwide.cc memwide.log mipname normal mipname.c mipname.log From bb0502a827f556c245224dbcb8050fa7b99c60fc Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 19:28:21 +0000 Subject: [PATCH 06/19] 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; From 0c61923636f5f5e14b4d3e6f0e2af4bd0855c90d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 22:04:29 +0000 Subject: [PATCH 07/19] Add regression tests for VPI value change callback with time reporting. --- ivtest/vpi/value_change.c | 124 +++++++++++++++++++++++++++++ ivtest/vpi/value_change.v | 47 +++++++++++ ivtest/vpi/value_change1.c | 2 + ivtest/vpi/value_change1.v | 1 + ivtest/vpi/value_change2.c | 2 + ivtest/vpi/value_change2.v | 1 + ivtest/vpi_gold/value_change1.gold | 16 ++++ ivtest/vpi_gold/value_change2.gold | 16 ++++ ivtest/vpi_regress.list | 2 + 9 files changed, 211 insertions(+) create mode 100644 ivtest/vpi/value_change.c create mode 100644 ivtest/vpi/value_change.v create mode 100644 ivtest/vpi/value_change1.c create mode 100644 ivtest/vpi/value_change1.v create mode 100644 ivtest/vpi/value_change2.c create mode 100644 ivtest/vpi/value_change2.v create mode 100644 ivtest/vpi_gold/value_change1.gold create mode 100644 ivtest/vpi_gold/value_change2.gold diff --git a/ivtest/vpi/value_change.c b/ivtest/vpi/value_change.c new file mode 100644 index 000000000..6527637a9 --- /dev/null +++ b/ivtest/vpi/value_change.c @@ -0,0 +1,124 @@ +#ifdef TEST_SCALED_TIME +#define TIME_TYPE vpiScaledRealTime +#else +#define TIME_TYPE vpiSimTime +#endif + +# include +# include +# include + +static PLI_INT32 report_change(p_cb_data cb) +{ + vpiHandle handle = (vpiHandle)(cb->user_data); + + assert(cb->time && (cb->time->type == TIME_TYPE)); + assert(cb->value); + + switch (cb->value->format) { + case vpiIntVal: +#ifdef TEST_SCALED_TIME + vpi_printf("At time %f %s = %d\n", cb->time->real, vpi_get_str(vpiName, handle), cb->value->value.integer); +#else + vpi_printf("At time %d %s = %d\n", cb->time->low, vpi_get_str(vpiName, handle), cb->value->value.integer); +#endif + break; + case vpiRealVal: +#ifdef TEST_SCALED_TIME + vpi_printf("At time %f %s = %f\n", cb->time->real, vpi_get_str(vpiName, handle), cb->value->value.real); +#else + vpi_printf("At time %d %s = %f\n", cb->time->low, vpi_get_str(vpiName, handle), cb->value->value.real); +#endif + break; + case vpiSuppressVal: +#ifdef TEST_SCALED_TIME + vpi_printf("At time %f %s changed\n", cb->time->real, vpi_get_str(vpiName, handle)); +#else + vpi_printf("At time %d %s changed\n", cb->time->low, vpi_get_str(vpiName, handle)); +#endif + break; + default: + vpi_printf("ERROR: unexpected value format %d\n", cb->value->format); + break; + } + return 0; +} + +static s_cb_data cb; +static s_vpi_time time; +static s_vpi_value value; + +static PLI_INT32 my_monitor_calltf(PLI_BYTE8 *xx) +{ + (void)xx; /* Parameter is not used. */ + + vpiHandle sys = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, sys); + + vpiHandle handle; + + memset(&cb, 0, sizeof(cb)); + memset(&time, 0, sizeof(time)); + memset(&value, 0, sizeof(value)); + + time.type = TIME_TYPE; + + cb.reason = cbValueChange; + cb.cb_rtn = report_change; + cb.time = &time; + cb.value = &value; + + while ((handle = vpi_scan(argv))) { + PLI_INT32 type = vpi_get(vpiType, handle); + cb.obj = handle; + cb.user_data = (char *)handle; + switch (type) { + case vpiNet: + case vpiReg: + case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: + case vpiPartSelect: + case vpiMemoryWord: + case vpiMemory: + value.format = vpiIntVal; + break; + case vpiRealVar: + value.format = vpiRealVal; + break; + case vpiNamedEvent: + value.format = vpiSuppressVal; + break; + default: + vpi_printf("ERROR: unexpected object type %d\n", type); + break; + } + vpi_register_cb(&cb); + } + + memset(&cb, 0, sizeof(cb)); + memset(&time, 0, sizeof(time)); + memset(&value, 0, sizeof(value)); + + return 0; +} + +static void my_monitor_register(void) +{ + s_vpi_systf_data tf_data; + + tf_data.type = vpiSysTask; + tf_data.tfname = "$my_monitor"; + tf_data.calltf = my_monitor_calltf; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + vpi_register_systf(&tf_data); +} + +void (*vlog_startup_routines[])(void) = { + my_monitor_register, + 0 +}; diff --git a/ivtest/vpi/value_change.v b/ivtest/vpi/value_change.v new file mode 100644 index 000000000..f3ec25757 --- /dev/null +++ b/ivtest/vpi/value_change.v @@ -0,0 +1,47 @@ +`timescale 1s/1ms + +module test; + +logic [3:0] v4; +wire [3:0] w4; +integer i4; + +bit [3:0] v2; +byte b2; +shortint s2; +int i2; +longint l2; + +real r; + +event e; + +logic [3:0] p4; + +logic [3:0] a4[3:0]; +// this causes a segfault - to be investigated +//bit [3:0] a2[3:0]; +logic [3:0] a2[3:0]; + +assign w4 = v4; + +initial begin + $my_monitor(v4, w4, i4, v2, b2, s2, i2, l2, r, e, p4[1:0], a4, a2[1]); + #1 v4 = 4'd1; + #1 i4 = 2; + #1 v2 = 4'd3; + #1 b2 = 4; + #1 s2 = 5; + #1 i2 = 6; + #1 l2 = 7; + #1 r = 8.0; + #1 ->e; + // NOTE: the value change callback on a part select returns the value of the entire variable. + #1 p4 = 4'd10; + #1 a4[0] = 4'd11; + #1 a4[1] = 4'd12; + #1 a2[0] = 4'd13; + #1 a2[1] = 4'd14; +end + +endmodule diff --git a/ivtest/vpi/value_change1.c b/ivtest/vpi/value_change1.c new file mode 100644 index 000000000..33830de7b --- /dev/null +++ b/ivtest/vpi/value_change1.c @@ -0,0 +1,2 @@ +#define TEST_SIM_TIME +#include "value_change.c" diff --git a/ivtest/vpi/value_change1.v b/ivtest/vpi/value_change1.v new file mode 100644 index 000000000..d1b7ef31b --- /dev/null +++ b/ivtest/vpi/value_change1.v @@ -0,0 +1 @@ +`include "vpi/value_change.v" diff --git a/ivtest/vpi/value_change2.c b/ivtest/vpi/value_change2.c new file mode 100644 index 000000000..ede0c8033 --- /dev/null +++ b/ivtest/vpi/value_change2.c @@ -0,0 +1,2 @@ +#define TEST_SCALED_TIME +#include "value_change.c" diff --git a/ivtest/vpi/value_change2.v b/ivtest/vpi/value_change2.v new file mode 100644 index 000000000..d1b7ef31b --- /dev/null +++ b/ivtest/vpi/value_change2.v @@ -0,0 +1 @@ +`include "vpi/value_change.v" diff --git a/ivtest/vpi_gold/value_change1.gold b/ivtest/vpi_gold/value_change1.gold new file mode 100644 index 000000000..5832d4203 --- /dev/null +++ b/ivtest/vpi_gold/value_change1.gold @@ -0,0 +1,16 @@ +Compiling vpi/value_change1.c... +Making value_change1.vpi from value_change1.o... +At time 1000 v4 = 1 +At time 1000 w4 = 1 +At time 2000 i4 = 2 +At time 3000 v2 = 3 +At time 4000 b2 = 4 +At time 5000 s2 = 5 +At time 6000 i2 = 6 +At time 7000 l2 = 7 +At time 8000 r = 8.000000 +At time 9000 e changed +At time 10000 p4[1:0] = 10 +At time 11000 a4 = 11 +At time 12000 a4 = 12 +At time 14000 a2[1] = 14 diff --git a/ivtest/vpi_gold/value_change2.gold b/ivtest/vpi_gold/value_change2.gold new file mode 100644 index 000000000..6e4c177b9 --- /dev/null +++ b/ivtest/vpi_gold/value_change2.gold @@ -0,0 +1,16 @@ +Compiling vpi/value_change2.c... +Making value_change2.vpi from value_change2.o... +At time 1.000000 v4 = 1 +At time 1.000000 w4 = 1 +At time 2.000000 i4 = 2 +At time 3.000000 v2 = 3 +At time 4.000000 b2 = 4 +At time 5.000000 s2 = 5 +At time 6.000000 i2 = 6 +At time 7.000000 l2 = 7 +At time 8.000000 r = 8.000000 +At time 9.000000 e changed +At time 10.000000 p4[1:0] = 10 +At time 11.000000 a4 = 11 +At time 12.000000 a4 = 12 +At time 14.000000 a2[1] = 14 diff --git a/ivtest/vpi_regress.list b/ivtest/vpi_regress.list index 2945bb4bf..218bb2188 100644 --- a/ivtest/vpi_regress.list +++ b/ivtest/vpi_regress.list @@ -135,6 +135,8 @@ scopes normal scopes.c scopes.log spec_delays normal,-gspecify spec_delays.c spec_delays.log start_of_simtime1 normal start_of_simtime1.c start_of_simtime1.log timescale normal timescale.c timescale.log +value_change1 normal,-g2009 value_change1.c value_change1.gold +value_change2 normal,-g2009 value_change2.c value_change2.gold # Add new tests in alphabetic/numeric order. If the test needs # a compile option or a different log file to run with an older From 872fcd13aec96b4a0142bcfb20ec321dffa15c40 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 22:12:33 +0000 Subject: [PATCH 08/19] vvp: Factor out code to scale time using the timescale of a VPI object. --- vvp/vpi_priv.cc | 16 +++++++++++----- vvp/vpi_priv.h | 2 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 26d59ac55..72b0e08f2 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -565,9 +565,18 @@ int vpip_time_precision_from_handle(vpiHandle obj) } } +double vpip_scaled_time_from_handle(vvp_time64_t time, vpiHandle obj) +{ + int scale = vpip_get_time_precision() - + vpip_time_units_from_handle(obj); + if (scale >= 0) + return (double)time * pow(10.0, scale); + else + return (double)time / pow(10.0, -scale); +} + void vpi_get_time(vpiHandle obj, s_vpi_time*vp) { - int scale; vvp_time64_t time; assert(vp); @@ -581,10 +590,7 @@ void vpi_get_time(vpiHandle obj, s_vpi_time*vp) break; case vpiScaledRealTime: - scale = vpip_get_time_precision() - - vpip_time_units_from_handle(obj); - if (scale >= 0) vp->real = (double)time * pow(10.0, scale); - else vp->real = (double)time / pow(10.0, -scale); + vp->real = vpip_scaled_time_from_handle(time, obj); break; default: diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 1c5f01652..7917112d8 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -1079,6 +1079,8 @@ extern void vpip_set_time_precision(int pres); extern int vpip_time_units_from_handle(vpiHandle obj); extern int vpip_time_precision_from_handle(vpiHandle obj); +extern double vpip_scaled_time_from_handle(vvp_time64_t time, vpiHandle obj); + extern void vpip_time_to_timestruct(struct t_vpi_time*ts, vvp_time64_t ti); extern vvp_time64_t vpip_timestruct_to_time(const struct t_vpi_time*ts); From f3f2dddf9ae1f998d26cc74e672322b919fae9e7 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 23:21:45 +0000 Subject: [PATCH 09/19] vvp: Factor out and extend code for finding timescale scope for a VPI object. --- vvp/vpi_priv.cc | 75 +++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 72b0e08f2..d8b370b61 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2023 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2024 Stephen Williams (steve@icarus.com) * Copyright (c) 2023 Leo Moser (leo.moser@pm.me) * * This source code is free software; you can redistribute it @@ -495,74 +495,75 @@ char* vpi_get_str(PLI_INT32 property, vpiHandle ref) return res; } -int vpip_time_units_from_handle(vpiHandle obj) +static __vpiScope*vpip_timescale_scope_from_handle(vpiHandle obj) { struct __vpiSysTaskCall*task; - __vpiScope*scope; struct __vpiSignal*signal; + struct __vpiRealVar*real; __vpiNamedEvent*event; - if (obj == 0) - return vpip_get_time_precision(); - switch (obj->get_type_code()) { case vpiSysTaskCall: task = dynamic_cast<__vpiSysTaskCall*>(obj); - return task->scope->time_units; + return task->scope; case vpiModule: - scope = dynamic_cast<__vpiScope*>(obj); - return scope->time_units; + return dynamic_cast<__vpiScope*>(obj); case vpiNet: case vpiReg: + case vpiIntegerVar: + case vpiBitVar: + case vpiByteVar: + case vpiShortIntVar: + case vpiIntVar: + case vpiLongIntVar: signal = dynamic_cast<__vpiSignal*>(obj); - scope = vpip_scope(signal); - return scope->time_units; + return vpip_scope(signal); + + case vpiRealVar: + real = dynamic_cast<__vpiRealVar*>(obj); + return vpip_scope(real); case vpiNamedEvent: event = dynamic_cast<__vpiNamedEvent*>(obj); - scope = event->get_scope(); - return scope->time_units; + return event->get_scope(); + + case vpiMemory: + case vpiMemoryWord: + case vpiPartSelect: + return dynamic_cast<__vpiScope*>(obj->vpi_handle(vpiScope)); default: - fprintf(stderr, "ERROR: vpip_time_units_from_handle called with " + fprintf(stderr, "ERROR: vpip_scope_from_handle called with " "object handle type=%d\n", obj->get_type_code()); assert(0); return 0; } } -int vpip_time_precision_from_handle(vpiHandle obj) +int vpip_time_units_from_handle(vpiHandle obj) { - struct __vpiSysTaskCall*task; - __vpiScope*scope; - struct __vpiSignal*signal; - if (obj == 0) return vpip_get_time_precision(); - switch (obj->get_type_code()) { - case vpiSysTaskCall: - task = dynamic_cast<__vpiSysTaskCall*>(obj); - return task->scope->time_precision; + __vpiScope*scope = vpip_timescale_scope_from_handle(obj); + if (scope == 0) + return vpip_get_time_precision(); - case vpiModule: - scope = dynamic_cast<__vpiScope*>(obj); - return scope->time_precision; + return scope->time_units; +} - case vpiNet: - case vpiReg: - signal = dynamic_cast<__vpiSignal*>(obj); - scope = vpip_scope(signal); - return scope->time_precision; +int vpip_time_precision_from_handle(vpiHandle obj) +{ + if (obj == 0) + return vpip_get_time_precision(); - default: - fprintf(stderr, "ERROR: vpip_time_precision_from_handle called " - "with object handle type=%d\n", obj->get_type_code()); - assert(0); - return 0; - } + __vpiScope*scope = vpip_timescale_scope_from_handle(obj); + if (scope == 0) + return vpip_get_time_precision(); + + return scope->time_precision; } double vpip_scaled_time_from_handle(vvp_time64_t time, vpiHandle obj) From 1d793ddba8f3c6838ab56dd5c15f70f72c0db770 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 5 Feb 2024 23:24:45 +0000 Subject: [PATCH 10/19] vvp: Fix time scaling when using vpiScaledRealTime in VPI callbacks. The old code only worked for VPI objects that represented variables and nets. For simulation time callbacks, the user might pass an object that represents a scope. --- vvp/vpi_callback.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index a7bec50a0..d4751048c 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -51,9 +51,7 @@ static void set_callback_time(p_cb_data data) 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); + data->time->real = vpip_scaled_time_from_handle(schedule_simtime(), data->obj); break; case vpiSuppressTime: break; From 5c1ca6eb9366144f940418f9fc28fc50c852a38d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 6 Feb 2024 09:04:13 +0000 Subject: [PATCH 11/19] Extend the VPI value change callback tests. Cover the vpiSuppressTime and null time pointer cases. --- ivtest/vpi/value_change.c | 31 +++++++++++++++++++++--------- ivtest/vpi/value_change3.c | 2 ++ ivtest/vpi/value_change3.v | 1 + ivtest/vpi/value_change4.c | 2 ++ ivtest/vpi/value_change4.v | 1 + ivtest/vpi_gold/value_change3.gold | 16 +++++++++++++++ ivtest/vpi_gold/value_change4.gold | 16 +++++++++++++++ ivtest/vpi_regress.list | 2 ++ 8 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 ivtest/vpi/value_change3.c create mode 100644 ivtest/vpi/value_change3.v create mode 100644 ivtest/vpi/value_change4.c create mode 100644 ivtest/vpi/value_change4.v create mode 100644 ivtest/vpi_gold/value_change3.gold create mode 100644 ivtest/vpi_gold/value_change4.gold diff --git a/ivtest/vpi/value_change.c b/ivtest/vpi/value_change.c index 6527637a9..cf3c09f7c 100644 --- a/ivtest/vpi/value_change.c +++ b/ivtest/vpi/value_change.c @@ -1,7 +1,9 @@ -#ifdef TEST_SCALED_TIME +#if defined(TEST_SCALED_TIME) #define TIME_TYPE vpiScaledRealTime -#else +#elif defined(TEST_SIM_TIME) #define TIME_TYPE vpiSimTime +#else +#define TIME_TYPE vpiSuppressTime #endif # include @@ -12,29 +14,40 @@ static PLI_INT32 report_change(p_cb_data cb) { vpiHandle handle = (vpiHandle)(cb->user_data); + s_vpi_time time; + +#ifndef TEST_NULL_TIME assert(cb->time && (cb->time->type == TIME_TYPE)); +#endif assert(cb->value); +#if defined(TEST_SCALED_TIME) || defined(TEST_SIM_TIME) + time = *(cb->time); +#else + time.type = vpiSimTime; + vpi_get_time(NULL, &time); +#endif + switch (cb->value->format) { case vpiIntVal: -#ifdef TEST_SCALED_TIME - vpi_printf("At time %f %s = %d\n", cb->time->real, vpi_get_str(vpiName, handle), cb->value->value.integer); +#if defined(TEST_SCALED_TIME) + vpi_printf("At time %f %s = %d\n", time.real, vpi_get_str(vpiName, handle), cb->value->value.integer); #else - vpi_printf("At time %d %s = %d\n", cb->time->low, vpi_get_str(vpiName, handle), cb->value->value.integer); + vpi_printf("At time %d %s = %d\n", time.low, vpi_get_str(vpiName, handle), cb->value->value.integer); #endif break; case vpiRealVal: #ifdef TEST_SCALED_TIME - vpi_printf("At time %f %s = %f\n", cb->time->real, vpi_get_str(vpiName, handle), cb->value->value.real); + vpi_printf("At time %f %s = %f\n", time.real, vpi_get_str(vpiName, handle), cb->value->value.real); #else - vpi_printf("At time %d %s = %f\n", cb->time->low, vpi_get_str(vpiName, handle), cb->value->value.real); + vpi_printf("At time %d %s = %f\n", time.low, vpi_get_str(vpiName, handle), cb->value->value.real); #endif break; case vpiSuppressVal: #ifdef TEST_SCALED_TIME - vpi_printf("At time %f %s changed\n", cb->time->real, vpi_get_str(vpiName, handle)); + vpi_printf("At time %f %s changed\n", time.real, vpi_get_str(vpiName, handle)); #else - vpi_printf("At time %d %s changed\n", cb->time->low, vpi_get_str(vpiName, handle)); + vpi_printf("At time %d %s changed\n", time.low, vpi_get_str(vpiName, handle)); #endif break; default: diff --git a/ivtest/vpi/value_change3.c b/ivtest/vpi/value_change3.c new file mode 100644 index 000000000..58462ceb7 --- /dev/null +++ b/ivtest/vpi/value_change3.c @@ -0,0 +1,2 @@ +#define TEST_SUPPRESS_TIME +#include "value_change.c" diff --git a/ivtest/vpi/value_change3.v b/ivtest/vpi/value_change3.v new file mode 100644 index 000000000..d1b7ef31b --- /dev/null +++ b/ivtest/vpi/value_change3.v @@ -0,0 +1 @@ +`include "vpi/value_change.v" diff --git a/ivtest/vpi/value_change4.c b/ivtest/vpi/value_change4.c new file mode 100644 index 000000000..c39b94168 --- /dev/null +++ b/ivtest/vpi/value_change4.c @@ -0,0 +1,2 @@ +#define TEST_NULL_TIME +#include "value_change.c" diff --git a/ivtest/vpi/value_change4.v b/ivtest/vpi/value_change4.v new file mode 100644 index 000000000..d1b7ef31b --- /dev/null +++ b/ivtest/vpi/value_change4.v @@ -0,0 +1 @@ +`include "vpi/value_change.v" diff --git a/ivtest/vpi_gold/value_change3.gold b/ivtest/vpi_gold/value_change3.gold new file mode 100644 index 000000000..2e1b32fb0 --- /dev/null +++ b/ivtest/vpi_gold/value_change3.gold @@ -0,0 +1,16 @@ +Compiling vpi/value_change3.c... +Making value_change3.vpi from value_change3.o... +At time 1000 v4 = 1 +At time 1000 w4 = 1 +At time 2000 i4 = 2 +At time 3000 v2 = 3 +At time 4000 b2 = 4 +At time 5000 s2 = 5 +At time 6000 i2 = 6 +At time 7000 l2 = 7 +At time 8000 r = 8.000000 +At time 9000 e changed +At time 10000 p4[1:0] = 10 +At time 11000 a4 = 11 +At time 12000 a4 = 12 +At time 14000 a2[1] = 14 diff --git a/ivtest/vpi_gold/value_change4.gold b/ivtest/vpi_gold/value_change4.gold new file mode 100644 index 000000000..aa9fb3008 --- /dev/null +++ b/ivtest/vpi_gold/value_change4.gold @@ -0,0 +1,16 @@ +Compiling vpi/value_change4.c... +Making value_change4.vpi from value_change4.o... +At time 1000 v4 = 1 +At time 1000 w4 = 1 +At time 2000 i4 = 2 +At time 3000 v2 = 3 +At time 4000 b2 = 4 +At time 5000 s2 = 5 +At time 6000 i2 = 6 +At time 7000 l2 = 7 +At time 8000 r = 8.000000 +At time 9000 e changed +At time 10000 p4[1:0] = 10 +At time 11000 a4 = 11 +At time 12000 a4 = 12 +At time 14000 a2[1] = 14 diff --git a/ivtest/vpi_regress.list b/ivtest/vpi_regress.list index 218bb2188..facced0c6 100644 --- a/ivtest/vpi_regress.list +++ b/ivtest/vpi_regress.list @@ -137,6 +137,8 @@ start_of_simtime1 normal start_of_simtime1.c start_of_simtime1.log timescale normal timescale.c timescale.log value_change1 normal,-g2009 value_change1.c value_change1.gold value_change2 normal,-g2009 value_change2.c value_change2.gold +value_change3 normal,-g2009 value_change3.c value_change3.gold +value_change4 normal,-g2009 value_change4.c value_change4.gold # Add new tests in alphabetic/numeric order. If the test needs # a compile option or a different log file to run with an older From 9d048092801a9793f2d19f3d1736fb090086ef91 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 6 Feb 2024 18:12:32 +0000 Subject: [PATCH 12/19] libveriuser: Fix calls to vpi_register_cb that had invalid time types. When registering a cbReadWriteSynch or cbReadOnlySynch callback, the time type must be either vpiSimTime or vpiScaledRealTime. vpiSuppressTime is illegal. The required behaviour is a delay of zero, so use vpiSimTime with the high and low fields set to 0. --- libveriuser/veriusertfs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libveriuser/veriusertfs.c b/libveriuser/veriusertfs.c index c09503f49..71d47e537 100644 --- a/libveriuser/veriusertfs.c +++ b/libveriuser/veriusertfs.c @@ -385,9 +385,7 @@ PLI_INT32 tf_isynchronize(void*obj) vpiHandle sys = (vpiHandle)obj; p_pli_data pli = vpi_get_userdata(sys); s_cb_data cb; - s_vpi_time ti; - - ti.type = vpiSuppressTime; + s_vpi_time ti = {vpiSimTime, 0, 0, 0.0}; cb.reason = cbReadWriteSynch; cb.cb_rtn = callback; @@ -414,7 +412,7 @@ PLI_INT32 tf_irosynchronize(void*obj) vpiHandle sys = (vpiHandle)obj; p_pli_data pli = vpi_get_userdata(sys); s_cb_data cb; - s_vpi_time ti = {vpiSuppressTime, 0, 0, 0.0}; + s_vpi_time ti = {vpiSimTime, 0, 0, 0.0}; cb.reason = cbReadOnlySynch; cb.cb_rtn = callback; From ad400ac468b3c769a211b11fe2d846c7ada6de74 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 6 Feb 2024 18:47:54 +0000 Subject: [PATCH 13/19] vvp: Remove restriction on time types for cbNextSimTime. IEEE 1364-1995 has different wording to later versions of the standard, stating "For reason cbNextSimTime, the time structure is ignored." So it's possible old VPI code might not pass a valid time pointer or time structure. So remove the checks that the time pointer is non-null and that the time type is not vpiSuppressTime. To allow a user to select the time type, we have to assume that if the time pointer is non-null, it is a valid pointer and not just an uninitialised field. --- ivtest/vpi/nextsimtime_common.c | 22 ++++++++++++------- ivtest/vpi_gold/nextsimtime_null_time.gold | 7 +++++- ivtest/vpi_gold/nextsimtime_scaled_time.gold | 6 ++--- ivtest/vpi_gold/nextsimtime_sim_time.gold | 6 ++--- .../vpi_gold/nextsimtime_suppress_time.gold | 7 +++++- vvp/vpi_callback.cc | 10 --------- 6 files changed, 32 insertions(+), 26 deletions(-) diff --git a/ivtest/vpi/nextsimtime_common.c b/ivtest/vpi/nextsimtime_common.c index 525f1a0f9..62da1b18c 100644 --- a/ivtest/vpi/nextsimtime_common.c +++ b/ivtest/vpi/nextsimtime_common.c @@ -37,20 +37,26 @@ static PLI_INT32 register_nextsimtime(struct t_cb_data* cb); static PLI_INT32 nextsimtime_cb(struct t_cb_data* cb) { s_vpi_time timerec; -#ifdef TEST_SCALED_TIME - timerec.type = vpiScaledRealTime; + +#ifdef TEST_NULL_TIME + (void)cb; +#else + assert(cb->time && (cb->time->type == TIME_TYPE)); +#endif + +#if defined(TEST_SCALED_TIME) || defined(TEST_SIM_TIME) + timerec = *(cb->time); #else timerec.type = vpiSimTime; + vpi_get_time(NULL, &timerec); #endif - 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); + vpi_printf("nextsimtime: %f\n", timerec.real); #else - uint64_t nextsimtime = ((uint64_t)cb->time->high << 32) | cb->time->low; uint64_t time = ((uint64_t)timerec.high << 32) | timerec.low; - vpi_printf("nextsimtime: %" PLI_UINT64_FMT " vpi_get_time: %" PLI_UINT64_FMT "\n", - nextsimtime, time); + vpi_printf("nextsimtime: %" PLI_UINT64_FMT "\n", time); #endif register_nextsimtime(NULL); return 0; diff --git a/ivtest/vpi_gold/nextsimtime_null_time.gold b/ivtest/vpi_gold/nextsimtime_null_time.gold index 020526985..1a513b1c7 100644 --- a/ivtest/vpi_gold/nextsimtime_null_time.gold +++ b/ivtest/vpi_gold/nextsimtime_null_time.gold @@ -1,3 +1,8 @@ Compiling vpi/nextsimtime_null_time.c... Making nextsimtime_null_time.vpi from nextsimtime_null_time.o... -ERROR: VPI: cbNextSimTime time pointer must be valid. +time 0: 0 +nextsimtime: 1000 +time 1: 1 +nextsimtime: 4000 +time 4: 4 +nextsimtime: 5000 diff --git a/ivtest/vpi_gold/nextsimtime_scaled_time.gold b/ivtest/vpi_gold/nextsimtime_scaled_time.gold index 1be7a2745..c3df10b6f 100644 --- a/ivtest/vpi_gold/nextsimtime_scaled_time.gold +++ b/ivtest/vpi_gold/nextsimtime_scaled_time.gold @@ -1,8 +1,8 @@ Compiling vpi/nextsimtime_scaled_time.c... Making nextsimtime_scaled_time.vpi from nextsimtime_scaled_time.o... time 0: 0 -nextsimtime: 1.000000 vpi_get_time: 1.000000 +nextsimtime: 1.000000 time 1: 1 -nextsimtime: 4.000000 vpi_get_time: 4.000000 +nextsimtime: 4.000000 time 4: 4 -nextsimtime: 5.000000 vpi_get_time: 5.000000 +nextsimtime: 5.000000 diff --git a/ivtest/vpi_gold/nextsimtime_sim_time.gold b/ivtest/vpi_gold/nextsimtime_sim_time.gold index ad034a206..3ad99a8af 100644 --- a/ivtest/vpi_gold/nextsimtime_sim_time.gold +++ b/ivtest/vpi_gold/nextsimtime_sim_time.gold @@ -1,8 +1,8 @@ Compiling vpi/nextsimtime_sim_time.c... Making nextsimtime_sim_time.vpi from nextsimtime_sim_time.o... time 0: 0 -nextsimtime: 1000 vpi_get_time: 1000 +nextsimtime: 1000 time 1: 1 -nextsimtime: 4000 vpi_get_time: 4000 +nextsimtime: 4000 time 4: 4 -nextsimtime: 5000 vpi_get_time: 5000 +nextsimtime: 5000 diff --git a/ivtest/vpi_gold/nextsimtime_suppress_time.gold b/ivtest/vpi_gold/nextsimtime_suppress_time.gold index 2906f3736..35edff5f3 100644 --- a/ivtest/vpi_gold/nextsimtime_suppress_time.gold +++ b/ivtest/vpi_gold/nextsimtime_suppress_time.gold @@ -1,3 +1,8 @@ Compiling vpi/nextsimtime_suppress_time.c... Making nextsimtime_suppress_time.vpi from nextsimtime_suppress_time.o... -ERROR: VPI: cbNextSimTime time type cannot be vpiSuppressTime. +time 0: 0 +nextsimtime: 1000 +time 1: 1 +nextsimtime: 4000 +time 4: 4 +nextsimtime: 5000 diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index d4751048c..72d5422c6 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -646,16 +646,6 @@ static simulator_callback* make_prepost(p_cb_data data) EndOfSimulation = obj; break; case cbNextSimTime: - if (!data->time) { - vpi_printf("ERROR: VPI: cbNextSimTime time pointer must be valid.\n"); - vpi_control(vpiFinish, 1); - break; - } - if (data->time->type == vpiSuppressTime) { - vpi_printf("ERROR: VPI: cbNextSimTime time type cannot be vpiSuppressTime.\n"); - vpi_control(vpiFinish, 1); - break; - } obj->next = NextSimTime; NextSimTime = obj; break; From 8b357d670d2236bf4d2f6c5ab306f8e065e9473f Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 6 Feb 2024 20:08:10 +0000 Subject: [PATCH 14/19] vvp: Comprehensively check the time type passed to vpi_register_cb. NOTE: This removes the ability to request vpiSuppressTime for the simulation time callbacks (other than cbNextSimTime). Requesting this is clearly stated to be an error in IEEE 1364-2001 onwards. --- vvp/vpi_callback.cc | 115 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 4 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 72d5422c6..93df4aae6 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -40,6 +40,98 @@ using namespace std; +static const char*cb_reason_name(PLI_INT32 reason) +{ + switch (reason) { + case cbValueChange: + return "cbValueChange"; + case cbStmt: + return "cbStmt"; + case cbForce: + return "cbForce"; + case cbRelease: + return "cbRelease"; + case cbAtStartOfSimTime: + return "cbAtStartOfSimTime"; + case cbReadWriteSynch: + return "cbReadWriteSynch"; + case cbReadOnlySynch: + return "cbReadOnlySynch"; + case cbNextSimTime: + return "cbNextSimTime"; + case cbAfterDelay: + return "cbAfterDelay"; + case cbEndOfCompile: + return "cbEndOfCompile"; + case cbStartOfSimulation: + return "cbStartOfSimulation"; + case cbEndOfSimulation: + return "cbEndOfSimulation"; + case cbError: + return "cbError"; + case cbTchkViolation: + return "cbTchkViolation"; + case cbStartOfSave: + return "cbStartOfSave"; + case cbEndOfSave: + return "cbEndOfSave"; + case cbStartOfRestart: + return "cbStartOfRestart"; + case cbEndOfRestart: + return "cbEndOfRestart"; + case cbStartOfReset: + return "cbStartOfReset"; + case cbEndOfReset: + return "cbEndOfReset"; + case cbEnterInteractive: + return "cbEnterInteractive"; + case cbExitInteractive: + return "cbExitInteractive"; + case cbInteractiveScopeChange: + return "cbInteractiveScopeChange"; + case cbUnresolvedSystf: + return "cbUnresolvedSystf"; + case cbAtEndOfSimTime: + return "cbAtEndOfSimTime"; + default: + return "unrecognised"; + } +} + +static bool check_callback_time(p_cb_data data, bool allow_suppress) +{ + assert(data); + if (!data->time) { + if (!allow_suppress) { + fprintf(stderr, "VPI error: null value passed in cb_data.time " + "when registering %s callback\n.", + cb_reason_name(data->reason)); + return false; + } + return true; + } + switch (data->time->type) { + case vpiSimTime: + break; + case vpiScaledRealTime: + break; + case vpiSuppressTime: + if (!allow_suppress) { + fprintf(stderr, "VPI error: vpiSuppressTime is not valid " + "when registering %s callback\n.", + cb_reason_name(data->reason)); + return false; + } + break; + default: + fprintf(stderr, "VPI error: invalid type passed in cb_data time " + "structure when registering %s callback\n.", + cb_reason_name(data->reason)); + return false; + } + return true; +} + static void set_callback_time(p_cb_data data) { assert(data && data->time); @@ -224,6 +316,9 @@ static value_callback*make_value_change_part(p_cb_data data) */ static value_callback* make_value_change(p_cb_data data) { + if (!check_callback_time(data, true)) + return 0; + if (vpi_get(vpiAutomatic, data->obj)) { fprintf(stderr, "vpi error: cannot place value change " "callback on automatically allocated " @@ -352,6 +447,9 @@ void sync_cb::run_run() static sync_callback* make_sync(p_cb_data data, bool readonly_flag) { + if (!check_callback_time(data, false)) + return 0; + sync_callback*obj = new sync_callback(data); struct sync_cb*cb = new sync_cb; @@ -361,9 +459,6 @@ static sync_callback* make_sync(p_cb_data data, bool readonly_flag) vvp_time64_t tv = 0; switch (obj->cb_time.type) { - case vpiSuppressTime: - break; - case vpiSimTime: tv = vpip_timestruct_to_time(&obj->cb_time); break; @@ -375,11 +470,15 @@ static sync_callback* make_sync(p_cb_data data, bool readonly_flag) break; } schedule_generic(cb, tv, true, readonly_flag); + return obj; } static struct __vpiCallback* make_afterdelay(p_cb_data data) { + if (!check_callback_time(data, false)) + return 0; + sync_callback*obj = new sync_callback(data); struct sync_cb*cb = new sync_cb; cb->sync_flag = false; @@ -398,7 +497,6 @@ static struct __vpiCallback* make_afterdelay(p_cb_data data) assert(0); break; } - schedule_generic(cb, tv, false); return obj; @@ -406,6 +504,9 @@ static struct __vpiCallback* make_afterdelay(p_cb_data data) static struct __vpiCallback* make_at_start_of_sim_time(p_cb_data data) { + if (!check_callback_time(data, false)) + return 0; + sync_callback*obj = new sync_callback(data); struct sync_cb*cb = new sync_cb; cb->sync_flag = false; @@ -441,6 +542,9 @@ static struct __vpiCallback* make_at_start_of_sim_time(p_cb_data data) static struct __vpiCallback* make_at_end_of_sim_time(p_cb_data data) { + if (!check_callback_time(data, false)) + return 0; + sync_callback*obj = new sync_callback(data); struct sync_cb*cb = new sync_cb; cb->sync_flag = false; @@ -629,6 +733,9 @@ void vpiNextSimTime(void) static simulator_callback* make_prepost(p_cb_data data) { + if ((data->reason == cbNextSimTime) && !check_callback_time(data, true)) + return 0; + simulator_callback*obj = new simulator_callback(data); /* Insert at head of list */ From c363231b9c536e1adfb371ceb80d8cab530223e6 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 6 Feb 2024 22:04:23 +0000 Subject: [PATCH 15/19] vvp: Add support for value change callback on 2-state array word. --- ivtest/vpi/value_change.v | 4 +--- vvp/array.cc | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ivtest/vpi/value_change.v b/ivtest/vpi/value_change.v index f3ec25757..3ebf8e436 100644 --- a/ivtest/vpi/value_change.v +++ b/ivtest/vpi/value_change.v @@ -19,9 +19,7 @@ event e; logic [3:0] p4; logic [3:0] a4[3:0]; -// this causes a segfault - to be investigated -//bit [3:0] a2[3:0]; -logic [3:0] a2[3:0]; +bit [3:0] a2[3:0]; assign w4 = v4; diff --git a/vvp/array.cc b/vvp/array.cc index 7b3d6699c..36d72c6fe 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2022 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2024 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -1319,11 +1319,29 @@ void __vpiArray::word_change(unsigned long addr) if (addr < vals->get_size()) vals->get_word(addr, val); vpip_real_get_value(val, cur->cb_data.value); - } else { + } else if (vals4) { vpip_vec4_get_value(vals4->get_word(addr), vals_width, signed_flag, cur->cb_data.value); + } else if (dynamic_cast*>(vals) + || dynamic_cast*>(vals) + || dynamic_cast*>(vals) + || dynamic_cast*>(vals) + || dynamic_cast*>(vals) + || dynamic_cast*>(vals) + || dynamic_cast*>(vals) + || dynamic_cast*>(vals) + || dynamic_cast(vals)) { + vvp_vector4_t val; + if (addr < vals->get_size()) + vals->get_word(addr, val); + vpip_vec4_get_value(val, + vals_width, + signed_flag, + cur->cb_data.value); + } else { + assert(0); } } From 8e754d180e090cc2db7b6b0a9957eaacb2b9fe4f Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 6 Feb 2024 23:35:05 +0000 Subject: [PATCH 16/19] vvp: Add support for vpiScaledRealTime in VPI simulation time callbacks. Factor out the common code for the four different sync callback types and extend it. --- vvp/vpi_callback.cc | 76 ++++++++++++++++----------------------------- vvp/vpi_priv.cc | 2 +- vvp/vpi_priv.h | 2 ++ 3 files changed, 29 insertions(+), 51 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 93df4aae6..e18bf00c7 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -445,6 +445,28 @@ void sync_cb::run_run() delete cur; } +static vvp_time64_t get_sync_cb_time(sync_callback*obj) +{ + vvp_time64_t tv = 0; + switch (obj->cb_time.type) { + case vpiSimTime: + tv = vpip_timestruct_to_time(&obj->cb_time); + break; + + case vpiScaledRealTime: + tv = vpip_scaled_real_to_time64(obj->cb_time.real, + vpip_timescale_scope_from_handle(obj->cb_data.obj)); + break; + + default: + fprintf(stderr, "get_sync_cb_time: Unsupported time type %d.\n", + (int)obj->cb_time.type); + assert(0); + break; + } + return tv; +} + static sync_callback* make_sync(p_cb_data data, bool readonly_flag) { if (!check_callback_time(data, false)) @@ -457,18 +479,7 @@ static sync_callback* make_sync(p_cb_data data, bool readonly_flag) cb->handle = obj; obj->cb_sync = cb; - vvp_time64_t tv = 0; - switch (obj->cb_time.type) { - case vpiSimTime: - tv = vpip_timestruct_to_time(&obj->cb_time); - break; - - default: - fprintf(stderr, "Unsupported time type %d.\n", - (int)obj->cb_time.type); - assert(0); - break; - } + vvp_time64_t tv = get_sync_cb_time(obj); schedule_generic(cb, tv, true, readonly_flag); return obj; @@ -485,18 +496,7 @@ static struct __vpiCallback* make_afterdelay(p_cb_data data) cb->handle = obj; obj->cb_sync = cb; - vvp_time64_t tv = 0; - switch (obj->cb_time.type) { - case vpiSimTime: - tv = vpip_timestruct_to_time(&obj->cb_time); - break; - - default: - fprintf(stderr, "Unsupported time type %d.\n", - (int)obj->cb_time.type); - assert(0); - break; - } + vvp_time64_t tv = get_sync_cb_time(obj); schedule_generic(cb, tv, false); return obj; @@ -513,19 +513,7 @@ static struct __vpiCallback* make_at_start_of_sim_time(p_cb_data data) cb->handle = obj; obj->cb_sync = cb; - vvp_time64_t tv = 0; - switch (obj->cb_time.type) { - case vpiSimTime: - tv = vpip_timestruct_to_time(&obj->cb_time); - break; - - default: - fprintf(stderr, "Unsupported time type %d.\n", - (int)obj->cb_time.type); - assert(0); - break; - } - + vvp_time64_t tv = get_sync_cb_time(obj); vvp_time64_t cur = schedule_simtime(); if (cur > tv) { tv = 0; @@ -551,19 +539,7 @@ static struct __vpiCallback* make_at_end_of_sim_time(p_cb_data data) cb->handle = obj; obj->cb_sync = cb; - vvp_time64_t tv = 0; - switch (obj->cb_time.type) { - case vpiSimTime: - tv = vpip_timestruct_to_time(&obj->cb_time); - break; - - default: - fprintf(stderr, "Unsupported time type %d.\n", - (int)obj->cb_time.type); - assert(0); - break; - } - + vvp_time64_t tv = get_sync_cb_time(obj); vvp_time64_t cur = schedule_simtime(); if (cur > tv) { tv = 0; diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index d8b370b61..27fe86210 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -495,7 +495,7 @@ char* vpi_get_str(PLI_INT32 property, vpiHandle ref) return res; } -static __vpiScope*vpip_timescale_scope_from_handle(vpiHandle obj) +__vpiScope*vpip_timescale_scope_from_handle(vpiHandle obj) { struct __vpiSysTaskCall*task; struct __vpiSignal*signal; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 7917112d8..55b26d5d3 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -1076,6 +1076,8 @@ vpiHandle vpip_sim_realtime(__vpiScope*scope); extern int vpip_get_time_precision(void); extern void vpip_set_time_precision(int pres); +extern __vpiScope*vpip_timescale_scope_from_handle(vpiHandle obj); + extern int vpip_time_units_from_handle(vpiHandle obj); extern int vpip_time_precision_from_handle(vpiHandle obj); From 3433c92742627f9cb5e9bfc9c83eb0a56e75606e Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 6 Feb 2024 23:42:12 +0000 Subject: [PATCH 17/19] Add regression tests for VPI simulation time callbacks with both time types. --- ivtest/vpi/sim_time_cb.c | 171 ++++++++++++++++++++++++++++++ ivtest/vpi/sim_time_cb1.c | 2 + ivtest/vpi/sim_time_cb1.v | 27 +++++ ivtest/vpi/sim_time_cb2.c | 2 + ivtest/vpi/sim_time_cb2.v | 27 +++++ ivtest/vpi_gold/sim_time_cb1.gold | 10 ++ ivtest/vpi_gold/sim_time_cb2.gold | 10 ++ ivtest/vpi_regress.list | 2 + 8 files changed, 251 insertions(+) create mode 100644 ivtest/vpi/sim_time_cb.c create mode 100644 ivtest/vpi/sim_time_cb1.c create mode 100644 ivtest/vpi/sim_time_cb1.v create mode 100644 ivtest/vpi/sim_time_cb2.c create mode 100644 ivtest/vpi/sim_time_cb2.v create mode 100644 ivtest/vpi_gold/sim_time_cb1.gold create mode 100644 ivtest/vpi_gold/sim_time_cb2.gold diff --git a/ivtest/vpi/sim_time_cb.c b/ivtest/vpi/sim_time_cb.c new file mode 100644 index 000000000..acb829972 --- /dev/null +++ b/ivtest/vpi/sim_time_cb.c @@ -0,0 +1,171 @@ +#ifdef TEST_SCALED_TIME +#define TIME_TYPE vpiScaledRealTime +#else +#define TIME_TYPE vpiSimTime +#endif + +#include +#include +#include + +static PLI_INT32 monitor_cb(p_cb_data cb_data) +{ + vpiHandle*var_list = (vpiHandle*)cb_data->user_data; + + s_vpi_time time; + s_vpi_value value; + PLI_INT32 index; + + time.type = TIME_TYPE; + vpi_get_time(var_list[0], &time); +#ifdef TEST_SCALED_TIME + vpi_printf(" @ %1.1f :", time.real); +#else + vpi_printf(" @ %04d :", time.low); +#endif + + value.format = vpiIntVal; + + index = 0; + while (var_list[index]) { + vpi_get_value(var_list[index], &value); + vpi_printf(" %s = %d", vpi_get_str(vpiName, var_list[index]), value.value.integer); + index++; + } + vpi_printf("\n"); + + return 0; +} + +static PLI_INT32 monitor_cb_start(p_cb_data cb_data) +{ + vpi_printf("cbStartOfSimTime"); + monitor_cb(cb_data); + return 0; +} + +static PLI_INT32 monitor_cb_delay(p_cb_data cb_data) +{ + vpi_printf("cbAfterDelay "); + monitor_cb(cb_data); + return 0; +} + +static PLI_INT32 monitor_cb_synch(p_cb_data cb_data) +{ + vpi_printf("cbReadWriteSynch"); + monitor_cb(cb_data); + return 0; +} + +static PLI_INT32 monitor_cb_end(p_cb_data cb_data) +{ + vpiHandle*var_list = (vpiHandle*)cb_data->user_data; + + vpi_printf("cbEndOfSimTime "); + monitor_cb(cb_data); + free(var_list); + return 0; +} + +static PLI_INT32 monitor_calltf(char*xx) +{ + vpiHandle sys = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, sys); + + vpiHandle*var_list = 0; + + vpiHandle handle; + PLI_INT32 index; + s_vpi_time time; + s_vpi_time delay; + s_vpi_value value; + s_cb_data cb_data; + + (void)xx; /* Parameter is not used. */ + + delay.type = TIME_TYPE; + delay.low = 0; + delay.high = 0; + delay.real = 0.0; + + assert(argv); + + handle = vpi_scan(argv); + assert(handle && (vpi_get(vpiType, handle) == vpiConstant)); +#ifdef TEST_SCALED_TIME + value.format = vpiRealVal; + vpi_get_value(handle, &value); + delay.real = value.value.real; +#else + value.format = vpiIntVal; + vpi_get_value(handle, &value); + delay.low = value.value.integer; +#endif + + index = 0; + while ((handle = vpi_scan(argv))) { + assert(vpi_get(vpiType, handle) == vpiReg); + var_list = realloc(var_list, (index + 1) * sizeof(vpiHandle)); + var_list[index++] = handle; + } + var_list = realloc(var_list, (index + 1) * sizeof(vpiHandle)); + var_list[index++] = 0; + + assert(index > 0); + + time.type = TIME_TYPE; + vpi_get_time(var_list[0], &time); + // cbAtStartOfSimTime and cbAtEndOfSimTime want an absolute time. + // We know the test is short, so can ignore the high part. +#ifdef TEST_SCALED_TIME + time.real += delay.real; +#else + time.low += delay.low; +#endif + + cb_data.reason = cbAtStartOfSimTime; + cb_data.cb_rtn = monitor_cb_start; + cb_data.user_data = (char*)var_list; + cb_data.time = &time; + vpi_register_cb(&cb_data); + + cb_data.reason = cbAfterDelay; + cb_data.cb_rtn = monitor_cb_delay; + cb_data.user_data = (char*)var_list; + cb_data.time = &delay; + vpi_register_cb(&cb_data); + + // Add cbNBASynch when we support it + + cb_data.reason = cbReadWriteSynch; + cb_data.cb_rtn = monitor_cb_synch; + cb_data.user_data = (char*)var_list; + cb_data.time = &delay; + vpi_register_cb(&cb_data); + + cb_data.reason = cbAtEndOfSimTime; + cb_data.cb_rtn = monitor_cb_end; + cb_data.user_data = (char*)var_list; + cb_data.time = &time; + vpi_register_cb(&cb_data); + + return 0; +} + +static void monitor_register(void) +{ + s_vpi_systf_data tf_data; + + tf_data.type = vpiSysTask; + tf_data.tfname = "$monitor_time_slot"; + tf_data.calltf = monitor_calltf; + tf_data.compiletf = 0; + tf_data.sizetf = 0; + vpi_register_systf(&tf_data); +} + +void (*vlog_startup_routines[])(void) = { + monitor_register, + 0 +}; diff --git a/ivtest/vpi/sim_time_cb1.c b/ivtest/vpi/sim_time_cb1.c new file mode 100644 index 000000000..d93ba2499 --- /dev/null +++ b/ivtest/vpi/sim_time_cb1.c @@ -0,0 +1,2 @@ +#define TEST_SIM_TIME +#include "sim_time_cb.c" diff --git a/ivtest/vpi/sim_time_cb1.v b/ivtest/vpi/sim_time_cb1.v new file mode 100644 index 000000000..e58741bf3 --- /dev/null +++ b/ivtest/vpi/sim_time_cb1.v @@ -0,0 +1,27 @@ +`timescale 1s/1ms + +module test; + +reg [7:0] a, b; + +initial begin + a = 0; b = 0; + $monitor_time_slot(2000, a, b); + $monitor_time_slot(5000, a, b); + #1; + a = 1; b <= 1; + #1; + a = 2; b <= 2; + #1; + a = 3; b <= 3; + #1; + a = 4; b <= 4; + #1; + a = 5; b <= 5; + #1; + a = 6; b <= 6; + #1; + $finish(0); +end + +endmodule diff --git a/ivtest/vpi/sim_time_cb2.c b/ivtest/vpi/sim_time_cb2.c new file mode 100644 index 000000000..dab1047ed --- /dev/null +++ b/ivtest/vpi/sim_time_cb2.c @@ -0,0 +1,2 @@ +#define TEST_SCALED_TIME +#include "sim_time_cb.c" diff --git a/ivtest/vpi/sim_time_cb2.v b/ivtest/vpi/sim_time_cb2.v new file mode 100644 index 000000000..cd547c2da --- /dev/null +++ b/ivtest/vpi/sim_time_cb2.v @@ -0,0 +1,27 @@ +`timescale 1s/1ms + +module test; + +reg [7:0] a, b; + +initial begin + a = 0; b = 0; + $monitor_time_slot(2.0, a, b); + $monitor_time_slot(5.0, a, b); + #1; + a = 1; b <= 1; + #1; + a = 2; b <= 2; + #1; + a = 3; b <= 3; + #1; + a = 4; b <= 4; + #1; + a = 5; b <= 5; + #1; + a = 6; b <= 6; + #1; + $finish(0); +end + +endmodule diff --git a/ivtest/vpi_gold/sim_time_cb1.gold b/ivtest/vpi_gold/sim_time_cb1.gold new file mode 100644 index 000000000..d99e5379b --- /dev/null +++ b/ivtest/vpi_gold/sim_time_cb1.gold @@ -0,0 +1,10 @@ +Compiling vpi/sim_time_cb1.c... +Making sim_time_cb1.vpi from sim_time_cb1.o... +cbStartOfSimTime @ 2000 : a = 1 b = 1 +cbAfterDelay @ 2000 : a = 1 b = 1 +cbReadWriteSynch @ 2000 : a = 2 b = 2 +cbEndOfSimTime @ 2000 : a = 2 b = 2 +cbStartOfSimTime @ 5000 : a = 4 b = 4 +cbAfterDelay @ 5000 : a = 4 b = 4 +cbReadWriteSynch @ 5000 : a = 5 b = 5 +cbEndOfSimTime @ 5000 : a = 5 b = 5 diff --git a/ivtest/vpi_gold/sim_time_cb2.gold b/ivtest/vpi_gold/sim_time_cb2.gold new file mode 100644 index 000000000..0ec0e5ae1 --- /dev/null +++ b/ivtest/vpi_gold/sim_time_cb2.gold @@ -0,0 +1,10 @@ +Compiling vpi/sim_time_cb2.c... +Making sim_time_cb2.vpi from sim_time_cb2.o... +cbStartOfSimTime @ 2.0 : a = 1 b = 1 +cbAfterDelay @ 2.0 : a = 1 b = 1 +cbReadWriteSynch @ 2.0 : a = 2 b = 2 +cbEndOfSimTime @ 2.0 : a = 2 b = 2 +cbStartOfSimTime @ 5.0 : a = 4 b = 4 +cbAfterDelay @ 5.0 : a = 4 b = 4 +cbReadWriteSynch @ 5.0 : a = 5 b = 5 +cbEndOfSimTime @ 5.0 : a = 5 b = 5 diff --git a/ivtest/vpi_regress.list b/ivtest/vpi_regress.list index facced0c6..24c928180 100644 --- a/ivtest/vpi_regress.list +++ b/ivtest/vpi_regress.list @@ -132,6 +132,8 @@ scanmem normal scanmem.cc scanmem.log scanmem2 normal scanmem2.cc scanmem2.log scanmem3 normal scanmem3.cc scanmem3.log scopes normal scopes.c scopes.log +sim_time_cb1 normal sim_time_cb1.c sim_time_cb1.gold +sim_time_cb2 normal sim_time_cb2.c sim_time_cb2.gold spec_delays normal,-gspecify spec_delays.c spec_delays.log start_of_simtime1 normal start_of_simtime1.c start_of_simtime1.log timescale normal timescale.c timescale.log From 851aed6272959b4ab7e8ee45d892ec4dca4aec41 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 7 Feb 2024 00:02:58 +0000 Subject: [PATCH 18/19] Rationalise new VPI callback test names. --- .../{nextsimtime_common.c => nextsimtime_cb.c} | 0 .../{nextsimtime_common.v => nextsimtime_cb.v} | 0 ivtest/vpi/nextsimtime_cb1.c | 2 ++ ivtest/vpi/nextsimtime_cb1.v | 1 + ivtest/vpi/nextsimtime_cb2.c | 2 ++ ivtest/vpi/nextsimtime_cb2.v | 1 + ivtest/vpi/nextsimtime_cb3.c | 2 ++ ivtest/vpi/nextsimtime_cb3.v | 1 + ivtest/vpi/nextsimtime_cb4.c | 2 ++ ivtest/vpi/nextsimtime_cb4.v | 1 + ivtest/vpi/nextsimtime_null_time.c | 2 -- ivtest/vpi/nextsimtime_null_time.v | 1 - ivtest/vpi/nextsimtime_scaled_time.c | 2 -- ivtest/vpi/nextsimtime_scaled_time.v | 1 - ivtest/vpi/nextsimtime_sim_time.c | 2 -- ivtest/vpi/nextsimtime_sim_time.v | 1 - ivtest/vpi/nextsimtime_suppress_time.c | 2 -- ivtest/vpi/nextsimtime_suppress_time.v | 1 - ivtest/vpi/value_change1.c | 2 -- ivtest/vpi/value_change1.v | 1 - ivtest/vpi/value_change2.c | 2 -- ivtest/vpi/value_change2.v | 1 - ivtest/vpi/value_change3.c | 2 -- ivtest/vpi/value_change3.v | 1 - ivtest/vpi/value_change4.c | 2 -- ivtest/vpi/value_change4.v | 1 - ivtest/vpi/{value_change.c => value_change_cb.c} | 6 +++--- ivtest/vpi/{value_change.v => value_change_cb.v} | 0 ivtest/vpi/value_change_cb1.c | 2 ++ ivtest/vpi/value_change_cb1.v | 1 + ivtest/vpi/value_change_cb2.c | 2 ++ ivtest/vpi/value_change_cb2.v | 1 + ivtest/vpi/value_change_cb3.c | 2 ++ ivtest/vpi/value_change_cb3.v | 1 + ivtest/vpi/value_change_cb4.c | 2 ++ ivtest/vpi/value_change_cb4.v | 1 + ivtest/vpi_gold/nextsimtime_cb1.gold | 8 ++++++++ ivtest/vpi_gold/nextsimtime_cb2.gold | 8 ++++++++ ivtest/vpi_gold/nextsimtime_cb3.gold | 8 ++++++++ ivtest/vpi_gold/nextsimtime_cb4.gold | 8 ++++++++ ivtest/vpi_gold/nextsimtime_null_time.gold | 8 -------- ivtest/vpi_gold/nextsimtime_scaled_time.gold | 8 -------- ivtest/vpi_gold/nextsimtime_sim_time.gold | 8 -------- ivtest/vpi_gold/nextsimtime_suppress_time.gold | 8 -------- ...{value_change1.gold => value_change_cb1.gold} | 4 ++-- ...{value_change2.gold => value_change_cb2.gold} | 4 ++-- ...{value_change3.gold => value_change_cb3.gold} | 4 ++-- ...{value_change4.gold => value_change_cb4.gold} | 4 ++-- ivtest/vpi_regress.list | 16 ++++++++-------- 49 files changed, 75 insertions(+), 75 deletions(-) rename ivtest/vpi/{nextsimtime_common.c => nextsimtime_cb.c} (100%) rename ivtest/vpi/{nextsimtime_common.v => nextsimtime_cb.v} (100%) create mode 100644 ivtest/vpi/nextsimtime_cb1.c create mode 100644 ivtest/vpi/nextsimtime_cb1.v create mode 100644 ivtest/vpi/nextsimtime_cb2.c create mode 100644 ivtest/vpi/nextsimtime_cb2.v create mode 100644 ivtest/vpi/nextsimtime_cb3.c create mode 100644 ivtest/vpi/nextsimtime_cb3.v create mode 100644 ivtest/vpi/nextsimtime_cb4.c create mode 100644 ivtest/vpi/nextsimtime_cb4.v delete mode 100644 ivtest/vpi/nextsimtime_null_time.c delete mode 100644 ivtest/vpi/nextsimtime_null_time.v delete mode 100644 ivtest/vpi/nextsimtime_scaled_time.c delete mode 100644 ivtest/vpi/nextsimtime_scaled_time.v delete mode 100644 ivtest/vpi/nextsimtime_sim_time.c delete mode 100644 ivtest/vpi/nextsimtime_sim_time.v delete mode 100644 ivtest/vpi/nextsimtime_suppress_time.c delete mode 100644 ivtest/vpi/nextsimtime_suppress_time.v delete mode 100644 ivtest/vpi/value_change1.c delete mode 100644 ivtest/vpi/value_change1.v delete mode 100644 ivtest/vpi/value_change2.c delete mode 100644 ivtest/vpi/value_change2.v delete mode 100644 ivtest/vpi/value_change3.c delete mode 100644 ivtest/vpi/value_change3.v delete mode 100644 ivtest/vpi/value_change4.c delete mode 100644 ivtest/vpi/value_change4.v rename ivtest/vpi/{value_change.c => value_change_cb.c} (97%) rename ivtest/vpi/{value_change.v => value_change_cb.v} (100%) create mode 100644 ivtest/vpi/value_change_cb1.c create mode 100644 ivtest/vpi/value_change_cb1.v create mode 100644 ivtest/vpi/value_change_cb2.c create mode 100644 ivtest/vpi/value_change_cb2.v create mode 100644 ivtest/vpi/value_change_cb3.c create mode 100644 ivtest/vpi/value_change_cb3.v create mode 100644 ivtest/vpi/value_change_cb4.c create mode 100644 ivtest/vpi/value_change_cb4.v create mode 100644 ivtest/vpi_gold/nextsimtime_cb1.gold create mode 100644 ivtest/vpi_gold/nextsimtime_cb2.gold create mode 100644 ivtest/vpi_gold/nextsimtime_cb3.gold create mode 100644 ivtest/vpi_gold/nextsimtime_cb4.gold delete mode 100644 ivtest/vpi_gold/nextsimtime_null_time.gold delete mode 100644 ivtest/vpi_gold/nextsimtime_scaled_time.gold delete mode 100644 ivtest/vpi_gold/nextsimtime_sim_time.gold delete mode 100644 ivtest/vpi_gold/nextsimtime_suppress_time.gold rename ivtest/vpi_gold/{value_change1.gold => value_change_cb1.gold} (76%) rename ivtest/vpi_gold/{value_change2.gold => value_change_cb2.gold} (79%) rename ivtest/vpi_gold/{value_change3.gold => value_change_cb3.gold} (76%) rename ivtest/vpi_gold/{value_change4.gold => value_change_cb4.gold} (76%) diff --git a/ivtest/vpi/nextsimtime_common.c b/ivtest/vpi/nextsimtime_cb.c similarity index 100% rename from ivtest/vpi/nextsimtime_common.c rename to ivtest/vpi/nextsimtime_cb.c diff --git a/ivtest/vpi/nextsimtime_common.v b/ivtest/vpi/nextsimtime_cb.v similarity index 100% rename from ivtest/vpi/nextsimtime_common.v rename to ivtest/vpi/nextsimtime_cb.v diff --git a/ivtest/vpi/nextsimtime_cb1.c b/ivtest/vpi/nextsimtime_cb1.c new file mode 100644 index 000000000..b90273b4b --- /dev/null +++ b/ivtest/vpi/nextsimtime_cb1.c @@ -0,0 +1,2 @@ +#define TEST_SIM_TIME +#include "nextsimtime_cb.c" diff --git a/ivtest/vpi/nextsimtime_cb1.v b/ivtest/vpi/nextsimtime_cb1.v new file mode 100644 index 000000000..d7c7cff1d --- /dev/null +++ b/ivtest/vpi/nextsimtime_cb1.v @@ -0,0 +1 @@ +`include "vpi/nextsimtime_cb.v" diff --git a/ivtest/vpi/nextsimtime_cb2.c b/ivtest/vpi/nextsimtime_cb2.c new file mode 100644 index 000000000..35d6dd690 --- /dev/null +++ b/ivtest/vpi/nextsimtime_cb2.c @@ -0,0 +1,2 @@ +#define TEST_SCALED_TIME +#include "nextsimtime_cb.c" diff --git a/ivtest/vpi/nextsimtime_cb2.v b/ivtest/vpi/nextsimtime_cb2.v new file mode 100644 index 000000000..d7c7cff1d --- /dev/null +++ b/ivtest/vpi/nextsimtime_cb2.v @@ -0,0 +1 @@ +`include "vpi/nextsimtime_cb.v" diff --git a/ivtest/vpi/nextsimtime_cb3.c b/ivtest/vpi/nextsimtime_cb3.c new file mode 100644 index 000000000..acf54664e --- /dev/null +++ b/ivtest/vpi/nextsimtime_cb3.c @@ -0,0 +1,2 @@ +#define TEST_SUPPRESS_TIME +#include "nextsimtime_cb.c" diff --git a/ivtest/vpi/nextsimtime_cb3.v b/ivtest/vpi/nextsimtime_cb3.v new file mode 100644 index 000000000..d7c7cff1d --- /dev/null +++ b/ivtest/vpi/nextsimtime_cb3.v @@ -0,0 +1 @@ +`include "vpi/nextsimtime_cb.v" diff --git a/ivtest/vpi/nextsimtime_cb4.c b/ivtest/vpi/nextsimtime_cb4.c new file mode 100644 index 000000000..8dae6b8f3 --- /dev/null +++ b/ivtest/vpi/nextsimtime_cb4.c @@ -0,0 +1,2 @@ +#define TEST_NULL_TIME +#include "nextsimtime_cb.c" diff --git a/ivtest/vpi/nextsimtime_cb4.v b/ivtest/vpi/nextsimtime_cb4.v new file mode 100644 index 000000000..d7c7cff1d --- /dev/null +++ b/ivtest/vpi/nextsimtime_cb4.v @@ -0,0 +1 @@ +`include "vpi/nextsimtime_cb.v" diff --git a/ivtest/vpi/nextsimtime_null_time.c b/ivtest/vpi/nextsimtime_null_time.c deleted file mode 100644 index 3a61905f6..000000000 --- a/ivtest/vpi/nextsimtime_null_time.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_NULL_TIME -#include "nextsimtime_common.c" diff --git a/ivtest/vpi/nextsimtime_null_time.v b/ivtest/vpi/nextsimtime_null_time.v deleted file mode 100644 index 4d31b0d01..000000000 --- a/ivtest/vpi/nextsimtime_null_time.v +++ /dev/null @@ -1 +0,0 @@ -`include "vpi/nextsimtime_common.v" diff --git a/ivtest/vpi/nextsimtime_scaled_time.c b/ivtest/vpi/nextsimtime_scaled_time.c deleted file mode 100644 index a33a17d6e..000000000 --- a/ivtest/vpi/nextsimtime_scaled_time.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_SCALED_TIME -#include "nextsimtime_common.c" diff --git a/ivtest/vpi/nextsimtime_scaled_time.v b/ivtest/vpi/nextsimtime_scaled_time.v deleted file mode 100644 index 4d31b0d01..000000000 --- a/ivtest/vpi/nextsimtime_scaled_time.v +++ /dev/null @@ -1 +0,0 @@ -`include "vpi/nextsimtime_common.v" diff --git a/ivtest/vpi/nextsimtime_sim_time.c b/ivtest/vpi/nextsimtime_sim_time.c deleted file mode 100644 index 3c4b79e39..000000000 --- a/ivtest/vpi/nextsimtime_sim_time.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_SIM_TIME -#include "nextsimtime_common.c" diff --git a/ivtest/vpi/nextsimtime_sim_time.v b/ivtest/vpi/nextsimtime_sim_time.v deleted file mode 100644 index 4d31b0d01..000000000 --- a/ivtest/vpi/nextsimtime_sim_time.v +++ /dev/null @@ -1 +0,0 @@ -`include "vpi/nextsimtime_common.v" diff --git a/ivtest/vpi/nextsimtime_suppress_time.c b/ivtest/vpi/nextsimtime_suppress_time.c deleted file mode 100644 index 14ba3e786..000000000 --- a/ivtest/vpi/nextsimtime_suppress_time.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_SUPPRESS_TIME -#include "nextsimtime_common.c" diff --git a/ivtest/vpi/nextsimtime_suppress_time.v b/ivtest/vpi/nextsimtime_suppress_time.v deleted file mode 100644 index 4d31b0d01..000000000 --- a/ivtest/vpi/nextsimtime_suppress_time.v +++ /dev/null @@ -1 +0,0 @@ -`include "vpi/nextsimtime_common.v" diff --git a/ivtest/vpi/value_change1.c b/ivtest/vpi/value_change1.c deleted file mode 100644 index 33830de7b..000000000 --- a/ivtest/vpi/value_change1.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_SIM_TIME -#include "value_change.c" diff --git a/ivtest/vpi/value_change1.v b/ivtest/vpi/value_change1.v deleted file mode 100644 index d1b7ef31b..000000000 --- a/ivtest/vpi/value_change1.v +++ /dev/null @@ -1 +0,0 @@ -`include "vpi/value_change.v" diff --git a/ivtest/vpi/value_change2.c b/ivtest/vpi/value_change2.c deleted file mode 100644 index ede0c8033..000000000 --- a/ivtest/vpi/value_change2.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_SCALED_TIME -#include "value_change.c" diff --git a/ivtest/vpi/value_change2.v b/ivtest/vpi/value_change2.v deleted file mode 100644 index d1b7ef31b..000000000 --- a/ivtest/vpi/value_change2.v +++ /dev/null @@ -1 +0,0 @@ -`include "vpi/value_change.v" diff --git a/ivtest/vpi/value_change3.c b/ivtest/vpi/value_change3.c deleted file mode 100644 index 58462ceb7..000000000 --- a/ivtest/vpi/value_change3.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_SUPPRESS_TIME -#include "value_change.c" diff --git a/ivtest/vpi/value_change3.v b/ivtest/vpi/value_change3.v deleted file mode 100644 index d1b7ef31b..000000000 --- a/ivtest/vpi/value_change3.v +++ /dev/null @@ -1 +0,0 @@ -`include "vpi/value_change.v" diff --git a/ivtest/vpi/value_change4.c b/ivtest/vpi/value_change4.c deleted file mode 100644 index c39b94168..000000000 --- a/ivtest/vpi/value_change4.c +++ /dev/null @@ -1,2 +0,0 @@ -#define TEST_NULL_TIME -#include "value_change.c" diff --git a/ivtest/vpi/value_change4.v b/ivtest/vpi/value_change4.v deleted file mode 100644 index d1b7ef31b..000000000 --- a/ivtest/vpi/value_change4.v +++ /dev/null @@ -1 +0,0 @@ -`include "vpi/value_change.v" diff --git a/ivtest/vpi/value_change.c b/ivtest/vpi/value_change_cb.c similarity index 97% rename from ivtest/vpi/value_change.c rename to ivtest/vpi/value_change_cb.c index cf3c09f7c..2f6a2d26b 100644 --- a/ivtest/vpi/value_change.c +++ b/ivtest/vpi/value_change_cb.c @@ -6,9 +6,9 @@ #define TIME_TYPE vpiSuppressTime #endif -# include -# include -# include +#include +#include +#include static PLI_INT32 report_change(p_cb_data cb) { diff --git a/ivtest/vpi/value_change.v b/ivtest/vpi/value_change_cb.v similarity index 100% rename from ivtest/vpi/value_change.v rename to ivtest/vpi/value_change_cb.v diff --git a/ivtest/vpi/value_change_cb1.c b/ivtest/vpi/value_change_cb1.c new file mode 100644 index 000000000..f1cf3b310 --- /dev/null +++ b/ivtest/vpi/value_change_cb1.c @@ -0,0 +1,2 @@ +#define TEST_SIM_TIME +#include "value_change_cb.c" diff --git a/ivtest/vpi/value_change_cb1.v b/ivtest/vpi/value_change_cb1.v new file mode 100644 index 000000000..98ad87dd4 --- /dev/null +++ b/ivtest/vpi/value_change_cb1.v @@ -0,0 +1 @@ +`include "vpi/value_change_cb.v" diff --git a/ivtest/vpi/value_change_cb2.c b/ivtest/vpi/value_change_cb2.c new file mode 100644 index 000000000..50d5529b9 --- /dev/null +++ b/ivtest/vpi/value_change_cb2.c @@ -0,0 +1,2 @@ +#define TEST_SCALED_TIME +#include "value_change_cb.c" diff --git a/ivtest/vpi/value_change_cb2.v b/ivtest/vpi/value_change_cb2.v new file mode 100644 index 000000000..98ad87dd4 --- /dev/null +++ b/ivtest/vpi/value_change_cb2.v @@ -0,0 +1 @@ +`include "vpi/value_change_cb.v" diff --git a/ivtest/vpi/value_change_cb3.c b/ivtest/vpi/value_change_cb3.c new file mode 100644 index 000000000..25047b1c4 --- /dev/null +++ b/ivtest/vpi/value_change_cb3.c @@ -0,0 +1,2 @@ +#define TEST_SUPPRESS_TIME +#include "value_change_cb.c" diff --git a/ivtest/vpi/value_change_cb3.v b/ivtest/vpi/value_change_cb3.v new file mode 100644 index 000000000..98ad87dd4 --- /dev/null +++ b/ivtest/vpi/value_change_cb3.v @@ -0,0 +1 @@ +`include "vpi/value_change_cb.v" diff --git a/ivtest/vpi/value_change_cb4.c b/ivtest/vpi/value_change_cb4.c new file mode 100644 index 000000000..005e36c68 --- /dev/null +++ b/ivtest/vpi/value_change_cb4.c @@ -0,0 +1,2 @@ +#define TEST_NULL_TIME +#include "value_change_cb.c" diff --git a/ivtest/vpi/value_change_cb4.v b/ivtest/vpi/value_change_cb4.v new file mode 100644 index 000000000..98ad87dd4 --- /dev/null +++ b/ivtest/vpi/value_change_cb4.v @@ -0,0 +1 @@ +`include "vpi/value_change_cb.v" diff --git a/ivtest/vpi_gold/nextsimtime_cb1.gold b/ivtest/vpi_gold/nextsimtime_cb1.gold new file mode 100644 index 000000000..c32082f43 --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_cb1.gold @@ -0,0 +1,8 @@ +Compiling vpi/nextsimtime_cb1.c... +Making nextsimtime_cb1.vpi from nextsimtime_cb1.o... +time 0: 0 +nextsimtime: 1000 +time 1: 1 +nextsimtime: 4000 +time 4: 4 +nextsimtime: 5000 diff --git a/ivtest/vpi_gold/nextsimtime_cb2.gold b/ivtest/vpi_gold/nextsimtime_cb2.gold new file mode 100644 index 000000000..5c68a4772 --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_cb2.gold @@ -0,0 +1,8 @@ +Compiling vpi/nextsimtime_cb2.c... +Making nextsimtime_cb2.vpi from nextsimtime_cb2.o... +time 0: 0 +nextsimtime: 1.000000 +time 1: 1 +nextsimtime: 4.000000 +time 4: 4 +nextsimtime: 5.000000 diff --git a/ivtest/vpi_gold/nextsimtime_cb3.gold b/ivtest/vpi_gold/nextsimtime_cb3.gold new file mode 100644 index 000000000..56d0f862e --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_cb3.gold @@ -0,0 +1,8 @@ +Compiling vpi/nextsimtime_cb3.c... +Making nextsimtime_cb3.vpi from nextsimtime_cb3.o... +time 0: 0 +nextsimtime: 1000 +time 1: 1 +nextsimtime: 4000 +time 4: 4 +nextsimtime: 5000 diff --git a/ivtest/vpi_gold/nextsimtime_cb4.gold b/ivtest/vpi_gold/nextsimtime_cb4.gold new file mode 100644 index 000000000..66c2b9cfd --- /dev/null +++ b/ivtest/vpi_gold/nextsimtime_cb4.gold @@ -0,0 +1,8 @@ +Compiling vpi/nextsimtime_cb4.c... +Making nextsimtime_cb4.vpi from nextsimtime_cb4.o... +time 0: 0 +nextsimtime: 1000 +time 1: 1 +nextsimtime: 4000 +time 4: 4 +nextsimtime: 5000 diff --git a/ivtest/vpi_gold/nextsimtime_null_time.gold b/ivtest/vpi_gold/nextsimtime_null_time.gold deleted file mode 100644 index 1a513b1c7..000000000 --- a/ivtest/vpi_gold/nextsimtime_null_time.gold +++ /dev/null @@ -1,8 +0,0 @@ -Compiling vpi/nextsimtime_null_time.c... -Making nextsimtime_null_time.vpi from nextsimtime_null_time.o... -time 0: 0 -nextsimtime: 1000 -time 1: 1 -nextsimtime: 4000 -time 4: 4 -nextsimtime: 5000 diff --git a/ivtest/vpi_gold/nextsimtime_scaled_time.gold b/ivtest/vpi_gold/nextsimtime_scaled_time.gold deleted file mode 100644 index c3df10b6f..000000000 --- a/ivtest/vpi_gold/nextsimtime_scaled_time.gold +++ /dev/null @@ -1,8 +0,0 @@ -Compiling vpi/nextsimtime_scaled_time.c... -Making nextsimtime_scaled_time.vpi from nextsimtime_scaled_time.o... -time 0: 0 -nextsimtime: 1.000000 -time 1: 1 -nextsimtime: 4.000000 -time 4: 4 -nextsimtime: 5.000000 diff --git a/ivtest/vpi_gold/nextsimtime_sim_time.gold b/ivtest/vpi_gold/nextsimtime_sim_time.gold deleted file mode 100644 index 3ad99a8af..000000000 --- a/ivtest/vpi_gold/nextsimtime_sim_time.gold +++ /dev/null @@ -1,8 +0,0 @@ -Compiling vpi/nextsimtime_sim_time.c... -Making nextsimtime_sim_time.vpi from nextsimtime_sim_time.o... -time 0: 0 -nextsimtime: 1000 -time 1: 1 -nextsimtime: 4000 -time 4: 4 -nextsimtime: 5000 diff --git a/ivtest/vpi_gold/nextsimtime_suppress_time.gold b/ivtest/vpi_gold/nextsimtime_suppress_time.gold deleted file mode 100644 index 35edff5f3..000000000 --- a/ivtest/vpi_gold/nextsimtime_suppress_time.gold +++ /dev/null @@ -1,8 +0,0 @@ -Compiling vpi/nextsimtime_suppress_time.c... -Making nextsimtime_suppress_time.vpi from nextsimtime_suppress_time.o... -time 0: 0 -nextsimtime: 1000 -time 1: 1 -nextsimtime: 4000 -time 4: 4 -nextsimtime: 5000 diff --git a/ivtest/vpi_gold/value_change1.gold b/ivtest/vpi_gold/value_change_cb1.gold similarity index 76% rename from ivtest/vpi_gold/value_change1.gold rename to ivtest/vpi_gold/value_change_cb1.gold index 5832d4203..6b9ff85b5 100644 --- a/ivtest/vpi_gold/value_change1.gold +++ b/ivtest/vpi_gold/value_change_cb1.gold @@ -1,5 +1,5 @@ -Compiling vpi/value_change1.c... -Making value_change1.vpi from value_change1.o... +Compiling vpi/value_change_cb1.c... +Making value_change_cb1.vpi from value_change_cb1.o... At time 1000 v4 = 1 At time 1000 w4 = 1 At time 2000 i4 = 2 diff --git a/ivtest/vpi_gold/value_change2.gold b/ivtest/vpi_gold/value_change_cb2.gold similarity index 79% rename from ivtest/vpi_gold/value_change2.gold rename to ivtest/vpi_gold/value_change_cb2.gold index 6e4c177b9..50d47629e 100644 --- a/ivtest/vpi_gold/value_change2.gold +++ b/ivtest/vpi_gold/value_change_cb2.gold @@ -1,5 +1,5 @@ -Compiling vpi/value_change2.c... -Making value_change2.vpi from value_change2.o... +Compiling vpi/value_change_cb2.c... +Making value_change_cb2.vpi from value_change_cb2.o... At time 1.000000 v4 = 1 At time 1.000000 w4 = 1 At time 2.000000 i4 = 2 diff --git a/ivtest/vpi_gold/value_change3.gold b/ivtest/vpi_gold/value_change_cb3.gold similarity index 76% rename from ivtest/vpi_gold/value_change3.gold rename to ivtest/vpi_gold/value_change_cb3.gold index 2e1b32fb0..df70b959e 100644 --- a/ivtest/vpi_gold/value_change3.gold +++ b/ivtest/vpi_gold/value_change_cb3.gold @@ -1,5 +1,5 @@ -Compiling vpi/value_change3.c... -Making value_change3.vpi from value_change3.o... +Compiling vpi/value_change_cb3.c... +Making value_change_cb3.vpi from value_change_cb3.o... At time 1000 v4 = 1 At time 1000 w4 = 1 At time 2000 i4 = 2 diff --git a/ivtest/vpi_gold/value_change4.gold b/ivtest/vpi_gold/value_change_cb4.gold similarity index 76% rename from ivtest/vpi_gold/value_change4.gold rename to ivtest/vpi_gold/value_change_cb4.gold index aa9fb3008..7ba3ee92b 100644 --- a/ivtest/vpi_gold/value_change4.gold +++ b/ivtest/vpi_gold/value_change_cb4.gold @@ -1,5 +1,5 @@ -Compiling vpi/value_change4.c... -Making value_change4.vpi from value_change4.o... +Compiling vpi/value_change_cb4.c... +Making value_change_cb4.vpi from value_change_cb4.o... At time 1000 v4 = 1 At time 1000 w4 = 1 At time 2000 i4 = 2 diff --git a/ivtest/vpi_regress.list b/ivtest/vpi_regress.list index 24c928180..982f61381 100644 --- a/ivtest/vpi_regress.list +++ b/ivtest/vpi_regress.list @@ -99,10 +99,10 @@ hello_tf normal hello_tf.c hello_tf.log hello_vpi normal hello_vpi.c hello.log hello_vpi2 normal hello_vpi2.c hello2.log vpi/hello_vpi1.c listparams normal listparams.c listparams.log -nextsimtime_null_time normal nextsimtime_null_time.c nextsimtime_null_time.gold -nextsimtime_scaled_time normal nextsimtime_scaled_time.c nextsimtime_scaled_time.gold -nextsimtime_sim_time normal nextsimtime_sim_time.c nextsimtime_sim_time.gold -nextsimtime_suppress_time normal nextsimtime_suppress_time.c nextsimtime_suppress_time.gold +nextsimtime_cb1 normal nextsimtime_cb1.c nextsimtime_cb1.gold +nextsimtime_cb2 normal nextsimtime_cb2.c nextsimtime_cb2.gold +nextsimtime_cb3 normal nextsimtime_cb3.c nextsimtime_cb3.gold +nextsimtime_cb4 normal nextsimtime_cb4.c nextsimtime_cb4.gold memmon normal,-g1995 memmon.c memmon.log memwide normal memwide.cc memwide.log mipname normal mipname.c mipname.log @@ -137,10 +137,10 @@ sim_time_cb2 normal sim_time_cb2.c sim_time_cb2.gold spec_delays normal,-gspecify spec_delays.c spec_delays.log start_of_simtime1 normal start_of_simtime1.c start_of_simtime1.log timescale normal timescale.c timescale.log -value_change1 normal,-g2009 value_change1.c value_change1.gold -value_change2 normal,-g2009 value_change2.c value_change2.gold -value_change3 normal,-g2009 value_change3.c value_change3.gold -value_change4 normal,-g2009 value_change4.c value_change4.gold +value_change_cb1 normal,-g2009 value_change_cb1.c value_change_cb1.gold +value_change_cb2 normal,-g2009 value_change_cb2.c value_change_cb2.gold +value_change_cb3 normal,-g2009 value_change_cb3.c value_change_cb3.gold +value_change_cb4 normal,-g2009 value_change_cb4.c value_change_cb4.gold # Add new tests in alphabetic/numeric order. If the test needs # a compile option or a different log file to run with an older From 616afdc4e7d326a6b1608bfefd6490513e9be612 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 9 Feb 2024 11:07:08 +0000 Subject: [PATCH 19/19] Fix and improve sim_time_cb test. cb_data.obj must be set to a valid handle when requesting vpiScaledRealTime. Check the returned time value as well as the actual callback time. Zero the requested cb_data after registering the callbacks to make sure it is not used during the callback execution. --- ivtest/vpi/sim_time_cb.c | 22 ++++++++++++---- ivtest/vpi/sim_time_cb2.v | 42 ++++++++++++++++++------------- ivtest/vpi_gold/sim_time_cb1.gold | 16 ++++++------ ivtest/vpi_gold/sim_time_cb2.gold | 16 ++++++------ 4 files changed, 58 insertions(+), 38 deletions(-) diff --git a/ivtest/vpi/sim_time_cb.c b/ivtest/vpi/sim_time_cb.c index acb829972..953905973 100644 --- a/ivtest/vpi/sim_time_cb.c +++ b/ivtest/vpi/sim_time_cb.c @@ -6,6 +6,7 @@ #include #include +#include #include static PLI_INT32 monitor_cb(p_cb_data cb_data) @@ -16,12 +17,14 @@ static PLI_INT32 monitor_cb(p_cb_data cb_data) s_vpi_value value; PLI_INT32 index; - time.type = TIME_TYPE; - vpi_get_time(var_list[0], &time); -#ifdef TEST_SCALED_TIME - vpi_printf(" @ %1.1f :", time.real); -#else + time.type = vpiSimTime; + vpi_get_time(NULL, &time); vpi_printf(" @ %04d :", time.low); + +#ifdef TEST_SCALED_TIME + vpi_printf(" cb_data.time = %1.1f :", cb_data->time->real); +#else + vpi_printf(" cb_data.time = %04d :", cb_data->time->low); #endif value.format = vpiIntVal; @@ -124,15 +127,19 @@ static PLI_INT32 monitor_calltf(char*xx) time.low += delay.low; #endif + memset(&cb_data, 0, sizeof(cb_data)); + cb_data.reason = cbAtStartOfSimTime; cb_data.cb_rtn = monitor_cb_start; cb_data.user_data = (char*)var_list; + cb_data.obj = var_list[0]; cb_data.time = &time; vpi_register_cb(&cb_data); cb_data.reason = cbAfterDelay; cb_data.cb_rtn = monitor_cb_delay; cb_data.user_data = (char*)var_list; + cb_data.obj = var_list[0]; cb_data.time = &delay; vpi_register_cb(&cb_data); @@ -141,15 +148,20 @@ static PLI_INT32 monitor_calltf(char*xx) cb_data.reason = cbReadWriteSynch; cb_data.cb_rtn = monitor_cb_synch; cb_data.user_data = (char*)var_list; + cb_data.obj = var_list[0]; cb_data.time = &delay; vpi_register_cb(&cb_data); cb_data.reason = cbAtEndOfSimTime; cb_data.cb_rtn = monitor_cb_end; cb_data.user_data = (char*)var_list; + cb_data.obj = var_list[0]; cb_data.time = &time; vpi_register_cb(&cb_data); + memset(&cb_data, 0, sizeof(cb_data)); + memset(&time , 0, sizeof(time)); + return 0; } diff --git a/ivtest/vpi/sim_time_cb2.v b/ivtest/vpi/sim_time_cb2.v index cd547c2da..171759ad0 100644 --- a/ivtest/vpi/sim_time_cb2.v +++ b/ivtest/vpi/sim_time_cb2.v @@ -1,26 +1,34 @@ `timescale 1s/1ms -module test; +module dut; reg [7:0] a, b; +endmodule + +`timescale 1ms/1ms + +module test; + +dut dut(); + initial begin - a = 0; b = 0; - $monitor_time_slot(2.0, a, b); - $monitor_time_slot(5.0, a, b); - #1; - a = 1; b <= 1; - #1; - a = 2; b <= 2; - #1; - a = 3; b <= 3; - #1; - a = 4; b <= 4; - #1; - a = 5; b <= 5; - #1; - a = 6; b <= 6; - #1; + dut.a = 0; dut.b = 0; + $monitor_time_slot(2.0, dut.a, dut.b); + $monitor_time_slot(5.0, dut.a, dut.b); + #1000; + dut.a = 1; dut.b <= 1; + #1000; + dut.a = 2; dut.b <= 2; + #1000; + dut.a = 3; dut.b <= 3; + #1000; + dut.a = 4; dut.b <= 4; + #1000; + dut.a = 5; dut.b <= 5; + #1000; + dut.a = 6; dut.b <= 6; + #1000; $finish(0); end diff --git a/ivtest/vpi_gold/sim_time_cb1.gold b/ivtest/vpi_gold/sim_time_cb1.gold index d99e5379b..a479bac8b 100644 --- a/ivtest/vpi_gold/sim_time_cb1.gold +++ b/ivtest/vpi_gold/sim_time_cb1.gold @@ -1,10 +1,10 @@ Compiling vpi/sim_time_cb1.c... Making sim_time_cb1.vpi from sim_time_cb1.o... -cbStartOfSimTime @ 2000 : a = 1 b = 1 -cbAfterDelay @ 2000 : a = 1 b = 1 -cbReadWriteSynch @ 2000 : a = 2 b = 2 -cbEndOfSimTime @ 2000 : a = 2 b = 2 -cbStartOfSimTime @ 5000 : a = 4 b = 4 -cbAfterDelay @ 5000 : a = 4 b = 4 -cbReadWriteSynch @ 5000 : a = 5 b = 5 -cbEndOfSimTime @ 5000 : a = 5 b = 5 +cbStartOfSimTime @ 2000 : cb_data.time = 2000 : a = 1 b = 1 +cbAfterDelay @ 2000 : cb_data.time = 2000 : a = 1 b = 1 +cbReadWriteSynch @ 2000 : cb_data.time = 2000 : a = 2 b = 2 +cbEndOfSimTime @ 2000 : cb_data.time = 2000 : a = 2 b = 2 +cbStartOfSimTime @ 5000 : cb_data.time = 5000 : a = 4 b = 4 +cbAfterDelay @ 5000 : cb_data.time = 5000 : a = 4 b = 4 +cbReadWriteSynch @ 5000 : cb_data.time = 5000 : a = 5 b = 5 +cbEndOfSimTime @ 5000 : cb_data.time = 5000 : a = 5 b = 5 diff --git a/ivtest/vpi_gold/sim_time_cb2.gold b/ivtest/vpi_gold/sim_time_cb2.gold index 0ec0e5ae1..253377053 100644 --- a/ivtest/vpi_gold/sim_time_cb2.gold +++ b/ivtest/vpi_gold/sim_time_cb2.gold @@ -1,10 +1,10 @@ Compiling vpi/sim_time_cb2.c... Making sim_time_cb2.vpi from sim_time_cb2.o... -cbStartOfSimTime @ 2.0 : a = 1 b = 1 -cbAfterDelay @ 2.0 : a = 1 b = 1 -cbReadWriteSynch @ 2.0 : a = 2 b = 2 -cbEndOfSimTime @ 2.0 : a = 2 b = 2 -cbStartOfSimTime @ 5.0 : a = 4 b = 4 -cbAfterDelay @ 5.0 : a = 4 b = 4 -cbReadWriteSynch @ 5.0 : a = 5 b = 5 -cbEndOfSimTime @ 5.0 : a = 5 b = 5 +cbStartOfSimTime @ 2000 : cb_data.time = 2.0 : a = 1 b = 1 +cbAfterDelay @ 2000 : cb_data.time = 2.0 : a = 1 b = 1 +cbReadWriteSynch @ 2000 : cb_data.time = 2.0 : a = 2 b = 2 +cbEndOfSimTime @ 2000 : cb_data.time = 2.0 : a = 2 b = 2 +cbStartOfSimTime @ 5000 : cb_data.time = 5.0 : a = 4 b = 4 +cbAfterDelay @ 5000 : cb_data.time = 5.0 : a = 4 b = 4 +cbReadWriteSynch @ 5000 : cb_data.time = 5.0 : a = 5 b = 5 +cbEndOfSimTime @ 5000 : cb_data.time = 5.0 : a = 5 b = 5