增加pli的书和源代码
This commit is contained in:
parent
bd4cc71c66
commit
903d50d4d8
BIN
me250300_pli/The Verilog PLI Handbook.pdf
Normal file
BIN
me250300_pli/The Verilog PLI Handbook.pdf
Normal file
Binary file not shown.
12
me250300_pli/pli_socket_example_unix/Makefile
Normal file
12
me250300_pli/pli_socket_example_unix/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
TARGETS:
|
||||
cd util; make
|
||||
cd vpi; make
|
||||
cd pli; make
|
||||
|
||||
clean:
|
||||
cd util; make clean
|
||||
cd vpi; make clean
|
||||
cd pli; make clean
|
||||
rm -f lib/*
|
||||
|
||||
|
18
me250300_pli/pli_socket_example_unix/Makefile.hppa
Normal file
18
me250300_pli/pli_socket_example_unix/Makefile.hppa
Normal file
@ -0,0 +1,18 @@
|
||||
ARCHDEBUG = -g
|
||||
ARCHLIBFLAGS =
|
||||
ARCHEXT = o
|
||||
ARCHEXE =
|
||||
ARCHCFLAGS = +Z -Aa -Ae
|
||||
ARCHDEFINES =
|
||||
ARCHDYNEXT = sl
|
||||
ARCHDYNEXTL = sl
|
||||
ARCLIB = a
|
||||
ARCHDYNLD = -b
|
||||
ARCHLDFLAG = -l
|
||||
ARCHLDOUT = -o
|
||||
ARCHCCOUT = -o
|
||||
ARCHDYNLIB = -lm
|
||||
ARCHPLILIB =
|
||||
|
||||
RM = rm
|
||||
LD = ld
|
15
me250300_pli/pli_socket_example_unix/Makefile.linux
Normal file
15
me250300_pli/pli_socket_example_unix/Makefile.linux
Normal file
@ -0,0 +1,15 @@
|
||||
ARCHDEBUG = -g
|
||||
ARCHLIBFLAGS =
|
||||
ARCHEXT = o
|
||||
ARCHEXE =
|
||||
ARCHCFLAGS = -fPIC -Wall
|
||||
ARCHDEFINES =
|
||||
ARCHDYNEXT = so
|
||||
ARCHDYNEXTL = so
|
||||
ARCLIB = a
|
||||
ARCHDYNLD = -G -export-dynamic
|
||||
ARCHLDFLAG = -l
|
||||
ARCHLDOUT = -o
|
||||
ARCHCCOUT = -o
|
||||
ARCHDYNLIB = -lm
|
||||
ARCHPLILIB =
|
15
me250300_pli/pli_socket_example_unix/Makefile.sun4v
Normal file
15
me250300_pli/pli_socket_example_unix/Makefile.sun4v
Normal file
@ -0,0 +1,15 @@
|
||||
ARCHDEBUG = -g -xs
|
||||
ARCHLIBFLAGS = -lsocket -lnsl
|
||||
ARCHEXT = o
|
||||
ARCHEXE =
|
||||
ARCHCFLAGS = -KPIC
|
||||
ARCHDEFINES = -DSUN4V
|
||||
ARCHDYNEXT = so
|
||||
ARCHDYNEXTL = so
|
||||
ARCLIB = a
|
||||
ARCHDYNLD = -G
|
||||
ARCHLDFLAG = -l
|
||||
ARCHLDOUT = -o
|
||||
ARCHCCOUT = -o
|
||||
ARCHDYNLIB = -lm
|
||||
ARCHPLILIB =
|
18
me250300_pli/pli_socket_example_unix/Makefile.winnt
Normal file
18
me250300_pli/pli_socket_example_unix/Makefile.winnt
Normal file
@ -0,0 +1,18 @@
|
||||
MSD = ${MSDIR}\VC
|
||||
|
||||
ARCHDEBUG =
|
||||
ARCHLIBFLAGS = wsock32.lib kernel32.lib
|
||||
ARCHEXT = obj
|
||||
ARCHEXE = .exe
|
||||
ARCHCFLAGS = -I${MSD}\include
|
||||
ARCHDEFINES = -DWINNT
|
||||
ARCHDYNEXT = dll
|
||||
ARCHDYNEXTL = lib
|
||||
ARCLIB = a
|
||||
ARCHDYNLD = /dll /pdb:none /debug
|
||||
ARCHLDFLAG = lib
|
||||
ARCHLDOUT = /out:
|
||||
ARCHCCOUT = /Fe
|
||||
ARCHDYNLIB = /libpath:${MSD}\lib wsock32.lib kernel32.lib
|
||||
ARCHLDDYNEXT = .lib
|
||||
ARCHPLILIB = ${PLILIB}
|
67
me250300_pli/pli_socket_example_unix/README
Normal file
67
me250300_pli/pli_socket_example_unix/README
Normal file
@ -0,0 +1,67 @@
|
||||
To be able to build and run these examples you will need to set two
|
||||
environment variables, ARCH and PLIINC
|
||||
|
||||
ARCH - must be set to one of the following
|
||||
|
||||
linux for a pc running linux
|
||||
sun4v for a solaris machine
|
||||
hppa for a HP PA-RISK machine
|
||||
winnt for either Win-95/98 or WINNT
|
||||
|
||||
PLIINC - must be set to contain the path to where the different PLI
|
||||
include files are stored.
|
||||
|
||||
Windows (Win95/Win98/WinNT) need two other environment variabels set
|
||||
|
||||
MSDIR - Path to the microsoft compilier. ex D:/msdev/DevStudio
|
||||
|
||||
PLILIB - Path to the simulator's import library
|
||||
|
||||
ex:
|
||||
d:/XYZ/tools/verilog/lib/verilog.lib (VerilogXL)
|
||||
or
|
||||
d:/XYZ/tools/lib/pliinterface.lib (NC-Verilog)
|
||||
or
|
||||
...
|
||||
|
||||
|
||||
NOTE: The assumption is that you are running in something like the
|
||||
MKS corn shell and have a real make installed in you search
|
||||
path. Sorry I am a UNIX bigot at heart. Also seeing that I
|
||||
was able to make one command "make" work on four different
|
||||
platforms consistency was a good thing.
|
||||
|
||||
|
||||
To get started type:
|
||||
|
||||
make
|
||||
|
||||
This will walk down to the util directory and build the different
|
||||
common utility(s) that will be used by the different example(s). When
|
||||
the build is completed the required libraries/objects will be copied
|
||||
into the ./lib directory and the required include files into the
|
||||
directory ./include.
|
||||
|
||||
It will then walk into the different PLI example directory(s) and build
|
||||
the PLI/VPI code used by the exmple(s).
|
||||
|
||||
|
||||
At this point you can cd to the directory vpi or pli /<example> and
|
||||
read the file "README" in the given directory.
|
||||
|
||||
When you are done playing around and want to clean up you can type
|
||||
|
||||
make clean
|
||||
|
||||
from this directory. All the generated file will be removed.
|
||||
|
||||
|
||||
**********************************************************************
|
||||
All the include/Makefile/*.c/*.h files in this directory and lower
|
||||
directories are free for the taking with no restriction on their usage
|
||||
being imposed and or implied. While some testing has been done to
|
||||
make sure the basic functionality works no guarantees are being made
|
||||
either.
|
||||
|
||||
|
||||
enjoy
|
24
me250300_pli/pli_socket_example_unix/README_FIRST
Normal file
24
me250300_pli/pli_socket_example_unix/README_FIRST
Normal file
@ -0,0 +1,24 @@
|
||||
=======================================================================
|
||||
COPYRIGHTS AND OWNERSHIP AND DISCLAIMERS:
|
||||
|
||||
The electronic text files in the directory "socket_example_PC" are
|
||||
provided by David Roberts. These files are provided with no
|
||||
restrictions on usage, copying or distribution. David Roberts, and
|
||||
Sutherland HDL, Inc. shall not be liable for damage in connection
|
||||
with, or arising out of, the furnishing, performance or use of this
|
||||
information.
|
||||
|
||||
This directory contains an example of using sockets to communicate
|
||||
between a PLI application and another C program. This example was
|
||||
created by David Roberts. Stuart Sutherland and Sutherland HDL have
|
||||
no involvement in this example, beyond including the example with
|
||||
the CD which accompanies "The PLI Handbook" by Stuart Sutherland.
|
||||
|
||||
Sutherland HDL includes this example on its web site for informational
|
||||
purposes only. We hope you find the example useful in learning and
|
||||
understanding the very complex topic of the Verilog Programming
|
||||
Language Interface!
|
||||
|
||||
Stu Sutherland
|
||||
|
||||
=======================================================================
|
16
me250300_pli/pli_socket_example_unix/include/com_exp.h
Normal file
16
me250300_pli/pli_socket_example_unix/include/com_exp.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Use this to export symbols on the Windows Ports
|
||||
*/
|
||||
#ifdef WINNT
|
||||
#ifdef EXPDEF
|
||||
#define DECLSPEC __declspec(dllexport)
|
||||
#else
|
||||
#define DECLSPEC __declspec(dllimport)
|
||||
#endif
|
||||
#define DECLEXP __declspec(dllexport)
|
||||
#define DECLIMP __declspec(dllimport)
|
||||
#else
|
||||
#define DECLSPEC
|
||||
#define DECLEXP
|
||||
#define DECLIMP
|
||||
#endif
|
12
me250300_pli/pli_socket_example_unix/include/com_exp.h~
Normal file
12
me250300_pli/pli_socket_example_unix/include/com_exp.h~
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Use this to export symbols on the Windows Ports
|
||||
*/
|
||||
#ifdef WIN32
|
||||
#ifdef EXPDEF
|
||||
#define DECLSPEC __declspec(dllexport)
|
||||
#else
|
||||
#define DECLSPEC __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define DECLSPEC
|
||||
#endif
|
66
me250300_pli/pli_socket_example_unix/include/socketUtil.h
Normal file
66
me250300_pli/pli_socket_example_unix/include/socketUtil.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Make sure to import or export the library functions if we are running
|
||||
* under windows (Win95/98 or WinNT)
|
||||
*
|
||||
* HP also has a default mode where we can TAG which symbols are to be
|
||||
* exported.
|
||||
*
|
||||
* Project do the same for the HP port and remove the
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get a line of data from the socket.
|
||||
* If the arg "nb" is non 0 then do not block if there is no data.
|
||||
*/
|
||||
DECLSPEC
|
||||
char *sockGetLine(int fd, int nb);
|
||||
|
||||
/*
|
||||
* Put a line of data to the socket.
|
||||
*/
|
||||
DECLSPEC
|
||||
int sockPutLine(int fd, char *buf);
|
||||
|
||||
/*
|
||||
* Make a client socket connection to the specified port and host.
|
||||
*
|
||||
* A value of -1 will be returned if an error is detected.
|
||||
*/
|
||||
DECLSPEC
|
||||
int sockMakeClient(int port, char *host);
|
||||
|
||||
/*
|
||||
* Make server to accept a connection. If block is non zero the call will
|
||||
* block socket blocking.
|
||||
*
|
||||
* A value of -1 will be returned if an error is detected.
|
||||
*/
|
||||
DECLSPEC
|
||||
int sockMakeServer(int port, int block);
|
||||
|
||||
/*
|
||||
* Accept a connection on a socket created by sockMakeServer. If the
|
||||
* socket was created with blocking then the call will block until somebody
|
||||
* connects to the socket.
|
||||
*
|
||||
* If there was a connection was made the point to a char * will contain
|
||||
* the string identifying who made the connection.
|
||||
*
|
||||
* A value of -1 will be returned if an error is detected.
|
||||
*/
|
||||
DECLSPEC
|
||||
int sockAcceptServer(int listener, char **who);
|
||||
|
||||
/*
|
||||
* Shut a server socket down.
|
||||
*/
|
||||
DECLSPEC
|
||||
void sockCloseServer(int fd, int listener);
|
||||
|
||||
/*
|
||||
* Get the text for the last error generated from a call to the socket
|
||||
* utility.
|
||||
*/
|
||||
DECLSPEC
|
||||
char *sockGetLastError();
|
6
me250300_pli/pli_socket_example_unix/pli/Makefile
Normal file
6
me250300_pli/pli_socket_example_unix/pli/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
TARGETS:
|
||||
cd dispargs; make
|
||||
|
||||
clean:
|
||||
cd dispargs; make clean
|
||||
|
46
me250300_pli/pli_socket_example_unix/pli/dispargs/Makefile
Normal file
46
me250300_pli/pli_socket_example_unix/pli/dispargs/Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
UTILNAME = dispargs
|
||||
BASEDIR = ../..
|
||||
|
||||
include ${BASEDIR}/Makefile.${ARCH}
|
||||
|
||||
UTILLIBS =
|
||||
|
||||
INCDIRS = -I${BASEDIR}/include -I${PLIINC}
|
||||
|
||||
#DFLAGS = ${ARCHDEBUG}
|
||||
DFLAGs =
|
||||
CFLAGS = ${ARCHDEFINES} ${ARCHCFLAGS} ${DFLAGS} ${ARCHGNU} ${INCDIRS}
|
||||
|
||||
TARGETS = \
|
||||
${PLILIBS}
|
||||
|
||||
PLIOBJ = dispargs.${ARCHEXT}
|
||||
|
||||
PLILIBS = dispargs.${ARCHDYNEXT}
|
||||
|
||||
CFILES = \
|
||||
${MODEL.${ARCHEXT}=.c}
|
||||
|
||||
.c.${ARCHEXT}:
|
||||
$(CC) -c $< ${CFLAGS} ${ARCHLIBFLAGS} ${INCDIRS}
|
||||
|
||||
target: ${TARGETS}
|
||||
|
||||
dispargs.${ARCHDYNEXT}: dispargs.${ARCHEXT}
|
||||
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}dispargs.${ARCHDYNEXT} dispargs.${ARCHEXT} ${ARCHPLILIB} ${ARCHLIBFLAGS}
|
||||
|
||||
|
||||
TAGS: ${CFILES} ${HFILES}
|
||||
etags -tTa ${HFILES} ${CFILES}
|
||||
|
||||
clean:
|
||||
-$(RM) *~ TAGS *.${ARCHEXT} ${UTILNAME}.tar* *.log *.key ${TARGETS}
|
||||
|
||||
ship:
|
||||
-$(RM) ${UTILNAME}.tar.gz
|
||||
tar -cvf ${UTILNAME}.tar Makefile ${CFILES} ${HFILES}
|
||||
gzip ${UTILNAME}.tar
|
||||
|
||||
depend:
|
||||
makedepend ${INCDIRS} ${CFILES}
|
||||
# DO NOT DELETE
|
7
me250300_pli/pli_socket_example_unix/pli/dispargs/README
Normal file
7
me250300_pli/pli_socket_example_unix/pli/dispargs/README
Normal file
@ -0,0 +1,7 @@
|
||||
This example will dump all the command line arguments. It will also
|
||||
dump out the contents of any -f <file> being used.
|
||||
|
||||
|
||||
To run the test case:
|
||||
|
||||
<simulator> -f run.vc
|
93
me250300_pli/pli_socket_example_unix/pli/dispargs/dispargs.c
Normal file
93
me250300_pli/pli_socket_example_unix/pli/dispargs/dispargs.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "veriuser.h"
|
||||
#include "vxl_veriuser.h"
|
||||
#include "acc_user.h"
|
||||
|
||||
#include "com_exp.h"
|
||||
|
||||
int indent = 5;
|
||||
|
||||
static void processFileArgs(char **args)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
io_printf(" %s\n", *args++);
|
||||
|
||||
indent += 5;
|
||||
while(*args != NULL)
|
||||
{
|
||||
for (cnt=0;cnt<indent;cnt++)
|
||||
{
|
||||
io_printf(" ");
|
||||
}
|
||||
io_printf("%s", *args);
|
||||
if (strcmp("-f", *args) == 0)
|
||||
{
|
||||
args++;
|
||||
cnt++;
|
||||
processFileArgs(((char **)*args));
|
||||
}
|
||||
else
|
||||
{
|
||||
io_printf("\n");
|
||||
}
|
||||
|
||||
args++;
|
||||
}
|
||||
indent -= 5;
|
||||
}
|
||||
|
||||
static int dispArgs(int data, int reason)
|
||||
{
|
||||
int cnt;
|
||||
char **args;
|
||||
int numArgs;
|
||||
|
||||
|
||||
args = acc_fetch_argv();
|
||||
numArgs = acc_fetch_argc();
|
||||
|
||||
io_printf("Commandline args used by the simulator: %s\n", *args);
|
||||
args++;
|
||||
for (cnt=1;cnt<numArgs;cnt++)
|
||||
{
|
||||
io_printf(" %s", *(args));
|
||||
if (strcmp("-f", *args) == 0)
|
||||
{
|
||||
args++;
|
||||
cnt++;
|
||||
processFileArgs(((char **)*args));
|
||||
}
|
||||
else
|
||||
{
|
||||
io_printf("\n");
|
||||
}
|
||||
args++;
|
||||
}
|
||||
io_printf("\n\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* boot strap for
|
||||
*
|
||||
* +loadpli1=dispargs:regDispArgs
|
||||
* or
|
||||
* -loadpli1 dispargs:regDispArgs
|
||||
*
|
||||
* If using the old veriusertfs method cut and paste the first line
|
||||
* below into your veriuserts array.
|
||||
*
|
||||
*/
|
||||
static s_tfcell tfTasks[] =
|
||||
{
|
||||
{usertask, 0, NULL, NULL, dispArgs, NULL, "$dumpargs", 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
DECLEXP
|
||||
p_tfcell regDispArgs()
|
||||
{
|
||||
return(&tfTasks[0]);
|
||||
}
|
4
me250300_pli/pli_socket_example_unix/pli/dispargs/run.vc
Normal file
4
me250300_pli/pli_socket_example_unix/pli/dispargs/run.vc
Normal file
@ -0,0 +1,4 @@
|
||||
-q
|
||||
test.v
|
||||
-f test1.vc
|
||||
+loadpli1=./dispargs:regDispArgs
|
7
me250300_pli/pli_socket_example_unix/pli/dispargs/test.v
Normal file
7
me250300_pli/pli_socket_example_unix/pli/dispargs/test.v
Normal file
@ -0,0 +1,7 @@
|
||||
module top;
|
||||
wire a;
|
||||
|
||||
initial
|
||||
$dumpargs;
|
||||
|
||||
endmodule
|
@ -0,0 +1,5 @@
|
||||
+a
|
||||
+b
|
||||
+c
|
||||
+d
|
||||
-f test2.vc
|
@ -0,0 +1,3 @@
|
||||
+a2
|
||||
+b2
|
||||
+c2
|
6
me250300_pli/pli_socket_example_unix/util/Makefile
Normal file
6
me250300_pli/pli_socket_example_unix/util/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
TARGETS:
|
||||
cd socket; make; make install
|
||||
|
||||
clean:
|
||||
cd socket; make clean
|
||||
|
59
me250300_pli/pli_socket_example_unix/util/socket/Makefile
Normal file
59
me250300_pli/pli_socket_example_unix/util/socket/Makefile
Normal file
@ -0,0 +1,59 @@
|
||||
UTILNAME = socketUtil
|
||||
BASEDIR = ../..
|
||||
include ${BASEDIR}/Makefile.${ARCH}
|
||||
|
||||
INCDIRS =
|
||||
|
||||
CFLAGS = ${ARCHDEFINES} ${ARCHCFLAGS} ${ARCHDEBUG} -I${BASEDIR}/include
|
||||
|
||||
SOCKETUTIL = \
|
||||
socketUtil.${ARCHEXT}
|
||||
|
||||
SOCKETLIB = libSocketUtil.${ARCHDYNEXT}
|
||||
|
||||
SOCKETINC = socketUtil.h
|
||||
|
||||
INCS = \
|
||||
${SOCKETINC}
|
||||
|
||||
LIBS = \
|
||||
${SOCKETLIB}
|
||||
|
||||
TARGETS = \
|
||||
${LIBS}
|
||||
|
||||
CFILES = \
|
||||
${SOCKETUTIL:.${ARCHEXT}=.c}
|
||||
|
||||
HFILES = \
|
||||
socketUtil.h
|
||||
|
||||
|
||||
.c.${ARCHEXT}:
|
||||
$(CC) -c $< -o $*.${ARCHEXT} ${CFLAGS} ${ARCHLIBFLAGS} ${INCDIRS}
|
||||
|
||||
all: ${TARGETS}
|
||||
|
||||
install: ${TARGETS}
|
||||
cp ${LIBS} *.${ARCHDYNEXTL} ${BASEDIR}/lib
|
||||
cp ${INCS} ${BASEDIR}/include
|
||||
|
||||
${SOCKETLIB}: ${SOCKETUTIL}
|
||||
-$(RM) ${SOCKETLIB}
|
||||
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}${SOCKETLIB} ${SOCKETUTIL} ${ARCHLIBFLAGS}
|
||||
|
||||
TAGS: ${CFILES} ${HFILES}
|
||||
etags -tTa ${HFILES} ${CFILES}
|
||||
|
||||
clean:
|
||||
-$(RM) *~ TAGS *.${ARCHEXT} ${UTILNAME}.tar* ${TARGETS}
|
||||
|
||||
ship:
|
||||
-$(RM) ${UTILNAME}.tar.gz
|
||||
tar -cvf ${UTILNAME}.tar Makefile* ${CFILES} ${HFILES}
|
||||
gzip ${UTILNAME}.tar
|
||||
|
||||
depend:
|
||||
makedepend ${INCDIRS} ${CFILES}
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
8
me250300_pli/pli_socket_example_unix/util/socket/README
Normal file
8
me250300_pli/pli_socket_example_unix/util/socket/README
Normal file
@ -0,0 +1,8 @@
|
||||
A general purpose utility to send/receive string data from different
|
||||
machines using sockets.
|
||||
|
||||
|
||||
To do:
|
||||
|
||||
Add a mode to the utility that uses the datagram level of sockets.
|
||||
This sould be much faster the the present stream mode.
|
326
me250300_pli/pli_socket_example_unix/util/socket/socketUtil.c
Normal file
326
me250300_pli/pli_socket_example_unix/util/socket/socketUtil.c
Normal file
@ -0,0 +1,326 @@
|
||||
#define SOCKUTIL_C
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef WINNT
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#if defined(SUN4V)
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#define EXPDEF
|
||||
#include "com_exp.h"
|
||||
#include "socketUtil.h"
|
||||
#undef EXPDEF
|
||||
|
||||
static char sockErrBuffer[1024];
|
||||
static int initSocketInterface = 1; /* Initialize the socket environ if needed */
|
||||
|
||||
static int initSocket()
|
||||
{
|
||||
#ifdef WINNT
|
||||
WORD wVersionRequested;WSADATA wsaData;int err;
|
||||
wVersionRequested = MAKEWORD( 2, 0 );
|
||||
err = WSAStartup( wVersionRequested, &wsaData );
|
||||
if ( err != 0 )
|
||||
{
|
||||
/* Tell the user that we couldn't find a usable */
|
||||
/* WinSock DLL. */
|
||||
return(1);
|
||||
}
|
||||
/* Confirm that the WinSock DLL supports 2.0.*/
|
||||
/* Note that if the DLL supports versions greater */
|
||||
/* than 2.0 in addition to 2.0, it will still return */
|
||||
/* 2.0 in wVersion since that is the version we */
|
||||
/* requested. */
|
||||
#if 0
|
||||
if ( LOBYTE( wsaData.wVersion ) != 2 ||
|
||||
HIBYTE( wsaData.wVersion ) != 0 )
|
||||
{
|
||||
/* Tell the user that we couldn't find a usable */
|
||||
/* WinSock DLL. */
|
||||
WSACleanup( );
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* The WinSock DLL is acceptable. Proceed. */
|
||||
return(0);
|
||||
}
|
||||
|
||||
static struct sockaddr *mkSockAddr(unsigned int port, char *host)
|
||||
{
|
||||
static struct hostent *hp = NULL;
|
||||
static struct sockaddr_in addrIn;
|
||||
|
||||
memset(&addrIn, 0, sizeof(addrIn));
|
||||
/* If !host do not tie socket to a machine name */
|
||||
if (host)
|
||||
{
|
||||
hp = gethostbyname(host);
|
||||
if (!hp)
|
||||
{
|
||||
sprintf(&sockErrBuffer[0], "failed to aquire host info!\n");
|
||||
return(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&addrIn.sin_addr, hp->h_addr, hp->h_length);
|
||||
addrIn.sin_family = hp->h_addrtype;
|
||||
}
|
||||
}
|
||||
addrIn.sin_family = AF_INET;
|
||||
addrIn.sin_port = htons((unsigned short)port);
|
||||
return((struct sockaddr *)&addrIn);
|
||||
}
|
||||
|
||||
int sockMakeClient(int port, char *host)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr *servAddr;
|
||||
int fdCon;
|
||||
char *defaultHost = "localhost";
|
||||
|
||||
if (!host)
|
||||
host = defaultHost;
|
||||
|
||||
if (initSocketInterface)
|
||||
{
|
||||
if (initSocket())
|
||||
{
|
||||
sprintf(&sockErrBuffer[0], "Sorry could not initialize the SOCKET interfacen!\n");
|
||||
return(-1);
|
||||
}
|
||||
initSocketInterface=0;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
{
|
||||
#ifdef WINNT
|
||||
int errorCode = WSAGetLastError();
|
||||
sprintf(&sockErrBuffer[0], "ERROR code was: %d\n", errorCode);
|
||||
#endif
|
||||
sprintf(&sockErrBuffer[0], "Sorry barfed on creating a socket!\n%s\n",
|
||||
strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
servAddr = mkSockAddr(port, host);
|
||||
if (!servAddr)
|
||||
{
|
||||
return(-1); /* Unable to grab the socket */
|
||||
}
|
||||
fdCon = connect(fd, servAddr, sizeof(struct sockaddr));
|
||||
if (fdCon < 0)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
return(fd);
|
||||
}
|
||||
|
||||
int sockMakeServer(int port, int block)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr *servAddr;
|
||||
int retVal;
|
||||
|
||||
if (initSocketInterface)
|
||||
{
|
||||
if (initSocket())
|
||||
{
|
||||
sprintf(&sockErrBuffer[0], "Sorry could not initialize the SOCKET interfacen!\n");
|
||||
return(-1);
|
||||
}
|
||||
initSocketInterface=0;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
{
|
||||
#ifdef WINNT
|
||||
int errorCode = WSAGetLastError();
|
||||
sprintf(&sockErrBuffer[0], "ERROR code was: %d\n", errorCode);
|
||||
#endif
|
||||
sprintf(&sockErrBuffer[0], "Sorry barfed on creating a socket!\n%s\n",
|
||||
strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* See if we need to make in non blocking */
|
||||
if (!block)
|
||||
{
|
||||
#ifndef WINNT
|
||||
if (fcntl(fd, F_SETFL, FNDELAY))
|
||||
{
|
||||
sprintf(&sockErrBuffer[0], "blocking was requested but could be granted!\n");
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
servAddr = mkSockAddr(port, NULL);
|
||||
if (!servAddr)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
retVal = bind(fd, servAddr, sizeof(struct sockaddr));
|
||||
if (retVal != 0)
|
||||
{
|
||||
switch(errno)
|
||||
{
|
||||
case EBADF:
|
||||
sprintf(&sockErrBuffer[0], "Server: bad sockfd!\n");
|
||||
break;
|
||||
case EINVAL:
|
||||
sprintf(&sockErrBuffer[0], "Server: socket already bound!\n");
|
||||
break;
|
||||
default:
|
||||
sprintf(&sockErrBuffer[0], "Server Failed to bind to a socket: %s!\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
retVal = listen(fd, 100);
|
||||
if (retVal != 0)
|
||||
{
|
||||
sprintf(&sockErrBuffer[0], "Server Failed to listen to a socket!\n");
|
||||
return(-1);
|
||||
}
|
||||
return(fd);
|
||||
}
|
||||
|
||||
int sockAcceptServer(int listener, char **who)
|
||||
{
|
||||
struct sockaddr servAddr;
|
||||
int clientSize = sizeof(struct sockaddr);
|
||||
int fd;
|
||||
static char *buffer = NULL;
|
||||
static int bufLen = 0;
|
||||
|
||||
fd = accept(listener, &servAddr, &clientSize);
|
||||
|
||||
if (who)
|
||||
{
|
||||
*who = NULL;
|
||||
if (clientSize >=0)
|
||||
{
|
||||
/* See if we can figure out who has connected */
|
||||
if (fd >=0)
|
||||
{
|
||||
struct hostent *hs;
|
||||
hs = gethostbyaddr(
|
||||
((char *) &((struct sockaddr_in *)&servAddr)->sin_addr.s_addr),
|
||||
sizeof(long), AF_INET);
|
||||
if (hs && hs->h_name)
|
||||
{
|
||||
if ((strlen(hs->h_name)+1) > bufLen)
|
||||
{
|
||||
bufLen = strlen(hs->h_name)+1;
|
||||
buffer = malloc(bufLen);
|
||||
}
|
||||
strcpy(buffer, hs->h_name);
|
||||
*who = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return(fd);
|
||||
}
|
||||
|
||||
void sockCloseServer(int fd, int listener)
|
||||
{
|
||||
close(fd);
|
||||
close(listener);
|
||||
}
|
||||
|
||||
int sockPutLine(int fd, char *buf)
|
||||
{
|
||||
int retVal = 0;
|
||||
static int stdTestOut = -1;
|
||||
if (stdTestOut == -1)
|
||||
stdTestOut = fileno(stdout);
|
||||
if (fd == stdTestOut)
|
||||
{
|
||||
write(stdTestOut, buf, strlen(buf)+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = send(fd, buf, strlen(buf)+1, 0);
|
||||
|
||||
}
|
||||
return(retVal);
|
||||
}
|
||||
|
||||
char *sockGetLine(int fd, int nb)
|
||||
{
|
||||
static char buffer[1024];
|
||||
int cnt;
|
||||
int status;
|
||||
|
||||
fd_set readfd;
|
||||
struct timeval timeOut;
|
||||
int retVal;
|
||||
static int stdTestIn = -1;
|
||||
if (stdTestIn == -1)
|
||||
stdTestIn = fileno(stdin);
|
||||
if (fd == stdTestIn)
|
||||
{
|
||||
int len;
|
||||
fgets(&buffer[0], 1024, stdin);
|
||||
len = strlen(&buffer[0]);
|
||||
buffer[len-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nb)
|
||||
{
|
||||
/* See if there is any data available */
|
||||
FD_ZERO(&readfd);
|
||||
FD_SET(fd, &readfd);
|
||||
timeOut.tv_sec = 0;
|
||||
timeOut.tv_usec = 0;
|
||||
retVal = select(fd+1, &readfd, NULL, NULL, &timeOut);
|
||||
if (retVal == 0)
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
for (cnt=0;cnt<1024;cnt++)
|
||||
{
|
||||
status = recv(fd, &buffer[cnt], 1, 0);
|
||||
if (status < 0)
|
||||
{
|
||||
/* Most likely the socket was shut down */
|
||||
return(NULL);
|
||||
}
|
||||
if (buffer[cnt] == '\0')
|
||||
return(&buffer[0]);
|
||||
}
|
||||
}
|
||||
buffer[1023] = '\0';
|
||||
return(&buffer[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* If somebody is interested give them the text from the last
|
||||
* generated error.
|
||||
*/
|
||||
char *sockGetLastError()
|
||||
{
|
||||
return(&sockErrBuffer[0]);
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Make sure to import or export the library functions if we are running
|
||||
* under windows (Win95/98 or WinNT)
|
||||
*
|
||||
* HP also has a default mode where we can TAG which symbols are to be
|
||||
* exported.
|
||||
*
|
||||
* Project do the same for the HP port and remove the
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get a line of data from the socket.
|
||||
* If the arg "nb" is non 0 then do not block if there is no data.
|
||||
*/
|
||||
DECLSPEC
|
||||
char *sockGetLine(int fd, int nb);
|
||||
|
||||
/*
|
||||
* Put a line of data to the socket.
|
||||
*/
|
||||
DECLSPEC
|
||||
int sockPutLine(int fd, char *buf);
|
||||
|
||||
/*
|
||||
* Make a client socket connection to the specified port and host.
|
||||
*
|
||||
* A value of -1 will be returned if an error is detected.
|
||||
*/
|
||||
DECLSPEC
|
||||
int sockMakeClient(int port, char *host);
|
||||
|
||||
/*
|
||||
* Make server to accept a connection. If block is non zero the call will
|
||||
* block socket blocking.
|
||||
*
|
||||
* A value of -1 will be returned if an error is detected.
|
||||
*/
|
||||
DECLSPEC
|
||||
int sockMakeServer(int port, int block);
|
||||
|
||||
/*
|
||||
* Accept a connection on a socket created by sockMakeServer. If the
|
||||
* socket was created with blocking then the call will block until somebody
|
||||
* connects to the socket.
|
||||
*
|
||||
* If there was a connection was made the point to a char * will contain
|
||||
* the string identifying who made the connection.
|
||||
*
|
||||
* A value of -1 will be returned if an error is detected.
|
||||
*/
|
||||
DECLSPEC
|
||||
int sockAcceptServer(int listener, char **who);
|
||||
|
||||
/*
|
||||
* Shut a server socket down.
|
||||
*/
|
||||
DECLSPEC
|
||||
void sockCloseServer(int fd, int listener);
|
||||
|
||||
/*
|
||||
* Get the text for the last error generated from a call to the socket
|
||||
* utility.
|
||||
*/
|
||||
DECLSPEC
|
||||
char *sockGetLastError();
|
8
me250300_pli/pli_socket_example_unix/vpi/Makefile
Normal file
8
me250300_pli/pli_socket_example_unix/vpi/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
TARGETS:
|
||||
cd dispargs; make
|
||||
cd remmodel; make
|
||||
|
||||
clean:
|
||||
cd dispargs; make clean
|
||||
cd remmodel; make clean
|
||||
|
BIN
me250300_pli/pli_socket_example_unix/vpi/dispargs/.so
Normal file
BIN
me250300_pli/pli_socket_example_unix/vpi/dispargs/.so
Normal file
Binary file not shown.
48
me250300_pli/pli_socket_example_unix/vpi/dispargs/Makefile
Normal file
48
me250300_pli/pli_socket_example_unix/vpi/dispargs/Makefile
Normal file
@ -0,0 +1,48 @@
|
||||
UTILNAME = dispargs
|
||||
BASEDIR = ../..
|
||||
PLIINC = ../../pliinc
|
||||
|
||||
include ${BASEDIR}/Makefile.${ARCH}
|
||||
|
||||
UTILLIBS =
|
||||
|
||||
INCDIRS = -I${BASEDIR}/include -I${PLIINC}
|
||||
|
||||
DFLAGS = ${ARCHDEBUG}
|
||||
#DFLAGs =
|
||||
CFLAGS = ${ARCHDEFINES} ${ARCHCFLAGS} ${DFLAGS} ${ARCHGNU} ${INCDIRS}
|
||||
|
||||
TARGETS = \
|
||||
${PLILIBS}
|
||||
|
||||
PLIOBJ = dispargs.${ARCHEXT}
|
||||
|
||||
PLILIBS = dispargs.${ARCHDYNEXT}
|
||||
|
||||
CFILES = \
|
||||
${MODEL.${ARCHEXT}=.c}
|
||||
|
||||
.c.${ARCHEXT}:
|
||||
$(CC) -c $< ${CFLAGS} ${ARCHLIBFLAGS} ${INCDIRS}
|
||||
|
||||
target: ${TARGETS}
|
||||
|
||||
dispargs.${ARCHDYNEXT}: dispargs.${ARCHEXT}
|
||||
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}dispargs.${ARCHDYNEXT} dispargs.${ARCHEXT} ${ARCHPLILIB} ${ARCHLIBFLAGS}
|
||||
|
||||
|
||||
TAGS: ${CFILES} ${HFILES}
|
||||
etags -tTa ${HFILES} ${CFILES}
|
||||
|
||||
|
||||
clean:
|
||||
-$(RM) *~ TAGS *.${ARCHEXT} ${UTILNAME}.tar* *.log *.key ${TARGETS}
|
||||
|
||||
ship:
|
||||
-$(RM) ${UTILNAME}.tar.gz
|
||||
tar -cvf ${UTILNAME}.tar Makefile ${CFILES} ${HFILES}
|
||||
gzip ${UTILNAME}.tar
|
||||
|
||||
depend:
|
||||
makedepend ${INCDIRS} ${CFILES}
|
||||
# DO NOT DELETE
|
7
me250300_pli/pli_socket_example_unix/vpi/dispargs/README
Normal file
7
me250300_pli/pli_socket_example_unix/vpi/dispargs/README
Normal file
@ -0,0 +1,7 @@
|
||||
This example will dump all the command line arguments. It will also
|
||||
dump out the contents of any -f <file> being used.
|
||||
|
||||
|
||||
To run the test case:
|
||||
|
||||
<simulator> -f run.vc
|
96
me250300_pli/pli_socket_example_unix/vpi/dispargs/dispargs.c
Normal file
96
me250300_pli/pli_socket_example_unix/vpi/dispargs/dispargs.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vpi_user.h"
|
||||
|
||||
#include "com_exp.h"
|
||||
|
||||
int indent = 5;
|
||||
|
||||
static void processFileArgs(char **args)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
vpi_printf(" %s\n", *args++);
|
||||
|
||||
indent += 5;
|
||||
while(*args != NULL)
|
||||
{
|
||||
for (cnt=0;cnt<indent;cnt++)
|
||||
{
|
||||
vpi_printf(" ");
|
||||
}
|
||||
vpi_printf("%s", *args);
|
||||
if (strcmp("-f", *args) == 0)
|
||||
{
|
||||
args++;
|
||||
cnt++;
|
||||
processFileArgs(((char **)*args));
|
||||
}
|
||||
else
|
||||
{
|
||||
vpi_printf("\n");
|
||||
}
|
||||
|
||||
args++;
|
||||
}
|
||||
indent -= 5;
|
||||
}
|
||||
|
||||
static int dispArgs(p_cb_data cbData)
|
||||
{
|
||||
s_vpi_vlog_info vlogInfo;
|
||||
int cnt;
|
||||
char **args;
|
||||
|
||||
vpi_get_vlog_info(&vlogInfo);
|
||||
|
||||
args = vlogInfo.argv;
|
||||
vpi_printf("Commandline args used by the simulator: %s\n", *args);
|
||||
args++;
|
||||
for (cnt=1;cnt<vlogInfo.argc;cnt++)
|
||||
{
|
||||
vpi_printf(" %s", *(args));
|
||||
if (strcmp("-f", *args) == 0)
|
||||
{
|
||||
args++;
|
||||
cnt++;
|
||||
processFileArgs(((char **)*args));
|
||||
}
|
||||
else
|
||||
{
|
||||
vpi_printf("\n");
|
||||
}
|
||||
args++;
|
||||
}
|
||||
vpi_printf("\n\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* boot strap for
|
||||
*
|
||||
* +loadvpi=dispargs:regDispArgs
|
||||
* or
|
||||
* -loadvpi dispargs:regDispArgs
|
||||
*
|
||||
* If using the old vlog_start_array method add the routine regDispArgs
|
||||
* to the array.
|
||||
*
|
||||
*/
|
||||
DECLEXP
|
||||
void regDispArgs()
|
||||
{
|
||||
s_cb_data cbData;
|
||||
vpiHandle retHand;
|
||||
|
||||
cbData.reason = cbStartOfSimulation;
|
||||
cbData.time = NULL;
|
||||
cbData.value = NULL;
|
||||
cbData.user_data = NULL;
|
||||
cbData.cb_rtn = dispArgs;
|
||||
retHand = vpi_register_cb(&cbData);
|
||||
if (retHand)
|
||||
{
|
||||
vpi_free_object(retHand);
|
||||
}
|
||||
}
|
4
me250300_pli/pli_socket_example_unix/vpi/dispargs/run.vc
Normal file
4
me250300_pli/pli_socket_example_unix/vpi/dispargs/run.vc
Normal file
@ -0,0 +1,4 @@
|
||||
-q
|
||||
test.v
|
||||
-f test1.vc
|
||||
+loadvpi=dispargs:regDispArgs
|
4
me250300_pli/pli_socket_example_unix/vpi/dispargs/test.v
Normal file
4
me250300_pli/pli_socket_example_unix/vpi/dispargs/test.v
Normal file
@ -0,0 +1,4 @@
|
||||
module top;
|
||||
wire a;
|
||||
|
||||
endmodule
|
@ -0,0 +1,5 @@
|
||||
+a
|
||||
+b
|
||||
+c
|
||||
+d
|
||||
-f test2.vc
|
@ -0,0 +1,3 @@
|
||||
+a2
|
||||
+b2
|
||||
+c2
|
59
me250300_pli/pli_socket_example_unix/vpi/remmodel/Makefile
Normal file
59
me250300_pli/pli_socket_example_unix/vpi/remmodel/Makefile
Normal file
@ -0,0 +1,59 @@
|
||||
UTILNAME = dumpToServer
|
||||
BASEDIR = ../..
|
||||
PLIINC = ../../pliinc
|
||||
|
||||
include ${BASEDIR}/Makefile.${ARCH}
|
||||
|
||||
UTILLIBS = -L${BASEDIR}/lib -lSocketUtil
|
||||
|
||||
INCDIRS = -I${BASEDIR}/include -I${PLIINC}
|
||||
|
||||
DFLAGS = ${ARCHDEBUG}
|
||||
#DFLAGs =
|
||||
CFLAGS = ${ARCHDEFINES} ${ARCHCFLAGS} ${DFLAGS} ${ARCHGNU} ${INCDIRS}
|
||||
|
||||
TARGETS = \
|
||||
runModel${ARCHEXE} \
|
||||
${REMLIB}
|
||||
|
||||
MODEL = modelMain.${ARCHEXT} \
|
||||
runModel.${ARCHEXT}
|
||||
|
||||
REMOBJ = remmodel.${ARCHEXT}
|
||||
|
||||
REMLIB = librem.${ARCHDYNEXT}
|
||||
|
||||
CFILES = \
|
||||
${MODEL.${ARCHEXT}=.c}
|
||||
|
||||
.c.${ARCHEXT}:
|
||||
$(CC) -c $< ${CFLAGS} ${ARCHLIBFLAGS} ${INCDIRS}
|
||||
|
||||
target: ${TARGETS}
|
||||
|
||||
${REMLIB}: ${REMOBJ}
|
||||
-$(RM) ${REMLIB}
|
||||
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}${REMLIB} ${REMOBJ} ${BASEDIR}/lib/libSocketUtil.${ARCHDYNEXTL} ${ARCHPLILIB} ${ARCHLIBFLAGS}
|
||||
|
||||
libvpi.${ARCHDYNEXT}: ${REMOBJ} vlogmodel.${ARCHEXT}
|
||||
-$(RM) libvpi.dll
|
||||
$(LD) ${ARCHDYNLD} ${ARCHLDOUT}libvpi.${ARCHDYNEXT} ${ARCHLIBFLAGS} ${REMOBJ} vlogmodel.${ARCHEXT} ${BASEDIR}/lib/libSocketUtil.${ARCHDYNEXTL} ${ARCHPLILIB}
|
||||
|
||||
runModel${ARCHEXE}: ${MODEL}
|
||||
$(CC) ${ARCHCCOUT}$@ ${MODEL} ${BASEDIR}/lib/libSocketUtil.${ARCHDYNEXTL} ${ARCHLIBFLAGS}
|
||||
|
||||
|
||||
TAGS: ${CFILES} ${HFILES}
|
||||
etags -tTa ${HFILES} ${CFILES}
|
||||
|
||||
clean:
|
||||
-$(RM) *~ TAGS *.${ARCHEXT} ${UTILNAME}.tar* *.log *.key ${TARGETS}
|
||||
|
||||
ship:
|
||||
-$(RM) ${UTILNAME}.tar.gz
|
||||
tar -cvf ${UTILNAME}.tar Makefile ${CFILES} ${HFILES}
|
||||
gzip ${UTILNAME}.tar
|
||||
|
||||
depend:
|
||||
makedepend ${INCDIRS} ${CFILES}
|
||||
# DO NOT DELETE
|
16
me250300_pli/pli_socket_example_unix/vpi/remmodel/README
Normal file
16
me250300_pli/pli_socket_example_unix/vpi/remmodel/README
Normal file
@ -0,0 +1,16 @@
|
||||
To run this example first type make. This will build the dynamic
|
||||
library that will be used by the simulator to communicate with some
|
||||
remote simulator. It will also build an exe that is a simple stand
|
||||
alone model of a multibit latch.
|
||||
|
||||
Next to start the remote model running type:
|
||||
|
||||
runModel 5511
|
||||
|
||||
You can now start the simulator in a different window on the HDL
|
||||
file test.v by using the command file "run.vc"
|
||||
|
||||
<simulator> -f run.vc
|
||||
|
||||
|
||||
|
@ -0,0 +1,91 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef WINNT
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "com_exp.h"
|
||||
#include "socketUtil.h"
|
||||
#include "runModel.h"
|
||||
|
||||
extern char *modelWho;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *port = NULL;
|
||||
char *host = NULL;
|
||||
char *data = NULL;
|
||||
int cnt = 1;
|
||||
int fd = fileno(stdin);
|
||||
int fdOut = fileno(stdout);
|
||||
int server = -1;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
while(cnt<argc)
|
||||
{
|
||||
if (argv[cnt][0] == '-')
|
||||
{
|
||||
if (!strcmp(argv[cnt], "host"))
|
||||
{
|
||||
host = argv[cnt];
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Bad argument: %s", argv[cnt]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!port)
|
||||
{
|
||||
port = argv[cnt];
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "The port was already given!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (port)
|
||||
{
|
||||
server = sockMakeServer(atoi(port), 1);
|
||||
if (server == -1)
|
||||
{
|
||||
printf("Failed to open the desired socket: %s\n", port);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Monitoring port: %s\n", port);
|
||||
fd = sockAcceptServer(server, &modelWho);
|
||||
fdOut = fd;
|
||||
printf("Received connection from host ");
|
||||
if (modelWho)
|
||||
{
|
||||
printf("%s\n", modelWho);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("<unknown>\n");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = fileno(stdin);
|
||||
fdOut = fileno(stdout);
|
||||
}
|
||||
|
||||
|
||||
while((data = sockGetLine(fd, 0)))
|
||||
{
|
||||
runModel(fdOut, server, data);
|
||||
}
|
||||
close(fd);
|
||||
exit(0);
|
||||
}
|
550
me250300_pli/pli_socket_example_unix/vpi/remmodel/remmodel.c
Normal file
550
me250300_pli/pli_socket_example_unix/vpi/remmodel/remmodel.c
Normal file
@ -0,0 +1,550 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "veriuser.h"
|
||||
#include "vpi_user.h"
|
||||
|
||||
#include "com_exp.h"
|
||||
#include "socketUtil.h"
|
||||
|
||||
/*
|
||||
* Data structures
|
||||
*/
|
||||
typedef struct remPort {
|
||||
struct remPort *next;
|
||||
char *name;
|
||||
int changed;
|
||||
int id;
|
||||
int size;
|
||||
char *val;
|
||||
vpiHandle obj;
|
||||
vpiHandle obj2;
|
||||
struct remModel *root;
|
||||
} s_remPort, *p_remPort;
|
||||
|
||||
typedef struct remModel {
|
||||
vpiHandle inst;
|
||||
int conn;
|
||||
int connIn;
|
||||
int server;
|
||||
int numPorts;
|
||||
p_remPort in;
|
||||
p_remPort out;
|
||||
p_remPort inout;
|
||||
int synched;
|
||||
p_remPort *portArray;
|
||||
} s_remModel, *p_remModel;
|
||||
|
||||
/*
|
||||
* Utility routines
|
||||
*/
|
||||
|
||||
static void remError(char *fmt, ...)
|
||||
{
|
||||
char buffer[10048]; /* A Large buffer */
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vsprintf(&buffer[0], fmt, ap);
|
||||
|
||||
/*
|
||||
* Use tf_error() to stop things until VPI has an error interface added
|
||||
*/
|
||||
tf_error(&buffer[0]);
|
||||
va_end(ap);
|
||||
tf_dostop();
|
||||
}
|
||||
|
||||
static void *remAlloc(int size)
|
||||
{
|
||||
void *retVal;
|
||||
|
||||
assert(size>0);
|
||||
|
||||
retVal = malloc(size);
|
||||
memset(retVal, 0, size);
|
||||
return(retVal);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send data down to the remote and get a response if requested
|
||||
*/
|
||||
static char *remSendData(int conn, int expectData, char *fmt, ...)
|
||||
{
|
||||
char buffer[2048]; /* Cheap lazy large buffer....
|
||||
* Watch this if you start using large vectors or
|
||||
* something
|
||||
*/
|
||||
char *retVal = NULL;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
vsprintf(&buffer[0], fmt, ap);
|
||||
sockPutLine(conn , &buffer[0]);
|
||||
if (expectData)
|
||||
{
|
||||
retVal = sockGetLine(expectData, 0);
|
||||
}
|
||||
return(retVal);
|
||||
}
|
||||
|
||||
static void remGetOutputs(p_remModel modelStr)
|
||||
{
|
||||
char *retVal;
|
||||
static char *buffer = NULL;
|
||||
static int bufferLen = 0;
|
||||
char *tmp;
|
||||
s_vpi_value valStr;
|
||||
p_remPort *array = modelStr->portArray;
|
||||
|
||||
int len;
|
||||
int id;
|
||||
|
||||
if (modelStr->conn == -1)
|
||||
return; /* The model has become disfunctional */
|
||||
|
||||
/* Tell model all data has been sent */
|
||||
remSendData(modelStr->conn, FALSE, "done");
|
||||
|
||||
while((retVal = sockGetLine(modelStr->connIn, FALSE)))
|
||||
{
|
||||
/* See if we are done */
|
||||
if (!strcmp(retVal, "done"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
len = strlen(retVal);
|
||||
if (len+1 > bufferLen)
|
||||
{
|
||||
if (buffer)
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
bufferLen = (((len+1)+256)/256)*256; /* Some multiple of 256 */
|
||||
buffer = remAlloc(bufferLen);
|
||||
}
|
||||
strcpy(buffer, retVal);
|
||||
|
||||
/* Get the ID */
|
||||
tmp = strtok(buffer, " ");
|
||||
id = atoi(tmp);
|
||||
|
||||
/* Get the value */
|
||||
tmp = strtok(NULL, " ");
|
||||
valStr.format = vpiBinStrVal;
|
||||
valStr.value.str = tmp;
|
||||
vpi_put_value((*(array+id))->obj, &valStr, NULL, vpiNoDelay);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* run time routines
|
||||
*/
|
||||
static int remFinishSim(p_cb_data cbData)
|
||||
{
|
||||
p_remModel modelStr = (p_remModel)cbData->user_data;
|
||||
|
||||
remSendData(modelStr->conn, FALSE, "finished");
|
||||
close(modelStr->conn);
|
||||
close(modelStr->connIn);
|
||||
close(modelStr->server);
|
||||
|
||||
vpi_printf("Remote model: %s\n", vpi_get_str(vpiFullName, modelStr->inst));
|
||||
vpi_printf(" has been terminated\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int remSynch(p_cb_data cbData)
|
||||
{
|
||||
int cnt;
|
||||
p_remModel modelStr = (p_remModel)cbData->user_data;
|
||||
p_remPort *ports = modelStr->portArray;
|
||||
|
||||
modelStr->synched = FALSE;
|
||||
|
||||
/* Send over the value of all the ports that have changed value */
|
||||
for (cnt=0;cnt<modelStr->numPorts;cnt++)
|
||||
{
|
||||
if ((*(ports+cnt))->changed)
|
||||
{
|
||||
remSendData(modelStr->conn, FALSE, "set %d %d %s",
|
||||
(*(ports+cnt))->id, (*(ports+cnt))->size,
|
||||
(*(ports+cnt))->val);
|
||||
(*(ports+cnt))->changed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get any outputs from the model */
|
||||
remGetOutputs(modelStr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int remCbInput(p_cb_data cbData)
|
||||
{
|
||||
p_remPort port = (p_remPort)cbData->user_data;
|
||||
static s_vpi_time time = {vpiSimTime, 0, 0, 0.0};
|
||||
static s_cb_data synch = {cbReadWriteSynch, remSynch, NULL, &time, NULL};
|
||||
|
||||
/* Schedule a wake up at the end of the present time slice */
|
||||
if (!port->root->synched)
|
||||
{
|
||||
/*
|
||||
* Register a callback for the end of the time slice.
|
||||
* remember to free the callback handle, seeing that we will never
|
||||
* cancel the callback.
|
||||
*/
|
||||
vpiHandle hCb;
|
||||
synch.user_data = (char *)port->root;
|
||||
hCb = vpi_register_cb(&synch);
|
||||
vpi_free_object(hCb);
|
||||
port->root->synched = TRUE;
|
||||
}
|
||||
port->changed = TRUE;
|
||||
strcpy(port->val, cbData->value->value.str);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void setupRemModel(p_remModel modelStr)
|
||||
{
|
||||
s_vpi_value valStr;
|
||||
p_remPort port;
|
||||
char *retOk;
|
||||
|
||||
/*
|
||||
* Now dump the information to the remote model and synch up
|
||||
*/
|
||||
valStr.format = vpiBinStrVal;
|
||||
port = modelStr->in;
|
||||
while(port)
|
||||
{
|
||||
vpi_get_value(port->obj, &valStr);
|
||||
retOk = remSendData(modelStr->conn, modelStr->connIn,
|
||||
"init %s %d %d %s", port->name, port->size,
|
||||
port->id, valStr.value.str);
|
||||
if (strcmp(retOk, "OK") != 0)
|
||||
{
|
||||
remError("model received bad return from remote model -- %s", retOk);
|
||||
}
|
||||
port = port->next;
|
||||
}
|
||||
port = modelStr->out;
|
||||
while(port)
|
||||
{
|
||||
vpi_get_value(port->obj, &valStr);
|
||||
retOk = remSendData(modelStr->conn, modelStr->connIn, "init %s %d %d %s",
|
||||
port->name, port->size,
|
||||
port->id, valStr.value.str);
|
||||
if (strcmp(retOk, "OK") != 0)
|
||||
{
|
||||
remError("model received bad return from remote model -- %s", retOk);
|
||||
}
|
||||
port = port->next;
|
||||
}
|
||||
port = modelStr->inout;
|
||||
while(port)
|
||||
{
|
||||
vpi_get_value(port->obj, &valStr);
|
||||
retOk = remSendData(modelStr->conn, modelStr->connIn, "init %s %d %d %s",
|
||||
port->name, port->size,
|
||||
port->id, valStr.value.str);
|
||||
if (strcmp(retOk, "OK") != 0)
|
||||
{
|
||||
remError("model received bad return from remote model -- %s", retOk);
|
||||
}
|
||||
port = port->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the models interface and sync up with the remote model.
|
||||
*/
|
||||
static int remModelCall(char *data)
|
||||
{
|
||||
vpiHandle hModule, hThisTask;
|
||||
vpiHandle hPortIter, hPort;
|
||||
vpiHandle hDriverIter, hDriver;
|
||||
vpiHandle hConn, hLhs;
|
||||
vpiHandle hArgIter, hArg;
|
||||
s_vpi_value valStr;
|
||||
s_cb_data cbData;
|
||||
int cntId = 0;
|
||||
int server;
|
||||
|
||||
int portNo, portNoIn;
|
||||
char *remMachine = NULL;
|
||||
|
||||
int conn, fdOut;
|
||||
p_remModel modelStr;
|
||||
p_remPort port;
|
||||
char buffer[1024];
|
||||
|
||||
|
||||
/*
|
||||
* See if we can establish a connection to the remote model.
|
||||
*/
|
||||
hThisTask = vpi_handle(vpiSysTfCall, NULL);
|
||||
hArgIter = vpi_iterate(vpiArgument, hThisTask);
|
||||
hArg = vpi_scan(hArgIter);
|
||||
valStr.format = vpiIntVal;
|
||||
vpi_get_value(hArg, &valStr);
|
||||
portNo = valStr.value.integer;
|
||||
|
||||
hArg = vpi_scan(hArgIter);
|
||||
if (hArg)
|
||||
{
|
||||
if ((vpi_get(vpiType, hArg) == vpiConstant) &&
|
||||
(vpi_get(vpiConstType, hArg)))
|
||||
{
|
||||
valStr.format = vpiStringVal;
|
||||
vpi_get_value(hArg, &valStr);
|
||||
remMachine = valStr.value.str;
|
||||
}
|
||||
}
|
||||
|
||||
vpi_printf("Starting connection for: %s\n",
|
||||
vpi_get_str(vpiFullName, vpi_handle(vpiScope, hThisTask)));
|
||||
vpi_printf(" on port = %d\n", portNo);
|
||||
if (remMachine)
|
||||
{
|
||||
vpi_printf(" machine = %s\n", remMachine);
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we can find a port to receive input on
|
||||
*/
|
||||
server = -1;
|
||||
portNoIn = portNo;
|
||||
while(server == -1)
|
||||
{
|
||||
portNoIn++;
|
||||
server = sockMakeServer(portNoIn, 1);
|
||||
}
|
||||
|
||||
conn = sockMakeClient(portNo, remMachine);
|
||||
if (conn == -1)
|
||||
{
|
||||
|
||||
sprintf(&buffer[0],
|
||||
"Failed to make a connection to the remote model at port = %d ",
|
||||
portNo);
|
||||
if (remMachine)
|
||||
{
|
||||
strcat(&buffer[0], "machine = ");
|
||||
strcat(&buffer[0], remMachine);
|
||||
}
|
||||
strcat(&buffer[0], " \n");
|
||||
remError(&buffer[0]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Now tell the other machine where to send data back */
|
||||
sprintf(&buffer[0], "port %d", portNoIn);
|
||||
sockPutLine(conn, &buffer[0]);
|
||||
fdOut = sockAcceptServer(server, NULL);
|
||||
|
||||
|
||||
/*
|
||||
* Now start building up the main data structure.
|
||||
*/
|
||||
modelStr = remAlloc(sizeof(s_remModel));
|
||||
modelStr->conn = conn;
|
||||
modelStr->connIn = fdOut;
|
||||
modelStr->server = server;
|
||||
|
||||
/*
|
||||
* Before we do anything else lets register for simulation
|
||||
* finish so we can shut down the remote connection if needed.
|
||||
*/
|
||||
cbData.reason = cbEndOfSimulation;
|
||||
cbData.user_data = (char *)modelStr;
|
||||
cbData.time = NULL;
|
||||
cbData.value = NULL;
|
||||
cbData.obj = NULL;
|
||||
cbData.cb_rtn = remFinishSim;
|
||||
vpi_register_cb(&cbData);
|
||||
|
||||
|
||||
/*
|
||||
* Get the port data.
|
||||
*/
|
||||
hModule = vpi_handle(vpiScope, hThisTask);
|
||||
modelStr->inst = hModule;
|
||||
hPortIter = vpi_iterate(vpiPort, hModule);
|
||||
if (!hPortIter)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
/* See how many ports there are */
|
||||
while((hPort = vpi_scan(hPortIter)))
|
||||
{
|
||||
cntId++;
|
||||
}
|
||||
modelStr->numPorts = cntId;
|
||||
modelStr->portArray = remAlloc(cntId * sizeof(p_remPort *));
|
||||
hPortIter = vpi_iterate(vpiPort, hModule);
|
||||
cntId = 0;
|
||||
|
||||
valStr.format = vpiBinStrVal;
|
||||
while((hPort = vpi_scan(hPortIter)))
|
||||
{
|
||||
hConn = vpi_handle(vpiLowConn, hPort);
|
||||
if (!hConn)
|
||||
{
|
||||
/* hmmm an empty port connection */
|
||||
continue;
|
||||
}
|
||||
port = remAlloc(sizeof(s_remPort));
|
||||
port->id = cntId;
|
||||
port->root = modelStr;
|
||||
port->obj = hConn;
|
||||
port->size = vpi_get(vpiSize, hConn);
|
||||
port->val = remAlloc(port->size+1);
|
||||
port->name = strdup(vpi_get_str(vpiName, hConn));
|
||||
*(modelStr->portArray+cntId) = port;
|
||||
cntId++;
|
||||
switch(vpi_get(vpiDirection, hPort))
|
||||
{
|
||||
case vpiInput:
|
||||
port->next = modelStr->in;
|
||||
modelStr->in = port;
|
||||
cbData.reason = cbValueChange;
|
||||
cbData.user_data = (char *)port;
|
||||
cbData.time = NULL;
|
||||
cbData.value = &valStr;
|
||||
cbData.obj = hConn;
|
||||
cbData.cb_rtn = remCbInput;
|
||||
vpi_register_cb(&cbData);
|
||||
break;
|
||||
case vpiOutput:
|
||||
port->next = modelStr->out;
|
||||
modelStr->out = port;
|
||||
break;
|
||||
case vpiInout:
|
||||
port->next = modelStr->inout;
|
||||
modelStr->inout = port;
|
||||
|
||||
cbData.reason = cbValueChange;
|
||||
cbData.user_data = (char *)port;
|
||||
cbData.time = NULL;
|
||||
cbData.value = &valStr;
|
||||
cbData.obj = hConn;
|
||||
cbData.cb_rtn = remCbInput;
|
||||
vpi_register_cb(&cbData);
|
||||
|
||||
/* find the reg */
|
||||
hDriverIter = vpi_iterate(vpiContAssign, hModule);
|
||||
while((hDriver = vpi_scan(hDriverIter)))
|
||||
{
|
||||
hLhs = vpi_handle(vpiLhs, hDriver);
|
||||
if (vpi_compare_objects(hLhs, hConn))
|
||||
{
|
||||
port->obj2 = vpi_handle(vpiRhs, hDriver);
|
||||
vpi_free_object(hDriverIter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case vpiMixedIO:
|
||||
default:
|
||||
/* Should never get here */
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
setupRemModel(modelStr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the port list is consistent with remote model.
|
||||
* Walk through the ports
|
||||
* Verify that all
|
||||
* inputs are wires
|
||||
* outputs are registers
|
||||
* inouts are wires with implicit cont assign with a register
|
||||
*
|
||||
*/
|
||||
static int remModelCompile(char *data)
|
||||
{
|
||||
vpiHandle hPortIter, hPort;
|
||||
vpiHandle hModule, hThisTask;
|
||||
vpiHandle hLowConn;
|
||||
vpiHandle hArgIter, hArg;
|
||||
|
||||
hThisTask = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
hArgIter = vpi_iterate(vpiArgument, hThisTask);
|
||||
if (!hArgIter)
|
||||
{
|
||||
remError("This system task must have a socket number\n");
|
||||
return(0);
|
||||
}
|
||||
hArg = vpi_scan(hArgIter);
|
||||
if (vpi_get(vpiType, hArg))
|
||||
{
|
||||
if (vpi_get(vpiConstType, hArg) == vpiDecConst)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
hModule = vpi_handle(vpiScope, hThisTask);
|
||||
if (hModule == NULL)
|
||||
{
|
||||
remError("This system task (%s) must be executed from inside a module\n",
|
||||
vpi_get_str(vpiName, hThisTask));
|
||||
return(0);
|
||||
}
|
||||
hPortIter = vpi_iterate(vpiPort, hModule);
|
||||
if (!hPortIter)
|
||||
{
|
||||
vpi_printf("There does not appear to be any port. Nothing much is going to happen\n");
|
||||
return(0);
|
||||
}
|
||||
while((hPort = vpi_scan(hPortIter)))
|
||||
{
|
||||
hLowConn = vpi_handle(vpiLowConn, hPort);
|
||||
if (!hLowConn)
|
||||
{
|
||||
/* hmmm an empty port connection */
|
||||
continue;
|
||||
}
|
||||
switch(vpi_get(vpiDirection, hPort))
|
||||
{
|
||||
case vpiInput:
|
||||
break;
|
||||
case vpiOutput:
|
||||
break;
|
||||
case vpiInout:
|
||||
break;
|
||||
case vpiMixedIO:
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
DECLEXP
|
||||
void regRemModel()
|
||||
{
|
||||
s_vpi_systf_data systf;
|
||||
|
||||
systf.type = vpiSysTask;
|
||||
systf.sysfunctype = 0;
|
||||
systf.tfname = "$remModel";
|
||||
systf.calltf = remModelCall;
|
||||
systf.compiletf = remModelCompile;
|
||||
systf.sizetf = NULL;
|
||||
systf.user_data = NULL;
|
||||
vpi_register_systf(&systf);
|
||||
}
|
||||
|
5
me250300_pli/pli_socket_example_unix/vpi/remmodel/run.vc
Normal file
5
me250300_pli/pli_socket_example_unix/vpi/remmodel/run.vc
Normal file
@ -0,0 +1,5 @@
|
||||
-q
|
||||
+accwarn
|
||||
+loadvpi=librem:regRemModel
|
||||
test.v
|
||||
|
378
me250300_pli/pli_socket_example_unix/vpi/remmodel/runModel.c
Normal file
378
me250300_pli/pli_socket_example_unix/vpi/remmodel/runModel.c
Normal file
@ -0,0 +1,378 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <assert.h>
|
||||
#ifndef WINNT
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "com_exp.h"
|
||||
#include "socketUtil.h"
|
||||
|
||||
#define IDEN 0
|
||||
#define IDIN 1
|
||||
#define IDOUT 2
|
||||
typedef struct port {
|
||||
char *name;
|
||||
int id;
|
||||
int realId;
|
||||
int size;
|
||||
int changed;
|
||||
char *value;
|
||||
} *p_port, s_port;
|
||||
|
||||
static s_port enable = {"enable", 0, IDEN, -1, 0, NULL};
|
||||
static s_port input = {"in", 0, IDIN, -1, 0, NULL};
|
||||
static s_port output = {"out", 0, IDOUT, -1, 0, NULL};
|
||||
|
||||
static p_port portArray[3];
|
||||
static char buffer[1025];
|
||||
char *modelWho = NULL;
|
||||
|
||||
static void *modelAlloc(int size)
|
||||
{
|
||||
void *retVal;
|
||||
|
||||
assert(size>0);
|
||||
|
||||
retVal = malloc(size);
|
||||
memset(retVal, 0, size);
|
||||
return(retVal);
|
||||
}
|
||||
|
||||
static void modelError(int fd, char *fmt, ...)
|
||||
{
|
||||
char buffer[2048]; /* Cheap lazy large buffer....
|
||||
* Watch this if you start using large vectors or
|
||||
* something
|
||||
*/
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsprintf(&buffer[0], fmt, ap);
|
||||
sockPutLine(fd , &buffer[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Different routines for the different string commands the model supports
|
||||
*/
|
||||
static void process_done(int fd, int fdRet)
|
||||
{
|
||||
static out = 0;
|
||||
char *c;
|
||||
int cnt;
|
||||
|
||||
/*
|
||||
* Ok folks here is the model.
|
||||
* Yes it's very simple. So what!
|
||||
*/
|
||||
out = 0;
|
||||
if (input.changed || enable.changed)
|
||||
{
|
||||
enable.changed = 0;
|
||||
input.changed = 0;
|
||||
|
||||
/* Calculate the new output value */
|
||||
/* update the output if enable == 1 */
|
||||
if ((*enable.value == '1') || (*enable.value == 'x'))
|
||||
{
|
||||
/* If enable is and X set the output to an X (Quick and dirty) */
|
||||
if (*enable.value == 'x')
|
||||
{
|
||||
if (strcmp(output.value, input.value) != 0)
|
||||
{
|
||||
/* If the input has changed then make the output an X */
|
||||
c = output.value;
|
||||
for (cnt = 0; cnt < output.size; cnt++)
|
||||
*(c++) = 'x';
|
||||
out = 1;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp(output.value, input.value))
|
||||
{
|
||||
out = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(output.value, input.value);
|
||||
out = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (out)
|
||||
{
|
||||
sprintf(buffer, "out %s", output.value);
|
||||
if (fdRet != -1)
|
||||
{
|
||||
sockPutLine(fdRet, buffer);
|
||||
}
|
||||
out = 0;
|
||||
}
|
||||
if (fdRet != -1)
|
||||
{
|
||||
sockPutLine(fdRet, "done");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void process_init(int fd, int fdRet)
|
||||
{
|
||||
char *c;
|
||||
char *cSize, *cVal;
|
||||
char *cId;
|
||||
int id, size;
|
||||
int cnt;
|
||||
|
||||
c = strtok(NULL, " "); /* Get the name of the net */
|
||||
if ( c == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad init line - missing NAME");
|
||||
}
|
||||
|
||||
cSize = strtok(NULL, " "); /* Get the size of the net */
|
||||
if ( cSize == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad init line - missing SIZE");
|
||||
}
|
||||
cId = strtok(NULL, " "); /* Get the ID */
|
||||
if ( cId == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad init line - missing ID");
|
||||
}
|
||||
cVal = strtok(NULL, " ");
|
||||
if ( cVal == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad init line - missing VALUE");
|
||||
}
|
||||
|
||||
id = atoi(cId);
|
||||
size = atoi(cSize);
|
||||
|
||||
if ((id < 0) || (id > 2))
|
||||
{
|
||||
modelError(fdRet, "ID out of range >>> 0 - 2");
|
||||
}
|
||||
|
||||
if (!strcmp(c, "out"))
|
||||
{
|
||||
if (input.size != -1)
|
||||
{
|
||||
if (input.size != size)
|
||||
{
|
||||
modelError(fdRet, "port input must have the same size of output");
|
||||
}
|
||||
}
|
||||
portArray[id] = &output;
|
||||
}
|
||||
else if (!strcmp(c, "in"))
|
||||
{
|
||||
if (output.size != -1)
|
||||
{
|
||||
if (output.size != size)
|
||||
{
|
||||
modelError(fdRet, "port input must have the same size of output");
|
||||
}
|
||||
}
|
||||
portArray[id] = &input;
|
||||
}
|
||||
else if (!strcmp(c, "enable"))
|
||||
{
|
||||
if (size != 1)
|
||||
{
|
||||
modelError(fdRet, "Port enable can only be one bit");
|
||||
}
|
||||
portArray[id] = &enable;
|
||||
}
|
||||
else
|
||||
{
|
||||
modelError(fdRet, "Bad port name - %s", c);
|
||||
}
|
||||
|
||||
portArray[id]->id = id;
|
||||
portArray[id]->size = size;
|
||||
portArray[id]->value = modelAlloc(size + 1);
|
||||
portArray[id]->changed = 1;
|
||||
|
||||
c = portArray[id]->value;
|
||||
for (cnt=0; cnt < size; cnt++)
|
||||
*c++ = *cVal++;
|
||||
*c = '\0';
|
||||
|
||||
sockPutLine(fdRet, "OK");
|
||||
}
|
||||
|
||||
static void process_set(int fd, int fdRet)
|
||||
{
|
||||
char *cId, *cSize, *cVal;
|
||||
int size;
|
||||
int id;
|
||||
|
||||
cId = strtok(NULL, " ");
|
||||
if ( cId == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad set line - missing ID");
|
||||
}
|
||||
cSize = strtok(NULL, " ");
|
||||
if ( cSize == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad set line - missing size");
|
||||
}
|
||||
cVal = strtok(NULL, " ");
|
||||
if ( cVal == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad set line - missing value");
|
||||
}
|
||||
|
||||
id = atoi(cId);
|
||||
if ((id < 0) || (id > 2))
|
||||
{
|
||||
modelError(fdRet, "Bad id in set command - %s", cId);
|
||||
}
|
||||
size = atoi(cSize);
|
||||
if (size != portArray[id]->size)
|
||||
{
|
||||
modelError(fdRet, "Bad size in set command, does not match objects size");
|
||||
}
|
||||
|
||||
switch(portArray[id]->realId)
|
||||
{
|
||||
case IDEN:
|
||||
case IDIN:
|
||||
strcpy(portArray[id]->value, cVal);
|
||||
portArray[id]->changed = 1;
|
||||
break;
|
||||
case IDOUT:
|
||||
modelError(fdRet, "Cannot set a value to the output port");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void process_value(int fd, int fdRet)
|
||||
{
|
||||
char *cId;
|
||||
int id;
|
||||
|
||||
cId = strtok(NULL, " "); /* Get the id of the net */
|
||||
if ( cId == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad value line - missing ID");
|
||||
}
|
||||
id = atoi(cId);
|
||||
if ((id < 0) || (id > 2))
|
||||
{
|
||||
modelError(fdRet, "Bad id in set command - %s", cId);
|
||||
}
|
||||
|
||||
sockPutLine(fdRet, portArray[id]->value);
|
||||
}
|
||||
|
||||
void runModel(int fd, int fdSrv, char *data)
|
||||
{
|
||||
char *c;
|
||||
static fdRet = -1;
|
||||
|
||||
char *cId;
|
||||
|
||||
c = strtok(data, " ");
|
||||
|
||||
if (c == NULL)
|
||||
return;
|
||||
|
||||
if (*c == '\0')
|
||||
return;
|
||||
|
||||
switch(*c)
|
||||
{
|
||||
|
||||
case 'd':
|
||||
if (!strcmp(c, "done"))
|
||||
{
|
||||
process_done(fd, fdRet);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 'f':
|
||||
{
|
||||
if (!strcmp(c, "finished"))
|
||||
{
|
||||
if (fdRet > 0)
|
||||
{
|
||||
close(fdRet);
|
||||
}
|
||||
close(fd);
|
||||
if (fdSrv > 0)
|
||||
{
|
||||
close(fdSrv);
|
||||
}
|
||||
printf("Shutting down!\n");
|
||||
exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'i':
|
||||
if (!strcmp(c, "init"))
|
||||
{
|
||||
process_init(fd, fdRet);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'p':
|
||||
if (!strcmp(c, "port")) /* update an input value */
|
||||
{
|
||||
cId = strtok(NULL, " ");
|
||||
if ( cId == NULL )
|
||||
{
|
||||
modelError(fdRet, "Bad portno - missing ID");
|
||||
}
|
||||
fdRet = sockMakeClient(atoi(cId), modelWho);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 's':
|
||||
|
||||
if (!strcmp(c, "set")) /* update an input value */
|
||||
{
|
||||
process_set(fd, fdRet);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 'v':
|
||||
if (!strcmp(c, "value"))
|
||||
{
|
||||
process_value(fd, fdRet);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
modelError(fdRet, "Bad input command");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
char *runModel(int fd, int fdServ, char *data);
|
63
me250300_pli/pli_socket_example_unix/vpi/remmodel/test.v
Normal file
63
me250300_pli/pli_socket_example_unix/vpi/remmodel/test.v
Normal file
@ -0,0 +1,63 @@
|
||||
`timescale 1ns / 1ns
|
||||
|
||||
`celldefine
|
||||
module latch(out, in, enable);
|
||||
input [3:0] in;
|
||||
output [3:0] out;
|
||||
reg [3:0] out;
|
||||
wire [3:0] outW;
|
||||
input enable;
|
||||
|
||||
initial
|
||||
$remModel(5510,,out, in, enable);
|
||||
|
||||
endmodule
|
||||
`endcelldefine
|
||||
|
||||
|
||||
module test;
|
||||
reg enable;
|
||||
reg [3:0] in;
|
||||
wire [3:0] out0;
|
||||
|
||||
latch u0(out0, in, enable);
|
||||
|
||||
initial
|
||||
begin
|
||||
$timeformat(-9, 0, "ns", 6);
|
||||
$monitor("%t", $time, " enable=", enable, " in=%b", in, " out -> %b", out0);
|
||||
end
|
||||
|
||||
initial
|
||||
begin
|
||||
// #0 $stop;
|
||||
#10 enable = 0;
|
||||
in = 4'b0100;
|
||||
#10 enable = 1;
|
||||
#10 enable = 0;
|
||||
#10 enable = 1'bx;
|
||||
#10 in = 4'b1000;
|
||||
// #10 $display("Saving Simulation to file: data.1");
|
||||
// $save("data.1");
|
||||
#10 enable = 1;
|
||||
#10 enable = 1'bx;
|
||||
// #10 $display("Incremental Save data.2");
|
||||
// $save("data.2");
|
||||
#10 in = 4'b0110;
|
||||
#10 enable = 1;
|
||||
#10 enable = 0;
|
||||
#10 enable = 1'bx;
|
||||
#10 in = 4'b0001;
|
||||
// #10 $display("Incremental Save data.3");
|
||||
// $incsave("data.3");
|
||||
#10 enable = 0;
|
||||
#10 enable = 1;
|
||||
#10 enable = 0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
extern void regRemModel();
|
||||
|
||||
#ifdef WINNT
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void (*vlog_startup_routines[])() =
|
||||
{
|
||||
regRemModel,
|
||||
0
|
||||
};
|
19
me250300_pli/plibook_examples_unix/chapter.01/build_MTI.mak
Normal file
19
me250300_pli/plibook_examples_unix/chapter.01/build_MTI.mak
Normal file
@ -0,0 +1,19 @@
|
||||
#
|
||||
# NMAKE makefile to make my_pli.dll for MTI Modelsim, using VisualC++ on Windows
|
||||
#
|
||||
|
||||
MTI_INSTALL_DIR=c:\progra~1\ModelTech
|
||||
|
||||
SOURCES = \
|
||||
hello_vpi.c \
|
||||
show_value_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(MTI_INSTALL_DIR)\include -MD
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
../mti_pli.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) -EXPORT:vlog_startup_routines $(MTI_INSTALL_DIR)/win32/mtipli.lib
|
19
me250300_pli/plibook_examples_unix/chapter.01/build_NC.mak
Normal file
19
me250300_pli/plibook_examples_unix/chapter.01/build_NC.mak
Normal file
@ -0,0 +1,19 @@
|
||||
#
|
||||
# sample NMAKE makefile to make libvpi.dll for Cadence Verilog-XL, using VisualC++ on Windows
|
||||
#
|
||||
|
||||
CDS_INST_DIR=C:/progra~1/cds/
|
||||
|
||||
SOURCES = \
|
||||
hello_vpi.c \
|
||||
show_value_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
libvpi.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib
|
18
me250300_pli/plibook_examples_unix/chapter.01/build_XL.mak
Normal file
18
me250300_pli/plibook_examples_unix/chapter.01/build_XL.mak
Normal file
@ -0,0 +1,18 @@
|
||||
#
|
||||
# sample NMAKE makefile to make libvpi.dll with VisualC++ on Windows
|
||||
# see windows.txt for more details.
|
||||
#
|
||||
|
||||
SOURCES = \
|
||||
hello_vpi.c \
|
||||
show_value_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
libvpi.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib
|
@ -0,0 +1,5 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
Hello World!
|
||||
|
||||
Simulation complete via $finish(1) at time 10 NS + 0
|
20
me250300_pli/plibook_examples_unix/chapter.01/hello_test.v
Normal file
20
me250300_pli/plibook_examples_unix/chapter.01/hello_test.v
Normal file
@ -0,0 +1,20 @@
|
||||
/**********************************************************************
|
||||
* $hello example -- Verilog HDL test bench.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module test;
|
||||
|
||||
initial
|
||||
begin
|
||||
$hello;
|
||||
// #10 $stop;
|
||||
#10 $finish;
|
||||
end
|
||||
endmodule
|
||||
/**********************************************************************/
|
45
me250300_pli/plibook_examples_unix/chapter.01/hello_vpi.c
Normal file
45
me250300_pli/plibook_examples_unix/chapter.01/hello_vpi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/**********************************************************************
|
||||
* $hello example -- PLI application using VPI routines
|
||||
*
|
||||
* C source to print "Hello World" as a PLI application.
|
||||
*
|
||||
* Usage: $hello;
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_hello_calltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpi_printf("\nHello World!\n\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* $hello Registration Data
|
||||
* (add this function name to the vlog_startup_routines array)
|
||||
*********************************************************************/
|
||||
void PLIbook_hello_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.sysfunctype = 0;
|
||||
tf_data.tfname = "$hello";
|
||||
tf_data.calltf = PLIbook_hello_calltf;
|
||||
tf_data.compiletf = NULL;
|
||||
tf_data.sizetf = NULL;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
Signal test.sum has the value 1
|
||||
Signal test.co has the value 0
|
||||
Signal test.i1.n3 has the value 0
|
||||
|
||||
Simulation complete via $finish(1) at time 30 NS + 0
|
@ -0,0 +1,57 @@
|
||||
/**********************************************************************
|
||||
* $show_value example -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the $show_value PLI application on a
|
||||
* 1-bit adder modeled using gate primitives.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module test;
|
||||
reg a, b, ci, clk;
|
||||
wire sum, co;
|
||||
|
||||
addbit i1 (a, b, ci, sum, co);
|
||||
|
||||
initial
|
||||
begin
|
||||
// $monitor("At %0d: \t a=%b b=%b ci=%b sum=%b co=%b",
|
||||
// $time, a, b, ci, sum, co);
|
||||
clk = 0;
|
||||
a = 0;
|
||||
b = 0;
|
||||
ci = 0;
|
||||
#10 a = 1;
|
||||
#10 b = 1;
|
||||
|
||||
$show_value(sum);
|
||||
$show_value(co);
|
||||
$show_value(i1.n3);
|
||||
|
||||
// #10 $stop;
|
||||
#10 $finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
/*** A gate level 1 bit adder model ***/
|
||||
`timescale 1ns / 1ns
|
||||
module addbit (a, b, ci, sum, co);
|
||||
input a, b, ci;
|
||||
output sum, co;
|
||||
|
||||
wire a, b, ci, sum, co,
|
||||
n1, n2, n3;
|
||||
|
||||
xor (n1, a, b);
|
||||
xor #2 (sum, n1, ci);
|
||||
and (n2, a, b);
|
||||
and (n3, n1, ci);
|
||||
or #2 (co, n2, n3);
|
||||
|
||||
endmodule
|
||||
/**********************************************************************/
|
||||
|
117
me250300_pli/plibook_examples_unix/chapter.01/show_value_vpi.c
Normal file
117
me250300_pli/plibook_examples_unix/chapter.01/show_value_vpi.c
Normal file
@ -0,0 +1,117 @@
|
||||
/**********************************************************************
|
||||
* $show_value example -- PLI application using VPI routines
|
||||
*
|
||||
* C source to print the name and current logic value of a net.
|
||||
*
|
||||
* Usage: $show_value(<signal_name>);
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* prototypes of routines in this PLI application */
|
||||
PLI_INT32 PLIbook_ShowVal_compiletf(PLI_BYTE8 *user_data);
|
||||
PLI_INT32 PLIbook_ShowVal_calltf(PLI_BYTE8 *user_data);
|
||||
|
||||
/**********************************************************************
|
||||
* $show_value Registration Data
|
||||
* (add this function name to the vlog_startup_routines array)
|
||||
*********************************************************************/
|
||||
void PLIbook_ShowVal_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.sysfunctype = 0;
|
||||
tf_data.tfname = "$show_value";
|
||||
tf_data.calltf = PLIbook_ShowVal_calltf;
|
||||
tf_data.compiletf = PLIbook_ShowVal_compiletf;
|
||||
tf_data.sizetf = NULL;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* compiletf application
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowVal_compiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_handle, arg_iterator, arg_handle;
|
||||
PLI_INT32 arg_type;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
if (systf_handle == NULL) {
|
||||
vpi_printf("ERROR: $show_value failed to obtain systf handle\n");
|
||||
vpi_control(vpiFinish,0); /* abort simulation */
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* obtain handles to system task arguments */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_iterator == NULL) {
|
||||
vpi_printf("ERROR: $show_value requires 1 argument\n");
|
||||
vpi_control(vpiFinish,0); /* abort simulation */
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* check the type of object in system task arguments */
|
||||
arg_handle = vpi_scan(arg_iterator);
|
||||
arg_type = vpi_get(vpiType, arg_handle);
|
||||
if (arg_type != vpiNet && arg_type != vpiReg) {
|
||||
vpi_printf("ERROR: $show_value arg must be a net or reg\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
vpi_control(vpiFinish,0); /* abort simulation */
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* check that there are no more system task arguments */
|
||||
arg_handle = vpi_scan(arg_iterator);
|
||||
if (arg_handle != NULL) {
|
||||
vpi_printf("ERROR: $show_value can only have 1 argument\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
vpi_control(vpiFinish,0); /* abort simulation */
|
||||
return(0);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowVal_calltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_handle, arg_iterator, arg_handle, net_handle;
|
||||
s_vpi_value current_value;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* obtain handle to system task argument
|
||||
compiletf has already verified only 1 arg with correct type */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
net_handle = vpi_scan(arg_iterator);
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
|
||||
/* read current value */
|
||||
current_value.format = vpiBinStrVal; /* read value as a string */
|
||||
vpi_get_value(net_handle, ¤t_value);
|
||||
vpi_printf("Signal %s ", vpi_get_str(vpiFullName, net_handle));
|
||||
vpi_printf("has the value %s\n", current_value.value.str);
|
||||
return(0);
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,5 @@
|
||||
// Example Synopsys VCS PLI table to register PLI applications
|
||||
// For the book, "The Verilog PLI Handbook"
|
||||
|
||||
$hello call=PLIbook_hello_calltf data=0
|
||||
$show_value check=PLIbook_ShowVal_compiletf call=PLIbook_ShowVal_calltf data=0 acc+=read:*
|
25
me250300_pli/plibook_examples_unix/chapter.01/vpi_user.c
Normal file
25
me250300_pli/plibook_examples_unix/chapter.01/vpi_user.c
Normal file
@ -0,0 +1,25 @@
|
||||
/**********************************************************************
|
||||
* Example vpi_user.c file
|
||||
*
|
||||
* vpi_user.c file to register PLI applications using the VPI library.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#include "vpi_user.h"
|
||||
|
||||
/* prototypes of the PLI registration routines */
|
||||
extern void PLIbook_hello_register();
|
||||
extern void PLIbook_ShowVal_register();
|
||||
|
||||
void (*vlog_startup_routines[])() =
|
||||
{
|
||||
/*** add user entries here ***/
|
||||
PLIbook_hello_register,
|
||||
PLIbook_ShowVal_register,
|
||||
0 /*** final entry must be 0 ***/
|
||||
};
|
19
me250300_pli/plibook_examples_unix/chapter.02/build_MTI.mak
Normal file
19
me250300_pli/plibook_examples_unix/chapter.02/build_MTI.mak
Normal file
@ -0,0 +1,19 @@
|
||||
#
|
||||
# NMAKE makefile to make my_pli.dll for MTI Modelsim, using VisualC++ on Windows
|
||||
#
|
||||
|
||||
MTI_INSTALL_DIR=c:\progra~1\ModelTech
|
||||
|
||||
SOURCES = \
|
||||
pow_vpi.c \
|
||||
user_data_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(MTI_INSTALL_DIR)\include -MD
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
../mti_pli.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) -EXPORT:vlog_startup_routines $(MTI_INSTALL_DIR)/win32/mtipli.lib
|
19
me250300_pli/plibook_examples_unix/chapter.02/build_NC.mak
Normal file
19
me250300_pli/plibook_examples_unix/chapter.02/build_NC.mak
Normal file
@ -0,0 +1,19 @@
|
||||
#
|
||||
# sample NMAKE makefile to make libvpi.dll for Cadence Verilog-XL, using VisualC++ on Windows
|
||||
#
|
||||
|
||||
CDS_INST_DIR=C:/progra~1/cds/
|
||||
|
||||
SOURCES = \
|
||||
pow_vpi.c \
|
||||
user_data_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
libvpi.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib
|
20
me250300_pli/plibook_examples_unix/chapter.02/build_XL.mak
Normal file
20
me250300_pli/plibook_examples_unix/chapter.02/build_XL.mak
Normal file
@ -0,0 +1,20 @@
|
||||
#
|
||||
# sample NMAKE makefile to make libvpi.dll with VisualC++ on Windows
|
||||
# see windows.txt for more details.
|
||||
#
|
||||
|
||||
CDS_INST_DIR=C:/progra~1/cds/
|
||||
|
||||
SOURCES = \
|
||||
pow_vpi.c \
|
||||
user_data_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
libvpi.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib
|
@ -0,0 +1,7 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
$pow PLI application is being used.
|
||||
|
||||
$pow(2,3) returns 8
|
||||
$pow(a,b) returns 1 (a=1 b=0)
|
||||
Simulation complete via $finish(1) at time 4 NS + 0
|
41
me250300_pli/plibook_examples_unix/chapter.02/pow_test.v
Normal file
41
me250300_pli/plibook_examples_unix/chapter.02/pow_test.v
Normal file
@ -0,0 +1,41 @@
|
||||
/**********************************************************************
|
||||
* $pow example -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the $pow PLI application.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module test;
|
||||
reg [32:0] result;
|
||||
reg a, b;
|
||||
|
||||
buf i1 (c,a);
|
||||
initial
|
||||
begin
|
||||
a = 1;
|
||||
b = 0;
|
||||
/* Test $pow with invalid arguments */
|
||||
/* These invalid calls will need to be commented out to use */
|
||||
/* the valid calls to $pow in simulation */
|
||||
// #1 result = $pow;
|
||||
// #1 result = $pow();
|
||||
// #1 result = $pow(1);
|
||||
// #1 result = $pow(2,i1);
|
||||
// #1 result = $pow(1,2,3);
|
||||
|
||||
/* Test $pow with valid values */
|
||||
#1 $display("$pow(2,3) returns %d", $pow(2,3));
|
||||
#1 result = $pow(a,b);
|
||||
#1 $display("$pow(a,b) returns %d (a=%d b=%d)", result, a, b);
|
||||
// #1 $stop;
|
||||
#1 $finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
/*********************************************************************/
|
||||
|
172
me250300_pli/plibook_examples_unix/chapter.02/pow_vpi.c
Normal file
172
me250300_pli/plibook_examples_unix/chapter.02/pow_vpi.c
Normal file
@ -0,0 +1,172 @@
|
||||
/**********************************************************************
|
||||
* $pow example -- PLI application using VPI routines
|
||||
*
|
||||
* C source to calculate the result of a number to the power of an
|
||||
* exponent. The result is returned as a 32-bit integer.
|
||||
*
|
||||
* Usage: result = $pow(<base>,<exponent>);
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* prototypes of PLI application routine names */
|
||||
PLI_INT32 PLIbook_PowSizetf(PLI_BYTE8 *user_data),
|
||||
PLIbook_PowCalltf(PLI_BYTE8 *user_data),
|
||||
PLIbook_PowCompiletf(PLI_BYTE8 *user_data),
|
||||
PLIbook_PowStartOfSim(s_cb_data *callback_data);
|
||||
|
||||
/**********************************************************************
|
||||
* $pow Registration Data
|
||||
* (add this function name to the vlog_startup_routines array)
|
||||
*********************************************************************/
|
||||
void PLIbook_pow_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
s_cb_data cb_data_s;
|
||||
vpiHandle callback_handle;
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiSysFuncSized;
|
||||
tf_data.tfname = "$pow";
|
||||
tf_data.calltf = PLIbook_PowCalltf;
|
||||
tf_data.compiletf = PLIbook_PowCompiletf;
|
||||
tf_data.sizetf = PLIbook_PowSizetf;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
cb_data_s.reason = cbStartOfSimulation;
|
||||
cb_data_s.cb_rtn = PLIbook_PowStartOfSim;
|
||||
cb_data_s.obj = NULL;
|
||||
cb_data_s.time = NULL;
|
||||
cb_data_s.value = NULL;
|
||||
cb_data_s.user_data = NULL;
|
||||
callback_handle = vpi_register_cb(&cb_data_s);
|
||||
vpi_free_object(callback_handle); /* don't need callback handle */
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Sizetf application
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_PowSizetf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
return(32); /* $pow returns 32-bit values */
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* compiletf application to verify valid systf args.
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_PowCompiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_handle, arg_itr, arg_handle;
|
||||
PLI_INT32 tfarg_type;
|
||||
int err_flag = 0;
|
||||
|
||||
do { /* group all tests, so can break out of group on error */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
arg_itr = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_itr == NULL) {
|
||||
vpi_printf("ERROR: $pow requires 2 arguments; has none\n");
|
||||
err_flag = 1;
|
||||
break;
|
||||
}
|
||||
arg_handle = vpi_scan(arg_itr);
|
||||
tfarg_type = vpi_get(vpiType, arg_handle);
|
||||
if ( (tfarg_type != vpiReg) &&
|
||||
(tfarg_type != vpiIntegerVar) &&
|
||||
(tfarg_type != vpiConstant) ) {
|
||||
vpi_printf("ERROR: $pow arg1 must be number, variable or net\n");
|
||||
err_flag = 1;
|
||||
break;
|
||||
}
|
||||
arg_handle = vpi_scan(arg_itr);
|
||||
if (arg_handle == NULL) {
|
||||
vpi_printf("ERROR: $pow requires 2nd argument\n");
|
||||
err_flag = 1;
|
||||
break;
|
||||
}
|
||||
tfarg_type = vpi_get(vpiType, arg_handle);
|
||||
if ( (tfarg_type != vpiReg) &&
|
||||
(tfarg_type != vpiIntegerVar) &&
|
||||
(tfarg_type != vpiConstant) ) {
|
||||
vpi_printf("ERROR: $pow arg2 must be number, variable or net\n");
|
||||
err_flag = 1;
|
||||
break;
|
||||
}
|
||||
if (vpi_scan(arg_itr) != NULL) {
|
||||
vpi_printf("ERROR: $pow requires 2 arguments; has too many\n");
|
||||
vpi_free_object(arg_itr);
|
||||
err_flag = 1;
|
||||
break;
|
||||
}
|
||||
} while (0 == 1); /* end of test group; only executed once */
|
||||
|
||||
if (err_flag) {
|
||||
vpi_control(vpiFinish, 1); /* abort simulation */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* calltf to calculate base to power of exponent and return result.
|
||||
*********************************************************************/
|
||||
#include <math.h>
|
||||
PLI_INT32 PLIbook_PowCalltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
s_vpi_value value_s;
|
||||
vpiHandle systf_handle, arg_itr, arg_handle;
|
||||
PLI_INT32 base, exp;
|
||||
double result;
|
||||
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
arg_itr = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_itr == NULL) {
|
||||
vpi_printf("ERROR: $pow failed to obtain systf arg handles\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* read base from systf arg 1 (compiletf has already verified) */
|
||||
arg_handle = vpi_scan(arg_itr);
|
||||
value_s.format = vpiIntVal;
|
||||
vpi_get_value(arg_handle, &value_s);
|
||||
base = value_s.value.integer;
|
||||
|
||||
/* read exponent from systf arg 2 (compiletf has already verified) */
|
||||
arg_handle = vpi_scan(arg_itr);
|
||||
vpi_free_object(arg_itr); /* not calling scan until returns null */
|
||||
vpi_get_value(arg_handle, &value_s);
|
||||
exp = value_s.value.integer;
|
||||
|
||||
/* calculate result of base to power of exponent */
|
||||
result = pow( (double)base, (double)exp );
|
||||
|
||||
/* write result to simulation as return value $pow */
|
||||
value_s.value.integer = (PLI_INT32)result;
|
||||
vpi_put_value(systf_handle, &value_s, NULL, vpiNoDelay);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Start-of-simulation application
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_PowStartOfSim(s_cb_data *callback_data)
|
||||
{
|
||||
vpi_printf("\n$pow PLI application is being used.\n\n");
|
||||
return(0);
|
||||
}
|
||||
/*********************************************************************/
|
||||
|
@ -0,0 +1,75 @@
|
||||
/*********************************************************************/
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
PLI_INT32 PLIbook_GetVectorCalltf(PLI_BYTE8 *user_data),
|
||||
PLIbook_GetVectorCompiletf(PLI_BYTE8 *user_data),
|
||||
PLIbook_GetVectorSizetf(PLI_BYTE8 *user_data);
|
||||
|
||||
/**********************************************************************
|
||||
* VPI Registration Data for $test_user_data_1;
|
||||
*********************************************************************/
|
||||
void PLIbook_test_user_data_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
char *id1 = malloc(sizeof(int)); /* allocate user_data storage */
|
||||
char *id2 = malloc(sizeof(int)); /* allocate user_data storage */
|
||||
*id1 = 1;
|
||||
*id2 = 2;
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiSysFuncSized;
|
||||
tf_data.tfname = "$get_vector_bin";
|
||||
tf_data.calltf = PLIbook_GetVectorCalltf;
|
||||
tf_data.compiletf = PLIbook_GetVectorCompiletf;
|
||||
tf_data.sizetf = PLIbook_GetVectorSizetf;
|
||||
tf_data.user_data = (PLI_BYTE8 *)id1;
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiSysFuncSized;
|
||||
tf_data.tfname = "$get_vector_hex";
|
||||
tf_data.calltf = PLIbook_GetVectorCalltf;
|
||||
tf_data.compiletf = PLIbook_GetVectorCompiletf;
|
||||
tf_data.sizetf = PLIbook_GetVectorSizetf;
|
||||
tf_data.user_data = (PLI_BYTE8 *)id2;
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* sizetf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_GetVectorSizetf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpi_printf("\nIn sizetf,\tuser_data = %d\n", *user_data);
|
||||
return(8);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* compiletf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_GetVectorCompiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpi_printf("\nIn compiletf,\tuser_data = %d\n", *user_data);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* test calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_GetVectorCalltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpi_printf("\nIn calltf,\tuser_data = %d\n", *user_data);
|
||||
if (*user_data == 1) {
|
||||
vpi_printf("calltf was invoked by $get_vector_bin()\n");
|
||||
/* read test vectors as binary values */
|
||||
}
|
||||
else if (*user_data == 2) {
|
||||
vpi_printf("calltf was invoked by $get_vector_hex()\n");
|
||||
/* read test vectors as hex values */
|
||||
}
|
||||
return(0);
|
||||
}/*********************************************************************/
|
@ -0,0 +1,26 @@
|
||||
/**********************************************************************
|
||||
* $get_vector* example -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the $get_vector* PLI application.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module test;
|
||||
|
||||
reg [7:0] vector;
|
||||
|
||||
initial
|
||||
begin
|
||||
#1 vector = $get_vector_bin;
|
||||
#1 vector = $get_vector_hex;
|
||||
#1 $finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
/*********************************************************************/
|
||||
|
@ -0,0 +1,4 @@
|
||||
// Example Synopsys VCS PLI table to register PLI applications
|
||||
// For the book, "The Verilog PLI Handbook"
|
||||
|
||||
$pow call=PLIbook_PowCalltf check=PLIbook_PowCompiletf size=32 data=0
|
25
me250300_pli/plibook_examples_unix/chapter.02/vpi_user.c
Normal file
25
me250300_pli/plibook_examples_unix/chapter.02/vpi_user.c
Normal file
@ -0,0 +1,25 @@
|
||||
/**********************************************************************
|
||||
* Example vpi_user.c file
|
||||
*
|
||||
* vpi_user.c file to register PLI applications using the VPI library.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#include "vpi_user.h"
|
||||
|
||||
/* prototypes of the PLI application routines */
|
||||
extern void PLIbook_pow_register();
|
||||
extern void PLIbook_test_user_data_register();
|
||||
|
||||
void (*vlog_startup_routines[])() =
|
||||
{
|
||||
/*** add user entries here ***/
|
||||
PLIbook_pow_register,
|
||||
PLIbook_test_user_data_register,
|
||||
0 /*** final entry must be 0 ***/
|
||||
};
|
21
me250300_pli/plibook_examples_unix/chapter.03/build_MTI.mak
Normal file
21
me250300_pli/plibook_examples_unix/chapter.03/build_MTI.mak
Normal file
@ -0,0 +1,21 @@
|
||||
#
|
||||
# NMAKE makefile to make my_pli.dll for MTI Modelsim, using VisualC++ on Windows
|
||||
#
|
||||
|
||||
MTI_INSTALL_DIR=c:\progra~1\ModelTech
|
||||
|
||||
SOURCES = \
|
||||
show_all_nets_vpi.c \
|
||||
show_all_signals_1_vpi.c \
|
||||
# show_all_signals_2_vpi.c \
|
||||
# show_all_signals_3_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(MTI_INSTALL_DIR)\include -MD
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
../mti_pli.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) -EXPORT:vlog_startup_routines $(MTI_INSTALL_DIR)/win32/mtipli.lib
|
21
me250300_pli/plibook_examples_unix/chapter.03/build_NC.mak
Normal file
21
me250300_pli/plibook_examples_unix/chapter.03/build_NC.mak
Normal file
@ -0,0 +1,21 @@
|
||||
#
|
||||
# sample NMAKE makefile to make libvpi.dll for Cadence Verilog-XL, using VisualC++ on Windows
|
||||
#
|
||||
|
||||
CDS_INST_DIR=C:/progra~1/cds/
|
||||
|
||||
SOURCES = \
|
||||
show_all_nets_vpi.c \
|
||||
show_all_signals_1_vpi.c \
|
||||
# show_all_signals_2_vpi.c \
|
||||
# show_all_signals_3_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
libvpi.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib
|
22
me250300_pli/plibook_examples_unix/chapter.03/build_XL.mak
Normal file
22
me250300_pli/plibook_examples_unix/chapter.03/build_XL.mak
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# sample NMAKE makefile to make libvpi.dll with VisualC++ on Windows
|
||||
# see windows.txt for more details.
|
||||
#
|
||||
|
||||
CDS_INST_DIR=C:/progra~1/cds/
|
||||
|
||||
SOURCES = \
|
||||
show_all_nets_vpi.c \
|
||||
show_all_signals_1_vpi.c \
|
||||
# show_all_signals_2_vpi.c \
|
||||
# show_all_signals_3_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
libvpi.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib
|
@ -0,0 +1,15 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
At time 20.00, nets in module top (top):
|
||||
net results value is 10 (binary)
|
||||
|
||||
At time 30.00, nets in module top.i1 (addbit):
|
||||
net a value is 1 (binary)
|
||||
net b value is 1 (binary)
|
||||
net ci value is 0 (binary)
|
||||
net sum value is 0 (binary)
|
||||
net co value is 1 (binary)
|
||||
net n1 value is 0 (binary)
|
||||
net n2 value is 1 (binary)
|
||||
net n3 value is 0 (binary)
|
||||
Simulation complete via $finish(1) at time 40 NS + 0
|
@ -0,0 +1,50 @@
|
||||
/**********************************************************************
|
||||
* $show_all_nets example -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the $show_all_nets PLI application on a
|
||||
* 1-bit adder modeled using gate primitives.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module top;
|
||||
reg [2:0] test;
|
||||
tri [1:0] results;
|
||||
|
||||
addbit i1 (test[0], test[1], test[2], results[0], results[1]);
|
||||
|
||||
initial
|
||||
begin
|
||||
test = 3'b000;
|
||||
#10 test = 3'b011;
|
||||
|
||||
#10 $show_all_nets(top);
|
||||
#10 $show_all_nets(i1);
|
||||
|
||||
// #10 $stop;
|
||||
#10 $finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
/*** A gate level 1 bit adder model ***/
|
||||
`timescale 1ns / 1ns
|
||||
module addbit (a, b, ci, sum, co);
|
||||
input a, b, ci;
|
||||
output sum, co;
|
||||
|
||||
wire a, b, ci, sum, co,
|
||||
n1, n2, n3;
|
||||
|
||||
xor (n1, a, b);
|
||||
xor #2 (sum, n1, ci);
|
||||
and (n2, a, b);
|
||||
and (n3, n1, ci);
|
||||
or #2 (co, n2, n3);
|
||||
|
||||
endmodule
|
||||
/*********************************************************************/
|
||||
|
@ -0,0 +1,135 @@
|
||||
/**********************************************************************
|
||||
* $show_all_nets example -- PLI application using VPI routines
|
||||
*
|
||||
* C source to scan through a module and list the names of all nets in
|
||||
* the module with the current logic value.
|
||||
*
|
||||
* Usage: $show_all_nets(<module_instance>);
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* prototypes of the PLI application routines */
|
||||
PLI_INT32 PLIbook_ShowNets_compiletf(PLI_BYTE8 *user_data),
|
||||
PLIbook_ShowNets_calltf(PLI_BYTE8 *user_data);
|
||||
|
||||
/**********************************************************************
|
||||
* $show_all_nets Registration Data
|
||||
*********************************************************************/
|
||||
void PLIbook_ShowNets_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.sysfunctype = 0;
|
||||
tf_data.tfname = "$show_all_nets";
|
||||
tf_data.calltf = PLIbook_ShowNets_calltf;
|
||||
tf_data.compiletf = PLIbook_ShowNets_compiletf;
|
||||
tf_data.sizetf = NULL;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* compiletf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowNets_compiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_handle, arg_iterator, arg_handle;
|
||||
PLI_INT32 tfarg_type;
|
||||
int err_flag = 0;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* obtain handles to system task arguments */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_iterator == NULL) {
|
||||
vpi_printf("ERROR: $show_all_nets requires 1 argument\n");
|
||||
err_flag = 1;
|
||||
}
|
||||
else {
|
||||
/* check the type of object in system task arguments */
|
||||
arg_handle = vpi_scan(arg_iterator);
|
||||
tfarg_type = vpi_get(vpiType, arg_handle);
|
||||
if (tfarg_type != vpiModule) {
|
||||
vpi_printf("ERROR: $show_all_nets arg must be module instance\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
err_flag = 1;
|
||||
}
|
||||
else {
|
||||
/* check that there is only 1 system task argument */
|
||||
arg_handle = vpi_scan(arg_iterator);
|
||||
if (arg_handle != NULL) {
|
||||
vpi_printf("ERROR: $show_all_nets can only have 1 argument\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
err_flag = 1;
|
||||
} } } /* end of if-else-if-else-if sequence */
|
||||
if (err_flag) {
|
||||
vpi_control(vpiFinish, 1); /* abort simulation */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowNets_calltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
|
||||
vpiHandle systf_handle, arg_iterator, module_handle,
|
||||
net_iterator, net_handle;
|
||||
s_vpi_time current_time;
|
||||
s_vpi_value current_value;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* obtain handle to system task argument */
|
||||
/* compiletf has already verified only 1 arg with correct type */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
module_handle = vpi_scan(arg_iterator);
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
|
||||
/* read current simulation time */
|
||||
current_time.type = vpiScaledRealTime;
|
||||
vpi_get_time(systf_handle, ¤t_time);
|
||||
|
||||
vpi_printf("\nAt time %2.2f, ", current_time.real);
|
||||
vpi_printf("nets in module %s ",
|
||||
vpi_get_str(vpiFullName, module_handle));
|
||||
vpi_printf("(%s):\n", vpi_get_str(vpiDefName, module_handle));
|
||||
|
||||
/* obtain handles to nets in module and read current value */
|
||||
net_iterator = vpi_iterate(vpiNet, module_handle);
|
||||
if (net_iterator == NULL)
|
||||
vpi_printf(" no nets found in this module\n");
|
||||
else {
|
||||
current_value.format = vpiBinStrVal; /* read values as a string */
|
||||
while ( (net_handle = vpi_scan(net_iterator)) != NULL ) {
|
||||
vpi_get_value(net_handle, ¤t_value);
|
||||
vpi_printf(" net %-10s value is %s (binary)\n",
|
||||
vpi_get_str(vpiName, net_handle),
|
||||
current_value.value.str);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
/*********************************************************************/
|
||||
|
@ -0,0 +1,17 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
At time 20.00, signals in module top (top):
|
||||
net results value is 10 (binary)
|
||||
integer test value is 3 (decimal)
|
||||
real foo value is 3.14
|
||||
time bar value is f000000ac000000e
|
||||
|
||||
|
||||
At time 30.00, signals in module top.i1 (addbit):
|
||||
net a value is 1 (binary)
|
||||
net b value is 1 (binary)
|
||||
net ci value is 0 (binary)
|
||||
reg sum value is 0 (binary)
|
||||
reg co value is 1 (binary)
|
||||
|
||||
Simulation complete via $finish(1) at time 40 NS + 0
|
@ -0,0 +1,56 @@
|
||||
/**********************************************************************
|
||||
* $show_all_signals example 1 -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the $show_all_signals PLI application on
|
||||
* a 1-bit adder modeled using gate primitives.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module top;
|
||||
tri [1:0] results;
|
||||
integer test;
|
||||
real foo;
|
||||
time bar;
|
||||
|
||||
addbit i1 (test[0], test[1], test[2], results[0], results[1]);
|
||||
|
||||
initial
|
||||
begin
|
||||
test = 3'b000;
|
||||
foo = 3.14;
|
||||
bar = 0;
|
||||
bar[63:60] = 4'hF;
|
||||
bar[35:32] = 4'hA;
|
||||
bar[31:28] = 4'hC;
|
||||
bar[03:00] = 4'hE;
|
||||
|
||||
#10 test = 3'b011;
|
||||
|
||||
#10 $show_all_signals(top);
|
||||
#10 $show_all_signals(i1);
|
||||
|
||||
// #10 $stop;
|
||||
#10 $finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
/*** An RTL level 1 bit adder model ***/
|
||||
`timescale 1ns / 1ns
|
||||
module addbit (a, b, ci, sum, co);
|
||||
input a, b, ci;
|
||||
output sum, co;
|
||||
|
||||
wire a, b, ci;
|
||||
reg sum, co;
|
||||
|
||||
always @(a or b or ci)
|
||||
{co, sum} = a + b + ci;
|
||||
|
||||
endmodule
|
||||
/*********************************************************************/
|
||||
|
@ -0,0 +1,193 @@
|
||||
/**********************************************************************
|
||||
* $show_all_signals example 1 -- PLI application using VPI routines
|
||||
*
|
||||
* C source to scan through a module and list the names of all nets,
|
||||
* reg and variables in the module, with their current logic value.
|
||||
*
|
||||
* Usage: $show_all_signals(<module_instance>);
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* prototypes of the PLI application routines */
|
||||
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data),
|
||||
PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data);
|
||||
void PLIbook_PrintSignalValues(vpiHandle signal_iterator);
|
||||
|
||||
/**********************************************************************
|
||||
* $show_all_signals Registration Data
|
||||
*********************************************************************/
|
||||
void PLIbook_ShowSignals_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.sysfunctype = 0;
|
||||
tf_data.tfname = "$show_all_signals";
|
||||
tf_data.calltf = PLIbook_ShowSignals_calltf;
|
||||
tf_data.compiletf = PLIbook_ShowSignals_compiletf;
|
||||
tf_data.sizetf = NULL;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* compiletf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_handle, arg_iterator, arg_handle;
|
||||
PLI_INT32 tfarg_type;
|
||||
int err_flag = 0;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* obtain handles to system task arguments */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_iterator == NULL) {
|
||||
vpi_printf("ERROR: $show_all_signals requires 1 argument\n");
|
||||
err_flag = 1;
|
||||
}
|
||||
else {
|
||||
/* check the type of object in system task arguments */
|
||||
arg_handle = vpi_scan(arg_iterator);
|
||||
tfarg_type = vpi_get(vpiType, arg_handle);
|
||||
if (tfarg_type != vpiModule) {
|
||||
vpi_printf("ERROR: $show_all_signals arg 1");
|
||||
vpi_printf(" must be a module instance\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
err_flag = 1;
|
||||
}
|
||||
else {
|
||||
/* check that there is only 1 system task argument */
|
||||
arg_handle = vpi_scan(arg_iterator);
|
||||
if (arg_handle != NULL) {
|
||||
vpi_printf("ERROR: $show_all_signals can only have 1 argument\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
err_flag = 1;
|
||||
} } } /* end of if-else-if-else-if sequence */
|
||||
if (err_flag) {
|
||||
vpi_control(vpiFinish, 1); /* abort simulation */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
|
||||
vpiHandle systf_handle, arg_iterator, module_handle,
|
||||
signal_iterator;
|
||||
PLI_INT32 format;
|
||||
s_vpi_time current_time;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* obtain handle to system task argument
|
||||
compiletf has already verified only 1 arg with correct type */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
module_handle = vpi_scan(arg_iterator);
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
|
||||
/* read current simulation time */
|
||||
current_time.type = vpiScaledRealTime;
|
||||
vpi_get_time(systf_handle, ¤t_time);
|
||||
|
||||
vpi_printf("\nAt time %2.2f, ", current_time.real);
|
||||
vpi_printf("signals in module %s ",
|
||||
vpi_get_str(vpiFullName, module_handle));
|
||||
vpi_printf("(%s):\n", vpi_get_str(vpiDefName, module_handle));
|
||||
|
||||
/* obtain handles to nets in module and read current value */
|
||||
signal_iterator = vpi_iterate(vpiNet, module_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
|
||||
/* obtain handles to regs in module and read current value */
|
||||
signal_iterator = vpi_iterate(vpiReg, module_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
|
||||
/* obtain handles to variables in module and read current value */
|
||||
signal_iterator = vpi_iterate(vpiVariables, module_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
|
||||
vpi_printf("\n"); /* add some white space to output */
|
||||
return(0);
|
||||
}
|
||||
|
||||
void PLIbook_PrintSignalValues(vpiHandle signal_iterator)
|
||||
{
|
||||
vpiHandle signal_handle;
|
||||
PLI_INT32 signal_type;
|
||||
s_vpi_value current_value;
|
||||
|
||||
while ( (signal_handle = vpi_scan(signal_iterator)) != NULL ) {
|
||||
signal_type = vpi_get(vpiType, signal_handle);
|
||||
switch (signal_type) {
|
||||
case vpiNet:
|
||||
current_value.format = vpiBinStrVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" net %-10s value is %s (binary)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.str);
|
||||
break;
|
||||
|
||||
case vpiReg:
|
||||
current_value.format = vpiBinStrVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" reg %-10s value is %s (binary)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.str);
|
||||
break;
|
||||
|
||||
case vpiIntegerVar:
|
||||
current_value.format = vpiIntVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" integer %-10s value is %d (decimal)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.integer);
|
||||
break;
|
||||
|
||||
case vpiRealVar:
|
||||
current_value.format = vpiRealVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" real %-10s value is %0.2f\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.real);
|
||||
break;
|
||||
|
||||
case vpiTimeVar:
|
||||
current_value.format = vpiTimeVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" time %-10s value is %x%x\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.time->high,
|
||||
current_value.value.time->low);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,37 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
At time 0.00, signals in scope top.i1:
|
||||
net a value is 0 (binary)
|
||||
net b value is 0 (binary)
|
||||
net ci value is 0 (binary)
|
||||
reg sum value is 0 (binary)
|
||||
reg co value is 0 (binary)
|
||||
|
||||
|
||||
At time 10.00, signals in scope top:
|
||||
net results value is 00 (binary)
|
||||
integer test value is 0 (decimal)
|
||||
real foo value is 3.14
|
||||
time bar value is f000000ac000000e
|
||||
|
||||
|
||||
At time 20.00, signals in scope top.i1:
|
||||
net a value is 0 (binary)
|
||||
net b value is 1 (binary)
|
||||
net ci value is 0 (binary)
|
||||
reg sum value is 1 (binary)
|
||||
reg co value is 0 (binary)
|
||||
|
||||
|
||||
At time 30.00, signals in scope top.local:
|
||||
reg foobar value is x (binary)
|
||||
|
||||
|
||||
At time 40.00, signals in scope top.i1:
|
||||
net a value is 0 (binary)
|
||||
net b value is 1 (binary)
|
||||
net ci value is 0 (binary)
|
||||
reg sum value is 1 (binary)
|
||||
reg co value is 0 (binary)
|
||||
|
||||
Simulation complete via $finish(1) at time 50 NS + 0
|
@ -0,0 +1,61 @@
|
||||
/**********************************************************************
|
||||
* $show_all_signals example 2 -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the $show_all_signals PLI application on
|
||||
* a 1-bit adder modeled using gate primitives.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module top;
|
||||
tri [1:0] results;
|
||||
integer test;
|
||||
real foo;
|
||||
time bar;
|
||||
|
||||
addbit i1 (test[0], test[1], test[2], results[0], results[1]);
|
||||
|
||||
initial
|
||||
begin
|
||||
test = 3'b000;
|
||||
foo = 3.14;
|
||||
bar = 0;
|
||||
bar[63:60] = 4'hF;
|
||||
bar[35:32] = 4'hA;
|
||||
bar[31:28] = 4'hC;
|
||||
bar[03:00] = 4'hE;
|
||||
#10 $show_all_signals;
|
||||
begin: local
|
||||
reg foobar;
|
||||
#10 test = 3'b010;
|
||||
#10 $show_all_signals;
|
||||
#10 $show_all_signals(top.i1);
|
||||
end
|
||||
// #10 $stop;
|
||||
#10 $finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
||||
/*** An RTL level 1 bit adder model ***/
|
||||
`timescale 1ns / 1ns
|
||||
module addbit (a, b, ci, sum, co);
|
||||
input a, b, ci;
|
||||
output sum, co;
|
||||
|
||||
wire a, b, ci;
|
||||
reg sum, co;
|
||||
|
||||
always @(a or b or ci)
|
||||
{co, sum} = a + b + ci;
|
||||
|
||||
always @(sum)
|
||||
$show_all_signals();
|
||||
|
||||
endmodule
|
||||
/*********************************************************************/
|
||||
|
@ -0,0 +1,217 @@
|
||||
/**********************************************************************
|
||||
* $show_all_signals example 2 -- PLI application using VPI routines
|
||||
*
|
||||
* C source to scan through a scope and list the names of all nets,
|
||||
* reg and variables in the scope, with their current logic value.
|
||||
* - No argument or a null argument to $show_all_signals() is
|
||||
* interpreted as the scope instance that called the application.
|
||||
*
|
||||
* Usage: $show_all_signals(<scope_instance>);
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* prototypes of the PLI application routines */
|
||||
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data),
|
||||
PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data);
|
||||
void PLIbook_PrintSignalValues(vpiHandle signal_iterator);
|
||||
|
||||
/**********************************************************************
|
||||
* $show_all_signals Registration Data
|
||||
*********************************************************************/
|
||||
void PLIbook_ShowSignals_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.sysfunctype = 0;
|
||||
tf_data.tfname = "$show_all_signals";
|
||||
tf_data.calltf = PLIbook_ShowSignals_calltf;
|
||||
tf_data.compiletf = PLIbook_ShowSignals_compiletf;
|
||||
tf_data.sizetf = NULL;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* compiletf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_handle, arg_iterator, arg_handle;
|
||||
PLI_INT32 tfarg_type;
|
||||
int err_flag = 0;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* obtain handles to system task arguments */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_iterator == NULL) {
|
||||
return(0); /* no arguments OK; skip remaining checks */
|
||||
}
|
||||
|
||||
/* check the type of object in system task arguments */
|
||||
arg_handle = vpi_scan(arg_iterator);
|
||||
tfarg_type = vpi_get(vpiType, arg_handle);
|
||||
switch (tfarg_type) {
|
||||
case vpiModule:
|
||||
case vpiTask:
|
||||
case vpiFunction:
|
||||
case vpiNamedBegin:
|
||||
case vpiNamedFork:
|
||||
break; /* arg is a scope instance; continue to next check */
|
||||
case vpiOperation:
|
||||
if (vpi_get(vpiOpType, arg_handle) == vpiNullOp)
|
||||
break; /* null argument OK; continue to next check */
|
||||
default:
|
||||
/* wrong type specified for an argument */
|
||||
vpi_printf("ERROR: $show_all_signals arg 1");
|
||||
vpi_printf(" must be a scope instance or null\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
err_flag = 1;
|
||||
}
|
||||
if (err_flag == 0) {
|
||||
/* check that there is only 1 system task argument */
|
||||
arg_handle = vpi_scan(arg_iterator);
|
||||
if (arg_handle != NULL) {
|
||||
vpi_printf("ERROR: $show_all_signals can only have 1 argument\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
err_flag = 1;
|
||||
} } /* end of tests */
|
||||
if (err_flag) {
|
||||
vpi_control(vpiFinish, 1); /* abort simulation */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
|
||||
vpiHandle systf_handle, arg_iterator, scope_handle,
|
||||
signal_iterator;
|
||||
PLI_INT32 format;
|
||||
s_vpi_time current_time;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* obtain handle to system task argument */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_iterator == NULL) {
|
||||
/* no arguments -- use scope that called this application */
|
||||
scope_handle = vpi_handle(vpiScope, systf_handle);
|
||||
}
|
||||
else {
|
||||
/* compiletf has already verified arg is scope instance or null */
|
||||
scope_handle = vpi_scan(arg_iterator);
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
if (vpi_get(vpiType, scope_handle) != vpiModule)
|
||||
/* arg isn't a module instance; assume it is null */
|
||||
scope_handle = vpi_handle(vpiScope, systf_handle);
|
||||
}
|
||||
|
||||
/* read current simulation time */
|
||||
current_time.type = vpiScaledRealTime;
|
||||
vpi_get_time(systf_handle, ¤t_time);
|
||||
|
||||
vpi_printf("\nAt time %2.2f, signals in scope %s:\n",
|
||||
current_time.real,
|
||||
vpi_get_str(vpiFullName, scope_handle));
|
||||
|
||||
/* obtain handles to nets in module and read current value */
|
||||
/* nets can only exist if scope is a module */
|
||||
if (vpi_get(vpiType, scope_handle) == vpiModule) {
|
||||
signal_iterator = vpi_iterate(vpiNet, scope_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
}
|
||||
|
||||
/* obtain handles to regs in scope and read current value */
|
||||
signal_iterator = vpi_iterate(vpiReg, scope_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
|
||||
/* obtain handles to variables in scope and read current value */
|
||||
signal_iterator = vpi_iterate(vpiVariables, scope_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
|
||||
vpi_printf("\n"); /* add some white space to output */
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
void PLIbook_PrintSignalValues(vpiHandle signal_iterator)
|
||||
{
|
||||
vpiHandle signal_handle;
|
||||
int signal_type;
|
||||
s_vpi_value current_value;
|
||||
|
||||
while ( (signal_handle = vpi_scan(signal_iterator)) != NULL ) {
|
||||
signal_type = vpi_get(vpiType, signal_handle);
|
||||
switch (signal_type) {
|
||||
case vpiNet:
|
||||
current_value.format = vpiBinStrVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" net %-10s value is %s (binary)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.str);
|
||||
break;
|
||||
|
||||
case vpiReg:
|
||||
current_value.format = vpiBinStrVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" reg %-10s value is %s (binary)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.str);
|
||||
break;
|
||||
|
||||
case vpiIntegerVar:
|
||||
current_value.format = vpiIntVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" integer %-10s value is %d (decimal)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.integer);
|
||||
break;
|
||||
|
||||
case vpiRealVar:
|
||||
current_value.format = vpiRealVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" real %-10s value is %0.2f\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.real);
|
||||
break;
|
||||
|
||||
case vpiTimeVar:
|
||||
current_value.format = vpiTimeVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" time %-10s value is %x%x\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.time->high,
|
||||
current_value.value.time->low);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,36 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
At time 0.00, signals in scope top.i1 (addbit):
|
||||
net a value is 0 (binary)
|
||||
net b value is 0 (binary)
|
||||
net ci value is 0 (binary)
|
||||
reg sum value is 0 (binary)
|
||||
reg co value is 0 (binary)
|
||||
|
||||
|
||||
At time 10.00, signals in scope top.i1 (addbit):
|
||||
net a value is 1 (binary)
|
||||
net b value is 0 (binary)
|
||||
net ci value is 0 (binary)
|
||||
reg sum value is 1 (binary)
|
||||
reg co value is 0 (binary)
|
||||
|
||||
|
||||
At time 20.00, signals in scope top.i1 (addbit):
|
||||
net a value is 1 (binary)
|
||||
net b value is 0 (binary)
|
||||
net ci value is 0 (binary)
|
||||
reg sum value is 1 (binary)
|
||||
reg co value is 0 (binary)
|
||||
|
||||
|
||||
At time 20.00, signals in scope top (top):
|
||||
net results value is 01 (binary)
|
||||
integer test value is 1 (decimal)
|
||||
|
||||
|
||||
At time 20.00, signals in scope top (top):
|
||||
net results value is 01 (binary)
|
||||
integer test value is 1 (decimal)
|
||||
|
||||
Simulation complete via $finish(1) at time 30 NS + 0
|
@ -0,0 +1,49 @@
|
||||
/**********************************************************************
|
||||
* $show_all_signals example 3 -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the $show_all_signals PLI application on
|
||||
* a 1-bit adder modeled using gate primitives.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module top;
|
||||
integer test;
|
||||
tri [1:0] results;
|
||||
|
||||
addbit i1 (test[0], test[1], test[2], results[0], results[1]);
|
||||
|
||||
initial
|
||||
begin
|
||||
test = 3'b000;
|
||||
#10 test = 3'b001;
|
||||
|
||||
#10 $show_all_signals(top.i1, ,top); /* second arg is null */
|
||||
|
||||
// #10 $stop;
|
||||
#10 $finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
/*** An RTL level 1 bit adder model ***/
|
||||
`timescale 1ns / 1ns
|
||||
module addbit (a, b, ci, sum, co);
|
||||
input a, b, ci;
|
||||
output sum, co;
|
||||
|
||||
wire a, b, ci;
|
||||
reg sum, co;
|
||||
|
||||
always @(a or b or ci)
|
||||
{co, sum} = a + b + ci;
|
||||
|
||||
always @(sum)
|
||||
$show_all_signals;
|
||||
|
||||
endmodule
|
||||
/*********************************************************************/
|
||||
|
@ -0,0 +1,226 @@
|
||||
/**********************************************************************
|
||||
* $show_all_signals example 3 -- PLI application using VPI routines
|
||||
*
|
||||
* C source to scan through a scope and list the names of all nets,
|
||||
* reg and variables in the scope, with their current logic value.
|
||||
* - No argument or a null argument to $show_all_signals() is
|
||||
* interpreted as the scope instance that called the application.
|
||||
* - Any number of scope instances can be passed to
|
||||
* $show_all_instances().
|
||||
*
|
||||
* Usage: $show_all_signals(<scope_instance>, <scope_instance>, ...);
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* prototypes of the PLI application routines */
|
||||
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data),
|
||||
PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data);
|
||||
void PLIbook_GetAllSignals(vpiHandle scope_handle,
|
||||
p_vpi_time current_time),
|
||||
PLIbook_PrintSignalValues(vpiHandle signal_iterator);
|
||||
|
||||
/**********************************************************************
|
||||
* $show_all_signals Registration Data
|
||||
*********************************************************************/
|
||||
void PLIbook_ShowSignals_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.sysfunctype = 0;
|
||||
tf_data.tfname = "$show_all_signals";
|
||||
tf_data.calltf = PLIbook_ShowSignals_calltf;
|
||||
tf_data.compiletf = PLIbook_ShowSignals_compiletf;
|
||||
tf_data.sizetf = NULL;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* compiletf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowSignals_compiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_handle, arg_iterator, arg_handle;
|
||||
PLI_INT32 tfarg_type;
|
||||
int err_flag = 0, tfarg_num = 0;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* obtain handles to system task arguments */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_iterator == NULL) {
|
||||
return(0); /* no arguments OK; skip remaining checks */
|
||||
}
|
||||
|
||||
/* check each argument */
|
||||
while ( (arg_handle = vpi_scan(arg_iterator)) != NULL ) {
|
||||
tfarg_num++;
|
||||
|
||||
/* check the type of object in system task arguments */
|
||||
tfarg_type = vpi_get(vpiType, arg_handle);
|
||||
switch (tfarg_type) {
|
||||
case vpiModule:
|
||||
case vpiTask:
|
||||
case vpiFunction:
|
||||
case vpiNamedBegin:
|
||||
case vpiNamedFork:
|
||||
break; /* arg is a scope instance; continue to next check */
|
||||
case vpiOperation:
|
||||
if (vpi_get(vpiOpType, arg_handle) == vpiNullOp) {
|
||||
break; /* null argument OK; continue to next check */
|
||||
}
|
||||
default:
|
||||
/* wrong type specified for an argument */
|
||||
vpi_printf("ERROR: $show_all_signals arg %d", tfarg_num);
|
||||
vpi_printf(" must be a scope instance or null\n");
|
||||
vpi_free_object(arg_iterator); /* free iterator memory */
|
||||
err_flag = 1;
|
||||
}
|
||||
} /* end of tests */
|
||||
if (err_flag) {
|
||||
vpi_control(vpiFinish, 1); /* abort simulation */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_ShowSignals_calltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
|
||||
vpiHandle systf_handle, arg_iterator, scope_handle;
|
||||
PLI_INT32 format;
|
||||
s_vpi_time current_time;
|
||||
|
||||
/* obtain a handle to the system task instance */
|
||||
systf_handle = vpi_handle(vpiSysTfCall, NULL);
|
||||
|
||||
/* read current simulation time */
|
||||
current_time.type = vpiScaledRealTime;
|
||||
vpi_get_time(systf_handle, ¤t_time);
|
||||
|
||||
/* obtain handle to system task argument */
|
||||
arg_iterator = vpi_iterate(vpiArgument, systf_handle);
|
||||
if (arg_iterator == NULL) {
|
||||
/* no arguments -- use scope that called this application */
|
||||
scope_handle = vpi_handle(vpiScope, systf_handle);
|
||||
PLIbook_GetAllSignals(scope_handle, ¤t_time);
|
||||
}
|
||||
else {
|
||||
/* compiletf has already verified arg is scope instance or null */
|
||||
while ( (scope_handle = vpi_scan(arg_iterator)) != NULL ) {
|
||||
if (vpi_get(vpiType, scope_handle) != vpiModule) {
|
||||
/* arg isn't a module instance; assume it is null */
|
||||
scope_handle = vpi_handle(vpiScope, systf_handle);
|
||||
}
|
||||
PLIbook_GetAllSignals(scope_handle, ¤t_time);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void PLIbook_GetAllSignals(vpiHandle scope_handle, p_vpi_time current_time)
|
||||
{
|
||||
vpiHandle signal_iterator;
|
||||
|
||||
vpi_printf("\nAt time %2.2f, ", current_time->real);
|
||||
vpi_printf("signals in scope %s ",
|
||||
vpi_get_str(vpiFullName, scope_handle));
|
||||
vpi_printf("(%s):\n", vpi_get_str(vpiDefName, scope_handle));
|
||||
|
||||
/* obtain handles to nets in module and read current value */
|
||||
/* nets can only exist if scope is a module */
|
||||
if (vpi_get(vpiType, scope_handle) == vpiModule) {
|
||||
signal_iterator = vpi_iterate(vpiNet, scope_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
}
|
||||
|
||||
/* obtain handles to regs in scope and read current value */
|
||||
signal_iterator = vpi_iterate(vpiReg, scope_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
|
||||
/* obtain handles to variables in scope and read current value */
|
||||
signal_iterator = vpi_iterate(vpiVariables, scope_handle);
|
||||
if (signal_iterator != NULL)
|
||||
PLIbook_PrintSignalValues(signal_iterator);
|
||||
|
||||
vpi_printf("\n"); /* add some white space to output */
|
||||
return;
|
||||
}
|
||||
|
||||
void PLIbook_PrintSignalValues(vpiHandle signal_iterator)
|
||||
{
|
||||
vpiHandle signal_handle;
|
||||
int signal_type;
|
||||
s_vpi_value current_value;
|
||||
|
||||
while ( (signal_handle = vpi_scan(signal_iterator)) != NULL ) {
|
||||
signal_type = vpi_get(vpiType, signal_handle);
|
||||
switch (signal_type) {
|
||||
case vpiNet:
|
||||
current_value.format = vpiBinStrVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" net %-10s value is %s (binary)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.str);
|
||||
break;
|
||||
|
||||
case vpiReg:
|
||||
current_value.format = vpiBinStrVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" reg %-10s value is %s (binary)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.str);
|
||||
break;
|
||||
|
||||
case vpiIntegerVar:
|
||||
current_value.format = vpiIntVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" integer %-10s value is %d (decimal)\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.integer);
|
||||
break;
|
||||
|
||||
case vpiRealVar:
|
||||
current_value.format = vpiRealVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" real %-10s value is %0.2f\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.real);
|
||||
break;
|
||||
|
||||
case vpiTimeVar:
|
||||
current_value.format = vpiTimeVal;
|
||||
vpi_get_value(signal_handle, ¤t_value);
|
||||
vpi_printf(" time %-10s value is %x%x\n",
|
||||
vpi_get_str(vpiName, signal_handle),
|
||||
current_value.value.time->high,
|
||||
current_value.value.time->low);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,6 @@
|
||||
// Example Synopsys VCS PLI table to register PLI applications
|
||||
// For the book, "The Verilog PLI Handbook"
|
||||
|
||||
$show_all_nets call=PLIbook_ShowNets_calltf check=PLIbook_ShowNets_compiletf data=0 acc+=read:*
|
||||
|
||||
$show_all_signals call=PLIbook_ShowSignals_calltf check=PLIbook_ShowSignals_compiletf data=0 acc+=read:*
|
25
me250300_pli/plibook_examples_unix/chapter.03/vpi_user.c
Normal file
25
me250300_pli/plibook_examples_unix/chapter.03/vpi_user.c
Normal file
@ -0,0 +1,25 @@
|
||||
/**********************************************************************
|
||||
* Example vpi_user.c file
|
||||
*
|
||||
* vpi_user.c file to register PLI applications using the VPI library.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#include "vpi_user.h"
|
||||
|
||||
/* prototypes of the PLI registration routines */
|
||||
extern void PLIbook_ShowNets_register();
|
||||
extern void PLIbook_ShowSignals_register();
|
||||
|
||||
void (*vlog_startup_routines[])() =
|
||||
{
|
||||
/*** add user entries here ***/
|
||||
PLIbook_ShowNets_register,
|
||||
PLIbook_ShowSignals_register,
|
||||
0 /*** final entry must be 0 ***/
|
||||
};
|
23
me250300_pli/plibook_examples_unix/chapter.04/build_MTI.mak
Normal file
23
me250300_pli/plibook_examples_unix/chapter.04/build_MTI.mak
Normal file
@ -0,0 +1,23 @@
|
||||
#
|
||||
# NMAKE makefile to make my_pli.dll for MTI Modelsim, using VisualC++ on Windows
|
||||
#
|
||||
|
||||
MTI_INSTALL_DIR=c:\progra~1\ModelTech
|
||||
|
||||
SOURCES = \
|
||||
count_args_vpi_test.c \
|
||||
get_arg_handle_vpi_test.c \
|
||||
list_pathout_ports_vpi.c \
|
||||
port_info_vpi.c \
|
||||
count_all_prims_vpi.c \
|
||||
invoke_options_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(MTI_INSTALL_DIR)\include -MD
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
../mti_pli.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) -EXPORT:vlog_startup_routines $(MTI_INSTALL_DIR)/win32/mtipli.lib
|
23
me250300_pli/plibook_examples_unix/chapter.04/build_NC.mak
Normal file
23
me250300_pli/plibook_examples_unix/chapter.04/build_NC.mak
Normal file
@ -0,0 +1,23 @@
|
||||
#
|
||||
# sample NMAKE makefile to make libvpi.dll for Cadence Verilog-XL, using VisualC++ on Windows
|
||||
#
|
||||
|
||||
CDS_INST_DIR=C:/progra~1/cds/
|
||||
|
||||
SOURCES = \
|
||||
count_args_vpi_test.c \
|
||||
get_arg_handle_vpi_test.c \
|
||||
list_pathout_ports_vpi.c \
|
||||
port_info_vpi.c \
|
||||
count_all_prims_vpi.c \
|
||||
invoke_options_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
libvpi.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib
|
24
me250300_pli/plibook_examples_unix/chapter.04/build_XL.mak
Normal file
24
me250300_pli/plibook_examples_unix/chapter.04/build_XL.mak
Normal file
@ -0,0 +1,24 @@
|
||||
#
|
||||
# sample NMAKE makefile to make libvpi.dll with VisualC++ on Windows
|
||||
# see windows.txt for more details.
|
||||
#
|
||||
|
||||
CDS_INST_DIR=C:/progra~1/cds/
|
||||
|
||||
SOURCES = \
|
||||
count_args_vpi_test.c \
|
||||
get_arg_handle_vpi_test.c \
|
||||
list_pathout_ports_vpi.c \
|
||||
port_info_vpi.c \
|
||||
count_all_prims_vpi.c \
|
||||
invoke_options_vpi.c \
|
||||
vpi_user.c
|
||||
|
||||
OBJS = $(SOURCES:.c=.obj)
|
||||
CFLAGS = -DMSC -DWIN32 -I$(CDS_INST_DIR)/tools/include -MD -O2
|
||||
|
||||
.c.obj:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
libvpi.dll: $(OBJS)
|
||||
link -dll /out:$@ $(OBJS) $(CDS_INST_DIR)/tools/lib/pliinterface.lib
|
@ -0,0 +1,5 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
Total number of primitives is 6
|
||||
|
||||
Simulation complete via $finish(1) at time 2 NS + 0
|
@ -0,0 +1,49 @@
|
||||
/**********************************************************************
|
||||
* $count_primitives example -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the $count_primitives PLI application
|
||||
* on a 1-bit adder modeled using gate primitives.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module test;
|
||||
reg a, b, ci, clk;
|
||||
wire sum, co, sum2;
|
||||
|
||||
addbit i1 (a, b, ci, sum, co);
|
||||
buf (sum2, sum);
|
||||
|
||||
initial
|
||||
begin
|
||||
#1 $count_primitives;
|
||||
#1 $finish;
|
||||
end
|
||||
endmodule
|
||||
|
||||
/*** A gate level 1 bit adder model ***/
|
||||
`timescale 1ns / 1ns
|
||||
module addbit (a, b, ci, sum, co);
|
||||
input a, b, ci;
|
||||
output sum, co;
|
||||
|
||||
wire a, b, ci, sum, co,
|
||||
n1, n2, n3;
|
||||
|
||||
xor (n1, a, b);
|
||||
xor #2 (sum, n1, ci);
|
||||
and (n2, a, b);
|
||||
and (n3, n1, ci);
|
||||
or #2 (co, n2, n3);
|
||||
|
||||
specify
|
||||
(a *> sum) = 5;
|
||||
(b *> sum, co) = 5;
|
||||
endspecify
|
||||
|
||||
endmodule
|
||||
/*********************************************************************/
|
@ -0,0 +1,116 @@
|
||||
/**********************************************************************
|
||||
* $count_primitives example -- PLI application using VPI routines
|
||||
*
|
||||
* C source to find and count all primitives in a design, beginning
|
||||
* with the top-level module and all levels of hierarchy below the top.
|
||||
*
|
||||
* Usage: $count_primitives;
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* prototypes of the PLI application routines */
|
||||
PLI_INT32 PLIbook_CountPrims_compiletf(PLI_BYTE8 *user_data);
|
||||
PLI_INT32 PLIbook_CountPrims_calltf(PLI_BYTE8 *user_data);
|
||||
int PLIbook_find_child_mod(vpiHandle this_mod_h);
|
||||
int PLIbook_count_local_prims(vpiHandle module_h);
|
||||
|
||||
/**********************************************************************
|
||||
* VPI Registration Data
|
||||
*********************************************************************/
|
||||
void PLIbook_CountPrims_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data; /* allocate register data structure */
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$count_primitives";
|
||||
tf_data.calltf = PLIbook_CountPrims_calltf;
|
||||
tf_data.compiletf = PLIbook_CountPrims_compiletf;
|
||||
tf_data.sizetf = NULL;
|
||||
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
/*********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Compiletf application
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_CountPrims_compiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_h, tfarg_itr, tfarg_h;
|
||||
|
||||
systf_h = vpi_handle(vpiSysTfCall, NULL);
|
||||
if (systf_h == NULL) {
|
||||
vpi_printf("ERROR: $count_primitives could not obtain handle to systf call\n");
|
||||
vpi_control(vpiFinish, 1); /* abort simulation */
|
||||
return(0);
|
||||
}
|
||||
tfarg_itr = vpi_iterate(vpiArgument, systf_h);
|
||||
if (tfarg_itr != NULL) {
|
||||
vpi_printf("WARNING: arguments to $count_primitives are ignored.\n");
|
||||
vpi_free_object(tfarg_itr); /* because not scanning until null */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_CountPrims_calltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle top_mod_itr, top_mod_h;
|
||||
int total_prims = 0;
|
||||
top_mod_itr = vpi_iterate(vpiModule, NULL); /*get top modules*/
|
||||
while (top_mod_h = vpi_scan(top_mod_itr)) {
|
||||
total_prims += PLIbook_find_child_mod(top_mod_h);
|
||||
}
|
||||
vpi_printf("\nTotal number of primitives is %d\n\n", total_prims);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Function to look for module instances in local scope.
|
||||
* THIS FUNCTION CALLS ITSELF RECURSIVELY.
|
||||
*********************************************************************/
|
||||
int PLIbook_find_child_mod(vpiHandle this_mod_h)
|
||||
{
|
||||
vpiHandle child_mod_itr, child_mod_h;
|
||||
int prims_in_child;
|
||||
|
||||
prims_in_child = PLIbook_count_local_prims(this_mod_h);
|
||||
child_mod_itr = vpi_iterate(vpiModule, this_mod_h);
|
||||
if (child_mod_itr != NULL)
|
||||
while (child_mod_h = vpi_scan(child_mod_itr))
|
||||
prims_in_child += PLIbook_find_child_mod(child_mod_h);
|
||||
return(prims_in_child);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Function to count primitives in local scope.
|
||||
*********************************************************************/
|
||||
int PLIbook_count_local_prims(vpiHandle module_h)
|
||||
{
|
||||
vpiHandle prim_itr, prim_h;
|
||||
int prims_in_mod = 0;
|
||||
|
||||
prim_itr = vpi_iterate(vpiPrimitive, module_h);
|
||||
if (prim_itr != NULL)
|
||||
while (prim_h = vpi_scan(prim_itr))
|
||||
prims_in_mod++;
|
||||
return (prims_in_mod);
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,8 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
Testing PLIbook_numargs_vpi()...
|
||||
Number of args found = 6: EXPECTED 6
|
||||
|
||||
*** All Tests Completed ***
|
||||
|
||||
Simulation complete via $finish(1) at time 20 NS + 0
|
@ -0,0 +1,46 @@
|
||||
/**********************************************************************
|
||||
* $count_args_vpi example -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the VPI utility applications.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module test;
|
||||
reg a, b, ci;
|
||||
wire sum, co;
|
||||
real r1;
|
||||
|
||||
addbit i1 (a, b, ci, sum, co);
|
||||
|
||||
initial
|
||||
begin
|
||||
a = 0; b = 1; ci = 1;
|
||||
r1 = 0.5;
|
||||
#10 $count_args_vpi(b, r1, "Hello world", i1, /*null arg*/, sum );
|
||||
#10 $finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
/*** A gate level 1 bit adder model ***/
|
||||
`timescale 1ns / 1ns
|
||||
module addbit (a, b, ci, sum, co);
|
||||
input a, b, ci;
|
||||
output sum, co;
|
||||
|
||||
wire a, b, ci, sum, co,
|
||||
n1, n2, n3;
|
||||
|
||||
xor (n1, a, b);
|
||||
xor #2 (sum, n1, ci);
|
||||
and (n2, a, b);
|
||||
and (n3, n1, ci);
|
||||
or #2 (co, n2, n3);
|
||||
|
||||
endmodule
|
||||
/**********************************************************************/
|
@ -0,0 +1,83 @@
|
||||
/**********************************************************************
|
||||
* VPI PLIbook_count_args_vpi Example -- PLI application using VPI
|
||||
* routines
|
||||
*
|
||||
* C code to test the VPI "PLIbook_count_args_vpi()" application.
|
||||
*
|
||||
* NOTE: THIS ROUTINE IS PROVIDED AS SHORT EXAMPLE ON HOW TO ACCESS
|
||||
* TASK/FUNCTION ARGUMENTS, AND HOW TO PERFORM ERROR CHECKING ON IF
|
||||
* THE DESIRED INFORMATION WAS OBTAINED. THIS EXAMPLE IS NOT
|
||||
* INTENDED TO BE AN EFFICIENT PLI APPLICATION. THE FILE
|
||||
* get_arg_handle_vpi_efficient CONTAINS A MORE EFFICIENT VERSION
|
||||
* OF THIS EXAMPLE.
|
||||
*
|
||||
* Usage:
|
||||
* numargs = PLIbook_count_args_vpi(<any_number_and_type_of_args>);
|
||||
* Returns the number of system task/function arguments.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define PLIbookDebug 1 /* set to non-zero for verbose debug messages */
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* Prototypes of the utility applications */
|
||||
int PLIbook_count_args_vpi();
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* PLIbook_count_args_vpi()
|
||||
* Counts the number of system task/function arguments. Similar to
|
||||
* tf_nump().
|
||||
*********************************************************************/
|
||||
int PLIbook_count_args_vpi()
|
||||
{
|
||||
vpiHandle systf_h, arg_itr, arg_h;
|
||||
int tfnum = 0;
|
||||
s_vpi_error_info err; /* structure for error handling */
|
||||
|
||||
systf_h = vpi_handle(vpiSysTfCall, NULL);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_count_args_vpi() could not obtain handle to systf call\n");
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#else /* if error, generate brief error message */
|
||||
if (systf_h == NULL)
|
||||
vpi_printf("ERROR: PLIbook_count_args_vpi() could not obtain handle to systf call\n");
|
||||
#endif
|
||||
|
||||
arg_itr = vpi_iterate(vpiArgument, systf_h);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_count_args_vpi() could not obtain iterator to systf args\n");
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#else /* if error, generate brief error message */
|
||||
if (arg_itr == NULL)
|
||||
vpi_printf("ERROR: PLIbook_count_args_vpi() could not obtain iterator to systf args\n");
|
||||
#endif
|
||||
|
||||
while (arg_h = vpi_scan(arg_itr) ) {
|
||||
tfnum++;
|
||||
}
|
||||
|
||||
return(tfnum);
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,57 @@
|
||||
/**********************************************************************
|
||||
* $count_args_vpi example -- PLI application using VPI routines
|
||||
*
|
||||
* Tests the VPI PLIbook_count_args_vpi() application.
|
||||
*
|
||||
* Usage: initial $count_args_vpi(<any_number_and_type_of_arguments>);
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
/* prototypes of the PLI application routines */
|
||||
PLI_INT32 PLIbook_CountArgsTestCall(PLI_BYTE8 *user_data);
|
||||
|
||||
#include "count_args_vpi.c" /* include the VPI application */
|
||||
/* #include "get_arg_handle_vpi_efficient.c" /* include VPI app. */
|
||||
|
||||
/**********************************************************************
|
||||
* VPI Registration Data
|
||||
*********************************************************************/
|
||||
void PLIbook_CountArgsTest_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.sysfunctype = 0;
|
||||
tf_data.tfname = "$count_args_vpi";
|
||||
tf_data.calltf = PLIbook_CountArgsTestCall;
|
||||
tf_data.compiletf = NULL;
|
||||
tf_data.sizetf = NULL;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
/**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine to exercise various utility functions.
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_CountArgsTestCall(PLI_BYTE8 *user_data)
|
||||
{
|
||||
int num_args;
|
||||
|
||||
vpi_printf("\n Testing PLIbook_numargs_vpi()...\n");
|
||||
num_args = PLIbook_count_args_vpi();
|
||||
vpi_printf(" Number of args found = %d: EXPECTED 6\n", num_args);
|
||||
|
||||
vpi_printf("\n*** All Tests Completed ***\n\n");
|
||||
return(0);
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,18 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
Testing PLIbook_get_arg_handle_vpi() With Good Values...
|
||||
|
||||
PLIbook_get_arg_handle_vpi() is allocating workarea storage for task args
|
||||
Handle to arg 1 is a: EXPECTED a
|
||||
Handle to arg 3 is sum: EXPECTED sum
|
||||
|
||||
Testing PLIbook_get_arg_handle_vpi_vpi() with invalid index numbers...
|
||||
|
||||
ERROR: PLIbook_get_arg_handle_vpi() arg index of 0 is invalid
|
||||
Handle to arg 0 is 0: EXPECTED 0 (NULL)
|
||||
ERROR: PLIbook_get_arg_handle_vpi() arg index of 6 is out-of-range
|
||||
Handle to arg 6 is 0: EXPECTED 0 (NULL)
|
||||
|
||||
*** All Tests Completed ***
|
||||
|
||||
Simulation complete via $finish(1) at time 20 NS + 0
|
@ -0,0 +1,26 @@
|
||||
/**********************************************************************
|
||||
* $get_arg_handle_test example -- Verilog HDL test bench.
|
||||
*
|
||||
* Verilog test bench to test the VPI get_arg_handle application.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module test;
|
||||
reg a, b, ci;
|
||||
wire sum, co;
|
||||
|
||||
initial
|
||||
begin
|
||||
a = 0; b = 1; ci = 1;
|
||||
#10 $get_arg_handle_test(a, b, sum);
|
||||
#10 $finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
/**********************************************************************/
|
@ -0,0 +1,199 @@
|
||||
/**********************************************************************
|
||||
* PLIbook_count_args_vpi and PLIbook_get_arg_handle_vpi Examples
|
||||
* PLI application using VPI routines
|
||||
*
|
||||
* C source for functions to access handles of system task/function
|
||||
* arguments.
|
||||
*
|
||||
* Usage:
|
||||
* numargs = PLIbook_count_args_vpi(<any_number_and_type_of_args>);
|
||||
* Returns the number of system task/function arguments.
|
||||
*
|
||||
* arg_handle = PLIbook_get_arg_handle_vpi(arg_index_number);
|
||||
* Returns a handke for a system task/function argument,
|
||||
* using the index number of the argument, beginning with 1.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define PLIbookDebug 1 /* set to non-zero for verbose debug messages */
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* Prototypes of the applications */
|
||||
int PLIbook_count_args_vpi();
|
||||
vpiHandle PLIbook_get_arg_handle_vpi(int argNum);
|
||||
vpiHandle *create_arg_array(vpiHandle systf_h);
|
||||
|
||||
/**********************************************************************
|
||||
* PLIbook_count_args_vpi() -- Efficient Version
|
||||
* Counts the number of system task/function arguments. Similar to
|
||||
* tf_nump().
|
||||
*********************************************************************/
|
||||
int PLIbook_count_args_vpi()
|
||||
{
|
||||
vpiHandle systf_h, arg_itr, arg_h;
|
||||
int tfnum = 0;
|
||||
vpiHandle *arg_array; /* array pointer to store arg handles */
|
||||
#if PLIbookDebug
|
||||
s_vpi_error_info err; /* structure for error handling */
|
||||
#endif
|
||||
|
||||
systf_h = vpi_handle(vpiSysTfCall, NULL);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_count_args_vpi() could not obtain handle to systf call\n");
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#else /* if error, generate brief error message */
|
||||
if (systf_h == NULL)
|
||||
vpi_printf("ERROR: PLIbook_count_args_vpi() could not obtain handle to systf call\n");
|
||||
#endif
|
||||
|
||||
/* retrieve pointer to array with all argument handles */
|
||||
arg_array = (vpiHandle *)vpi_get_userdata(systf_h);
|
||||
if (arg_array == NULL) {
|
||||
/* array with all argument handles doesn't exist, create it */
|
||||
arg_array = create_arg_array(systf_h);
|
||||
}
|
||||
|
||||
return((int)arg_array[0]);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* PLIbook_get_arg_handle_vpi() -- Efficient Version
|
||||
* Obtain a handle to a system task/function argument, using the
|
||||
* argument index number. Similar to acc_handle_tfarg().
|
||||
*
|
||||
* ARGUMENTS ARE NUMBERED FROM LEFT TO RIGHT, BEGINNING WITH 1.
|
||||
*
|
||||
* This version is more efficient because it allocates memory and
|
||||
* stores the task arg handles so that vpi_iterate() and vpi_scan()
|
||||
* do not need to be called each time this application is called.
|
||||
*********************************************************************/
|
||||
vpiHandle PLIbook_get_arg_handle_vpi(int argNum)
|
||||
{
|
||||
vpiHandle systf_h, arg_h;
|
||||
vpiHandle *arg_array; /* array pointer to store arg handles */
|
||||
#if PLIbookDebug
|
||||
s_vpi_error_info err; /* structure for error handling */
|
||||
#endif
|
||||
|
||||
if (argNum < 1) {
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() arg index of %d is invalid\n",
|
||||
argNum);
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
systf_h = vpi_handle(vpiSysTfCall, NULL);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain handle to systf call\n");
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#else /* if error, generate brief error message */
|
||||
if (systf_h == NULL) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain handle to systf call\n");
|
||||
return(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* retrieve pointer to array with all argument handles */
|
||||
arg_array = (vpiHandle *)vpi_get_userdata(systf_h);
|
||||
if (arg_array == NULL) {
|
||||
/* array with all argument handles doesn't exist, create it */
|
||||
arg_array = create_arg_array(systf_h);
|
||||
}
|
||||
|
||||
if (argNum > (int)arg_array[0]) {
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() arg index of %d is out-of-range\n",
|
||||
argNum);
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* get requested tfarg handle from array */
|
||||
arg_h = (vpiHandle)arg_array[argNum];
|
||||
return(arg_h);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Subroutine to allocate an array and store the number of arguments
|
||||
* and all argument handles in the array.
|
||||
*********************************************************************/
|
||||
vpiHandle *create_arg_array(vpiHandle systf_h)
|
||||
{
|
||||
vpiHandle arg_itr, arg_h;
|
||||
vpiHandle *arg_array; /* array pointer to store arg handles */
|
||||
int i, tfnum = 0;
|
||||
#if PLIbookDebug
|
||||
s_vpi_error_info err; /* structure for error handling */
|
||||
#endif
|
||||
|
||||
/* allocate array based on the number of task/function arguments */
|
||||
arg_itr = vpi_iterate(vpiArgument, systf_h);
|
||||
if (arg_itr == NULL) {
|
||||
vpi_printf("ERROR: PLIbook_numargs_vpi() could not obtain iterator to systf args\n");
|
||||
return(NULL);
|
||||
}
|
||||
while (arg_h = vpi_scan(arg_itr) ) { /* count number of args */
|
||||
tfnum++;
|
||||
}
|
||||
arg_array = (vpiHandle *)malloc(sizeof(vpiHandle) * (tfnum + 1));
|
||||
|
||||
/* store pointer to array in simulator-allocated user_data storage
|
||||
that is unique for each task/func instance */
|
||||
vpi_put_userdata(systf_h, (void *)arg_array);
|
||||
|
||||
/* store number of arguments in first address in array */
|
||||
arg_array[0] = (vpiHandle)tfnum;
|
||||
|
||||
/* fill the array with handles to each task/function argument */
|
||||
arg_itr = vpi_iterate(vpiArgument, systf_h);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain iterator to systf args\n");
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#else /* if error, generate brief error message */
|
||||
if (systf_h == NULL) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain iterator to systf args\n");
|
||||
return(NULL);
|
||||
}
|
||||
#endif
|
||||
for (i=1; i<=tfnum; i++) {
|
||||
arg_h = vpi_scan(arg_itr);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain handle to systf arg %d\n", i);
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#endif
|
||||
arg_array[i] = arg_h;
|
||||
}
|
||||
if (arg_h != NULL)
|
||||
vpi_free_object(arg_itr); /* free iterator--didn't scan all args */
|
||||
|
||||
return(arg_array);
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,119 @@
|
||||
/**********************************************************************
|
||||
* PLIbook_get_arg_handle_vpi Example -- PLI application using VPI
|
||||
* routines
|
||||
*
|
||||
* C source for function to access handles of system task/function
|
||||
* arguments.
|
||||
*
|
||||
* NOTE: THIS ROUTINE IS PROVIDED AS A SHORT EXAMPLE ON HOW TO ACCESS
|
||||
* TASK/FUNCTION ARGUMENTS, AND HOW TO PERFORM ERROR CHECKING ON IF
|
||||
* THE DESIRED INFORMATION WAS OBTAINED. THE EXAMPLE IS NOT
|
||||
* INTENDED TO BE A COMPLETE PLI APPLICATION IN AND OF ITSELF, AND
|
||||
* IS NOT EFFICIENT FOR SIMULATION PERFORMACE.
|
||||
*
|
||||
* Usage:
|
||||
* arg_handle = PLIbook_get_arg_handle_vpi(arg_index_number);
|
||||
* Returns a handke for a system task/function argument,
|
||||
* using the index number of the argument, beginning with 1.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define PLIbookDebug 1 /* set to non-zero for verbose debug messages */
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* Prototypes of the applications */
|
||||
vpiHandle PLIbook_get_arg_handle_vpi(int argNum);
|
||||
|
||||
/**********************************************************************
|
||||
* PLIbook_get_arg_handle_vpi()
|
||||
* Obtain a handle to a system task/function argument, using the
|
||||
* argument index number. Similar to acc_handle_tfarg().
|
||||
*
|
||||
* ARGUMENTS ARE NUMBERED FROM LEFT TO RIGHT, BEGINNING WITH 1.
|
||||
*
|
||||
* The method used in this version is not as efficient as it could be,
|
||||
* because this example must call vpi_iterate() and vpi_scan() each
|
||||
* time this application is called.
|
||||
*********************************************************************/
|
||||
vpiHandle PLIbook_get_arg_handle_vpi(int argNum)
|
||||
{
|
||||
vpiHandle systf_h, arg_itr, arg_h;
|
||||
int i;
|
||||
#if PLIbookDebug
|
||||
s_vpi_error_info err; /* structure for error handling */
|
||||
#endif
|
||||
|
||||
if (argNum < 1) {
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() arg index of %d is invalid\n",
|
||||
argNum);
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
systf_h = vpi_handle(vpiSysTfCall, NULL);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain handle to systf call\n");
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#else /* if error, generate brief error message */
|
||||
if (systf_h == NULL) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain handle to systf call\n");
|
||||
return(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
arg_itr = vpi_iterate(vpiArgument, systf_h);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain iterator to systf args\n");
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#else /* if error, generate brief error message */
|
||||
if (systf_h == NULL) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain iterator to systf args\n");
|
||||
return(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i=1; i<=argNum; i++) {
|
||||
arg_h = vpi_scan(arg_itr);
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
if (vpi_chk_error(&err)) {
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() could not obtain handle to systf arg %d\n", i);
|
||||
vpi_printf("File %s, Line %d: %s\n",
|
||||
err.file, err.line, err.message);
|
||||
}
|
||||
#endif
|
||||
if (arg_h == NULL) {
|
||||
#if PLIbookDebug /* if error, generate verbose debug message */
|
||||
vpi_printf("ERROR: PLIbook_get_arg_handle_vpi() arg index of %d is out-of-range\n",
|
||||
argNum);
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
if (arg_h != NULL)
|
||||
vpi_free_object(arg_itr); /* free iterator--didn't scan all args */
|
||||
|
||||
return(arg_h);
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,78 @@
|
||||
/**********************************************************************
|
||||
* $get_arg_handle_test example -- PLI application using VPI routines
|
||||
*
|
||||
* C code to test the VPI "PLIbook_get_arg_handle_vpi() application.
|
||||
*
|
||||
* Usage: initial
|
||||
* $get_arg_handle_test(arg1, arg2, arg3);
|
||||
*
|
||||
* The arguments can be any Verilog data type.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
/* prototypes of the PLI application routines */
|
||||
PLI_INT32 PLIbook_GetArgTestCall(PLI_BYTE8 *user_data);
|
||||
|
||||
|
||||
/* #include "get_arg_handle_vpi_inefficient.c" /* include VPI app. */
|
||||
#include "get_arg_handle_vpi_efficient.c" /* include VPI app. */
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* VPI Registration Data
|
||||
*********************************************************************/
|
||||
void PLIbook_GetArgTest_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.sysfunctype = 0;
|
||||
tf_data.tfname = "$get_arg_handle_test";
|
||||
tf_data.calltf = PLIbook_GetArgTestCall;
|
||||
tf_data.compiletf = NULL;
|
||||
tf_data.sizetf = NULL;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
/**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine to exercise various utility functions.
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_GetArgTestCall(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle arg0_h, arg1_h, arg2_h, arg3_h, arg4_h, arg5_h, arg6_h;
|
||||
|
||||
vpi_printf("\nTesting PLIbook_get_arg_handle_vpi() With Good Values...\n\n");
|
||||
|
||||
arg1_h = PLIbook_get_arg_handle_vpi(1);
|
||||
vpi_printf(" Handle to arg 1 is %s: EXPECTED a\n",
|
||||
vpi_get_str(vpiName, arg1_h));
|
||||
|
||||
arg3_h = PLIbook_get_arg_handle_vpi(3);
|
||||
vpi_printf(" Handle to arg 3 is %s: EXPECTED sum\n",
|
||||
vpi_get_str(vpiName, arg3_h));
|
||||
|
||||
|
||||
vpi_printf("\nTesting PLIbook_get_arg_handle_vpi_vpi() with invalid index numbers...\n\n");
|
||||
arg0_h = PLIbook_get_arg_handle_vpi(0);
|
||||
vpi_printf(" Handle to arg 0 is %d: EXPECTED 0 (NULL)\n",
|
||||
arg0_h);
|
||||
|
||||
arg6_h = PLIbook_get_arg_handle_vpi(6);
|
||||
vpi_printf(" Handle to arg 6 is %d: EXPECTED 0 (NULL)\n",
|
||||
arg6_h);
|
||||
|
||||
vpi_printf("\n*** All Tests Completed ***\n\n");
|
||||
return(0);
|
||||
}
|
||||
/*********************************************************************/
|
@ -0,0 +1,41 @@
|
||||
ncverilog: v3.20.(p1): (c) Copyright 1995 - 2000 Cadence Design Systems, Inc.
|
||||
|
||||
ncverilog
|
||||
+a
|
||||
+b
|
||||
-f
|
||||
invoke_options_test1.f
|
||||
invoke_options_test.v
|
||||
+a1
|
||||
+b1
|
||||
-f
|
||||
invoke_options_test2.f
|
||||
+a2
|
||||
+b2
|
||||
+test2
|
||||
+c2
|
||||
+c1
|
||||
+c
|
||||
|
||||
Simulation was NOT invoked with a +test1 option
|
||||
|
||||
ncverilog
|
||||
+a
|
||||
+b
|
||||
-f
|
||||
invoke_options_test1.f
|
||||
invoke_options_test.v
|
||||
+a1
|
||||
+b1
|
||||
-f
|
||||
invoke_options_test2.f
|
||||
+a2
|
||||
+b2
|
||||
+test2
|
||||
+c2
|
||||
+c1
|
||||
+c
|
||||
|
||||
Simulation WAS invoked with a +test2 option
|
||||
|
||||
Simulation complete via $finish(1) at time 1 NS + 0
|
@ -0,0 +1,37 @@
|
||||
/**************************************************************************
|
||||
* $test_invoke_options example -- Verilog test bench source code
|
||||
*
|
||||
* Verilog test bench to test the $test_invoke_options PLI application.
|
||||
*
|
||||
* NOTE: This test uses two supplemental files: invoke_options_test1.f and
|
||||
* invoke_options_test1.f. This test is designed to be invoked as follows:
|
||||
*
|
||||
* <simulator_compile_command> invoke_options_test.v
|
||||
* <simulator_run_command> +a +b -f invoke_options_test1.f +c
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*************************************************************************/
|
||||
`timescale 1ns / 1ns
|
||||
module test;
|
||||
reg option_exists;
|
||||
initial
|
||||
begin
|
||||
option_exists = $test_invoke_options("+test1");
|
||||
if (option_exists)
|
||||
$display("\nSimulation WAS invoked with a +test1 option\n");
|
||||
else
|
||||
$display("\nSimulation was NOT invoked with a +test1 option\n");
|
||||
|
||||
if ($test_invoke_options("+test2"))
|
||||
$display("\nSimulation WAS invoked with a +test2 option\n");
|
||||
else
|
||||
$display("\nSimulation was NOT invoked with a +test2 option\n");
|
||||
|
||||
#1 $finish;
|
||||
end
|
||||
|
||||
endmodule
|
@ -0,0 +1,7 @@
|
||||
//command file
|
||||
invoke_options_test.v
|
||||
+a1
|
||||
+b1
|
||||
//+test1
|
||||
-f invoke_options_test2.f
|
||||
+c1
|
@ -0,0 +1,5 @@
|
||||
//command file
|
||||
+a2
|
||||
+b2
|
||||
+test2
|
||||
+c2
|
@ -0,0 +1,189 @@
|
||||
/**********************************************************************
|
||||
* $test_invoke_options example -- PLI application using VPI routines
|
||||
*
|
||||
* C source to test for aany simulation invocation option, including
|
||||
* user-defined options. The system function will return 1 if an
|
||||
* invocation option was present when simulation was invoked, and will
|
||||
* return 0 if the option did not exist.
|
||||
*
|
||||
* Usage: reg flag;
|
||||
flag = $test_invoke_options("<invocation_option>");
|
||||
* Where <invocation_option can be any + or - option.
|
||||
*
|
||||
* Debug tip: Uncomment the line "#define PLIbook_verbose" to enable
|
||||
* this application to list all simulation invocation options.
|
||||
*
|
||||
* For the book, "The Verilog PLI Handbook" by Stuart Sutherland
|
||||
* Copyright 1999 & 2001, Kluwer Academic Publishers, Norwell, MA, USA
|
||||
* Contact: www.wkap.il
|
||||
* Example copyright 1998, Sutherland HDL Inc, Portland, Oregon, USA
|
||||
* Contact: www.sutherland-hdl.com
|
||||
*********************************************************************/
|
||||
|
||||
#define PLIbook_verbose 1 /* set to non-zero for verbose messages */
|
||||
|
||||
#define VPI_1995 0 /* set to non-zero for Verilog-1995 compatibility */
|
||||
|
||||
#include <stdlib.h> /* ANSI C standard library */
|
||||
#include <stdio.h> /* ANSI C standard input/output library */
|
||||
#include <stdarg.h> /* ANSI C standard arguments library */
|
||||
#include "vpi_user.h" /* IEEE 1364 PLI VPI routine library */
|
||||
|
||||
#if VPI_1995
|
||||
#include "../vpi_1995_compat.h" /* kludge new Verilog-2001 routines */
|
||||
#endif
|
||||
|
||||
/* prototypes of routines in this PLI application */
|
||||
PLI_INT32 PLIbook_TestInvokeOptions_calltf(PLI_BYTE8 *user_data);
|
||||
PLI_INT32 PLIbook_TestInvokeOptions_compiletf(PLI_BYTE8 *user_data);
|
||||
PLI_INT32 PLIbook_TestInvokeOptions_sizetf(PLI_BYTE8 *user_data);
|
||||
int PLIbook_GetOptions(char *option, int argc, char **argv);
|
||||
void PLIbook_ScanCommandFile(char *option, char **arg);
|
||||
|
||||
/**********************************************************************
|
||||
* VPI Registration Data
|
||||
*********************************************************************/
|
||||
void PLIbook_TestInvokeOptions_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
tf_data.type = vpiSysFunc;
|
||||
tf_data.sysfunctype = vpiSysFuncSized;
|
||||
tf_data.tfname = "$test_invoke_options";
|
||||
tf_data.calltf = PLIbook_TestInvokeOptions_calltf;
|
||||
tf_data.compiletf = PLIbook_TestInvokeOptions_compiletf;
|
||||
tf_data.sizetf = PLIbook_TestInvokeOptions_sizetf;
|
||||
tf_data.user_data = NULL;
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* sizetf application
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_TestInvokeOptions_sizetf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
return(1); /* $test_invoke_options returns a 1-bit value */
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* calltf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_TestInvokeOptions_calltf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_h, arg_itr, arg_h;
|
||||
char *option_name;
|
||||
s_vpi_value value_s;
|
||||
s_vpi_vlog_info sim_info;
|
||||
int found;
|
||||
|
||||
vpi_get_vlog_info(&sim_info);
|
||||
|
||||
/* get system function arg--compiletf already verified correctness */
|
||||
systf_h = vpi_handle(vpiSysTfCall, NULL);
|
||||
arg_itr = vpi_iterate(vpiArgument, systf_h);
|
||||
arg_h = vpi_scan(arg_itr);
|
||||
vpi_free_object(arg_itr); /* free iterator -- did not scan to null */
|
||||
|
||||
/* read target option name from first tfarg */
|
||||
value_s.format = vpiStringVal;
|
||||
vpi_get_value(arg_h, &value_s);
|
||||
option_name = value_s.value.str;
|
||||
|
||||
/* test for target option and return true/false to system function */
|
||||
found = PLIbook_GetOptions((char *)option_name,
|
||||
(int)sim_info.argc,
|
||||
(char **)sim_info.argv );
|
||||
value_s.format = vpiIntVal;
|
||||
value_s.value.integer = found;
|
||||
vpi_put_value(systf_h, &value_s, NULL, vpiNoDelay);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int PLIbook_optfound = 0; /* global variable for option found flag */
|
||||
int PLIbook_indent = 0; /* global variable to format text indenting */
|
||||
|
||||
int PLIbook_GetOptions(char *option, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
PLIbook_optfound = 0;
|
||||
PLIbook_indent = 0;
|
||||
for (i=0; i<argc; i++) {
|
||||
#if PLIbook_verbose
|
||||
vpi_printf("%s\n", *argv);
|
||||
#endif
|
||||
if (strcmp(*argv, option) == 0) {
|
||||
PLIbook_optfound = 1;
|
||||
}
|
||||
if (strcmp(*argv, "-f") == 0) {
|
||||
argv++; /* next arg is address to array of strings */
|
||||
i++;
|
||||
PLIbook_ScanCommandFile(option, (char **)*argv);
|
||||
}
|
||||
argv++; /* increment to next argument */
|
||||
}
|
||||
return(PLIbook_optfound);
|
||||
}
|
||||
|
||||
void PLIbook_ScanCommandFile(char *option, char **arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
#if PLIbook_verbose
|
||||
PLIbook_indent += 4; /* increase text indentation */
|
||||
#endif
|
||||
while ( *arg != NULL ) { /* loop until null termination */
|
||||
#if PLIbook_verbose
|
||||
for (i=0; i<=PLIbook_indent; i++)
|
||||
vpi_printf(" ");
|
||||
vpi_printf("%s\n", *arg);
|
||||
#endif
|
||||
if (strcmp(*arg, option) == 0) {
|
||||
PLIbook_optfound = 1;
|
||||
}
|
||||
if (strcmp(*arg, "-f") == 0) {
|
||||
arg++; /* next arg is address to array of strings */
|
||||
PLIbook_ScanCommandFile(option, (char **)*arg);
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
#if PLIbook_verbose
|
||||
PLIbook_indent -= 4; /* decrease text indentation */
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* compiletf routine
|
||||
*********************************************************************/
|
||||
PLI_INT32 PLIbook_TestInvokeOptions_compiletf(PLI_BYTE8 *user_data)
|
||||
{
|
||||
vpiHandle systf_h, arg_itr, arg_h;
|
||||
int err = 0;
|
||||
|
||||
systf_h = vpi_handle(vpiSysTfCall, NULL);
|
||||
arg_itr = vpi_iterate(vpiArgument, systf_h);
|
||||
if (arg_itr == NULL) {
|
||||
vpi_printf("ERROR: $test_invoke_options requires 1 argument\n");
|
||||
vpi_control(vpiFinish, 1); /* abort simulation */
|
||||
return(0);
|
||||
}
|
||||
arg_h = vpi_scan(arg_itr); /* get handle for first tfarg */
|
||||
if (vpi_get(vpiType, arg_h) != vpiConstant) {
|
||||
vpi_printf("$test_invoke_options arg must be a quoted name\n");
|
||||
err = 1;
|
||||
}
|
||||
else if (vpi_get(vpiConstType, arg_h) != vpiStringConst) {
|
||||
vpi_printf("$test_invoke_options arg must be a string\n");
|
||||
err = 1;
|
||||
}
|
||||
if (vpi_scan(arg_itr) != NULL) {
|
||||
vpi_printf("test_invoke_options requires only 1 argument\n");
|
||||
vpi_free_object(arg_itr);
|
||||
err = 1;
|
||||
}
|
||||
if (err)
|
||||
vpi_control(vpiFinish, 1); /* abort simulation */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user