Add structures for VPI support, and all the %vpi_call
instruction. Get linking of VPI modules to work.
This commit is contained in:
parent
32f3881344
commit
f2c1902984
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.3 2001/03/14 19:26:01 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.4 2001/03/16 01:44:34 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -43,6 +43,9 @@ CPPFLAGS = @CPPFLAGS@ @DEFS@
|
|||
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
dllib=@DLLIB@
|
||||
rdynamic=@rdynamic@
|
||||
|
||||
all: vvp
|
||||
|
||||
clean:
|
||||
|
|
@ -51,11 +54,13 @@ clean:
|
|||
distclean: clean
|
||||
rm -f config.h Makefile config.cache config.log config.status
|
||||
|
||||
V = vpi_modules.o vpi_iter.o vpi_mcd.o vpi_priv.o vpi_tasks.o
|
||||
|
||||
O = main.o parse.o parse_misc.o lexor.o compile.o functor.o symbols.o \
|
||||
codes.o vthread.o schedule.o tables.o
|
||||
codes.o vthread.o schedule.o tables.o $V
|
||||
|
||||
vvp: $O
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o vvp $O
|
||||
$(CXX) $(rdynamic) $(CXXFLAGS) $(LDFLAGS) -o vvp $O $(dllib)
|
||||
|
||||
|
||||
%.o: %.cc
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: codes.h,v 1.2 2001/03/11 23:06:49 steve Exp $"
|
||||
#ident "$Id: codes.h,v 1.3 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -40,6 +40,7 @@ extern bool of_DELAY(vthread_t thr, vvp_code_t code);
|
|||
extern bool of_END(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_VPI_CALL(vthread_t thr, vvp_code_t code);
|
||||
|
||||
/*
|
||||
* This is the format of a machine code instruction.
|
||||
|
|
@ -51,6 +52,7 @@ struct vvp_code_s {
|
|||
unsigned number;
|
||||
vvp_ipoint_t iptr;
|
||||
vvp_cpoint_t cptr;
|
||||
struct __vpiHandle*handle;
|
||||
};
|
||||
|
||||
unsigned short bit_idx1;
|
||||
|
|
@ -83,6 +85,10 @@ extern void codespace_dump(FILE*fd);
|
|||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.3 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.2 2001/03/11 23:06:49 steve
|
||||
* Compact the vvp_code_s structure.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: compile.cc,v 1.3 2001/03/11 23:06:49 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.4 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
# include "symbols.h"
|
||||
# include "codes.h"
|
||||
# include "schedule.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "vthread.h"
|
||||
# include "parse_misc.h"
|
||||
# include <malloc.h>
|
||||
|
|
@ -297,6 +298,30 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
|
|||
free(mnem);
|
||||
}
|
||||
|
||||
void compile_vpi_call(char*label, char*name)
|
||||
{
|
||||
vvp_cpoint_t ptr = codespace_allocate();
|
||||
|
||||
/* First, I can give the label a value that is the current
|
||||
codespace pointer. Don't need the text of the label after
|
||||
this is done. */
|
||||
if (label) {
|
||||
sym_set_value(sym_codespace, label, ptr);
|
||||
free(label);
|
||||
}
|
||||
|
||||
/* Create an instruction in the code space. */
|
||||
vvp_code_t code = codespace_index(ptr);
|
||||
code->opcode = &of_VPI_CALL;
|
||||
|
||||
/* Create a vpiHandle that bundles the call information, and
|
||||
store that handle in the instruction. */
|
||||
code->handle = vpip_build_vpi_call(name);
|
||||
|
||||
/* Done with the lexor-allocated name string. */
|
||||
free(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* When the parser finds a thread statement, I create a new thread
|
||||
* with the start address referenced by the program symbol passed to
|
||||
|
|
@ -391,6 +416,10 @@ void compile_dump(FILE*fd)
|
|||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.4 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.3 2001/03/11 23:06:49 steve
|
||||
* Compact the vvp_code_s structure.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: compile.h,v 1.2 2001/03/11 22:42:11 steve Exp $"
|
||||
#ident "$Id: compile.h,v 1.3 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -77,6 +77,7 @@ struct comp_operands_s {
|
|||
typedef struct comp_operands_s*comp_operands_t;
|
||||
|
||||
extern void compile_code(char*label, char*mnem, comp_operands_t opa);
|
||||
extern void compile_vpi_call(char*label, char*name);
|
||||
|
||||
/*
|
||||
* The parser uses this function to declare a thread. The start_sym is
|
||||
|
|
@ -97,6 +98,10 @@ extern void compile_dump(FILE*fd);
|
|||
|
||||
/*
|
||||
* $Log: compile.h,v $
|
||||
* Revision 1.3 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||
* Functor values and propagation.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,15 +19,24 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: config.h.in,v 1.1 2001/03/11 00:29:38 steve Exp $"
|
||||
#ident "$Id: config.h.in,v 1.2 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# define SIZEOF_UNSIGNED_LONG 0
|
||||
# define SIZEOF_UNSIGNED 0
|
||||
|
||||
# undef HAVE_DLFCN_H
|
||||
# undef HAVE_DL_H
|
||||
|
||||
# define LU ""
|
||||
# define TU ""
|
||||
|
||||
/*
|
||||
* $Log: config.h.in,v $
|
||||
* Revision 1.2 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||
* Add the vvp engine to cvs.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -10,4 +10,45 @@ AC_PROG_INSTALL
|
|||
AC_CHECK_SIZEOF(unsigned long)
|
||||
AC_CHECK_SIZEOF(unsigned)
|
||||
|
||||
# --
|
||||
# Look for a dl library to use. First look for the standard dlopen
|
||||
# functions, and failing that look for the HP specific shl_load function.
|
||||
|
||||
AC_CHECK_HEADERS(dlfcn.h dl.h, break)
|
||||
|
||||
DLLIB=''
|
||||
AC_CHECK_LIB(dl,dlopen,[DLLIB=-ldl])
|
||||
if test -z "$DLLIB" ; then
|
||||
AC_CHECK_LIB(dld,shl_load,[DLLIB=-ldld])
|
||||
fi
|
||||
AC_SUBST(DLLIB)
|
||||
|
||||
|
||||
# The -rdynamic flag is used by iverilog when compiling the target,
|
||||
# to know how to export symbols of the main program to loadable modules
|
||||
# that are brought in by -ldl. VPI support requires this.
|
||||
AC_MSG_CHECKING("for -rdynamic compiler flag")
|
||||
|
||||
rdynamic=-rdynamic
|
||||
case "${host}" in
|
||||
|
||||
*-*-netbsd*)
|
||||
rdynamic="-Wl,--export-dynamic"
|
||||
;;
|
||||
|
||||
*-*-solaris*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-cygwin*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-hpux*)
|
||||
rdynamic="-E"
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(rdynamic)
|
||||
AC_MSG_RESULT($rdynamic)
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
#ifndef __ivl_dlfcn_H
|
||||
#define __ivl_dlfcn_H
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: ivl_dlfcn.h,v 1.1 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_DLFCN_H)
|
||||
# include <dlfcn.h>
|
||||
typedef void* ivl_dll_t;
|
||||
#elif defined(HAVE_DL_H)
|
||||
# include <dl.h>
|
||||
typedef shl_t ivl_dll_t;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_DLFCN_H)
|
||||
inline ivl_dll_t ivl_dlopen(const char*name)
|
||||
{ return dlopen(name,RTLD_NOW); }
|
||||
|
||||
inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
{ return dlsym(dll, nm); }
|
||||
|
||||
inline void ivl_dlclose(ivl_dll_t dll)
|
||||
{ dlclose(dll); }
|
||||
|
||||
#elif defined(HAVE_DL_H)
|
||||
inline ivl_dll_t ivl_dlopen(const char*name)
|
||||
{ return shl_load(name, BIND_IMMEDIATE, 0); }
|
||||
|
||||
inline void* ivl_dlsym(ivl_dll_t dll, const char*nm)
|
||||
{
|
||||
void*sym;
|
||||
int rc = shl_findsym(&dll, nm, TYPE_PROCEDURE, &sym);
|
||||
return (rc == 0) ? sym : 0;
|
||||
}
|
||||
|
||||
inline void ivl_dlclose(ivl_dll_t dll)
|
||||
{ shl_unload(dll); }
|
||||
|
||||
inline const char*dlerror(void)
|
||||
{ return strerror( errno ); }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: ivl_dlfcn.h,v $
|
||||
* Revision 1.1 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.1 2001/01/14 17:12:59 steve
|
||||
* possible HP/UX portability support.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -13,6 +13,13 @@
|
|||
yylval.text = strdup(yytext);
|
||||
return T_LABEL; }
|
||||
|
||||
/* String tokens are parsed here. Return as the token value the
|
||||
contents of the string without the enclosing quotes. */
|
||||
\"[^\"]*\" {
|
||||
yytext[strlen(yytext)-1] = 0;
|
||||
yylval.text = strdup(yytext+1);
|
||||
return T_STRING; }
|
||||
|
||||
|
||||
/* These are some keywords that are recognized. */
|
||||
".functor" { return K_FUNCTOR; }
|
||||
|
|
@ -21,7 +28,12 @@
|
|||
|
||||
|
||||
/* instructions start with a % character. The compiler decides what
|
||||
kind of instruction this really is. */
|
||||
kind of instruction this really is. The few exceptions (that have
|
||||
exceptional parameter requirements) are listed first. */
|
||||
|
||||
"%vpi_call" {
|
||||
return K_vpi_call; }
|
||||
|
||||
"%"[.$_/a-zA-Z0-9]+ {
|
||||
yylval.text = strdup(yytext);
|
||||
return T_INSTR; }
|
||||
|
|
|
|||
20
vvp/main.cc
20
vvp/main.cc
|
|
@ -17,17 +17,22 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: main.cc,v 1.1 2001/03/11 00:29:38 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.2 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "parse_misc.h"
|
||||
# include "compile.h"
|
||||
# include "schedule.h"
|
||||
# include "vpi_priv.h"
|
||||
# include <stdio.h>
|
||||
# include <getopt.h>
|
||||
|
||||
|
||||
const char*module_path = ".";
|
||||
unsigned module_cnt = 0;
|
||||
const char*module_tab[64];
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
int opt;
|
||||
|
|
@ -35,10 +40,16 @@ int main(int argc, char*argv[])
|
|||
const char*dump_path = 0;
|
||||
const char*design_path = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "D:")) != EOF) switch (opt) {
|
||||
while ((opt = getopt(argc, argv, "D:M:m:")) != EOF) switch (opt) {
|
||||
case 'D':
|
||||
dump_path = optarg;
|
||||
break;
|
||||
case 'M':
|
||||
module_path = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
module_tab[module_cnt++] = optarg;
|
||||
break;
|
||||
default:
|
||||
flag_errors += 1;
|
||||
}
|
||||
|
|
@ -54,6 +65,7 @@ int main(int argc, char*argv[])
|
|||
design_path = argv[optind];
|
||||
|
||||
compile_init();
|
||||
vpip_load_modules(module_cnt, module_tab, module_path);
|
||||
compile_design(design_path);
|
||||
compile_cleanup();
|
||||
|
||||
|
|
@ -69,6 +81,10 @@ int main(int argc, char*argv[])
|
|||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.2 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||
* Add the vvp engine to cvs.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -34,6 +34,16 @@ value. Once the set completes, the value is immediately available to
|
|||
be read out of the variable. The <bit> is the address of the thread
|
||||
register that contains the bit value to assign.
|
||||
|
||||
* %vpi_call <name> [, ...]
|
||||
|
||||
This instruction makes a call to a system task or function that was
|
||||
declared using VPI. The name is given in the source as a string. It is
|
||||
not yet defined how arguments are to be passed.
|
||||
|
||||
* %waitfor <functor-label>
|
||||
|
||||
XXXX
|
||||
When a thread executes this instruction, it places itself in the
|
||||
sensitive list for the addressed functor. The functor holds all the
|
||||
threads that await the functor. When the defined sort of event occurs
|
||||
on the functor, a thread schedule event is created for all the threads
|
||||
in its list and the list is cleared.
|
||||
|
|
|
|||
12
vvp/parse.y
12
vvp/parse.y
|
|
@ -21,11 +21,12 @@ extern FILE*yyin;
|
|||
};
|
||||
|
||||
|
||||
%token K_FUNCTOR K_THREAD K_VAR
|
||||
%token K_FUNCTOR K_THREAD K_VAR K_vpi_call
|
||||
|
||||
%token <text> T_INSTR
|
||||
%token <text> T_LABEL
|
||||
%token <numb> T_NUMBER
|
||||
%token <text> T_STRING
|
||||
%token <text> T_SYMBOL
|
||||
|
||||
%type <textv> symbols
|
||||
|
|
@ -69,6 +70,15 @@ statement
|
|||
{ compile_code(0, $1, $2);
|
||||
}
|
||||
|
||||
/* %vpi_call statements are instructions that have unusual operand
|
||||
requirements so are handled by their own rules. */
|
||||
|
||||
| T_LABEL K_vpi_call T_STRING ';'
|
||||
{ compile_vpi_call($1, $3); }
|
||||
|
||||
| K_vpi_call T_STRING ';'
|
||||
{ compile_vpi_call(0, $2); }
|
||||
|
||||
/* Thread statements declare a thread with its starting address. The
|
||||
starting address must already be defined. */
|
||||
|
||||
|
|
|
|||
47
vvp/vpi.txt
47
vvp/vpi.txt
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* $Id: vpi.txt,v 1.1 2001/03/14 19:26:58 steve Exp $
|
||||
* $Id: vpi.txt,v 1.2 2001/03/16 01:44:34 steve Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -47,16 +47,43 @@ access to the system task call by calling back the VPI requesting the
|
|||
handle. It uses the handle, in turn, to get hold of the operands for
|
||||
the task.
|
||||
|
||||
In VPI Land, there is a vpiHandle for each system task call. However,
|
||||
since only one is accessible at a time, there is no need for more then
|
||||
the one that is active. Therefore, vvp will construct the vpiHande for
|
||||
the task call at the time the call is made.
|
||||
|
||||
All that vvp needs to know about a system task call is the handle of
|
||||
the system task (created by the vpi_register_systf function) and the
|
||||
arguments of the actual call. The arguments are tricky because the
|
||||
list has no bound, even though each particular call in the Verilog
|
||||
source has a specific set of parameters.
|
||||
the system task definitions (created by the vpi_register_systf
|
||||
function) and the arguments of the actual call. The arguments are
|
||||
tricky because the list has no bound, even though each particular call
|
||||
in the Verilog source has a specific set of parameters.
|
||||
|
||||
Since each call takes a fixed number of parameters, the input source
|
||||
can include in the statement the list of arguments. The argument list
|
||||
will not fit in a single generated instruction, but a vpiHandle that
|
||||
refers to a vpiSysTfCall does. Therefore, the compiler can take the
|
||||
long argument list and form a vpiSysTaskCall object. The generated
|
||||
instruction then only needs to be a %vpi_call with the single parameter
|
||||
that is the vpiHandle for the call.
|
||||
|
||||
|
||||
SYSTEM FUNCTION CALLS
|
||||
|
||||
System function calls are similar to system tasks. The only
|
||||
differences are that all the arguments are input only, and there is a
|
||||
single magic output that is the return value. The same %vpi_call can
|
||||
even be used to call a function.
|
||||
|
||||
System functions, like system tasks, can only be called from thread
|
||||
code. However, they can appear in expressions, even when that
|
||||
expression is entirely structural. The desired effect is achieved by
|
||||
writing a wrapper thread that calls the function when inputs change,
|
||||
and that writes the output into the containing expression.
|
||||
|
||||
|
||||
SYSTEM TASK/FUNCTION ARGUMENTS
|
||||
|
||||
The arguments to each system task or call are not stored in the
|
||||
instruction op-code, but in the vpiSysTfCall object that the compiler
|
||||
creates and that the %vpi_call instruction ultimately refers to. All
|
||||
the arguments must be some sort of object that can be represented by a
|
||||
vpiHandle at compile time.
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_iter.cc,v 1.1 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find here the methods functions in support of iterator objects.
|
||||
*/
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
static const struct __vpirt vpip_iterator_rt = {
|
||||
vpiIterator,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
vpiHandle vpip_make_iterator(unsigned nargs, vpiHandle*args)
|
||||
{
|
||||
struct __vpiIterator*res = (struct __vpiIterator*)
|
||||
calloc(1, sizeof(struct __vpiIterator));
|
||||
res->base.vpi_type = &vpip_iterator_rt;
|
||||
res->args = args;
|
||||
res->nargs = nargs;
|
||||
res->next = 0;
|
||||
|
||||
return &(res->base);
|
||||
}
|
||||
|
||||
/*
|
||||
* The vpi_scan function only applies to iterators. It returns the
|
||||
* next vpiHandle in the iterated list.
|
||||
*/
|
||||
vpiHandle vpi_scan(vpiHandle ref)
|
||||
{
|
||||
struct __vpiIterator*hp = (struct __vpiIterator*)ref;
|
||||
assert(ref->vpi_type->type_code == vpiIterator);
|
||||
|
||||
if (hp->next == hp->nargs) {
|
||||
vpi_free_object(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hp->args[hp->next++];
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_iter.cc,v $
|
||||
* Revision 1.1 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Stephen G. Tell <steve@telltronics.org>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_mcd.cc,v 1.1 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <assert.h>
|
||||
# include <stdarg.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
struct mcd_entry {
|
||||
FILE *fp;
|
||||
char *filename;
|
||||
};
|
||||
|
||||
static struct mcd_entry mcd_table[32];
|
||||
|
||||
/* Initialize mcd portion of vpi. Must be called before
|
||||
* any vpi_mcd routines can be used.
|
||||
*/
|
||||
void vpi_mcd_init(void)
|
||||
{
|
||||
mcd_table[0].fp = stdout;
|
||||
mcd_table[0].filename = "<stdout>";
|
||||
mcd_table[1].fp = stderr;
|
||||
mcd_table[1].filename = "<stderr>";
|
||||
mcd_table[2].fp = stdout; /* TODO: initialize this to log file */
|
||||
mcd_table[2].filename = "<stdlog>";
|
||||
}
|
||||
|
||||
/*
|
||||
* close one or more channels. we silently refuse to close the preopened ones.
|
||||
*/
|
||||
unsigned int vpi_mcd_close(unsigned int mcd)
|
||||
{
|
||||
int i;
|
||||
int rc;
|
||||
rc = 0;
|
||||
for(i = 3; i < 31; i++) {
|
||||
if( ((mcd>>i) & 1) && mcd_table[i].filename) {
|
||||
if(fclose(mcd_table[i].fp) != 0)
|
||||
rc |= 1<<i;
|
||||
free(mcd_table[i].filename);
|
||||
mcd_table[i].fp = NULL;
|
||||
mcd_table[i].filename = NULL;
|
||||
} else {
|
||||
rc |= 1<<i;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
char *vpi_mcd_name(unsigned int mcd)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 31; i++) {
|
||||
if( (mcd>>i) & 1)
|
||||
return mcd_table[i].filename;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int vpi_mcd_open(char *name)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 31; i++) {
|
||||
if(mcd_table[i].filename == NULL)
|
||||
goto got_entry;
|
||||
}
|
||||
return 0; /* too many open mcd's */
|
||||
|
||||
got_entry:
|
||||
mcd_table[i].fp = fopen(name, "w");
|
||||
if(mcd_table[i].fp == NULL)
|
||||
return 0;
|
||||
mcd_table[i].filename = strdup(name);
|
||||
return 1<<i;
|
||||
}
|
||||
|
||||
int vpi_mcd_printf(unsigned int mcd, const char*fmt, ...)
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
int rc;
|
||||
va_list ap;
|
||||
|
||||
rc = len = 0;
|
||||
va_start(ap, fmt);
|
||||
for(i = 0; i < 31; i++) {
|
||||
if( (mcd>>i) & 1) {
|
||||
if(mcd_table[i].fp)
|
||||
len = vfprintf(mcd_table[i].fp, fmt, ap);
|
||||
else
|
||||
rc = EOF;
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if(rc)
|
||||
return rc;
|
||||
else
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_modules.cc,v 1.1 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "vpi_priv.h"
|
||||
# include "ivl_dlfcn.h"
|
||||
# include <stdio.h>
|
||||
|
||||
typedef void (*vlog_startup_routines_t)(void);
|
||||
|
||||
void vpip_load_modules(unsigned cnt, const char*mod[], const char*path)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
char buf[4096];
|
||||
sprintf(buf, "%s/%s.vpi", path, mod[idx]);
|
||||
printf("Load %s...\n", buf);
|
||||
|
||||
ivl_dll_t dll = ivl_dlopen(buf);
|
||||
if (dll == 0) {
|
||||
fprintf(stderr, "%s: %s\n", mod[idx], dlerror());
|
||||
continue;
|
||||
}
|
||||
|
||||
void*table = ivl_dlsym(dll, LU "vlog_startup_routines" TU);
|
||||
if (table == 0) {
|
||||
fprintf(stderr, "%s: no vlog_startup_routines\n", mod[idx]);
|
||||
ivl_dlclose(dll);
|
||||
continue;
|
||||
}
|
||||
|
||||
vlog_startup_routines_t*routines = (vlog_startup_routines_t*)table;
|
||||
for (unsigned tmp = 0 ; routines[tmp] ; tmp += 1)
|
||||
(routines[tmp])();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_modules.cc,v $
|
||||
* Revision 1.1 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_priv.cc,v 1.1 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
# include <stdio.h>
|
||||
# include <stdarg.h>
|
||||
# include <assert.h>
|
||||
# include <malloc.h>
|
||||
|
||||
/*
|
||||
* When a task is called, this value is set so that vpi_handle can
|
||||
* fathom the vpi_handle(vpiSysTfCall,0) function.
|
||||
*/
|
||||
struct __vpiSysTaskCall*vpip_cur_task = 0;
|
||||
|
||||
int vpi_free_object(vpiHandle ref)
|
||||
{
|
||||
free(ref);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vpip_get_global(int property)
|
||||
{
|
||||
switch (property) {
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int vpi_get(int property, vpiHandle ref)
|
||||
{
|
||||
if (property == vpiType)
|
||||
return ref->vpi_type->type_code;
|
||||
|
||||
if (ref == 0)
|
||||
return vpip_get_global(property);
|
||||
|
||||
if (ref->vpi_type->vpi_get_ == 0)
|
||||
return -1;
|
||||
|
||||
return (ref->vpi_type->vpi_get_)(property, ref);
|
||||
}
|
||||
|
||||
char* vpi_get_str(int property, vpiHandle ref)
|
||||
{
|
||||
if (ref->vpi_type->vpi_get_str_ == 0)
|
||||
return 0;
|
||||
|
||||
return (ref->vpi_type->vpi_get_str_)(property, ref);
|
||||
}
|
||||
|
||||
void vpi_get_time(vpiHandle obj, s_vpi_time*t)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void vpi_get_value(vpiHandle expr, s_vpi_value*vp)
|
||||
{
|
||||
if (expr->vpi_type->vpi_get_value_) {
|
||||
(expr->vpi_type->vpi_get_value_)(expr, vp);
|
||||
return;
|
||||
}
|
||||
|
||||
vp->format = vpiSuppressVal;
|
||||
}
|
||||
|
||||
vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp,
|
||||
s_vpi_time*tp, int flags)
|
||||
{
|
||||
if (obj->vpi_type->vpi_put_value_)
|
||||
return (obj->vpi_type->vpi_put_value_)(obj, vp, tp, flags);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
vpiHandle vpi_handle(int type, vpiHandle ref)
|
||||
{
|
||||
if (type == vpiSysTfCall) {
|
||||
assert(ref == 0);
|
||||
return &vpip_cur_task->base;
|
||||
}
|
||||
|
||||
assert(ref->vpi_type->handle_);
|
||||
return (ref->vpi_type->handle_)(type, ref);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function asks the object to return an iterator for
|
||||
* the specified reference. It is up to the iterate_ method to
|
||||
* allocate a properly formed iterator.
|
||||
*/
|
||||
vpiHandle vpi_iterate(int type, vpiHandle ref)
|
||||
{
|
||||
assert(ref->vpi_type->iterate_);
|
||||
return (ref->vpi_type->iterate_)(type, ref);
|
||||
}
|
||||
|
||||
vpiHandle vpi_handle_by_index(vpiHandle ref, int idx)
|
||||
{
|
||||
assert(ref->vpi_type->index_);
|
||||
return (ref->vpi_type->index_)(ref, idx);
|
||||
}
|
||||
|
||||
void vpi_printf(const char*fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
/* STUBS */
|
||||
|
||||
vpiHandle vpi_register_cb(p_cb_data data)
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int vpi_remove_cb(vpiHandle ref)
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vpi_sim_control(int operation, ...)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.cc,v $
|
||||
* Revision 1.1 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
#ifndef __vpi_priv_H
|
||||
#define __vpi_priv_H
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_priv.h,v 1.1 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
|
||||
/*
|
||||
* This header file contains the internal definitions that the vvp
|
||||
* program uses to implement the public interface in the vpi_user.h
|
||||
* header file elsewhere.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This structure is the very base of a vpiHandle. Every handle
|
||||
* structure starts with this structure, so that the library can
|
||||
* internally pass the derived types as pointers to one of these.
|
||||
*/
|
||||
struct __vpiHandle {
|
||||
const struct __vpirt *vpi_type;
|
||||
};
|
||||
|
||||
/*
|
||||
* Objects with this structure are used to represent a type of
|
||||
* vpiHandle. A specific object becomes of this type by holding a
|
||||
* pointer to an instance of this structure.
|
||||
*/
|
||||
struct __vpirt {
|
||||
int type_code;
|
||||
|
||||
/* These methods extract information from the handle. */
|
||||
int (*vpi_get_)(int, vpiHandle);
|
||||
char* (*vpi_get_str_)(int, vpiHandle);
|
||||
void (*vpi_get_value_)(vpiHandle, p_vpi_value);
|
||||
vpiHandle (*vpi_put_value_)(vpiHandle, p_vpi_value, p_vpi_time, int);
|
||||
|
||||
/* These methods follow references. */
|
||||
vpiHandle (*handle_)(int, vpiHandle);
|
||||
vpiHandle (*iterate_)(int, vpiHandle);
|
||||
vpiHandle (*index_)(vpiHandle, int);
|
||||
};
|
||||
|
||||
/*
|
||||
* The vpiHandle for an iterator has this structure. The definition of
|
||||
* the methods lives in vpi_iter.c
|
||||
*/
|
||||
struct __vpiIterator {
|
||||
struct __vpiHandle base;
|
||||
vpiHandle *args;
|
||||
unsigned nargs;
|
||||
unsigned next;
|
||||
};
|
||||
|
||||
/*
|
||||
* When a loaded VPI module announces a system task/function, one
|
||||
* __vpiUserSystf object is created to hold the definition of that
|
||||
* task/function.
|
||||
*
|
||||
* When the compiler encounters a %vpi_call statement, it creates a
|
||||
* __vpiSysTaskCall to represent that particular call. The call refers
|
||||
* to the definition handle so that when the %vpi_call instruction is
|
||||
* encountered at run-time, the definition can be located and used.
|
||||
*/
|
||||
struct __vpiUserSystf {
|
||||
struct __vpiHandle base;
|
||||
s_vpi_systf_data info;
|
||||
};
|
||||
|
||||
struct __vpiSysTaskCall {
|
||||
struct __vpiHandle base;
|
||||
struct __vpiUserSystf*defn;
|
||||
unsigned nargs;
|
||||
vpiHandle*args;
|
||||
};
|
||||
|
||||
extern struct __vpiSysTaskCall*vpip_cur_task;
|
||||
|
||||
/*
|
||||
* This function is called before any compilation to load VPI
|
||||
* modules. This gives the modules a chance to announce their
|
||||
* contained functions before compilation commences. It is called only
|
||||
* once.
|
||||
*/
|
||||
extern void vpip_load_modules(unsigned cnt, const char*tab[], const char*path);
|
||||
|
||||
/*
|
||||
* The vpip_build_vpi_call function creates a __vpiSysTaskCall object
|
||||
* and returns the handle. The compiler uses this function when it
|
||||
* encounters a %vpi_call statement.
|
||||
*
|
||||
* The %vpi_call instruction has as its only parameter the handle that
|
||||
* is returned by the vpip_build_vpi_call. This includes all the
|
||||
* information needed by vpip_execute_vpi_call to actually execute the
|
||||
* call.
|
||||
*/
|
||||
extern vpiHandle vpip_build_vpi_call(const char*name);
|
||||
|
||||
extern void vpip_execute_vpi_call(vpiHandle obj);
|
||||
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.h,v $
|
||||
* Revision 1.1 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vpi_tasks.cc,v 1.1 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file keeps the table of system/task definitions. This table is
|
||||
* built up before the input source file is parsed, and is used by the
|
||||
* compiler when %vpi_call statements are encountered.
|
||||
*/
|
||||
# include "vpi_priv.h"
|
||||
# include <stdio.h>
|
||||
# include <malloc.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
static vpiHandle systask_handle(int type, vpiHandle ref)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* the iter function only supports getting an iterator of the
|
||||
* arguments. This works equally well for tasks and functions.
|
||||
*/
|
||||
static vpiHandle systask_iter(int type, vpiHandle ref)
|
||||
{
|
||||
struct __vpiSysTaskCall*rfp = (struct __vpiSysTaskCall*)ref;
|
||||
assert((ref->vpi_type->type_code == vpiSysTaskCall)
|
||||
|| (ref->vpi_type->type_code == vpiSysFuncCall));
|
||||
|
||||
if (rfp->nargs == 0)
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
return vpip_make_iterator(rfp->nargs, rfp->args);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct __vpirt vpip_systask_rt = {
|
||||
vpiSysTaskCall,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
systask_handle,
|
||||
systask_iter
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* A value *can* be put to a vpiSysFuncCall object. This is how the
|
||||
* return value is set. The value that is given should be converted to
|
||||
* bits and set into the return value bit array.
|
||||
*/
|
||||
static vpiHandle sysfunc_put_value(vpiHandle ref, p_vpi_value val,
|
||||
p_vpi_time t, int flag)
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct __vpirt vpip_sysfunc_rt = {
|
||||
vpiSysFuncCall,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
sysfunc_put_value,
|
||||
0,
|
||||
systask_iter
|
||||
};
|
||||
|
||||
/* **** Manipulate the internal datastructures. **** */
|
||||
|
||||
static struct __vpiUserSystf**def_table = 0;
|
||||
static unsigned def_count = 0;
|
||||
|
||||
static struct __vpiUserSystf* allocate_def(void)
|
||||
{
|
||||
if (def_table == 0) {
|
||||
def_table = (struct __vpiUserSystf**)
|
||||
malloc(sizeof (struct __vpiUserSystf*));
|
||||
|
||||
def_table[0] = (struct __vpiUserSystf*)
|
||||
calloc(1, sizeof(struct __vpiUserSystf));
|
||||
|
||||
def_count = 1;
|
||||
return def_table[0];
|
||||
}
|
||||
|
||||
def_table = (struct __vpiUserSystf**)
|
||||
realloc(def_table, (def_count+1)*sizeof (struct __vpiUserSystf*));
|
||||
|
||||
def_table[def_count] = (struct __vpiUserSystf*)
|
||||
calloc(1, sizeof(struct __vpiUserSystf));
|
||||
|
||||
return def_table[def_count++];
|
||||
}
|
||||
|
||||
|
||||
static struct __vpiUserSystf* vpip_find_systf(const char*name)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < def_count ; idx += 1)
|
||||
if (strcmp(def_table[idx]->info.tfname, name) == 0)
|
||||
return def_table[idx];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A vpi_call is actually built up into a vpiSysTaskCall VPI object
|
||||
* that refers back to the vpiUserSystf VPI object that is the
|
||||
* definition. So this function is called by the compiler when a
|
||||
* %vpi_call statement is encountered. Create here a vpiHandle that
|
||||
* describes the call, and return it. The %vpi_call instruction will
|
||||
* store this handle for when it is executed.
|
||||
*/
|
||||
vpiHandle vpip_build_vpi_call(const char*name)
|
||||
{
|
||||
struct __vpiSysTaskCall*obj = (struct __vpiSysTaskCall*)
|
||||
calloc(1, sizeof (struct __vpiSysTaskCall));
|
||||
|
||||
obj->base.vpi_type = &vpip_systask_rt;
|
||||
obj->defn = vpip_find_systf(name);
|
||||
obj->nargs = 0;
|
||||
obj->args = 0;
|
||||
|
||||
/* If there is a compiletf function, call it here. */
|
||||
if (obj->defn->info.compiletf)
|
||||
obj->defn->info.compiletf (obj->defn->info.user_data);
|
||||
|
||||
return &obj->base;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function is used by the %vpi_call instruction to actually
|
||||
* place the call to the system task/function. For now, only support
|
||||
* calls to system tasks.
|
||||
*/
|
||||
void vpip_execute_vpi_call(vpiHandle ref)
|
||||
{
|
||||
assert(ref->vpi_type->type_code == vpiSysTaskCall);
|
||||
|
||||
vpip_cur_task = (struct __vpiSysTaskCall*)ref;
|
||||
|
||||
assert(vpip_cur_task->defn->info.calltf);
|
||||
vpip_cur_task->defn->info.calltf (vpip_cur_task->defn->info.user_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the entry function that a VPI module uses to hook a new
|
||||
* task/function into the simulator. The function creates a new
|
||||
* __vpi_userSystf to represent the definition for the calls that come
|
||||
* to pass later.
|
||||
*/
|
||||
void vpi_register_systf(const struct t_vpi_systf_data*ss)
|
||||
{
|
||||
struct __vpiUserSystf*cur = allocate_def();
|
||||
cur->info = *ss;
|
||||
cur->info.tfname = strdup(ss->tfname);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vpi_tasks.cc,v $
|
||||
* Revision 1.1 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -17,13 +17,14 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vthread.cc,v 1.3 2001/03/11 23:06:49 steve Exp $"
|
||||
#ident "$Id: vthread.cc,v 1.4 2001/03/16 01:44:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vthread.h"
|
||||
# include "codes.h"
|
||||
# include "schedule.h"
|
||||
# include "functor.h"
|
||||
# include "vpi_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
struct vthread_s {
|
||||
|
|
@ -53,6 +54,7 @@ void vthread_run(vthread_t thr)
|
|||
vvp_code_t cp = codespace_index(thr->pc);
|
||||
thr->pc += 1;
|
||||
|
||||
assert(cp->opcode);
|
||||
bool rc = (cp->opcode)(thr, cp);
|
||||
if (rc == false)
|
||||
return;
|
||||
|
|
@ -110,8 +112,19 @@ bool of_SET(vthread_t thr, vvp_code_t cp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool of_VPI_CALL(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
printf("thread %p: %%vpi_call\n", thr);
|
||||
vpip_execute_vpi_call(cp->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vthread.cc,v $
|
||||
* Revision 1.4 2001/03/16 01:44:34 steve
|
||||
* Add structures for VPI support, and all the %vpi_call
|
||||
* instruction. Get linking of VPI modules to work.
|
||||
*
|
||||
* Revision 1.3 2001/03/11 23:06:49 steve
|
||||
* Compact the vvp_code_s structure.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue