Rework libveriuser to make vpiSysTfCall handles available in callbacks.
PLI 1.0 callbacks are directly associated with the instance of the system
task/function that initiated them, allowing them to access the task/function
arguments. However, we implement them using VPI callbacks, which are not so
associated. So we need to pass the VPI handle for the associated task/function
instance to the callback routine via the VPI callback user_data pointer,
because vpi_handle(vpiSysTfCall, 0) will return null when called from the
callback function.
This is the first step to a proper fix for issue #141, to replace the
problematic fix that was reverted in commit 8da8261f.
This commit is contained in:
parent
df72e1d362
commit
3f9a49ae01
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2020 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
|
||||
|
|
@ -21,6 +21,8 @@
|
|||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
vpiHandle cur_instance = 0;
|
||||
|
||||
FILE* pli_trace = 0;
|
||||
|
||||
static char string_buffer[8192];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_priv_H
|
||||
#define IVL_priv_H
|
||||
/*
|
||||
* Copyright (c) 2003-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2020 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
|
||||
|
|
@ -20,6 +20,14 @@
|
|||
*/
|
||||
|
||||
# include <stdio.h>
|
||||
# include "vpi_user.h"
|
||||
|
||||
/*
|
||||
* The VPI handle for the current task/function instance. This is the
|
||||
* handle returned by vpi_handle(vpiSysTfCall, 0) when the task/function
|
||||
* is compiled or called, but we also need it when executing a callback.
|
||||
*/
|
||||
extern vpiHandle cur_instance;
|
||||
|
||||
/*
|
||||
* This function implements the acc_ string buffer, by adding the
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2018 Michael Ruff (mruff at chiaro.com)
|
||||
* Copyright (c) 2002-2020 Michael Ruff (mruff at chiaro.com)
|
||||
* Michael Runyan (mrunyan at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
|
|
@ -34,11 +34,12 @@
|
|||
# include "ivl_alloc.h"
|
||||
|
||||
/*
|
||||
* local structure used to hold the persistent veriusertfs data
|
||||
* and anything else we decide to put in here, like workarea data.
|
||||
* Data to be passed to the callback function via the VPI callback
|
||||
* user data pointer.
|
||||
*/
|
||||
typedef struct t_pli_data {
|
||||
p_tfcell tf; /* pointer to veriusertfs cell */
|
||||
vpiHandle call_handle; /* handle returned by vpiSysTfCall */
|
||||
int paramvc; /* parameter number for misctf */
|
||||
} s_pli_data, *p_pli_data;
|
||||
|
||||
|
|
@ -54,6 +55,21 @@ static PLI_INT32 callback(p_cb_data);
|
|||
static p_pli_data* udata_store = 0;
|
||||
static unsigned udata_count = 0;
|
||||
|
||||
static p_pli_data new_pli_data(p_tfcell tf, vpiHandle call_handle, int paramvc)
|
||||
{
|
||||
p_pli_data data = calloc(1, sizeof(s_pli_data));
|
||||
data->tf = tf;
|
||||
data->call_handle = call_handle;
|
||||
data->paramvc = paramvc;
|
||||
|
||||
udata_count += 1;
|
||||
udata_store = (p_pli_data*)realloc(udata_store,
|
||||
udata_count*sizeof(p_pli_data*));
|
||||
udata_store[udata_count-1] = data;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static PLI_INT32 sys_end_of_simulation(p_cb_data cb_data)
|
||||
{
|
||||
unsigned idx;
|
||||
|
|
@ -80,7 +96,6 @@ void veriusertfs_register_table(p_tfcell vtable)
|
|||
const char*path;
|
||||
p_tfcell tf;
|
||||
s_vpi_systf_data tf_data;
|
||||
p_pli_data data;
|
||||
|
||||
if (!pli_trace && (path = getenv("PLI_TRACE"))) {
|
||||
static char trace_buf[1024];
|
||||
|
|
@ -106,12 +121,6 @@ void veriusertfs_register_table(p_tfcell vtable)
|
|||
tf->tfname);
|
||||
}
|
||||
|
||||
/* squirrel away veriusertfs in persistent user_data */
|
||||
data = calloc(1, sizeof(s_pli_data));
|
||||
udata_count += 1;
|
||||
udata_store = (p_pli_data*)realloc(udata_store,
|
||||
udata_count*sizeof(p_pli_data*));
|
||||
udata_store[udata_count-1] = data;
|
||||
if (need_EOS_cb) {
|
||||
s_cb_data cb_data;
|
||||
|
||||
|
|
@ -123,7 +132,6 @@ void veriusertfs_register_table(p_tfcell vtable)
|
|||
|
||||
need_EOS_cb = 0;
|
||||
}
|
||||
data->tf = tf;
|
||||
|
||||
/* Build a VPI system task/function structure, and point
|
||||
it to the pli_data that represents this
|
||||
|
|
@ -152,7 +160,7 @@ void veriusertfs_register_table(p_tfcell vtable)
|
|||
tf_data.compiletf = compiletf;
|
||||
tf_data.calltf = calltf;
|
||||
tf_data.sizetf = sizetf;
|
||||
tf_data.user_data = (char *)data;
|
||||
tf_data.user_data = (PLI_BYTE8*)tf;
|
||||
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "Registering system %s:\n",
|
||||
|
|
@ -183,50 +191,49 @@ void veriusertfs_register_table(p_tfcell vtable)
|
|||
*/
|
||||
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
||||
{
|
||||
p_pli_data pli;
|
||||
p_tfcell tf;
|
||||
p_pli_data pli;
|
||||
s_cb_data cb_data;
|
||||
vpiHandle call_h, arg_i, arg_h;
|
||||
vpiHandle arg_i, arg_h;
|
||||
int rtn = 0;
|
||||
|
||||
/* cast back from opaque */
|
||||
pli = (p_pli_data)data;
|
||||
tf = pli->tf;
|
||||
tf = (p_tfcell)data;
|
||||
|
||||
/* get call handle */
|
||||
call_h = vpi_handle(vpiSysTfCall, NULL);
|
||||
cur_instance = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* Attach the pli_data structure to the vpi handle of the
|
||||
/* build callback user data for this instance */
|
||||
pli = new_pli_data(tf, cur_instance, 0);
|
||||
|
||||
/* Attach the pli_data structure to the VPI handle of the
|
||||
system task. This is how I manage the map from vpiHandle to
|
||||
PLI1 pli data. We do it here (instead of during register)
|
||||
PLI1 user data. We do it here (instead of during register)
|
||||
because this is the first that I have both the vpiHandle
|
||||
and the pli_data. */
|
||||
vpi_put_userdata(call_h, pli);
|
||||
and the user data. */
|
||||
vpi_put_userdata(cur_instance, pli);
|
||||
|
||||
/* default cb_data */
|
||||
memset(&cb_data, 0, sizeof(s_cb_data));
|
||||
cb_data.cb_rtn = callback;
|
||||
cb_data.user_data = data;
|
||||
cb_data.user_data = (PLI_BYTE8*)pli;
|
||||
|
||||
/* register EOS misctf callback */
|
||||
cb_data.reason = cbEndOfSimulation;
|
||||
cb_data.obj = call_h;
|
||||
vpi_register_cb(&cb_data);
|
||||
|
||||
/* If there is a misctf function, then create a value change
|
||||
callback for all the arguments. In the tf_* API, misctf
|
||||
functions get value change callbacks, controlled by the
|
||||
tf_asyncon and tf_asyncoff functions. */
|
||||
if (tf->misctf && ((arg_i = vpi_iterate(vpiArgument, call_h)) != NULL)) {
|
||||
if (tf->misctf && ((arg_i = vpi_iterate(vpiArgument, cur_instance)) != NULL)) {
|
||||
int paramvc = 1;
|
||||
|
||||
cb_data.reason = cbValueChange;
|
||||
while ((arg_h = vpi_scan(arg_i)) != NULL) {
|
||||
/* replicate user_data for each instance */
|
||||
p_pli_data dp = calloc(1, sizeof(s_pli_data));
|
||||
memcpy(dp, cb_data.user_data, sizeof(s_pli_data));
|
||||
dp->paramvc = paramvc++;
|
||||
cb_data.user_data = (char *)dp;
|
||||
p_pli_data dp = new_pli_data(tf, cur_instance, paramvc++);
|
||||
cb_data.user_data = (PLI_BYTE8*)dp;
|
||||
cb_data.obj = arg_h;
|
||||
vpi_register_cb(&cb_data);
|
||||
}
|
||||
|
|
@ -255,6 +262,7 @@ static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
|||
tf->misctf(tf->data, reason_endofcompile, 0);
|
||||
}
|
||||
|
||||
cur_instance = 0;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
|
@ -264,12 +272,13 @@ static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
|||
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
||||
{
|
||||
int rc = 0;
|
||||
p_pli_data pli;
|
||||
p_tfcell tf;
|
||||
|
||||
/* cast back from opaque */
|
||||
pli = (p_pli_data)data;
|
||||
tf = pli->tf;
|
||||
tf = (p_tfcell)data;
|
||||
|
||||
/* get call handle */
|
||||
cur_instance = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* execute calltf */
|
||||
if (tf->calltf) {
|
||||
|
|
@ -281,6 +290,7 @@ static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
|||
rc = tf->calltf(tf->data, reason_calltf);
|
||||
}
|
||||
|
||||
cur_instance = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -290,12 +300,13 @@ static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
|||
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
||||
{
|
||||
int rc = 32;
|
||||
p_pli_data pli;
|
||||
p_tfcell tf;
|
||||
|
||||
/* cast back from opaque */
|
||||
pli = (p_pli_data)data;
|
||||
tf = pli->tf;
|
||||
tf = (p_tfcell)data;
|
||||
|
||||
/* get call handle */
|
||||
cur_instance = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* execute sizetf */
|
||||
if (tf->sizetf) {
|
||||
|
|
@ -307,6 +318,7 @@ static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
|||
rc = tf->sizetf(tf->data, reason_sizetf);
|
||||
}
|
||||
|
||||
cur_instance = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -329,7 +341,9 @@ static PLI_INT32 callback(p_cb_data data)
|
|||
|
||||
/* cast back from opaque */
|
||||
pli = (p_pli_data)data->user_data;
|
||||
|
||||
tf = pli->tf;
|
||||
cur_instance = pli->call_handle;
|
||||
|
||||
switch (data->reason) {
|
||||
case cbValueChange:
|
||||
|
|
@ -362,6 +376,7 @@ static PLI_INT32 callback(p_cb_data data)
|
|||
/* execute misctf */
|
||||
rc = (tf->misctf) ? tf->misctf(tf->data, reason, paramvc) : 0;
|
||||
|
||||
cur_instance = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -378,7 +393,7 @@ PLI_INT32 tf_isynchronize(void*obj)
|
|||
cb.cb_rtn = callback;
|
||||
cb.obj = sys;
|
||||
cb.time = &ti;
|
||||
cb.user_data = (char *)pli;
|
||||
cb.user_data = (PLI_BYTE8*)pli;
|
||||
|
||||
vpi_register_cb(&cb);
|
||||
|
||||
|
|
@ -405,7 +420,7 @@ PLI_INT32 tf_irosynchronize(void*obj)
|
|||
cb.cb_rtn = callback;
|
||||
cb.obj = sys;
|
||||
cb.time = &ti;
|
||||
cb.user_data = (char *)pli;
|
||||
cb.user_data = (PLI_BYTE8*)pli;
|
||||
|
||||
vpi_register_cb(&cb);
|
||||
|
||||
|
|
@ -439,7 +454,7 @@ PLI_INT32 tf_isetrealdelay(double dly, void*obj)
|
|||
cb.cb_rtn = callback;
|
||||
cb.obj = sys;
|
||||
cb.time = &ti;
|
||||
cb.user_data = (char *)pli;
|
||||
cb.user_data = (PLI_BYTE8*)pli;
|
||||
|
||||
vpi_register_cb(&cb);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue