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
|
# 59 Temple Place - Suite 330
|
||||||
# Boston, MA 02111-1307, USA
|
# 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
|
SHELL = /bin/sh
|
||||||
|
|
@ -43,6 +43,9 @@ CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||||
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)
|
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = @LDFLAGS@
|
||||||
|
|
||||||
|
dllib=@DLLIB@
|
||||||
|
rdynamic=@rdynamic@
|
||||||
|
|
||||||
all: vvp
|
all: vvp
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
@ -51,11 +54,13 @@ clean:
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f config.h Makefile config.cache config.log config.status
|
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 \
|
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
|
vvp: $O
|
||||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o vvp $O
|
$(CXX) $(rdynamic) $(CXXFLAGS) $(LDFLAGS) -o vvp $O $(dllib)
|
||||||
|
|
||||||
|
|
||||||
%.o: %.cc
|
%.o: %.cc
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#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_END(vthread_t thr, vvp_code_t code);
|
||||||
extern bool of_SET(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_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.
|
* This is the format of a machine code instruction.
|
||||||
|
|
@ -51,6 +52,7 @@ struct vvp_code_s {
|
||||||
unsigned number;
|
unsigned number;
|
||||||
vvp_ipoint_t iptr;
|
vvp_ipoint_t iptr;
|
||||||
vvp_cpoint_t cptr;
|
vvp_cpoint_t cptr;
|
||||||
|
struct __vpiHandle*handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned short bit_idx1;
|
unsigned short bit_idx1;
|
||||||
|
|
@ -83,6 +85,10 @@ extern void codespace_dump(FILE*fd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: codes.h,v $
|
* $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
|
* Revision 1.2 2001/03/11 23:06:49 steve
|
||||||
* Compact the vvp_code_s structure.
|
* Compact the vvp_code_s structure.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include "compile.h"
|
# include "compile.h"
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
# include "symbols.h"
|
# include "symbols.h"
|
||||||
# include "codes.h"
|
# include "codes.h"
|
||||||
# include "schedule.h"
|
# include "schedule.h"
|
||||||
|
# include "vpi_priv.h"
|
||||||
# include "vthread.h"
|
# include "vthread.h"
|
||||||
# include "parse_misc.h"
|
# include "parse_misc.h"
|
||||||
# include <malloc.h>
|
# include <malloc.h>
|
||||||
|
|
@ -297,6 +298,30 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
|
||||||
free(mnem);
|
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
|
* When the parser finds a thread statement, I create a new thread
|
||||||
* with the start address referenced by the program symbol passed to
|
* with the start address referenced by the program symbol passed to
|
||||||
|
|
@ -391,6 +416,10 @@ void compile_dump(FILE*fd)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: compile.cc,v $
|
* $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
|
* Revision 1.3 2001/03/11 23:06:49 steve
|
||||||
* Compact the vvp_code_s structure.
|
* Compact the vvp_code_s structure.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
|
|
@ -77,6 +77,7 @@ struct comp_operands_s {
|
||||||
typedef struct comp_operands_s*comp_operands_t;
|
typedef struct comp_operands_s*comp_operands_t;
|
||||||
|
|
||||||
extern void compile_code(char*label, char*mnem, comp_operands_t opa);
|
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
|
* 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 $
|
* $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
|
* Revision 1.2 2001/03/11 22:42:11 steve
|
||||||
* Functor values and propagation.
|
* Functor values and propagation.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,24 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# define SIZEOF_UNSIGNED_LONG 0
|
# define SIZEOF_UNSIGNED_LONG 0
|
||||||
# define SIZEOF_UNSIGNED 0
|
# define SIZEOF_UNSIGNED 0
|
||||||
|
|
||||||
|
# undef HAVE_DLFCN_H
|
||||||
|
# undef HAVE_DL_H
|
||||||
|
|
||||||
|
# define LU ""
|
||||||
|
# define TU ""
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: config.h.in,v $
|
* $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
|
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||||
* Add the vvp engine to cvs.
|
* Add the vvp engine to cvs.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,45 @@ AC_PROG_INSTALL
|
||||||
AC_CHECK_SIZEOF(unsigned long)
|
AC_CHECK_SIZEOF(unsigned long)
|
||||||
AC_CHECK_SIZEOF(unsigned)
|
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)
|
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);
|
yylval.text = strdup(yytext);
|
||||||
return T_LABEL; }
|
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. */
|
/* These are some keywords that are recognized. */
|
||||||
".functor" { return K_FUNCTOR; }
|
".functor" { return K_FUNCTOR; }
|
||||||
|
|
@ -21,7 +28,12 @@
|
||||||
|
|
||||||
|
|
||||||
/* instructions start with a % character. The compiler decides what
|
/* 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]+ {
|
"%"[.$_/a-zA-Z0-9]+ {
|
||||||
yylval.text = strdup(yytext);
|
yylval.text = strdup(yytext);
|
||||||
return T_INSTR; }
|
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
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
# include "parse_misc.h"
|
# include "parse_misc.h"
|
||||||
# include "compile.h"
|
# include "compile.h"
|
||||||
# include "schedule.h"
|
# include "schedule.h"
|
||||||
|
# include "vpi_priv.h"
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
# include <getopt.h>
|
# include <getopt.h>
|
||||||
|
|
||||||
|
|
||||||
|
const char*module_path = ".";
|
||||||
|
unsigned module_cnt = 0;
|
||||||
|
const char*module_tab[64];
|
||||||
|
|
||||||
int main(int argc, char*argv[])
|
int main(int argc, char*argv[])
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
|
|
@ -35,10 +40,16 @@ int main(int argc, char*argv[])
|
||||||
const char*dump_path = 0;
|
const char*dump_path = 0;
|
||||||
const char*design_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':
|
case 'D':
|
||||||
dump_path = optarg;
|
dump_path = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
module_path = optarg;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
module_tab[module_cnt++] = optarg;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
flag_errors += 1;
|
flag_errors += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -54,6 +65,7 @@ int main(int argc, char*argv[])
|
||||||
design_path = argv[optind];
|
design_path = argv[optind];
|
||||||
|
|
||||||
compile_init();
|
compile_init();
|
||||||
|
vpip_load_modules(module_cnt, module_tab, module_path);
|
||||||
compile_design(design_path);
|
compile_design(design_path);
|
||||||
compile_cleanup();
|
compile_cleanup();
|
||||||
|
|
||||||
|
|
@ -69,6 +81,10 @@ int main(int argc, char*argv[])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: main.cc,v $
|
* $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
|
* Revision 1.1 2001/03/11 00:29:38 steve
|
||||||
* Add the vvp engine to cvs.
|
* 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
|
be read out of the variable. The <bit> is the address of the thread
|
||||||
register that contains the bit value to assign.
|
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>
|
* %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_INSTR
|
||||||
%token <text> T_LABEL
|
%token <text> T_LABEL
|
||||||
%token <numb> T_NUMBER
|
%token <numb> T_NUMBER
|
||||||
|
%token <text> T_STRING
|
||||||
%token <text> T_SYMBOL
|
%token <text> T_SYMBOL
|
||||||
|
|
||||||
%type <textv> symbols
|
%type <textv> symbols
|
||||||
|
|
@ -69,6 +70,15 @@ statement
|
||||||
{ compile_code(0, $1, $2);
|
{ 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
|
/* Thread statements declare a thread with its starting address. The
|
||||||
starting address must already be defined. */
|
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)
|
* 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
|
handle. It uses the handle, in turn, to get hold of the operands for
|
||||||
the task.
|
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
|
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
|
the system task definitions (created by the vpi_register_systf
|
||||||
arguments of the actual call. The arguments are tricky because the
|
function) and the arguments of the actual call. The arguments are
|
||||||
list has no bound, even though each particular call in the Verilog
|
tricky because the list has no bound, even though each particular call
|
||||||
source has a specific set of parameters.
|
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)
|
* 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
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#if !defined(WINNT)
|
#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
|
#endif
|
||||||
|
|
||||||
# include "vthread.h"
|
# include "vthread.h"
|
||||||
# include "codes.h"
|
# include "codes.h"
|
||||||
# include "schedule.h"
|
# include "schedule.h"
|
||||||
# include "functor.h"
|
# include "functor.h"
|
||||||
|
# include "vpi_priv.h"
|
||||||
# include <assert.h>
|
# include <assert.h>
|
||||||
|
|
||||||
struct vthread_s {
|
struct vthread_s {
|
||||||
|
|
@ -53,6 +54,7 @@ void vthread_run(vthread_t thr)
|
||||||
vvp_code_t cp = codespace_index(thr->pc);
|
vvp_code_t cp = codespace_index(thr->pc);
|
||||||
thr->pc += 1;
|
thr->pc += 1;
|
||||||
|
|
||||||
|
assert(cp->opcode);
|
||||||
bool rc = (cp->opcode)(thr, cp);
|
bool rc = (cp->opcode)(thr, cp);
|
||||||
if (rc == false)
|
if (rc == false)
|
||||||
return;
|
return;
|
||||||
|
|
@ -110,8 +112,19 @@ bool of_SET(vthread_t thr, vvp_code_t cp)
|
||||||
return true;
|
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 $
|
* $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
|
* Revision 1.3 2001/03/11 23:06:49 steve
|
||||||
* Compact the vvp_code_s structure.
|
* Compact the vvp_code_s structure.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue