2009-12-10 21:48:24 +01:00
|
|
|
/*
|
2020-12-04 00:38:51 +01:00
|
|
|
* Copyright (c) 2002-2020 Michael Ruff (mruff at chiaro.com)
|
2009-01-29 19:38:22 +01:00
|
|
|
* Michael Runyan (mrunyan at chiaro.com)
|
2002-05-30 04:37:26 +02:00
|
|
|
*
|
|
|
|
|
* 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
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-05-30 04:37:26 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Contains the routines required to implement veriusertfs routines
|
2008-01-29 21:19:59 +01:00
|
|
|
* via VPI. This is extremely ugly, so don't look after eating dinner.
|
2002-05-30 04:37:26 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include <string.h>
|
|
|
|
|
# include <stdlib.h>
|
2002-06-04 03:42:58 +02:00
|
|
|
# include <assert.h>
|
2003-06-04 03:56:20 +02:00
|
|
|
# include <math.h>
|
|
|
|
|
# include "config.h"
|
|
|
|
|
# include "priv.h"
|
2002-05-30 04:37:26 +02:00
|
|
|
# include "vpi_user.h"
|
|
|
|
|
# include "veriuser.h"
|
2010-10-24 00:52:56 +02:00
|
|
|
# include "ivl_alloc.h"
|
2002-05-30 04:37:26 +02:00
|
|
|
|
|
|
|
|
/*
|
2020-12-04 00:38:51 +01:00
|
|
|
* Data to be passed to the callback function via the VPI callback
|
|
|
|
|
* user data pointer.
|
2002-05-30 04:37:26 +02:00
|
|
|
*/
|
|
|
|
|
typedef struct t_pli_data {
|
2002-05-31 20:21:39 +02:00
|
|
|
p_tfcell tf; /* pointer to veriusertfs cell */
|
2020-12-04 00:38:51 +01:00
|
|
|
vpiHandle call_handle; /* handle returned by vpiSysTfCall */
|
2002-06-04 03:42:58 +02:00
|
|
|
int paramvc; /* parameter number for misctf */
|
2002-05-30 04:37:26 +02:00
|
|
|
} s_pli_data, *p_pli_data;
|
|
|
|
|
|
2018-09-29 09:53:32 +02:00
|
|
|
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8 *);
|
|
|
|
|
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8 *);
|
2018-10-06 23:56:04 +02:00
|
|
|
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8 *);
|
2006-10-30 23:45:36 +01:00
|
|
|
static PLI_INT32 callback(p_cb_data);
|
2002-05-30 04:37:26 +02:00
|
|
|
|
2009-01-29 19:38:22 +01:00
|
|
|
/*
|
|
|
|
|
* Keep a pointer to the user data so that it can be freed when the
|
|
|
|
|
* simulation is finished.
|
|
|
|
|
*/
|
|
|
|
|
static p_pli_data* udata_store = 0;
|
|
|
|
|
static unsigned udata_count = 0;
|
|
|
|
|
|
2020-12-04 00:38:51 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-29 19:38:22 +01:00
|
|
|
static PLI_INT32 sys_end_of_simulation(p_cb_data cb_data)
|
|
|
|
|
{
|
|
|
|
|
unsigned idx;
|
|
|
|
|
|
2014-07-09 23:16:57 +02:00
|
|
|
(void)cb_data; /* Parameter is not used. */
|
|
|
|
|
|
2009-01-29 19:38:22 +01:00
|
|
|
for (idx = 0; idx < udata_count; idx += 1) {
|
|
|
|
|
free(udata_store[idx]);
|
|
|
|
|
}
|
|
|
|
|
free(udata_store);
|
|
|
|
|
udata_store = 0;
|
|
|
|
|
udata_count = 0;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-30 04:37:26 +02:00
|
|
|
/*
|
2003-04-23 17:01:29 +02:00
|
|
|
* Register veriusertfs routines/wrappers. Iterate over the tfcell
|
|
|
|
|
* array, registering each function.
|
2002-05-30 04:37:26 +02:00
|
|
|
*/
|
2003-02-16 03:23:14 +01:00
|
|
|
void veriusertfs_register_table(p_tfcell vtable)
|
2002-05-30 04:37:26 +02:00
|
|
|
{
|
2009-01-29 19:38:22 +01:00
|
|
|
static int need_EOS_cb = 1;
|
2003-05-18 02:16:35 +02:00
|
|
|
const char*path;
|
2002-05-31 20:21:39 +02:00
|
|
|
p_tfcell tf;
|
2002-05-30 04:37:26 +02:00
|
|
|
s_vpi_systf_data tf_data;
|
|
|
|
|
|
2003-06-17 18:55:07 +02:00
|
|
|
if (!pli_trace && (path = getenv("PLI_TRACE"))) {
|
2013-04-15 20:53:07 +02:00
|
|
|
static char trace_buf[1024];
|
2003-05-18 02:16:35 +02:00
|
|
|
if (strcmp(path,"-") == 0)
|
|
|
|
|
pli_trace = stdout;
|
2003-05-30 06:05:32 +02:00
|
|
|
else {
|
2003-05-18 02:16:35 +02:00
|
|
|
pli_trace = fopen(path, "w");
|
2003-06-17 18:55:07 +02:00
|
|
|
if (!pli_trace) {
|
|
|
|
|
perror(path);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
2003-05-30 06:05:32 +02:00
|
|
|
}
|
2007-05-09 00:01:26 +02:00
|
|
|
setvbuf(pli_trace, trace_buf, _IOLBF, sizeof(trace_buf));
|
2003-05-18 02:16:35 +02:00
|
|
|
}
|
|
|
|
|
|
2003-02-16 03:23:14 +01:00
|
|
|
for (tf = vtable; tf; tf++) {
|
2002-05-30 04:37:26 +02:00
|
|
|
/* last element */
|
2002-05-31 20:21:39 +02:00
|
|
|
if (tf->type == 0) break;
|
2002-05-30 04:37:26 +02:00
|
|
|
|
2002-06-04 03:42:58 +02:00
|
|
|
/* force forwref true */
|
2002-05-31 20:21:39 +02:00
|
|
|
if (!tf->forwref) {
|
2002-06-04 03:42:58 +02:00
|
|
|
vpi_printf("veriusertfs: %s, forcing forwref = true\n",
|
2002-05-31 20:21:39 +02:00
|
|
|
tf->tfname);
|
2002-05-30 04:37:26 +02:00
|
|
|
}
|
|
|
|
|
|
2009-01-29 19:38:22 +01:00
|
|
|
if (need_EOS_cb) {
|
|
|
|
|
s_cb_data cb_data;
|
|
|
|
|
|
|
|
|
|
cb_data.reason = cbEndOfSimulation;
|
|
|
|
|
cb_data.time = 0;
|
|
|
|
|
cb_data.cb_rtn = sys_end_of_simulation;
|
|
|
|
|
cb_data.user_data = "system";
|
|
|
|
|
vpi_register_cb(&cb_data);
|
|
|
|
|
|
|
|
|
|
need_EOS_cb = 0;
|
|
|
|
|
}
|
2002-05-30 04:37:26 +02:00
|
|
|
|
2003-04-23 17:01:29 +02:00
|
|
|
/* Build a VPI system task/function structure, and point
|
|
|
|
|
it to the pli_data that represents this
|
|
|
|
|
function. Supply wrapper functions for the system
|
|
|
|
|
task actions. */
|
2004-09-11 01:13:05 +02:00
|
|
|
memset(&tf_data, 0, sizeof(s_vpi_systf_data));
|
2002-05-31 20:21:39 +02:00
|
|
|
switch (tf->type) {
|
2003-04-23 17:01:29 +02:00
|
|
|
case usertask:
|
|
|
|
|
tf_data.type = vpiSysTask;
|
2002-05-30 04:37:26 +02:00
|
|
|
break;
|
2003-04-23 17:01:29 +02:00
|
|
|
case userfunction:
|
2007-12-19 19:11:17 +01:00
|
|
|
tf_data.sysfunctype = vpiIntFunc;
|
|
|
|
|
tf_data.type = vpiSysFunc;
|
|
|
|
|
break;
|
|
|
|
|
case userrealfunction:
|
|
|
|
|
tf_data.sysfunctype = vpiRealFunc;
|
2003-04-23 17:01:29 +02:00
|
|
|
tf_data.type = vpiSysFunc;
|
2002-05-30 04:37:26 +02:00
|
|
|
break;
|
2003-04-23 17:01:29 +02:00
|
|
|
default:
|
|
|
|
|
vpi_printf("veriusertfs: %s, unsupported type %d\n",
|
|
|
|
|
tf->tfname, tf->type);
|
|
|
|
|
continue;
|
2002-05-30 04:37:26 +02:00
|
|
|
}
|
2003-02-16 03:23:14 +01:00
|
|
|
|
2002-05-31 20:21:39 +02:00
|
|
|
tf_data.tfname = tf->tfname;
|
2002-05-30 04:37:26 +02:00
|
|
|
tf_data.compiletf = compiletf;
|
|
|
|
|
tf_data.calltf = calltf;
|
2018-10-06 23:56:04 +02:00
|
|
|
tf_data.sizetf = sizetf;
|
2020-12-04 00:38:51 +01:00
|
|
|
tf_data.user_data = (PLI_BYTE8*)tf;
|
2002-05-30 04:37:26 +02:00
|
|
|
|
2003-05-18 02:16:35 +02:00
|
|
|
if (pli_trace) {
|
2003-06-18 00:09:45 +02:00
|
|
|
fprintf(pli_trace, "Registering system %s:\n",
|
|
|
|
|
tf->type == usertask ? "task" : "function");
|
|
|
|
|
fprintf(pli_trace, " tfname : %s\n", tf->tfname);
|
|
|
|
|
if (tf->data)
|
|
|
|
|
fprintf(pli_trace, " data : %d\n", tf->data);
|
|
|
|
|
if (tf->checktf)
|
|
|
|
|
fprintf(pli_trace, " checktf: %p\n", tf->checktf);
|
|
|
|
|
if (tf->sizetf)
|
|
|
|
|
fprintf(pli_trace, " sizetf : %p\n", tf->sizetf);
|
|
|
|
|
if (tf->calltf)
|
|
|
|
|
fprintf(pli_trace, " calltf : %p\n", tf->calltf);
|
|
|
|
|
if (tf->misctf)
|
|
|
|
|
fprintf(pli_trace, " misctf : %p\n", tf->misctf);
|
2003-05-18 02:16:35 +02:00
|
|
|
}
|
|
|
|
|
|
2002-05-30 04:37:26 +02:00
|
|
|
/* register */
|
|
|
|
|
vpi_register_systf(&tf_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This function calls the veriusertfs checktf and sets up all the
|
|
|
|
|
* callbacks misctf requires.
|
|
|
|
|
*/
|
2018-09-29 09:53:32 +02:00
|
|
|
static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
2002-05-30 04:37:26 +02:00
|
|
|
{
|
2002-05-31 20:21:39 +02:00
|
|
|
p_tfcell tf;
|
2020-12-04 00:38:51 +01:00
|
|
|
p_pli_data pli;
|
2002-05-30 04:37:26 +02:00
|
|
|
s_cb_data cb_data;
|
2020-12-04 00:38:51 +01:00
|
|
|
vpiHandle arg_i, arg_h;
|
2003-05-28 04:42:43 +02:00
|
|
|
int rtn = 0;
|
2002-05-30 04:37:26 +02:00
|
|
|
|
|
|
|
|
/* cast back from opaque */
|
2020-12-04 00:38:51 +01:00
|
|
|
tf = (p_tfcell)data;
|
2002-05-30 04:37:26 +02:00
|
|
|
|
|
|
|
|
/* get call handle */
|
2020-12-04 00:38:51 +01:00
|
|
|
cur_instance = vpi_handle(vpiSysTfCall, NULL);
|
|
|
|
|
|
|
|
|
|
/* build callback user data for this instance */
|
|
|
|
|
pli = new_pli_data(tf, cur_instance, 0);
|
2002-05-30 04:37:26 +02:00
|
|
|
|
2020-12-04 00:38:51 +01:00
|
|
|
/* Attach the pli_data structure to the VPI handle of the
|
2003-04-23 17:01:29 +02:00
|
|
|
system task. This is how I manage the map from vpiHandle to
|
2020-12-04 00:38:51 +01:00
|
|
|
PLI1 user data. We do it here (instead of during register)
|
2003-04-23 17:01:29 +02:00
|
|
|
because this is the first that I have both the vpiHandle
|
2020-12-04 00:38:51 +01:00
|
|
|
and the user data. */
|
|
|
|
|
vpi_put_userdata(cur_instance, pli);
|
2003-04-23 17:01:29 +02:00
|
|
|
|
2002-05-30 04:37:26 +02:00
|
|
|
/* default cb_data */
|
2004-09-11 01:13:05 +02:00
|
|
|
memset(&cb_data, 0, sizeof(s_cb_data));
|
2002-05-30 04:37:26 +02:00
|
|
|
cb_data.cb_rtn = callback;
|
2020-12-04 00:38:51 +01:00
|
|
|
cb_data.user_data = (PLI_BYTE8*)pli;
|
2002-05-30 04:37:26 +02:00
|
|
|
|
2002-06-04 03:42:58 +02:00
|
|
|
/* register EOS misctf callback */
|
2002-05-30 04:37:26 +02:00
|
|
|
cb_data.reason = cbEndOfSimulation;
|
|
|
|
|
vpi_register_cb(&cb_data);
|
|
|
|
|
|
2003-04-23 17:01:29 +02:00
|
|
|
/* 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. */
|
2020-12-04 00:38:51 +01:00
|
|
|
if (tf->misctf && ((arg_i = vpi_iterate(vpiArgument, cur_instance)) != NULL)) {
|
2010-04-19 19:25:42 +02:00
|
|
|
int paramvc = 1;
|
2003-04-23 17:01:29 +02:00
|
|
|
|
|
|
|
|
cb_data.reason = cbValueChange;
|
2002-05-30 04:37:26 +02:00
|
|
|
while ((arg_h = vpi_scan(arg_i)) != NULL) {
|
2002-06-04 03:42:58 +02:00
|
|
|
/* replicate user_data for each instance */
|
2020-12-04 00:38:51 +01:00
|
|
|
p_pli_data dp = new_pli_data(tf, cur_instance, paramvc++);
|
|
|
|
|
cb_data.user_data = (PLI_BYTE8*)dp;
|
2002-05-30 04:37:26 +02:00
|
|
|
cb_data.obj = arg_h;
|
|
|
|
|
vpi_register_cb(&cb_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-04 03:42:58 +02:00
|
|
|
/*
|
|
|
|
|
* Since we are in compiletf, checktf and misctf need to
|
|
|
|
|
* be executed. Check runs first to match other simulators.
|
|
|
|
|
*/
|
2003-05-18 02:16:35 +02:00
|
|
|
if (tf->checktf) {
|
|
|
|
|
if (pli_trace) {
|
|
|
|
|
fprintf(pli_trace, "Call %s->checktf(reason_checktf)\n",
|
|
|
|
|
tf->tfname);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rtn = tf->checktf(tf->data, reason_checktf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tf->misctf) {
|
|
|
|
|
if (pli_trace) {
|
|
|
|
|
fprintf(pli_trace, "Call %s->misctf"
|
2003-06-18 00:09:45 +02:00
|
|
|
"(user_data=%d, reason=%d, paramvc=%d)\n",
|
2003-05-18 02:16:35 +02:00
|
|
|
tf->tfname, tf->data, reason_endofcompile, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tf->misctf(tf->data, reason_endofcompile, 0);
|
|
|
|
|
}
|
2002-05-30 04:37:26 +02:00
|
|
|
|
2020-12-04 00:38:51 +01:00
|
|
|
cur_instance = 0;
|
2002-06-04 03:42:58 +02:00
|
|
|
return rtn;
|
2002-05-30 04:37:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This function is the wrapper for the veriusertfs calltf routine.
|
|
|
|
|
*/
|
2018-09-29 09:53:32 +02:00
|
|
|
static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
2002-05-30 04:37:26 +02:00
|
|
|
{
|
2003-04-23 17:01:29 +02:00
|
|
|
int rc = 0;
|
2002-05-31 20:21:39 +02:00
|
|
|
p_tfcell tf;
|
2002-05-30 04:37:26 +02:00
|
|
|
|
|
|
|
|
/* cast back from opaque */
|
2020-12-04 00:38:51 +01:00
|
|
|
tf = (p_tfcell)data;
|
|
|
|
|
|
|
|
|
|
/* get call handle */
|
|
|
|
|
cur_instance = vpi_handle(vpiSysTfCall, NULL);
|
2002-05-30 04:37:26 +02:00
|
|
|
|
|
|
|
|
/* execute calltf */
|
2003-05-18 02:16:35 +02:00
|
|
|
if (tf->calltf) {
|
|
|
|
|
if (pli_trace) {
|
|
|
|
|
fprintf(pli_trace, "Call %s->calltf(%d, %d)\n",
|
2003-05-28 04:42:43 +02:00
|
|
|
tf->tfname, tf->data, reason_calltf);
|
2003-05-18 02:16:35 +02:00
|
|
|
}
|
|
|
|
|
|
2003-04-23 17:01:29 +02:00
|
|
|
rc = tf->calltf(tf->data, reason_calltf);
|
2003-05-18 02:16:35 +02:00
|
|
|
}
|
2003-04-23 17:01:29 +02:00
|
|
|
|
2020-12-04 00:38:51 +01:00
|
|
|
cur_instance = 0;
|
2003-04-23 17:01:29 +02:00
|
|
|
return rc;
|
2002-05-30 04:37:26 +02:00
|
|
|
}
|
|
|
|
|
|
2018-10-06 23:56:04 +02:00
|
|
|
/*
|
|
|
|
|
* This function is the wrapper for the veriusertfs sizetf routine.
|
|
|
|
|
*/
|
|
|
|
|
static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8*data)
|
|
|
|
|
{
|
|
|
|
|
int rc = 32;
|
|
|
|
|
p_tfcell tf;
|
|
|
|
|
|
|
|
|
|
/* cast back from opaque */
|
2020-12-04 00:38:51 +01:00
|
|
|
tf = (p_tfcell)data;
|
|
|
|
|
|
|
|
|
|
/* get call handle */
|
|
|
|
|
cur_instance = vpi_handle(vpiSysTfCall, NULL);
|
2018-10-06 23:56:04 +02:00
|
|
|
|
|
|
|
|
/* execute sizetf */
|
|
|
|
|
if (tf->sizetf) {
|
|
|
|
|
if (pli_trace) {
|
|
|
|
|
fprintf(pli_trace, "Call %s->sizetf(%d, %d)\n",
|
|
|
|
|
tf->tfname, tf->data, reason_sizetf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc = tf->sizetf(tf->data, reason_sizetf);
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-04 00:38:51 +01:00
|
|
|
cur_instance = 0;
|
2018-10-06 23:56:04 +02:00
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-30 04:37:26 +02:00
|
|
|
/*
|
|
|
|
|
* This function is the wrapper for all the misctf callbacks
|
|
|
|
|
*/
|
2002-06-04 03:42:58 +02:00
|
|
|
extern int async_misctf_enable;
|
|
|
|
|
|
2006-10-30 23:45:36 +01:00
|
|
|
static PLI_INT32 callback(p_cb_data data)
|
2002-05-30 04:37:26 +02:00
|
|
|
{
|
|
|
|
|
p_pli_data pli;
|
2002-05-31 20:21:39 +02:00
|
|
|
p_tfcell tf;
|
2002-05-30 04:37:26 +02:00
|
|
|
int reason;
|
2002-06-04 03:42:58 +02:00
|
|
|
int paramvc = 0;
|
2006-10-30 23:45:36 +01:00
|
|
|
PLI_INT32 rc;
|
2002-06-04 03:42:58 +02:00
|
|
|
|
2003-04-23 17:01:29 +02:00
|
|
|
/* not enabled */
|
|
|
|
|
if (data->reason == cbValueChange && !async_misctf_enable)
|
|
|
|
|
return 0;
|
2002-05-30 04:37:26 +02:00
|
|
|
|
2003-04-23 17:01:29 +02:00
|
|
|
/* cast back from opaque */
|
2002-05-30 04:37:26 +02:00
|
|
|
pli = (p_pli_data)data->user_data;
|
2020-12-04 00:38:51 +01:00
|
|
|
|
2002-05-31 20:21:39 +02:00
|
|
|
tf = pli->tf;
|
2020-12-04 00:38:51 +01:00
|
|
|
cur_instance = pli->call_handle;
|
2002-05-30 04:37:26 +02:00
|
|
|
|
|
|
|
|
switch (data->reason) {
|
2003-04-23 17:01:29 +02:00
|
|
|
case cbValueChange:
|
|
|
|
|
reason = reason_paramvc;
|
|
|
|
|
paramvc = pli->paramvc;
|
|
|
|
|
break;
|
|
|
|
|
case cbEndOfSimulation:
|
|
|
|
|
reason = reason_finish;
|
|
|
|
|
break;
|
|
|
|
|
case cbReadWriteSynch:
|
|
|
|
|
reason = reason_synch;
|
|
|
|
|
break;
|
2003-05-30 06:05:32 +02:00
|
|
|
case cbReadOnlySynch:
|
|
|
|
|
reason = reason_rosynch;
|
|
|
|
|
break;
|
2003-06-04 03:56:20 +02:00
|
|
|
case cbAfterDelay:
|
|
|
|
|
reason = reason_reactivate;
|
|
|
|
|
break;
|
2003-04-23 17:01:29 +02:00
|
|
|
default:
|
2009-12-10 21:48:24 +01:00
|
|
|
reason = -1;
|
2003-04-23 17:01:29 +02:00
|
|
|
assert(0);
|
2002-05-30 04:37:26 +02:00
|
|
|
}
|
|
|
|
|
|
2003-05-18 02:16:35 +02:00
|
|
|
if (pli_trace) {
|
|
|
|
|
fprintf(pli_trace, "Call %s->misctf"
|
2003-06-18 00:09:45 +02:00
|
|
|
"(user_data=%d, reason=%d, paramvc=%d)\n",
|
2003-05-18 02:16:35 +02:00
|
|
|
tf->tfname, tf->data, reason, paramvc);
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-30 04:37:26 +02:00
|
|
|
/* execute misctf */
|
2003-05-18 02:16:35 +02:00
|
|
|
rc = (tf->misctf) ? tf->misctf(tf->data, reason, paramvc) : 0;
|
|
|
|
|
|
2020-12-04 00:38:51 +01:00
|
|
|
cur_instance = 0;
|
2003-05-18 02:16:35 +02:00
|
|
|
return rc;
|
2002-05-30 04:37:26 +02:00
|
|
|
}
|
|
|
|
|
|
2003-04-23 17:01:29 +02:00
|
|
|
PLI_INT32 tf_isynchronize(void*obj)
|
|
|
|
|
{
|
|
|
|
|
vpiHandle sys = (vpiHandle)obj;
|
|
|
|
|
p_pli_data pli = vpi_get_userdata(sys);
|
|
|
|
|
s_cb_data cb;
|
2024-02-06 19:12:32 +01:00
|
|
|
s_vpi_time ti = {vpiSimTime, 0, 0, 0.0};
|
2003-04-23 17:01:29 +02:00
|
|
|
|
|
|
|
|
cb.reason = cbReadWriteSynch;
|
|
|
|
|
cb.cb_rtn = callback;
|
|
|
|
|
cb.obj = sys;
|
|
|
|
|
cb.time = &ti;
|
2020-12-04 00:38:51 +01:00
|
|
|
cb.user_data = (PLI_BYTE8*)pli;
|
2003-04-23 17:01:29 +02:00
|
|
|
|
|
|
|
|
vpi_register_cb(&cb);
|
2003-05-30 06:05:32 +02:00
|
|
|
|
|
|
|
|
if (pli_trace)
|
|
|
|
|
fprintf(pli_trace, "tf_isynchronize(%p) --> %d\n", obj, 0);
|
|
|
|
|
|
2003-04-23 17:01:29 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PLI_INT32 tf_synchronize(void)
|
|
|
|
|
{
|
|
|
|
|
return tf_isynchronize(tf_getinstance());
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-30 06:05:32 +02:00
|
|
|
|
|
|
|
|
PLI_INT32 tf_irosynchronize(void*obj)
|
|
|
|
|
{
|
|
|
|
|
vpiHandle sys = (vpiHandle)obj;
|
|
|
|
|
p_pli_data pli = vpi_get_userdata(sys);
|
|
|
|
|
s_cb_data cb;
|
2024-02-06 19:12:32 +01:00
|
|
|
s_vpi_time ti = {vpiSimTime, 0, 0, 0.0};
|
2003-05-30 06:05:32 +02:00
|
|
|
|
|
|
|
|
cb.reason = cbReadOnlySynch;
|
|
|
|
|
cb.cb_rtn = callback;
|
|
|
|
|
cb.obj = sys;
|
|
|
|
|
cb.time = &ti;
|
2020-12-04 00:38:51 +01:00
|
|
|
cb.user_data = (PLI_BYTE8*)pli;
|
2003-05-30 06:05:32 +02:00
|
|
|
|
|
|
|
|
vpi_register_cb(&cb);
|
|
|
|
|
|
|
|
|
|
if (pli_trace)
|
|
|
|
|
fprintf(pli_trace, "tf_irosynchronize(%p) --> %d\n", obj, 0);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PLI_INT32 tf_rosynchronize(void)
|
|
|
|
|
{
|
|
|
|
|
return tf_irosynchronize(tf_getinstance());
|
|
|
|
|
}
|
|
|
|
|
|
2003-06-04 03:56:20 +02:00
|
|
|
|
|
|
|
|
PLI_INT32 tf_isetrealdelay(double dly, void*obj)
|
|
|
|
|
{
|
|
|
|
|
vpiHandle sys = (vpiHandle)obj;
|
|
|
|
|
p_pli_data pli = vpi_get_userdata(sys);
|
|
|
|
|
s_cb_data cb;
|
2014-07-09 03:45:39 +02:00
|
|
|
s_vpi_time ti = {vpiSimTime, 0, 0, 0.0};
|
2003-06-04 03:56:20 +02:00
|
|
|
|
2008-09-30 03:06:47 +02:00
|
|
|
/* Scale delay to SimTime */
|
2003-06-04 03:56:20 +02:00
|
|
|
ivl_u64_t delay = ((dly
|
2011-12-17 04:02:52 +01:00
|
|
|
/ pow(10, tf_gettimeunit() - tf_gettimeprecision()))
|
2003-06-04 03:56:20 +02:00
|
|
|
+ 0.5);
|
|
|
|
|
ti.high = delay >> 32 & 0xffffffff;
|
|
|
|
|
ti.low = delay & 0xffffffff;
|
|
|
|
|
|
|
|
|
|
cb.reason = cbAfterDelay;
|
|
|
|
|
cb.cb_rtn = callback;
|
|
|
|
|
cb.obj = sys;
|
|
|
|
|
cb.time = &ti;
|
2020-12-04 00:38:51 +01:00
|
|
|
cb.user_data = (PLI_BYTE8*)pli;
|
2003-06-04 03:56:20 +02:00
|
|
|
|
|
|
|
|
vpi_register_cb(&cb);
|
|
|
|
|
|
|
|
|
|
if (pli_trace)
|
|
|
|
|
fprintf(pli_trace, "tf_isetrealdelay(%f, %p) --> %d\n",
|
|
|
|
|
dly, obj, 0);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PLI_INT32 tf_setrealdelay(double dly)
|
|
|
|
|
{
|
|
|
|
|
return tf_isetrealdelay(dly, tf_getinstance());
|
|
|
|
|
}
|