Convert vvm to implement system tasks with vpi.

This commit is contained in:
steve 1999-08-15 01:23:56 +00:00
parent f1825c54a7
commit 2d0e11283d
19 changed files with 1323 additions and 472 deletions

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.11 1999/08/07 20:05:51 steve Exp $"
#ident "$Id: Makefile.in,v 1.12 1999/08/15 01:23:56 steve Exp $"
#
#
SHELL = /bin/sh
@ -46,11 +46,13 @@ CXXFLAGS = @CXXFLAGS@
LDFLAGS = @LDFLAGS@
all: ivl
cd vpi ; make all
cd vvm ; make all
cd ivlpp ; make all
clean:
rm *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc
cd vpi ; make clean
cd vvm ; make clean
cd ivlpp ; make clean
@ -87,6 +89,7 @@ lexor.cc: lexor.lex
flex -PVL -s -olexor.cc lexor.lex
install: all installdirs $(bindir)/ivl
cd vpi ; make install
cd vvm ; make install
cd ivlpp ; make install

View File

@ -6,4 +6,4 @@ AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_OUTPUT(Makefile ivlpp/Makefile vvm/Makefile)
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile)

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: t-vvm.cc,v 1.34 1999/08/02 00:19:16 steve Exp $"
#ident "$Id: t-vvm.cc,v 1.35 1999/08/15 01:23:56 steve Exp $"
#endif
# include <iostream>
@ -306,6 +306,14 @@ static string emit_proc_rval(ostream&os, unsigned indent, const NetExpr*expr)
return scan.result;
}
/*
* The vvm_parm_rval class scans expressions for the purpose of making
* parameters for system tasks/functions. Thus, the generated code is
* geared towards making the handles needed to make the call.
*
* The result of any parm rval scan is a vpiHandle, or a string that
* automatically converts to a vpiHandle on assignment.
*/
class vvm_parm_rval : public expr_scan_t {
public:
@ -326,8 +334,11 @@ class vvm_parm_rval : public expr_scan_t {
void vvm_parm_rval::expr_const(const NetEConst*expr)
{
if (expr->value().is_string()) {
result = "\"";
result = result + expr->value().as_string() + "\"";
result = make_temp();
os_ << " struct __vpiHandle " << result << ";" << endl;
os_ << " vvm_make_vpi_parm(&" << result << ", \""
<< expr->value().as_string() << "\");" << endl;
result = "&" + result;
return;
}
@ -353,16 +364,19 @@ void vvm_parm_rval::expr_const(const NetEConst*expr)
os_ << ";" << endl;
}
result = tname;
result = make_temp();
os_ << " struct __vpiHandle " << result << ";" << endl;
os_ << " vvm_make_vpi_parm(&" << result << ", &" << tname
<< ");" << endl;
result = "&" + result;
}
void vvm_parm_rval::expr_ident(const NetEIdent*expr)
{
if (expr->name() == "$time") {
string res = make_temp();
os_ << " vvm_calltf_parm " << res <<
"(vvm_calltf_parm::TIME);" << endl;
result = res;
os_ << " system_time.val.time.low "
"= sim_->get_sim_time();" << endl;
result = string("&system_time");
} else {
cerr << "Unhandled identifier: " << expr->name() << endl;
}
@ -370,12 +384,7 @@ void vvm_parm_rval::expr_ident(const NetEIdent*expr)
void vvm_parm_rval::expr_signal(const NetESignal*expr)
{
string res = make_temp();
os_ << " vvm_calltf_parm::SIG " << res << ";" << endl;
os_ << " " << res << ".bits = &" <<
mangle(expr->name()) << "_bits;" << endl;
os_ << " " << res << ".mon = &" <<
mangle(expr->name()) << ";" << endl;
string res = string("&") + mangle(expr->name()) + "_vpi";
result = res;
}
@ -393,11 +402,16 @@ void target_vvm::start_design(ostream&os, const Design*mod)
os << "# include \"vvm_func.h\"" << endl;
os << "# include \"vvm_calltf.h\"" << endl;
os << "# include \"vvm_thread.h\"" << endl;
os << "# include \"vpi_user.h\"" << endl;
os << "# include \"vpi_priv.h\"" << endl;
os << "static struct __vpiHandle system_time;" << endl;
process_counter = 0;
init_code << "static void design_init(vvm_simulation&sim)" << endl;
init_code << "{" << endl;
init_code << " vvm_init_vpi_timevar(&system_time, \"$time\");"
<< endl;
start_code << "static void design_start(vvm_simulation&sim)" << endl;
start_code << "{" << endl;
}
@ -414,6 +428,7 @@ void target_vvm::end_design(ostream&os, const Design*mod)
os << start_code.str();
os << "main()" << endl << "{" << endl;
os << " vvm_load_vpi_module(\"system.vpi\");" << endl;
os << " vvm_simulation sim;" << endl;
os << " design_init(sim);" << endl;
os << " design_start(sim);" << endl;
@ -818,6 +833,14 @@ void target_vvm::net_esignal(ostream&os, const NetESignal*net)
os << "static vvm_signal_t<" << net->pin_count() << "> " <<
mangle(net->name()) << "(\"" << net->name() << "\", &" <<
mangle(net->name()) << "_bits);" << endl;
os << "static struct __vpiHandle " << mangle(net->name()) <<
"_vpi;" << endl;
init_code << " vvm_init_vpi_handle(&" <<
mangle(net->name()) << "_vpi, &" << mangle(net->name()) <<
"_bits, &" << mangle(net->name()) << ");" << endl;
}
/*
@ -1139,16 +1162,42 @@ void target_vvm::proc_repeat(ostream&os, const NetRepeat*net)
void target_vvm::proc_stask(ostream&os, const NetSTask*net)
{
string ptmp = make_temp();
os << " struct vvm_calltf_parm " << ptmp << "[" <<
#if 0
os << " struct __vpiHandle " << ptmp << "[" <<
net->nparms() << "];" << endl;
for (unsigned idx = 0 ; idx < net->nparms() ; idx += 1)
if (net->parm(idx)) {
string val = emit_parm_rval(os, net->parm(idx));
os << " " << ptmp << "[" << idx << "] = " <<
val << ";" << endl;
os << " vvm_make_vpi_parm(&" << ptmp << "["
<< idx << "], " << val << ");" << endl;
} else {
os << " vvm_make_vpi_parm(&" << ptmp << "["
<< idx << "]);" << endl;
}
#else
os << " vpiHandle " << ptmp << "[" << net->nparms() <<
"];" << endl;
for (unsigned idx = 0 ; idx < net->nparms() ; idx += 1) {
string val;
if (net->parm(idx)) {
val = emit_parm_rval(os, net->parm(idx));
} else {
val = make_temp();
os << " struct __vpiHandle " << val << ";" << endl;
os << " vvm_make_vpi_parm(&" << val << ");" << endl;
val = string("&") + val;
}
os << " " << ptmp << "[" << idx << "] = " << val << ";"
<< endl;
}
#endif
os << " vvm_calltask(sim_, \"" << net->name() << "\", " <<
net->nparms() << ", " << ptmp << ");" << endl;
}
void target_vvm::proc_utask(ostream&os, const NetUTask*net)
@ -1308,6 +1357,9 @@ extern const struct target tgt_vvm = {
};
/*
* $Log: t-vvm.cc,v $
* Revision 1.35 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
* Revision 1.34 1999/08/02 00:19:16 steve
* Get rid of excess set/init of NetESignal objects.
*

56
vpi.txt Normal file
View File

@ -0,0 +1,56 @@
HOW IT WORKS
The VPI interface for Icarus Verilog works by creating from a
collection of PLI applications a single vpi module. The vpi module
includes compiled code for the applications linked together (with any
other libraries that the applications need) into a module with a
single exported symbol, the vlog_startup_routines array.
The product that wishes to invoke the module (normally at run time)
loads the module, locates the vlog_startup_routines table, and calls
all the startup routines contained in that table. It is possible for a
product to link with many modules. In that case, all the modules are
linked in and startup routines are called in order.
The product that uses vpi modules uses the environment variable
VPI_MODULE_PATH as a ':' separated list of directories. This is the
module search path. When a module is specified by name (using whatever
means the product supports) the module search path is scanned until
the module is located.
The special module name "system.vpi" is part of the core Icarus
Verilog distribution and includes implementations of the standard
system tasks/functions.
COMPILING A VPI MODULE (LINUX)
To compile a module, first compile down to object files all the PLI
applications that you wish to include in the module. Then, create a
small "C" source file that defines only the startup table like so:
extern void hello_register();
void (*vlog_startup_routines[])() = {
hello_register,
0
};
Compile this table source down to its object file, as well. Finally,
link the application with the command:
cc -o foo.vpi -shared <all the .o files>
No VPI libraries need to be included because the product that loads
the module will supply all the standard vpi functions. If you use any
non-vpi library functions, you may need to include libraries to
support them.
The resulting foo.vpi file is the vpi module. Place it in a location
where the product to use it can locate it.
CAVEAT EMPTOR
Only the calltf function is supported. The compiletf and sizetf
functions are invoked at compile time, and the ivl compiler does not
yet support VPI.

3
vpi/.cvsignore Normal file
View File

@ -0,0 +1,3 @@
Makefile
system.vpi
dep

86
vpi/Makefile.in Normal file
View File

@ -0,0 +1,86 @@
#
# This source code is free software; you can redistribute it
# and/or modify it in source code form under the terms of the GNU
# Library General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option)
# any later version. In order to redistribute the software in
# binary form, you will need a Picture Elements Binary Software
# License.
#
# 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 Library General Public License for more details.
#
# You should have received a copy of the GNU Library 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
#
#ident "$Id: Makefile.in,v 1.1 1999/08/15 01:23:56 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
VPATH = $(srcdir)
bindir = $(exec_prefix)/bin
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
CC = @CC@
CXX = @CXX@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @CPPFLAGS@ @DEFS@
CXXFLAGS = @CXXFLAGS@
LDFLAGS = @LDFLAGS@
all: system.vpi
%.o dep/%.d: %.c
@[ -d dep ] || mkdir dep
$(CC) -Wall $(CPPFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = sys_table.o sys_display.o sys_finish.o
system.vpi: $O
$(CC) -shared -o $@ $O
clean:
rm -f *.o dep/*.d
install: all installdirs $(libdir)/ivl/system.vpi \
$(includedir)/vpi_user.h \
$(includedir)/veriuser.h
$(libdir)/ivl/system.vpi: ./system.vpi
$(INSTALL_PROGRAM) ./system.vpi $(libdir)/ivl/system.vpi
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
$(INSTALL_DATA) $(srcdir)/veriuser.h $(includedir)/veriuser.h
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl
uninstall:
rm -f $(libdir)/ivl/system.vpi
rm -f $(includedir)/vpi_user.h
rm -f $(includedir)/veriuser.h
-include $(patsubst %.o, dep/%.d, $O)

226
vpi/sys_display.c Normal file
View File

@ -0,0 +1,226 @@
/*
* Copyright (c) 1999 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
* 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)
#ident "$Id: sys_display.c,v 1.1 1999/08/15 01:23:56 steve Exp $"
#endif
# include "vpi_user.h"
# include <assert.h>
# include <string.h>
# include <ctype.h>
# include <stdlib.h>
static void format_binary(vpiHandle argv, int fsize)
{
s_vpi_value value;
vpiHandle item = vpi_scan(argv);
if (item == 0) return;
value.format = vpiBinStrVal;
vpi_get_value(item, &value);
vpi_printf("%s", value.value.str);
}
static void format_decimal(vpiHandle argv, int fsize)
{
s_vpi_value value;
vpiHandle item = vpi_scan(argv);
if (item == 0) return;
value.format = vpiDecStrVal;
vpi_get_value(item, &value);
vpi_printf("%s", value.value.str);
}
static void format_hex(vpiHandle argv, int fsize)
{
s_vpi_value value;
vpiHandle item = vpi_scan(argv);
if (item == 0) return;
value.format = vpiHexStrVal;
vpi_get_value(item, &value);
vpi_printf("%s", value.value.str);
}
static void format_m(vpiHandle argv, int fsize)
{
vpiHandle item = vpi_scan(argv);
if (item == 0) return;
vpi_printf("%s", vpi_get_str(vpiFullName, item));
}
/*
* If $display discovers a string as a parameter, this function is
* called to process it as a format string. I need the argv handle as
* well so that I can look for arguments as I move forward through the
* string.
*/
static void format(s_vpi_value*fmt, vpiHandle argv)
{
char buf[256];
char*cp = fmt->value.str;
assert(fmt->value.str);
while (*cp) {
size_t cnt = strcspn(cp, "%\\");
if (cnt > 0) {
if (cnt >= sizeof buf)
cnt = sizeof buf - 1;
strncpy(buf, cp, cnt);
buf[cnt] = 0;
vpi_printf("%s", buf);
cp += cnt;
} else if (*cp == '%') {
int fsize = -1;
cp += 1;
if (isdigit(*cp))
fsize = strtoul(cp, &cp, 10);
switch (*cp) {
case 0:
break;
case 'b':
case 'B':
format_binary(argv, fsize);
cp += 1;
break;
case 'd':
case 'D':
format_decimal(argv, fsize);
cp += 1;
break;
case 'h':
case 'H':
case 'x':
case 'X':
format_hex(argv, fsize);
cp += 1;
break;
case 'm':
format_m(argv, fsize);
cp += 1;
break;
case '%':
vpi_printf("%%");
cp += 1;
break;
default:
vpi_printf("%c", *cp);
cp += 1;
break;
}
} else {
cp += 1;
switch (*cp) {
case 0:
break;
case 'n':
vpi_printf("\n");
cp += 1;
break;
default:
vpi_printf("%c", *cp);
cp += 1;
}
}
}
}
static int sys_display_calltf(char *xx)
{
s_vpi_value value;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item;
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
switch (vpi_get(vpiType, item)) {
case 0:
vpi_printf(" ");
break;
case vpiConstant:
value.format = vpiObjTypeVal;
vpi_get_value(item, &value);
switch (value.format) {
case vpiStringVal:
format(&value, argv);
break;
case vpiSuppressVal:
break;
default:
vpi_printf("?");
break;
}
break;
case vpiNet:
case vpiReg:
value.format = vpiBinStrVal;
vpi_get_value(item, &value);
vpi_printf("%s", value.value.str);
break;
case vpiTimeVar:
value.format = vpiTimeVal;
vpi_get_value(item, &value);
vpi_printf("%u", value.value.time->low);
break;
default:
vpi_printf("?");
break;
}
}
vpi_printf("\n");
vpi_free_object(argv);
return 0;
}
void sys_display_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.tfname = "$display";
tf_data.calltf = sys_display_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
vpi_register_systf(&tf_data);
}
/*
* $Log: sys_display.c,v $
* Revision 1.1 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
*/

50
vpi/sys_finish.c Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 1999 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
* 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)
#ident "$Id: sys_finish.c,v 1.1 1999/08/15 01:23:56 steve Exp $"
#endif
# include "vpi_user.h"
# include "veriuser.h"
static int sys_finish_calltf(char *xx)
{
tf_dofinish();
return 0;
}
void sys_finish_register()
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.tfname = "$finish";
tf_data.calltf = sys_finish_calltf;
tf_data.compiletf = 0;
tf_data.sizetf = 0;
vpi_register_systf(&tf_data);
}
/*
* $Log: sys_finish.c,v $
* Revision 1.1 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
*/

39
vpi/sys_table.c Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 1999 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
* 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)
#ident "$Id: sys_table.c,v 1.1 1999/08/15 01:23:56 steve Exp $"
#endif
extern void sys_finish_register();
extern void sys_display_register();
void (*vlog_startup_routines[])() = {
sys_finish_register,
sys_display_register,
0
};
/*
* $Log: sys_table.c,v $
* Revision 1.1 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
*/

47
vpi/veriuser.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef __veriuser_H
#define __veriuser_H
/*
* Copyright (c) 1999 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
* 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)
#ident "$Id: veriuser.h,v 1.1 1999/08/15 01:23:56 steve Exp $"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* This header file only exists as a stub, and to carry the function
* declaration for the tf_dofinish() function. I plan on removing both
* as soon as a VPI way of doing this appears.
*/
extern void tf_dofinish();
#ifdef __cplusplus
}
#endif
/*
* $Log: veriuser.h,v $
* Revision 1.1 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
*/
#endif

147
vpi/vpi_user.h Normal file
View File

@ -0,0 +1,147 @@
#ifndef __vpi_user_H
#define __vpi_user_H
/*
* Copyright (c) 1999 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
* 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)
#ident "$Id: vpi_user.h,v 1.1 1999/08/15 01:23:56 steve Exp $"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct __vpiHandle *vpiHandle;
/*
* This structure is created by the VPI application to provide hooks
* into the application that the compiler/simulator can access.
*/
typedef struct t_vpi_systf_data {
int type;
int subtype;
char *tfname;
int (*calltf)(char*);
int (*compiletf)(char*);
int (*sizetf)();
char *user_data;
} s_vpi_systf_data, *p_vpi_systf_data;
/* The type in the above structure can have one of the following
values: */
#define vpiSysTask 1
#define vpiSysFunc 2
typedef struct t_vpi_time {
int type;
unsigned int high;
unsigned int low;
double real;
} s_vpi_time, *p_vpi_time;
#define vpiScaledRealTime 1
#define vpiSimTime 2
#define vpiSuppressTime 3
/*
* This structure holds values that are passed back and forth between
* the simulator and the application.
*/
typedef struct t_vpi_value {
int format;
union {
char*str;
int scalar;
int integer;
double real;
struct t_vpi_time *time;
struct t_vpi_vecval *vector;
struct t_vpi_strengthval *strength;
char*misc;
} value;
} s_vpi_value, *p_vpi_value;
/* These are valid codes for the format of the t_vpi_value structure. */
#define vpiBinStrVal 1
#define vpiOctStrVal 2
#define vpiDecStrVal 3
#define vpiHexStrVal 4
#define vpiScalerVal 5
#define vpiIntVal 6
#define vpiReadVal 7
#define vpiStringVal 8
#define vpiVectorVal 9
#define vpiStrengthVal 10
#define vpiTimeVal 11
#define vpiObjTypeVal 12
#define vpiSuppressVal 13
/* OBJECT CODES */
#define vpiConstant 7
#define vpiNet 36
#define vpiReg 48
#define vpiSysTaskCall 57
#define vpiTimeVar 63
#define vpiSysTfCall 85
#define vpiArgument 89
/* PROPERTIES */
#define vpiType 1
#define vpiName 2
#define vpiFullName 3
#define vpiConstType 43
# define vpiDecConst 1
# define vpiRealConst 2
# define vpiBinaryConst 3
# define vpiOctConst 4
# define vpiHexConst 5
# define vpiStringConst 6
/* VPI FUNCTIONS */
extern void vpi_register_systf(const struct t_vpi_systf_data*ss);
extern void vpi_printf(const char*fmt, ...);
extern vpiHandle vpi_handle(int type, vpiHandle ref);
extern vpiHandle vpi_iterate(int type, vpiHandle ref);
extern vpiHandle vpi_scan(vpiHandle iter);
extern int vpi_get(int property, vpiHandle ref);
extern char* vpi_get_str(int property, vpiHandle ref);
extern void vpi_get_value(vpiHandle expr, p_vpi_value value);
extern int vpi_free_object(vpiHandle ref);
/* This is the table of startup routines included in each module. */
extern void (*vlog_startup_routines[])();
#ifdef __cplusplus
}
#endif
/*
* $Log: vpi_user.h,v $
* Revision 1.1 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
*/
#endif

16
vvm.txt
View File

@ -16,6 +16,17 @@ So a sample command line to compile a Verilog file to C++ would be:
ivl -F nobufz -F sigfold -F propinit -t vvm -o foo.cc foo.vl
Once the program is compiled down to C++ code, it needs to be further
compiled and linked into an executable image. The command for doing
this is highly dependent on the system where you use Icarus
Verilog. For Linux, the compile command is typically:
c++ -o foo foo.cc -lvvm -ldl
On any system, the compiled program requires that the VPI_MODULE_PATH
be set to a ':' separated list of directories to search for vpi files,
the system.vpi file in particular. This is a run time requirement.
ATTRIBUTES
(none)
@ -99,8 +110,11 @@ bits are at:
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
$Id: vvm.txt,v 1.1 1999/04/29 16:29:04 steve Exp $
$Id: vvm.txt,v 1.2 1999/08/15 01:23:56 steve Exp $
$Log: vvm.txt,v $
Revision 1.2 1999/08/15 01:23:56 steve
Convert vvm to implement system tasks with vpi.
Revision 1.1 1999/04/29 16:29:04 steve
Add vvm target documentation

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.3 1999/05/09 01:24:59 steve Exp $"
#ident "$Id: Makefile.in,v 1.4 1999/08/15 01:23:56 steve Exp $"
#
#
SHELL = /bin/sh
@ -36,7 +36,7 @@ libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
CC = @CC@
CXX = @CXX@
CXX = @CXX@ -I../vpi
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
@ -52,9 +52,8 @@ all: libvvm.a
$(CXX) -Wall -fno-exceptions $(CXXFLAGS) -MD -c $< -o $*.o
mv $*.d dep
TF = display.o
O = vvm_bit.o vvm_calltf.o vvm_event.o vvm_monitor.o vvm_pevent.o \
vvm_simulation.o vvm_thread.o $(TF)
vvm_simulation.o vvm_thread.o
libvvm.a: $O
rm -f $@

View File

@ -1,264 +0,0 @@
/*
* Copyright (c) 1998 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
* 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)
#ident "$Id: display.cc,v 1.5 1999/05/31 15:46:36 steve Exp $"
#endif
# include "vvm.h"
# include "vvm_calltf.h"
# include <iostream>
static void format_hex(vvm_simulation*sim, ostream&os,
class vvm_calltf_parm*parm)
{
switch (parm->type()) {
case vvm_calltf_parm::TIME:
os << sim->get_sim_time();
break;
case vvm_calltf_parm::NONE:
os << "z";
break;
case vvm_calltf_parm::ULONG:
os << ((parm->as_ulong()&1) ? "0" : "1");
break;
case vvm_calltf_parm::STRING:
os << parm->as_string();
break;
case vvm_calltf_parm::BITS:
unsigned c = 0;
for (unsigned idx = parm->as_bits()->get_width()
; idx > 0 ; idx -= 1)
c = (c << 1) | parm->as_bits()->get_bit(idx-1);
cout.form("%x",c);
break;
}
}
static void format_bit(vvm_simulation*sim, ostream&os,
class vvm_calltf_parm*parm)
{
switch (parm->type()) {
case vvm_calltf_parm::TIME:
os << (sim->get_sim_time()&1);
break;
case vvm_calltf_parm::NONE:
os << "z";
break;
case vvm_calltf_parm::ULONG:
os << ((parm->as_ulong()&1) ? "0" : "1");
break;
case vvm_calltf_parm::STRING:
os << parm->as_string();
break;
case vvm_calltf_parm::BITS:
for (unsigned idx = parm->as_bits()->get_width()
; idx > 0 ; idx -= 1)
os << parm->as_bits()->get_bit(idx-1);
break;
}
}
static void format_dec(vvm_simulation*sim, ostream&os,
class vvm_calltf_parm*parm)
{
switch (parm->type()) {
case vvm_calltf_parm::TIME:
os << sim->get_sim_time();
break;
case vvm_calltf_parm::NONE:
os << "0";
break;
case vvm_calltf_parm::ULONG:
os << parm->as_ulong();
break;
case vvm_calltf_parm::STRING:
os << parm->as_string();
break;
case vvm_calltf_parm::BITS: {
unsigned long val = 0;
unsigned long mask = 1;
const vvm_bits_t*bstr = parm->as_bits();
for (unsigned idx = 0 ; idx < bstr->get_width() ; idx += 1) {
if (bstr->get_bit(idx) == V1) val |= mask;
mask <<= 1;
}
os << val;
break;
}
}
}
static void format_name(ostream&os, class vvm_calltf_parm*parm)
{
switch (parm->type()) {
case vvm_calltf_parm::TIME:
os << "$time";
break;
case vvm_calltf_parm::NONE:
break;
case vvm_calltf_parm::ULONG:
os << parm->as_ulong();
break;
case vvm_calltf_parm::STRING:
os << "\"" << parm->as_string() << "\"";
break;
case vvm_calltf_parm::BITS:
os << parm->sig_name();
break;
}
}
static unsigned format(vvm_simulation*sim, const string&str,
unsigned nparms,
class vvm_calltf_parm*parms)
{
char prev = 0;
unsigned next_parm = 0;
unsigned idx = 0;
while (idx < str.length()) {
if (prev == '%') {
switch (str[idx]) {
case 'b':
case 'B':
format_bit(sim, cout, parms+next_parm);
next_parm += 1;
break;
case 'x':
case 'X':
case 'h':
case 'H':
format_hex(sim, cout, parms+next_parm);
next_parm += 1;
break;
case 'd':
case 'D':
format_dec(sim, cout, parms+next_parm);
next_parm += 1;
break;
case 'm':
case 'M':
format_name(cout, parms+next_parm);
next_parm += 1;
break;
case '%':
cout << str[idx];
break;
}
prev = 0;
} else {
if (str[idx] != '%')
cout << str[idx];
else
prev = '%';
}
idx += 1;
}
return next_parm;
}
void Sdisplay(vvm_simulation*sim, const string&name,
unsigned nparms, class vvm_calltf_parm*parms)
{
for (unsigned idx = 0 ; idx < nparms ; idx += 1)
switch (parms[idx].type()) {
case vvm_calltf_parm::NONE:
cout << " ";
break;
case vvm_calltf_parm::TIME:
cout << sim->get_sim_time();
break;
case vvm_calltf_parm::ULONG:
cout << parms[idx].as_ulong();
break;
case vvm_calltf_parm::STRING:
idx += format(sim, parms[idx].as_string(),
nparms-idx-1, parms+idx+1);
break;
case vvm_calltf_parm::BITS:
cout << *parms[idx].as_bits();
break;
}
cout << endl;
}
class monitor_event : public vvm_event {
public:
monitor_event(vvm_simulation*sim,
unsigned nparms, class vvm_calltf_parm*parms)
{ sim_ = sim;
nparms_ = nparms;
parms_ = new vvm_calltf_parm[nparms];
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
parms_[idx] = parms[idx];
}
~monitor_event() { delete[]parms_; }
private:
vvm_simulation*sim_;
unsigned nparms_;
vvm_calltf_parm*parms_;
void event_function();
};
void monitor_event::event_function()
{
Sdisplay(sim_, "$display", nparms_, parms_);
}
static monitor_event*mon = 0;
void Smonitor(vvm_simulation*sim, const string&name,
unsigned nparms, class vvm_calltf_parm*parms)
{
if (mon) delete mon;
mon = new monitor_event(sim, nparms, parms);
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
if (parms[idx].type() != vvm_calltf_parm::BITS)
continue;
parms[idx].as_mon()->enable(mon);
}
}
/*
* $Log: display.cc,v $
* Revision 1.5 1999/05/31 15:46:36 steve
* Handle time in more places.
*
* Revision 1.4 1999/05/12 04:02:17 steve
* Add %x support contributed by Steve Wilson.
*
* Revision 1.3 1999/01/01 01:44:40 steve
* Proberly print vectors in binary.
*
* Revision 1.2 1998/11/10 00:48:31 steve
* Add support it vvm target for level-sensitive
* triggers (i.e. the Verilog wait).
* Fix display of $time is format strings.
*
* Revision 1.1 1998/11/09 23:44:10 steve
* Add vvm library.
*
*/

97
vvm/vpi_priv.h Normal file
View File

@ -0,0 +1,97 @@
#ifndef __vpi_priv_H
#define __vpi_priv_H
/*
* Copyright (c) 1999 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
* 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)
#ident "$Id: vpi_priv.h,v 1.1 1999/08/15 01:23:56 steve Exp $"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* This is the most basic type in the vpi implementation. A handle can
* exist to refer to most any of the supported vpi objects. The
* interpretation of the parts depends in general on the type of the
* object.
*/
struct __vpiHandle {
int type;
int subtype;
/* These are property values. */
char*full_name;
/* This pointer is used for to-one references. */
struct __vpiHandle*referent;
/* This pointer table is used for to-many refrences to
arguments, and is used by the vpiArgument iterator. */
struct __vpiHandle**arguments;
unsigned narguments;
/* These methods support the various vpi_get() functions. */
int (*get_)(int property, vpiHandle ref);
char* (*get_str_)(int property, vpiHandle ref);
/* This method is used to get a value. */
void (*get_value_)(struct __vpiHandle*expr, s_vpi_value*vp);
/* This is a value union, that reflect state or the value of a
handle. */
union {
unsigned unum;
struct vvm_bits_t*bits;
struct t_vpi_time time;
} val;
};
/* TYPE MEANINGS:
*
* vpiArgument
* This type of handle contains a single referent, the item that has
* many arguments. It is an iterator.
*
* vpiConstant
* Constant values, such as strings and numbers, are this type.
*
* vpiSysTaskCall
* This handle type represents a call to a system task. It has a
* to-many reference to argument expressions, and a to-one reference
* to a vpiUserSystf object.
*
* vpiTimeVar
* This type is a special kind of variable, that holds a time. The
* time value is a more complex structure then a single number. The
* type really seems to exist to implement the $time system variable.
*/
#ifdef __cplusplus
}
#endif
/*
* $Log: vpi_priv.h,v $
* Revision 1.1 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
*/
#endif

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vvm.h,v 1.9 1999/06/21 01:02:34 steve Exp $"
#ident "$Id: vvm.h,v 1.10 1999/08/15 01:23:56 steve Exp $"
#endif
# include <vector>
@ -235,17 +235,17 @@ class vvm_simulation {
*/
class vvm_monitor_t {
public:
vvm_monitor_t(const string&);
vvm_monitor_t(const char*);
void trigger(vvm_simulation*sim)
{ if (event_) sim->monitor_event(event_); }
const string& name() const { return name_; }
const char* name() const { return name_; }
void enable(vvm_event*e) { event_ = e; }
private:
string name_;
const char* name_;
vvm_event*event_;
private: // not implemented
@ -257,7 +257,7 @@ class vvm_monitor_t {
template <unsigned WIDTH> class vvm_signal_t : public vvm_monitor_t {
public:
vvm_signal_t(const string&n, vvm_bitset_t<WIDTH>*b)
vvm_signal_t(const char*n, vvm_bitset_t<WIDTH>*b)
: vvm_monitor_t(n), bits_(b)
{ }
@ -280,6 +280,9 @@ template <unsigned WIDTH> class vvm_signal_t : public vvm_monitor_t {
/*
* $Log: vvm.h,v $
* Revision 1.10 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
* Revision 1.9 1999/06/21 01:02:34 steve
* Add init to vvm_signal_t.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-1999 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
@ -17,153 +17,461 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vvm_calltf.cc,v 1.2 1999/05/31 15:46:36 steve Exp $"
#ident "$Id: vvm_calltf.cc,v 1.3 1999/08/15 01:23:56 steve Exp $"
#endif
# include "vvm_calltf.h"
# include <vpi_user.h>
# include "vpi_priv.h"
# include <new>
# include <iostream>
# include <assert.h>
# include <stdlib.h>
# include <stdarg.h>
# include <malloc.h>
# include <stdio.h>
# include <dlfcn.h>
vvm_calltf_parm::vvm_calltf_parm()
: type_(NONE)
{
}
# define MAX_PATHLEN 1024
vvm_calltf_parm::vvm_calltf_parm(TYPE t)
: type_(t)
{
assert((t == NONE) || (t == TIME));
}
/* This simulation pointer is used by vpi functions to get back to the
simulation. */
static vvm_simulation*vpi_sim;
void vvm_calltf_parm::release_()
{
switch (type_) {
case NONE:
case TIME:
case ULONG:
break;
case STRING:
((string*)string_)->string::~string();
break;
case BITS:
break;
}
type_ = NONE;
}
static vpiHandle vvm_vpi_cur_task;
vvm_calltf_parm& vvm_calltf_parm::operator= (unsigned long val)
{
release_();
type_ = ULONG;
ulong_ = val;
return *this;
}
vvm_calltf_parm& vvm_calltf_parm::operator= (const string&val)
{
release_();
type_ = STRING;
new (string_) string (val);
return *this;
}
vvm_calltf_parm& vvm_calltf_parm::operator= (const vvm_calltf_parm::SIG&val)
{
release_();
type_ = BITS;
bits_ = val;
return *this;
}
vvm_calltf_parm& vvm_calltf_parm::operator= (const vvm_calltf_parm&that)
{
if (this == &that)
return *this;
release_();
switch (that.type_) {
case NONE:
case TIME:
type_ = that.type_;
break;
case ULONG:
type_ = ULONG;
ulong_ = that.ulong_;
break;
case STRING:
type_ = STRING;
new (string_) string (that.as_string());
break;
case BITS:
type_ = BITS;
bits_ = that.bits_;
break;
}
return *this;
}
vvm_calltf_parm::~vvm_calltf_parm()
{
release_();
}
extern void Sdisplay(vvm_simulation*sim, const string&name,
unsigned nparms, class vvm_calltf_parm*parms);
extern void Smonitor(vvm_simulation*sim, const string&name,
unsigned nparms, class vvm_calltf_parm*parms);
static void Sfinish(vvm_simulation*sim, const string&,
unsigned, class vvm_calltf_parm*)
{
sim->s_finish();
}
static struct {
const string name;
void (*func)(vvm_simulation*, const string&,
unsigned, class vvm_calltf_parm*);
} sys_table[] = {
{ "$display", &Sdisplay },
{ "$finish", &Sfinish },
{ "$monitor", &Smonitor },
{ "", 0 }
/*
* 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;
};
void vvm_calltask(vvm_simulation*sim, const string&fname,
unsigned nparms, class vvm_calltf_parm*parms)
static struct systf_entry*systf_list = 0;
extern "C" void vpi_register_systf(const struct t_vpi_systf_data*systf)
{
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;
}
for (unsigned idx = 0 ; sys_table[idx].func ; idx += 1)
if (fname == sys_table[idx].name) {
sys_table[idx].func(sim, fname, nparms, parms);
return;
}
extern "C" void vpi_printf(const char*fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
cout << "Call " << fname << "(";
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
if (idx > 0) cout << ", ";
switch (parms[idx].type()) {
case vvm_calltf_parm::NONE:
break;
case vvm_calltf_parm::ULONG:
cout << parms[idx].as_ulong();
break;
case vvm_calltf_parm::STRING:
cout << "\"" << parms[idx].as_string() << "\"";
break;
case vvm_calltf_parm::BITS:
cout << *parms[idx].as_bits();
break;
case vvm_calltf_parm::TIME:
break;
}
extern "C" void tf_dofinish()
{
vpi_sim->s_finish();
}
extern "C" vpiHandle vpi_handle(int type, vpiHandle ref)
{
switch (type) {
case vpiSysTfCall:
return vvm_vpi_cur_task;
default:
return 0;
}
cout << ")" << endl;
}
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)
{
assert(ref->type == vpiArgument);
if (ref->val.unum >= ref->referent->narguments)
return 0;
return ref->referent->arguments[ref->val.unum++];
}
extern "C" int vpi_get(int property, vpiHandle ref)
{
if (property == vpiType)
return ref->type;
if (ref->get_ == 0)
return -1;
return (ref->get_)(property, ref);
}
extern "C" char* vpi_get_str(int property, vpiHandle ref)
{
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;
}
static void get_value_strconst(vpiHandle ref, s_vpi_value*vp)
{
switch (vp->format) {
case vpiObjTypeVal:
case vpiStringVal:
vp->value.str = ref->full_name;
vp->format = vpiStringVal;
break;
default:
vp->format = vpiSuppressVal;
break;
}
}
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;
break;
case vpiDecStrVal:
sprintf(buf, "%u", ref->val.time.low);
vp->value.str = buf;
break;
default:
vp->format = vpiSuppressVal;
vp->value.str = 0;
break;
}
}
/*
* 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)
{
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])();
}
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;
}
void vvm_make_vpi_parm(vpiHandle ref, vvm_bits_t*val)
{
memset(ref, 0, sizeof*ref);
ref->type = vpiConstant;
ref->subtype = vpiBinaryConst;
ref->full_name = "";
ref->val.bits = val;
ref->get_value_ = &get_value_bits;
}
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;
}
void vvm_calltask(vvm_simulation*sim, const string&fname,
unsigned nparms, vpiHandle*parms)
{
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;
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);
return;
}
/* 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;
}
/*
* $Log: vvm_calltf.cc,v $
* Revision 1.3 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
* Revision 1.2 1999/05/31 15:46:36 steve
* Handle time in more places.
*

View File

@ -19,69 +19,51 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vvm_calltf.h,v 1.1 1998/11/09 23:44:11 steve Exp $"
#ident "$Id: vvm_calltf.h,v 1.2 1999/08/15 01:23:56 steve Exp $"
#endif
# include "vvm.h"
# include <string>
typedef struct __vpiHandle*vpiHandle;
/*
* This function loads a vpi module by name.
*/
extern void vvm_load_vpi_module(const char*path);
/*
* The vvm_init_vpi_handle functions initialize statis VPI handles
* that may be used many places within the program.
*/
extern void vvm_init_vpi_handle(vpiHandle, vvm_bits_t*, vvm_monitor_t*);
extern void vvm_init_vpi_timevar(vpiHandle, const char*name);
/*
* The vvm_make_vpi_parm functions initialize the vpiHandles to
* represent objects suitable for use as vvm_calltask parameters.
*/
extern void vvm_make_vpi_parm(vpiHandle ref, const char*val);
extern void vvm_make_vpi_parm(vpiHandle ref, vvm_bits_t*val);
extern void vvm_make_vpi_parm(vpiHandle ref);
/*
* The vvm environment supports external calls to C++ by
* vvm_calltask. The code generator generates calls to vvm_calltask
* that corresponds to the system call in the Verilog source. The
* vvm_calltask in turn locates the function (by name) and calls the
* C++ code that implements the task.
*
* The parameters of the task are implemented as an array of
* vvm_calltf_parm objects. Each object represents a paramter from the
* source.
* vvm_calltask in turn locates the vpi implementation (by name) and
* calls the VPI that implements the task.
*/
class vvm_calltf_parm {
public:
enum TYPE { NONE, ULONG, STRING, BITS, TIME };
vvm_calltf_parm();
explicit vvm_calltf_parm(TYPE);
vvm_calltf_parm(const vvm_calltf_parm&);
~vvm_calltf_parm();
TYPE type() const { return type_; }
struct SIG {
vvm_bits_t*bits;
vvm_monitor_t*mon;
};
unsigned long as_ulong() const { return ulong_; }
string as_string() const { return *(string*)string_; }
vvm_bits_t* as_bits() const { return bits_.bits; }
vvm_monitor_t* as_mon() const { return bits_.mon; }
const string& sig_name() const { return bits_.mon->name(); }
vvm_calltf_parm& operator= (unsigned long);
vvm_calltf_parm& operator= (const string&);
vvm_calltf_parm& operator= (const SIG&);
vvm_calltf_parm& operator= (const vvm_calltf_parm&);
private:
TYPE type_;
union {
unsigned long ulong_;
char string_[sizeof(string)];
SIG bits_;
};
void release_();
};
extern void vvm_calltask(vvm_simulation*sim, const string&name,
unsigned nparms, class vvm_calltf_parm*parms);
unsigned nparms, vpiHandle*parms);
/*
* $Log: vvm_calltf.h,v $
* Revision 1.2 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*

View File

@ -17,13 +17,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT)
#ident "$Id: vvm_monitor.cc,v 1.1 1998/11/09 23:44:11 steve Exp $"
#ident "$Id: vvm_monitor.cc,v 1.2 1999/08/15 01:23:56 steve Exp $"
#endif
# include "vvm.h"
vvm_monitor_t::vvm_monitor_t(const string&n)
vvm_monitor_t::vvm_monitor_t(const char*n)
: name_(n)
{
}
@ -31,6 +31,9 @@ vvm_monitor_t::vvm_monitor_t(const string&n)
/*
* $Log: vvm_monitor.cc,v $
* Revision 1.2 1999/08/15 01:23:56 steve
* Convert vvm to implement system tasks with vpi.
*
* Revision 1.1 1998/11/09 23:44:11 steve
* Add vvm library.
*