1998-11-10 00:44:10 +01:00
|
|
|
/*
|
1999-08-15 03:23:56 +02:00
|
|
|
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
1998-11-10 00:44:10 +01: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
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
#if !defined(WINNT)
|
1999-08-19 04:51:03 +02:00
|
|
|
#ident "$Id: vvm_calltf.cc,v 1.4 1999/08/19 02:51:11 steve Exp $"
|
1998-11-10 00:44:10 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
# include "vvm_calltf.h"
|
1999-08-15 03:23:56 +02:00
|
|
|
# include <vpi_user.h>
|
|
|
|
|
# include "vpi_priv.h"
|
1998-11-10 00:44:10 +01:00
|
|
|
# include <new>
|
|
|
|
|
# include <iostream>
|
|
|
|
|
# include <assert.h>
|
1999-08-15 03:23:56 +02:00
|
|
|
# include <stdlib.h>
|
|
|
|
|
# include <stdarg.h>
|
|
|
|
|
# include <malloc.h>
|
|
|
|
|
# include <stdio.h>
|
|
|
|
|
# include <dlfcn.h>
|
1998-11-10 00:44:10 +01:00
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
# define MAX_PATHLEN 1024
|
|
|
|
|
|
|
|
|
|
/* This simulation pointer is used by vpi functions to get back to the
|
|
|
|
|
simulation. */
|
|
|
|
|
static vvm_simulation*vpi_sim;
|
|
|
|
|
|
|
|
|
|
static vpiHandle vvm_vpi_cur_task;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Keep a list of vpi_systf_data structures. This list is searched
|
|
|
|
|
* forward whenever a function is invoked by name, and items are
|
|
|
|
|
* pushed in front of the list whenever they are registered. This
|
|
|
|
|
* allows entries to override older entries.
|
|
|
|
|
*/
|
|
|
|
|
struct systf_entry {
|
|
|
|
|
struct systf_entry* next;
|
|
|
|
|
s_vpi_systf_data systf_data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct systf_entry*systf_list = 0;
|
|
|
|
|
|
|
|
|
|
extern "C" void vpi_register_systf(const struct t_vpi_systf_data*systf)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
struct systf_entry*cur = new struct systf_entry;
|
|
|
|
|
cur->systf_data = *systf;
|
|
|
|
|
cur->systf_data.tfname = strdup(systf->tfname);
|
|
|
|
|
cur->next = systf_list;
|
|
|
|
|
systf_list = cur;
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
extern "C" void vpi_printf(const char*fmt, ...)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
va_list ap;
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
vprintf(fmt, ap);
|
|
|
|
|
va_end(ap);
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
|
1999-08-19 04:51:03 +02:00
|
|
|
extern "C" void vpi_sim_control(int func, ...)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-19 04:51:03 +02:00
|
|
|
switch (func) {
|
|
|
|
|
case vpiFinish:
|
|
|
|
|
vpi_sim->s_finish();
|
|
|
|
|
break;
|
|
|
|
|
}
|
1999-08-15 03:23:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" vpiHandle vpi_handle(int type, vpiHandle ref)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case vpiSysTfCall:
|
|
|
|
|
return vvm_vpi_cur_task;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
extern "C" vpiHandle vpi_iterate(int type, vpiHandle ref)
|
|
|
|
|
{
|
|
|
|
|
vpiHandle res = (vpiHandle)calloc(1, sizeof (struct __vpiHandle));
|
|
|
|
|
res->type = type;
|
|
|
|
|
res->referent = ref;
|
|
|
|
|
res->val.unum = 0;
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" vpiHandle vpi_scan(vpiHandle ref)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
assert(ref->type == vpiArgument);
|
|
|
|
|
if (ref->val.unum >= ref->referent->narguments)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return ref->referent->arguments[ref->val.unum++];
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
extern "C" int vpi_get(int property, vpiHandle ref)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
if (property == vpiType)
|
|
|
|
|
return ref->type;
|
|
|
|
|
|
|
|
|
|
if (ref->get_ == 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
return (ref->get_)(property, ref);
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
extern "C" char* vpi_get_str(int property, vpiHandle ref)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
if (property == vpiFullName)
|
|
|
|
|
return ref->full_name;
|
|
|
|
|
|
|
|
|
|
if (ref->get_str_ == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return (ref->get_str_)(property, ref);
|
|
|
|
|
|
|
|
|
|
switch (property) {
|
|
|
|
|
case vpiName:
|
|
|
|
|
return ref->full_name;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
|
|
|
|
|
{
|
|
|
|
|
if (expr->get_value_) {
|
|
|
|
|
expr->get_value_(expr, vp);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vp->format = vpiSuppressVal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" int vpi_free_object(vpiHandle ref)
|
|
|
|
|
{
|
|
|
|
|
free(ref);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This function is a get_value_ method of a vpiHandle, that supports
|
|
|
|
|
* reading bits as a string.
|
|
|
|
|
*/
|
|
|
|
|
static void get_value_bits(vpiHandle ref, s_vpi_value*vp)
|
|
|
|
|
{
|
|
|
|
|
static char buff[1024];
|
|
|
|
|
char*cp;
|
|
|
|
|
unsigned width, bytes;
|
|
|
|
|
unsigned val;
|
|
|
|
|
assert(ref->val.bits);
|
|
|
|
|
width = ref->val.bits->get_width();
|
|
|
|
|
cp = buff;
|
|
|
|
|
|
|
|
|
|
switch (vp->format) {
|
|
|
|
|
case vpiObjTypeVal:
|
|
|
|
|
case vpiBinStrVal:
|
|
|
|
|
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
|
|
|
|
switch (ref->val.bits->get_bit(width-idx-1)) {
|
|
|
|
|
case V0:
|
|
|
|
|
*cp++ = '0';
|
|
|
|
|
break;
|
|
|
|
|
case V1:
|
|
|
|
|
*cp++ = '1';
|
|
|
|
|
break;
|
|
|
|
|
case Vx:
|
|
|
|
|
*cp++ = 'x';
|
|
|
|
|
break;
|
|
|
|
|
case Vz:
|
|
|
|
|
*cp++ = 'z';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
vp->format = vpiBinStrVal;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vpiDecStrVal:
|
|
|
|
|
val = 0;
|
|
|
|
|
for (unsigned idx = 0 ; idx < width ; idx += 1) {
|
|
|
|
|
val *= 2;
|
|
|
|
|
switch (ref->val.bits->get_bit(width-idx-1)) {
|
|
|
|
|
case V0:
|
|
|
|
|
case Vx:
|
|
|
|
|
case Vz:
|
|
|
|
|
break;
|
|
|
|
|
case V1:
|
|
|
|
|
val += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
sprintf(cp, "%u", val);
|
|
|
|
|
cp += strlen(cp);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vpiOctStrVal:
|
|
|
|
|
bytes = width%3;
|
|
|
|
|
if (bytes) {
|
|
|
|
|
*cp++ = '?';
|
|
|
|
|
}
|
|
|
|
|
for (unsigned idx = bytes ; idx < width ; idx += 3) {
|
|
|
|
|
unsigned x = 0;
|
|
|
|
|
unsigned z = 0;
|
|
|
|
|
unsigned v = 0;
|
|
|
|
|
for (unsigned i = idx ; i < idx+3 ; i += 1) {
|
|
|
|
|
v *= 2;
|
|
|
|
|
switch (ref->val.bits->get_bit(width-idx-i-1)) {
|
|
|
|
|
case V0:
|
|
|
|
|
break;
|
|
|
|
|
case V1:
|
|
|
|
|
v += 1;
|
|
|
|
|
break;
|
|
|
|
|
case Vx:
|
|
|
|
|
x += 1;
|
|
|
|
|
break;
|
|
|
|
|
case Vz:
|
|
|
|
|
z += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (x == 3)
|
|
|
|
|
*cp++ = 'x';
|
|
|
|
|
else if (x > 0)
|
|
|
|
|
*cp++ = 'X';
|
|
|
|
|
else if (z == 3)
|
|
|
|
|
*cp++ = 'z';
|
|
|
|
|
else if (z > 0)
|
|
|
|
|
*cp++ = 'Z';
|
|
|
|
|
else
|
|
|
|
|
*cp++ = "01234567"[v];
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case vpiHexStrVal:
|
|
|
|
|
bytes = width%4;
|
|
|
|
|
if (bytes) {
|
|
|
|
|
*cp++ = '?';
|
|
|
|
|
}
|
|
|
|
|
for (unsigned idx = bytes ; idx < width ; idx += 4) {
|
|
|
|
|
unsigned x = 0;
|
|
|
|
|
unsigned z = 0;
|
|
|
|
|
unsigned v = 0;
|
|
|
|
|
for (unsigned i = idx ; i < idx+4 ; i += 1) {
|
|
|
|
|
v *= 2;
|
|
|
|
|
switch (ref->val.bits->get_bit(width-idx-i-1)) {
|
|
|
|
|
case V0:
|
|
|
|
|
break;
|
|
|
|
|
case V1:
|
|
|
|
|
v += 1;
|
|
|
|
|
break;
|
|
|
|
|
case Vx:
|
|
|
|
|
x += 1;
|
|
|
|
|
break;
|
|
|
|
|
case Vz:
|
|
|
|
|
z += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (x == 4)
|
|
|
|
|
*cp++ = 'x';
|
|
|
|
|
else if (x > 0)
|
|
|
|
|
*cp++ = 'X';
|
|
|
|
|
else if (z == 4)
|
|
|
|
|
*cp++ = 'z';
|
|
|
|
|
else if (z > 0)
|
|
|
|
|
*cp++ = 'Z';
|
|
|
|
|
else
|
|
|
|
|
*cp++ = "01234567abcdef"[v];
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
*cp++ = '(';
|
|
|
|
|
*cp++ = '?';
|
|
|
|
|
*cp++ = ')';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*cp++ = 0;
|
|
|
|
|
vp->value.str = buff;
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
static void get_value_strconst(vpiHandle ref, s_vpi_value*vp)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
switch (vp->format) {
|
|
|
|
|
case vpiObjTypeVal:
|
|
|
|
|
case vpiStringVal:
|
|
|
|
|
vp->value.str = ref->full_name;
|
|
|
|
|
vp->format = vpiStringVal;
|
|
|
|
|
break;
|
1998-11-10 00:44:10 +01:00
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
default:
|
|
|
|
|
vp->format = vpiSuppressVal;
|
1998-11-10 00:44:10 +01:00
|
|
|
break;
|
1999-08-15 03:23:56 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void get_value_timevar(vpiHandle ref, s_vpi_value*vp)
|
|
|
|
|
{
|
|
|
|
|
static char buf[128];
|
|
|
|
|
switch (vp->format) {
|
|
|
|
|
case vpiObjTypeVal:
|
|
|
|
|
case vpiTimeVal:
|
|
|
|
|
vp->value.time = &ref->val.time;
|
|
|
|
|
vp->format = vpiTimeVal;
|
1998-11-10 00:44:10 +01:00
|
|
|
break;
|
1999-08-15 03:23:56 +02:00
|
|
|
|
|
|
|
|
case vpiDecStrVal:
|
|
|
|
|
sprintf(buf, "%u", ref->val.time.low);
|
|
|
|
|
vp->value.str = buf;
|
1998-11-10 00:44:10 +01:00
|
|
|
break;
|
1999-08-15 03:23:56 +02:00
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
vp->format = vpiSuppressVal;
|
|
|
|
|
vp->value.str = 0;
|
1998-11-10 00:44:10 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
/*
|
|
|
|
|
* The load_vpi_module function attempts to locate and load the named
|
|
|
|
|
* vpi module and call the included startup routines. This is invoked
|
|
|
|
|
* by the generated C++ code to load all the modules that the
|
|
|
|
|
* simulation requires.
|
|
|
|
|
*
|
|
|
|
|
* If there is a '/' character in the name, or there is no
|
|
|
|
|
* VPI_MODULE_PATH, the the name is usd as is. No path is searched for
|
|
|
|
|
* the module.
|
|
|
|
|
*
|
|
|
|
|
* If there is a VPI_MODULE_PATH and there is no '/' in the name, the
|
|
|
|
|
* VPI_MODULE_PATH is taken as a ':' separated list of directory
|
|
|
|
|
* names. Each directory is searched for a module with the right name
|
|
|
|
|
* that will link in. The current working directory is not implicitly
|
|
|
|
|
* tried. If you wish '.' be in th search path, include it.
|
|
|
|
|
*/
|
|
|
|
|
typedef void (*vlog_startup_routines_t)(void);
|
|
|
|
|
|
|
|
|
|
void vvm_load_vpi_module(const char*name)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
void*mod = 0;
|
|
|
|
|
const char*path = getenv("VPI_MODULE_PATH");
|
|
|
|
|
|
|
|
|
|
if ((path == 0) || (strchr(name, '/'))) {
|
|
|
|
|
mod = dlopen(name, RTLD_NOW);
|
|
|
|
|
if (mod == 0) {
|
|
|
|
|
cerr << name << ": " << dlerror() << endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
const char*cur = path;
|
|
|
|
|
const char*ep;
|
|
|
|
|
for (cur = path ; cur ; cur = ep? ep+1 : 0) {
|
|
|
|
|
char dest[MAX_PATHLEN+1];
|
|
|
|
|
|
|
|
|
|
ep = strchr(cur, ':');
|
|
|
|
|
size_t n = ep? ep-cur : strlen(cur);
|
|
|
|
|
if ((n + strlen(name) + 2) > sizeof dest)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
strncpy(dest, cur, n);
|
|
|
|
|
dest[n] = '/';
|
|
|
|
|
dest[n+1] = 0;
|
|
|
|
|
strcat(dest, name);
|
|
|
|
|
|
|
|
|
|
mod = dlopen(dest, RTLD_NOW);
|
|
|
|
|
if (mod) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mod == 0) {
|
|
|
|
|
cerr << dlerror() << endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void*table = dlsym(mod, "vlog_startup_routines");
|
|
|
|
|
vlog_startup_routines_t*routines = (vlog_startup_routines_t*)table;
|
|
|
|
|
if (routines == 0) {
|
|
|
|
|
cerr << name << ": Unable to locate the vlog_startup_routines"
|
|
|
|
|
" table." << endl;
|
|
|
|
|
dlclose(mod);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; routines[idx] ; idx += 1)
|
|
|
|
|
(routines[idx])();
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
void vvm_make_vpi_parm(vpiHandle ref, const char*val)
|
|
|
|
|
{
|
|
|
|
|
memset(ref, 0, sizeof*ref);
|
|
|
|
|
ref->type = vpiConstant;
|
|
|
|
|
ref->subtype = vpiStringConst;
|
|
|
|
|
ref->full_name = const_cast<char*>(val);
|
|
|
|
|
ref->get_value_ = &get_value_strconst;
|
|
|
|
|
}
|
1998-11-10 00:44:10 +01:00
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
void vvm_make_vpi_parm(vpiHandle ref, vvm_bits_t*val)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
memset(ref, 0, sizeof*ref);
|
|
|
|
|
ref->type = vpiConstant;
|
|
|
|
|
ref->subtype = vpiBinaryConst;
|
|
|
|
|
ref->full_name = "";
|
|
|
|
|
ref->val.bits = val;
|
|
|
|
|
ref->get_value_ = &get_value_bits;
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
void vvm_init_vpi_handle(vpiHandle ref, vvm_bits_t*bits, vvm_monitor_t*mon)
|
|
|
|
|
{
|
|
|
|
|
memset(ref, 0, sizeof*ref);
|
|
|
|
|
ref->type = vpiReg;
|
|
|
|
|
ref->full_name = const_cast<char*>(mon->name());
|
|
|
|
|
ref->val.bits = bits;
|
|
|
|
|
ref->get_value_ = &get_value_bits;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvm_init_vpi_timevar(vpiHandle ref, const char*name)
|
|
|
|
|
{
|
|
|
|
|
memset(ref, 0, sizeof*ref);
|
|
|
|
|
ref->type = vpiTimeVar;
|
|
|
|
|
ref->full_name = const_cast<char*>(name);
|
|
|
|
|
ref->get_value_ = &get_value_timevar;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vvm_make_vpi_parm(vpiHandle ref)
|
|
|
|
|
{
|
|
|
|
|
memset(ref, 0, sizeof*ref);
|
|
|
|
|
ref->type = 0;
|
|
|
|
|
}
|
1998-11-10 00:44:10 +01:00
|
|
|
|
|
|
|
|
void vvm_calltask(vvm_simulation*sim, const string&fname,
|
1999-08-15 03:23:56 +02:00
|
|
|
unsigned nparms, vpiHandle*parms)
|
1998-11-10 00:44:10 +01:00
|
|
|
{
|
1999-08-15 03:23:56 +02:00
|
|
|
vpi_sim = sim;
|
|
|
|
|
|
|
|
|
|
struct __vpiHandle cur_task;
|
|
|
|
|
cur_task.type = vpiSysTaskCall;
|
|
|
|
|
cur_task.full_name = 0;
|
|
|
|
|
cur_task.referent = 0;
|
|
|
|
|
cur_task.arguments = parms;
|
|
|
|
|
cur_task.narguments = nparms;
|
1998-11-10 00:44:10 +01:00
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
vvm_vpi_cur_task = &cur_task;
|
|
|
|
|
|
|
|
|
|
/* Look for a systf function to invoke. */
|
|
|
|
|
for (systf_entry*idx = systf_list ; idx ; idx = idx->next)
|
|
|
|
|
if (fname == idx->systf_data.tfname) {
|
|
|
|
|
cur_task.full_name = idx->systf_data.tfname;
|
|
|
|
|
idx->systf_data.calltf(idx->systf_data.user_data);
|
1998-11-10 00:44:10 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
|
|
|
|
|
/* Finally, if nothing is found then something is not
|
|
|
|
|
right. Print out the function name all the parameters
|
|
|
|
|
passed, so that someone can deal with it. */
|
|
|
|
|
cout << "Call " << fname << endl;
|
1998-11-10 00:44:10 +01:00
|
|
|
}
|
|
|
|
|
|
1999-08-15 03:23:56 +02:00
|
|
|
|
1998-11-10 00:44:10 +01:00
|
|
|
/*
|
|
|
|
|
* $Log: vvm_calltf.cc,v $
|
1999-08-19 04:51:03 +02:00
|
|
|
* Revision 1.4 1999/08/19 02:51:11 steve
|
|
|
|
|
* Add vpi_sim_control
|
|
|
|
|
*
|
1999-08-15 03:23:56 +02:00
|
|
|
* Revision 1.3 1999/08/15 01:23:56 steve
|
|
|
|
|
* Convert vvm to implement system tasks with vpi.
|
|
|
|
|
*
|
1999-05-31 17:46:36 +02:00
|
|
|
* Revision 1.2 1999/05/31 15:46:36 steve
|
|
|
|
|
* Handle time in more places.
|
|
|
|
|
*
|
1998-11-10 00:44:10 +01:00
|
|
|
* Revision 1.1 1998/11/09 23:44:10 steve
|
|
|
|
|
* Add vvm library.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|