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)
This commit is contained in:
parent
2299fc1b2b
commit
53e8a139b0
|
|
@ -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 <assert.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
};
|
||||||
|
|
@ -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 <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
#define TEST_NULL
|
||||||
|
#include "nextsimtime_errors.c"
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
`include "vpi/nextsimtime_fill_time.v"
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
#define TEST_SCALED
|
||||||
|
#include "nextsimtime_errors.c"
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
`include "vpi/nextsimtime_fill_time.v"
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
#define TEST_SUPPRESS
|
||||||
|
#include "nextsimtime_errors.c"
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
`include "vpi/nextsimtime_fill_time.v"
|
||||||
|
|
@ -47,6 +47,7 @@ static PLI_INT32 test_next_compiletf(PLI_BYTE8 *name)
|
||||||
static PLI_INT32 test_next_calltf(PLI_BYTE8 *name)
|
static PLI_INT32 test_next_calltf(PLI_BYTE8 *name)
|
||||||
{
|
{
|
||||||
vpiHandle sys, argv, value;
|
vpiHandle sys, argv, value;
|
||||||
|
static s_vpi_time dummy_time = {vpiSimTime, 0, 0, 0};
|
||||||
|
|
||||||
(void)name; /* Parameter is not used. */
|
(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)) {
|
for (value = vpi_scan(argv) ; value ; value = vpi_scan(argv)) {
|
||||||
s_cb_data cb;
|
s_cb_data cb;
|
||||||
cb.reason = cbNextSimTime;
|
cb.reason = cbNextSimTime;
|
||||||
|
cb.time = &dummy_time;
|
||||||
cb.cb_rtn = next_sim_time_callback;
|
cb.cb_rtn = next_sim_time_callback;
|
||||||
cb.user_data = (char*)value;
|
cb.user_data = (char*)value;
|
||||||
vpi_register_cb(&cb);
|
vpi_register_cb(&cb);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -99,6 +99,10 @@ hello_tf normal hello_tf.c hello_tf.log
|
||||||
hello_vpi normal hello_vpi.c hello.log
|
hello_vpi normal hello_vpi.c hello.log
|
||||||
hello_vpi2 normal hello_vpi2.c hello2.log vpi/hello_vpi1.c
|
hello_vpi2 normal hello_vpi2.c hello2.log vpi/hello_vpi1.c
|
||||||
listparams normal listparams.c listparams.log
|
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
|
memmon normal,-g1995 memmon.c memmon.log
|
||||||
memwide normal memwide.cc memwide.log
|
memwide normal memwide.cc memwide.log
|
||||||
mipname normal mipname.c mipname.log
|
mipname normal mipname.c mipname.log
|
||||||
|
|
|
||||||
|
|
@ -577,17 +577,30 @@ void vpiPostsim(void) {
|
||||||
void vpiNextSimTime(void)
|
void vpiNextSimTime(void)
|
||||||
{
|
{
|
||||||
simulator_callback* cur;
|
simulator_callback* cur;
|
||||||
|
simulator_callback* last_cb = NextSimTime;
|
||||||
|
|
||||||
assert(vpi_mode_flag == VPI_MODE_NONE);
|
assert(vpi_mode_flag == VPI_MODE_NONE);
|
||||||
vpi_mode_flag = VPI_MODE_RWSYNC;
|
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<simulator_callback*>(last_cb->next);
|
||||||
|
}
|
||||||
|
|
||||||
while (NextSimTime) {
|
while (NextSimTime) {
|
||||||
cur = NextSimTime;
|
cur = NextSimTime;
|
||||||
NextSimTime = dynamic_cast<simulator_callback*>(cur->next);
|
NextSimTime = dynamic_cast<simulator_callback*>(cur->next);
|
||||||
if (cur->cb_data.cb_rtn != 0) {
|
if (cur->cb_data.cb_rtn != 0) {
|
||||||
(cur->cb_data.cb_rtn)(&cur->cb_data);
|
// only vpiSimTime implemented right now
|
||||||
}
|
vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
|
||||||
delete cur;
|
(cur->cb_data.cb_rtn)(&cur->cb_data);
|
||||||
|
}
|
||||||
|
delete cur;
|
||||||
|
if (cur == last_cb) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vpi_mode_flag = VPI_MODE_NONE;
|
vpi_mode_flag = VPI_MODE_NONE;
|
||||||
|
|
@ -599,21 +612,37 @@ static simulator_callback* make_prepost(p_cb_data data)
|
||||||
|
|
||||||
/* Insert at head of list */
|
/* Insert at head of list */
|
||||||
switch (data->reason) {
|
switch (data->reason) {
|
||||||
case cbEndOfCompile:
|
case cbEndOfCompile:
|
||||||
obj->next = EndOfCompile;
|
obj->next = EndOfCompile;
|
||||||
EndOfCompile = obj;
|
EndOfCompile = obj;
|
||||||
break;
|
break;
|
||||||
case cbStartOfSimulation:
|
case cbStartOfSimulation:
|
||||||
obj->next = StartOfSimulation;
|
obj->next = StartOfSimulation;
|
||||||
StartOfSimulation = obj;
|
StartOfSimulation = obj;
|
||||||
break;
|
break;
|
||||||
case cbEndOfSimulation:
|
case cbEndOfSimulation:
|
||||||
obj->next = EndOfSimulation;
|
obj->next = EndOfSimulation;
|
||||||
EndOfSimulation = obj;
|
EndOfSimulation = obj;
|
||||||
break;
|
break;
|
||||||
case cbNextSimTime:
|
case cbNextSimTime:
|
||||||
obj->next = NextSimTime;
|
if (!data->time) {
|
||||||
NextSimTime = obj;
|
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;
|
return obj;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue