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)
|
||||
{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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_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
|
||||
|
|
|
|||
|
|
@ -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<simulator_callback*>(last_cb->next);
|
||||
}
|
||||
|
||||
while (NextSimTime) {
|
||||
cur = NextSimTime;
|
||||
NextSimTime = dynamic_cast<simulator_callback*>(cur->next);
|
||||
if (cur->cb_data.cb_rtn != 0) {
|
||||
(cur->cb_data.cb_rtn)(&cur->cb_data);
|
||||
}
|
||||
delete cur;
|
||||
cur = NextSimTime;
|
||||
NextSimTime = dynamic_cast<simulator_callback*>(cur->next);
|
||||
if (cur->cb_data.cb_rtn != 0) {
|
||||
// only vpiSimTime implemented right now
|
||||
vpip_time_to_timestruct(cur->cb_data.time, schedule_simtime());
|
||||
(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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue