Skip to content

Commit

Permalink
Merge pull request #1098 from steveicarus/vpi-callback-improvements
Browse files Browse the repository at this point in the history
VPI callback improvements
  • Loading branch information
martinwhitaker authored Feb 12, 2024
2 parents 72e86d3 + 616afdc commit 202d41a
Show file tree
Hide file tree
Showing 42 changed files with 973 additions and 136 deletions.
96 changes: 96 additions & 0 deletions ivtest/vpi/nextsimtime_cb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2022 Jevin Sweval ([email protected])
*
* 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_SIM_TIME)
#define TIME_TYPE vpiSimTime
#elif defined(TEST_SCALED_TIME)
#define TIME_TYPE vpiScaledRealTime
#else
#define TIME_TYPE vpiSuppressTime
#endif

#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) {
s_vpi_time timerec;

#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


#ifdef TEST_SCALED_TIME
vpi_printf("nextsimtime: %f\n", timerec.real);
#else
uint64_t time = ((uint64_t)timerec.high << 32) | timerec.low;
vpi_printf("nextsimtime: %" PLI_UINT64_FMT "\n", time);
#endif
register_nextsimtime(NULL);
return 0;
}

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;
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
};
31 changes: 31 additions & 0 deletions ivtest/vpi/nextsimtime_cb.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022 Jevin Sweval ([email protected])
*
* 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
*/

`timescale 1s/1ms

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
2 changes: 2 additions & 0 deletions ivtest/vpi/nextsimtime_cb1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define TEST_SIM_TIME
#include "nextsimtime_cb.c"
1 change: 1 addition & 0 deletions ivtest/vpi/nextsimtime_cb1.v
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`include "vpi/nextsimtime_cb.v"
2 changes: 2 additions & 0 deletions ivtest/vpi/nextsimtime_cb2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define TEST_SCALED_TIME
#include "nextsimtime_cb.c"
1 change: 1 addition & 0 deletions ivtest/vpi/nextsimtime_cb2.v
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`include "vpi/nextsimtime_cb.v"
2 changes: 2 additions & 0 deletions ivtest/vpi/nextsimtime_cb3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define TEST_SUPPRESS_TIME
#include "nextsimtime_cb.c"
1 change: 1 addition & 0 deletions ivtest/vpi/nextsimtime_cb3.v
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`include "vpi/nextsimtime_cb.v"
2 changes: 2 additions & 0 deletions ivtest/vpi/nextsimtime_cb4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define TEST_NULL_TIME
#include "nextsimtime_cb.c"
1 change: 1 addition & 0 deletions ivtest/vpi/nextsimtime_cb4.v
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`include "vpi/nextsimtime_cb.v"
2 changes: 2 additions & 0 deletions ivtest/vpi/pr686.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */

Expand All @@ -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);
Expand Down
183 changes: 183 additions & 0 deletions ivtest/vpi/sim_time_cb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#ifdef TEST_SCALED_TIME
#define TIME_TYPE vpiScaledRealTime
#else
#define TIME_TYPE vpiSimTime
#endif

#include <vpi_user.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

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 = 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;

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

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);

// 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.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;
}

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
};
2 changes: 2 additions & 0 deletions ivtest/vpi/sim_time_cb1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define TEST_SIM_TIME
#include "sim_time_cb.c"
27 changes: 27 additions & 0 deletions ivtest/vpi/sim_time_cb1.v
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions ivtest/vpi/sim_time_cb2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define TEST_SCALED_TIME
#include "sim_time_cb.c"
Loading

0 comments on commit 202d41a

Please sign in to comment.