From a59b183bd1890eff63cc59d38084dde15de281ff Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 22 Oct 2019 16:00:13 +0100 Subject: [PATCH] Allow VPI modules to be loaded by multiple clients under Windows. The old scheme of linking the VPI modules with the vvp exports meant they did not work when loaded by the compiler. Instead, let each client create a jump table for the VPI routines and pass that to each VPI module as it is loaded. --- cadpli/Makefile.in | 2 +- driver-vpi/config.h.in | 4 +- iverilog-vpi.sh | 4 +- libveriuser/Makefile.in | 2 +- vpi/Makefile.in | 45 ++++++++++------- {vvp => vpi}/libvpi.c | 11 +++-- vpi_modules.cc | 53 ++++++++++++++++++++ vpi_user.h | 107 +++++++++++++++++++++++++++++++++++++++- vvp/Makefile.in | 34 ++----------- vvp/cppcheck.sup | 4 -- vvp/vpi_modules.cc | 8 +++ vvp/vpi_priv.cc | 44 +++++++++++++++++ vvp/vpi_priv.h | 2 + vvp/vvp.def | 45 ----------------- 14 files changed, 257 insertions(+), 108 deletions(-) rename {vvp => vpi}/libvpi.c (79%) delete mode 100644 vvp/vvp.def diff --git a/cadpli/Makefile.in b/cadpli/Makefile.in index 8d9af5a51..6c811c808 100644 --- a/cadpli/Makefile.in +++ b/cadpli/Makefile.in @@ -71,7 +71,7 @@ dep: $(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< mv $*.d dep -SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi +SYSTEM_VPI_LDFLAGS = -L../vpi -lvpi ifeq (@MINGW32@,yes) SYSTEM_VPI_LDFLAGS += @EXTRALIBS@ endif diff --git a/driver-vpi/config.h.in b/driver-vpi/config.h.in index 2b6789dd4..eacfbc1db 100644 --- a/driver-vpi/config.h.in +++ b/driver-vpi/config.h.in @@ -3,8 +3,8 @@ * This may change in the future once I have thought about it more. */ #define IVERILOG_VPI_CC "@IVLCC@" #define IVERILOG_VPI_CXX "@IVLCXX@" -#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@" -#define IVERILOG_VPI_CXXFLAGS " @IVLCXXFLAGS@" +#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@ -DIVL_VPI_MODULE" +#define IVERILOG_VPI_CXXFLAGS " @IVLCXXFLAGS@ -DIVL_VPI_MODULE" #define IVERILOG_VPI_LDFLAGS "@SHARED@" #define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@" #define IVERILOG_SUFFIX "@SUFFIX@" diff --git a/iverilog-vpi.sh b/iverilog-vpi.sh index 026e3e6ea..f350a4e52 100644 --- a/iverilog-vpi.sh +++ b/iverilog-vpi.sh @@ -21,8 +21,8 @@ # These are the variables used for compiling files CC="@IVCC@" CXX=@IVCXX@ -CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@" -CXXFLAGS="@PIC@ @IVCXXFLAGS@ -I@INCLUDEDIR@" +CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@ -DIVL_VPI_MODULE" +CXXFLAGS="@PIC@ @IVCXXFLAGS@ -I@INCLUDEDIR@ -DIVL_VPI_MODULE" SUFFIX=@SUFFIX@ diff --git a/libveriuser/Makefile.in b/libveriuser/Makefile.in index 461b4a526..ad86ba3c2 100644 --- a/libveriuser/Makefile.in +++ b/libveriuser/Makefile.in @@ -47,7 +47,7 @@ LDRELOCFLAGS = @LDRELOCFLAGS@ LDTARGETFLAGS = @LDTARGETFLAGS@ -CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const @PICFLAG@ +CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const -DIVL_VPI_MODULE @PICFLAG@ CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@ A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \ diff --git a/vpi/Makefile.in b/vpi/Makefile.in index abb1e10ae..783bc0393 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -45,7 +45,7 @@ else INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/.. endif -CPPFLAGS = $(INCLUDE_PATH) @file64_support@ @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const @PICFLAG@ +CPPFLAGS = $(INCLUDE_PATH) @file64_support@ @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const -DIVL_VPI_MODULE @PICFLAG@ CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ LDFLAGS = @LDFLAGS@ @@ -83,12 +83,12 @@ VHDL_TEXTIO = vhdl_textio.o sys_priv.o VPI_DEBUG = vpi_debug.o -all: dep system.vpi va_math.vpi v2005_math.vpi v2009.vpi vhdl_sys.vpi vhdl_textio.vpi vpi_debug.vpi $(ALL32) +all: dep libvpi.a system.vpi va_math.vpi v2005_math.vpi v2009.vpi vhdl_sys.vpi vhdl_textio.vpi vpi_debug.vpi $(ALL32) check: all clean: - rm -rf *.o sys_readmem_lex.c dep system.vpi + rm -rf *.o sys_readmem_lex.c dep libvpi.a system.vpi rm -f sdf_lexor.c sdf_parse.c sdf_parse.output sdf_parse.h rm -f table_mod_parse.c table_mod_parse.h table_mod_parse.output rm -f table_mod_lexor.c @@ -122,6 +122,12 @@ dep: $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o mv $*.d dep +libvpi.a: libvpi.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< + rm -f libvpi.a + $(AR) cqv libvpi.a libvpi.o + $(RANLIB) libvpi.a + LIBS = @LIBS@ SYSTEM_VPI_LDFLAGS = $(LIBS) VA_MATH_LDFLAGS = @@ -130,8 +136,8 @@ ifeq (@MINGW32@,yes) VA_MATH_LDFLAGS += @EXTRALIBS@ endif -system.vpi: $O $(OPP) ../vvp/libvpi.a - $(CXX) @shared@ -o $@ $O $(OPP) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) +system.vpi: $O $(OPP) libvpi.a + $(CXX) @shared@ -o $@ $O $(OPP) -L. $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) sys_readmem_lex.c: $(srcdir)/sys_readmem_lex.lex $(LEX) -t $< > $@ @@ -156,23 +162,23 @@ table_mod_parse.c: $(srcdir)/table_mod_parse.y $(YACC) --verbose -t -p tblmod -d -o $@ $< table_mod_parse.h: table_mod_parse.c -v2005_math.vpi: $M ../vvp/libvpi.a - $(CC) @shared@ -o $@ $M -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS) +v2005_math.vpi: $M libvpi.a + $(CC) @shared@ -o $@ $M -L. $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS) -v2009.vpi: $(V2009) ../vvp/libvpi.a - $(CC) @shared@ -o $@ $(V2009) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) +v2009.vpi: $(V2009) libvpi.a + $(CC) @shared@ -o $@ $(V2009) -L. $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) -va_math.vpi: $V ../vvp/libvpi.a - $(CC) @shared@ -o $@ $V -L../vvp $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS) +va_math.vpi: $V libvpi.a + $(CC) @shared@ -o $@ $V -L. $(LDFLAGS) -lvpi $(VA_MATH_VPI_LDFLAGS) -vhdl_sys.vpi: $(VHDL_SYS) ../vvp/libvpi.a - $(CC) @shared@ -o $@ $(VHDL_SYS) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) +vhdl_sys.vpi: $(VHDL_SYS) libvpi.a + $(CC) @shared@ -o $@ $(VHDL_SYS) -L. $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) -vhdl_textio.vpi: $(VHDL_TEXTIO) ../vvp/libvpi.a - $(CC) @shared@ -o $@ $(VHDL_TEXTIO) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) +vhdl_textio.vpi: $(VHDL_TEXTIO) libvpi.a + $(CC) @shared@ -o $@ $(VHDL_TEXTIO) -L. $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) -vpi_debug.vpi: $(VPI_DEBUG) ../vvp/libvpi.a - $(CC) @shared@ -o $@ $(VPI_DEBUG) -L../vvp $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) +vpi_debug.vpi: $(VPI_DEBUG) libvpi.a + $(CC) @shared@ -o $@ $(VPI_DEBUG) -L. $(LDFLAGS) -lvpi $(SYSTEM_VPI_LDFLAGS) stamp-vpi_config-h: $(srcdir)/vpi_config.h.in ../config.status @rm -f $@ @@ -180,6 +186,7 @@ stamp-vpi_config-h: $(srcdir)/vpi_config.h.in ../config.status vpi_config.h: stamp-vpi_config-h install: all installdirs \ + $(libdir)/libvpi$(suffix).a \ $(vpidir)/system.vpi \ $(vpidir)/va_math.vpi \ $(vpidir)/v2005_math.vpi \ @@ -188,6 +195,9 @@ install: all installdirs \ $(vpidir)/vhdl_textio.vpi \ $(vpidir)/vpi_debug.vpi +$(libdir)/libvpi$(suffix).a : ./libvpi.a + $(INSTALL_DATA) libvpi.a "$(DESTDIR)$(libdir)/libvpi$(suffix).a" + $(vpidir)/system.vpi: ./system.vpi $(INSTALL_PROGRAM) ./system.vpi "$(DESTDIR)$(vpidir)/system.vpi" @@ -213,6 +223,7 @@ installdirs: $(srcdir)/../mkinstalldirs $(srcdir)/../mkinstalldirs "$(DESTDIR)$(libdir)" "$(DESTDIR)$(vpidir)" uninstall: + rm -f "$(DESTDIR)$(libdir)/libvpi$(suffix).a" rm -f "$(DESTDIR)$(vpidir)/system.vpi" rm -f "$(DESTDIR)$(vpidir)/va_math.vpi" rm -f "$(DESTDIR)$(vpidir)/v2005_math.vpi" diff --git a/vvp/libvpi.c b/vpi/libvpi.c similarity index 79% rename from vvp/libvpi.c rename to vpi/libvpi.c index df6388f17..afa546ef6 100644 --- a/vvp/libvpi.c +++ b/vpi/libvpi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Stephen Williams (steve@icarus.com) + * Copyright (c) 2019 Martin Whitaker (icarus@martin-whitaker.me.uk) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -17,10 +17,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* - * Things that should be statically linked by VPI modules go here. - */ +#include "vpi_user.h" -void __libvpi_c_dummy_function(void) +vpip_routines_s*vpip = 0; + +DLLEXPORT void vpip_set_callback(vpip_routines_s*routines) { + vpip = routines; } diff --git a/vpi_modules.cc b/vpi_modules.cc index ec75d6f4f..0952f8913 100644 --- a/vpi_modules.cc +++ b/vpi_modules.cc @@ -184,6 +184,51 @@ vpiHandle vpi_register_systf(const struct t_vpi_systf_data*ss) return 0; } +vpip_routines_s vpi_routines = { + .register_cb = vpi_register_cb, + .remove_cb = vpi_remove_cb, + .register_systf = vpi_register_systf, + .get_systf_info = vpi_get_systf_info, + .handle_by_name = vpi_handle_by_name, + .handle_by_index = vpi_handle_by_index, + .handle = vpi_handle, + .iterate = vpi_iterate, + .scan = vpi_scan, + .get = vpi_get, + .get_str = vpi_get_str, + .get_delays = vpi_get_delays, + .put_delays = vpi_put_delays, + .get_value = vpi_get_value, + .put_value = vpi_put_value, + .get_time = vpi_get_time, + .get_userdata = vpi_get_userdata, + .put_userdata = vpi_put_userdata, + .mcd_open = vpi_mcd_open, + .mcd_close = vpi_mcd_close, + .mcd_flush = vpi_mcd_flush, + .mcd_name = vpi_mcd_name, + .mcd_printf = vpi_mcd_printf, + .mcd_vprintf = vpi_mcd_vprintf, + .flush = vpi_flush, + .printf = vpi_printf, + .vprintf = vpi_vprintf, + .chk_error = vpi_chk_error, + .compare_objects = vpi_compare_objects, + .free_object = vpi_free_object, + .get_vlog_info = vpi_get_vlog_info, + .control = vpi_control, + .sim_control = vpi_sim_control, + .fopen = vpi_fopen, + .get_file = vpi_get_file, + .calc_clog2 = vpip_calc_clog2, + .count_drivers = vpip_count_drivers, + .format_strength = vpip_format_strength, + .make_systf_system_defined = vpip_make_systf_system_defined, + .mcd_rawwrite = vpip_mcd_rawwrite, + .set_return_value = vpip_set_return_value, +}; + +typedef void (*vpip_set_callback_t)(vpip_routines_s*); typedef void (*vlog_startup_routines_t)(void); bool load_vpi_module(const char*path) @@ -195,6 +240,14 @@ bool load_vpi_module(const char*path) return false; } + vpip_set_callback_t set_callback = (vpip_set_callback_t)ivl_dlsym(dll, "vpip_set_callback"); + if (set_callback == 0) { + cerr << "warning: '" << path << "' has no vpip_set_callback()" << endl; + ivl_dlclose(dll); + return true; + } + set_callback(&vpi_routines); + #ifdef __MINGW32__ void*table = ivl_dlsym(dll, "vlog_startup_routines"); #else diff --git a/vpi_user.h b/vpi_user.h index 0be7fbfeb..18cb0de01 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -1,7 +1,7 @@ #ifndef VPI_USER_H #define VPI_USER_H /* - * Copyright (c) 1999-2018 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2019 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 @@ -675,6 +675,111 @@ extern void vpip_count_drivers(vpiHandle ref, unsigned idx, # define _vpi_at_APV 6 #endif +/* + * In Linux, a shared library can bind by name to functions provided by its + * client when it is loaded. In Windows, a DLL can only do this statically at + * link time, and is then tied to a specific client. So to enable VPI modules + * to be used by both the compiler and the simulator, we construct a jump table + * for the VPI routines that we can pass down to the VPI modules. + */ +typedef struct { + vpiHandle (*register_cb)(p_cb_data); + PLI_INT32 (*remove_cb)(vpiHandle); + vpiHandle (*register_systf)(const struct t_vpi_systf_data*ss); + void (*get_systf_info)(vpiHandle, p_vpi_systf_data); + vpiHandle (*handle_by_name)(const char*, vpiHandle); + vpiHandle (*handle_by_index)(vpiHandle, PLI_INT32); + vpiHandle (*handle)(PLI_INT32, vpiHandle); + vpiHandle (*iterate)(PLI_INT32, vpiHandle); + vpiHandle (*scan)(vpiHandle); + PLI_INT32 (*get)(int, vpiHandle); + char* (*get_str)(PLI_INT32, vpiHandle); + void (*get_delays)(vpiHandle, p_vpi_delay); + void (*put_delays)(vpiHandle, p_vpi_delay); + void (*get_value)(vpiHandle, p_vpi_value); + vpiHandle (*put_value)(vpiHandle, p_vpi_value, p_vpi_time, PLI_INT32); + void (*get_time)(vpiHandle, s_vpi_time*); + void* (*get_userdata)(vpiHandle); + PLI_INT32 (*put_userdata)(vpiHandle, void*); + PLI_UINT32 (*mcd_open)(char *); + PLI_UINT32 (*mcd_close)(PLI_UINT32); + PLI_INT32 (*mcd_flush)(PLI_UINT32); + char* (*mcd_name)(PLI_UINT32); + PLI_INT32 (*mcd_printf)(PLI_UINT32, const char*, ...); + PLI_INT32 (*mcd_vprintf)(PLI_UINT32, const char*, va_list); + PLI_INT32 (*flush)(void); + PLI_INT32 (*printf)(const char*, ...); + PLI_INT32 (*vprintf)(const char*, va_list); + PLI_INT32 (*chk_error)(p_vpi_error_info); + PLI_INT32 (*compare_objects)(vpiHandle, vpiHandle); + PLI_INT32 (*free_object)(vpiHandle); + PLI_INT32 (*get_vlog_info)(p_vpi_vlog_info info) ; + void (*control)(PLI_INT32, ...); + void (*sim_control)(PLI_INT32, ...); + PLI_INT32 (*fopen)(const char*, const char*); + FILE* (*get_file)(PLI_INT32); + s_vpi_vecval(*calc_clog2)(vpiHandle); + void (*count_drivers)(vpiHandle, unsigned, unsigned [4]); + void (*format_strength)(char*, s_vpi_value*, unsigned); + void (*make_systf_system_defined)(vpiHandle); + void (*mcd_rawwrite)(PLI_UINT32, const char*, size_t); + void (*set_return_value)(int); +} vpip_routines_s; + +extern DLLEXPORT void vpip_set_callback(vpip_routines_s*routines); + +/* + * IVL_VPI_MODULE should be defined when compiling a VPI module to route + * all VPI routine calls through the jump table. + */ +#ifdef IVL_VPI_MODULE + +extern vpip_routines_s*vpip; + +#define vpi_register_cb(...) vpip->register_cb(__VA_ARGS__) +#define vpi_remove_cb(...) vpip->remove_cb(__VA_ARGS__) +#define vpi_register_systf(...) vpip->register_systf(__VA_ARGS__) +#define vpi_get_systf_info(...) vpip->get_systf_info(__VA_ARGS__) +#define vpi_handle_by_name(...) vpip->handle_by_name(__VA_ARGS__) +#define vpi_handle_by_index(...) vpip->handle_by_index(__VA_ARGS__) +#define vpi_handle(...) vpip->handle(__VA_ARGS__) +#define vpi_iterate(...) vpip->iterate(__VA_ARGS__) +#define vpi_scan(...) vpip->scan(__VA_ARGS__) +#define vpi_get(...) vpip->get(__VA_ARGS__) +#define vpi_get_str(...) vpip->get_str(__VA_ARGS__) +#define vpi_get_delays(...) vpip->get_delays(__VA_ARGS__) +#define vpi_put_delays(...) vpip->put_delays(__VA_ARGS__) +#define vpi_get_value(...) vpip->get_value(__VA_ARGS__) +#define vpi_put_value(...) vpip->put_value(__VA_ARGS__) +#define vpi_get_time(...) vpip->get_time(__VA_ARGS__) +#define vpi_get_userdata(...) vpip->get_userdata(__VA_ARGS__) +#define vpi_put_userdata(...) vpip->put_userdata(__VA_ARGS__) +#define vpi_mcd_open(...) vpip->mcd_open(__VA_ARGS__) +#define vpi_mcd_close(...) vpip->mcd_close(__VA_ARGS__) +#define vpi_mcd_flush(...) vpip->mcd_flush(__VA_ARGS__) +#define vpi_mcd_name(...) vpip->mcd_name(__VA_ARGS__) +#define vpi_mcd_printf(...) vpip->mcd_printf(__VA_ARGS__) +#define vpi_mcd_vprintf(...) vpip->mcd_vprintf(__VA_ARGS__) +#define vpi_flush(...) vpip->flush(__VA_ARGS__) +#define vpi_printf(...) vpip->printf(__VA_ARGS__) +#define vpi_vprintf(...) vpip->vprintf(__VA_ARGS__) +#define vpi_chk_error(...) vpip->chk_error(__VA_ARGS__) +#define vpi_compare_objects(...) vpip->compare_objects(__VA_ARGS__) +#define vpi_free_object(...) vpip->free_object(__VA_ARGS__) +#define vpi_get_vlog_info(...) vpip->get_vlog_info(__VA_ARGS__) +#define vpi_control(...) vpip->control(__VA_ARGS__) +#define vpi_sim_control(...) vpip->sim_control(__VA_ARGS__) +#define vpi_fopen(...) vpip->fopen(__VA_ARGS__) +#define vpi_get_file(...) vpip->get_file(__VA_ARGS__) +#define vpip_calc_clog2(...) vpip->calc_clog2(__VA_ARGS__) +#define vpip_count_drivers(...) vpip->count_drivers(__VA_ARGS__) +#define vpip_format_strength(...) vpip->format_strength(__VA_ARGS__) +#define vpip_make_systf_system_defined(...) vpip->make_systf_system_defined(__VA_ARGS__) +#define vpip_mcd_rawwrite(...) vpip->mcd_rawwrite(__VA_ARGS__) +#define vpip_set_return_value(...) vpip->set_return_value(__VA_ARGS__) + +#endif // IVL_VPI_MODULE + EXTERN_C_END #endif /* VPI_USER_H */ diff --git a/vvp/Makefile.in b/vvp/Makefile.in index 897aa6e17..ee367089d 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -82,7 +82,7 @@ O = main.o parse.o parse_misc.o lexor.o arith.o array_common.o array.o bufif.o c vvp_object.o vvp_cobject.o vvp_darray.o event.o logic.o delay.o \ words.o island_tran.o $(VPI) -all: dep vvp@EXEEXT@ libvpi.a vvp.man +all: dep vvp@EXEEXT@ vvp.man check: all ifeq (@WIN32@,yes) @@ -101,13 +101,13 @@ endif clean: rm -f *.o *~ parse.cc parse.h lexor.cc tables.cc - rm -rf dep vvp@EXEEXT@ libvpi.a parse.output vvp.man vvp.ps vvp.pdf vvp.exp + rm -rf dep vvp@EXEEXT@ parse.output vvp.man vvp.ps vvp.pdf vvp.exp distclean: clean rm -f Makefile config.log rm -f stamp-config-h config.h -cppcheck: $(O:.o=.cc) libvpi.c draw_tt.c +cppcheck: $(O:.o=.cc) draw_tt.c cppcheck --enable=all --std=posix --std=c99 --std=c++03 -f \ --suppressions-list=$(srcdir)/cppcheck.sup \ -UMODULE_DIR1 -UMODULE_DIR2 -UYY_USER_INIT \ @@ -121,30 +121,8 @@ Makefile: $(srcdir)/Makefile.in dep: mkdir dep -ifeq (@WIN32@,yes) -# Under Windows (mingw) I need to make the vvp.exe in two steps. -# The first step makes an vvp.exe that dlltool can use to make an -# export and import library, and the last link makes a, vvp.exe -# that really exports the things that the import library imports. -# -# To get this to work correctly we must use the suffixed version of the -# executable to build the library. -vvp@EXEEXT@ libvpi.a: $O $(srcdir)/vvp.def - $(CXX) -o vvp$(suffix)@EXEEXT@ $(LDFLAGS) $O $(dllib) $(LIBS) - $(DLLTOOL) --dllname vvp$(suffix)@EXEEXT@ --def $(srcdir)/vvp.def \ - --output-lib libvpi.a --output-exp vvp.exp - rm -f vvp$(suffix)@EXEEXT@ - $(CXX) $(LDFLAGS) -o vvp@EXEEXT@ vvp.exp $(LDFLAGS) $O $(dllib) $(LIBS) -else -libvpi.a: libvpi.c - $(CC) $(CPPFLAGS) $(CFLAGS) -c $< - rm -f libvpi.a - $(AR) cqv libvpi.a libvpi.o - $(RANLIB) libvpi.a - vvp@EXEEXT@: $O $(CXX) $(LDFLAGS) -o vvp@EXEEXT@ $O $(LIBS) $(dllib) -endif %.o: %.cc config.h $(CXX) $(CPPFLAGS) -DIVL_SUFFIX='"$(suffix)"' $(MDIR1) $(MDIR2) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o @@ -207,14 +185,11 @@ stamp-config-h: $(srcdir)/config.h.in ../config.status cd ..; ./config.status --header=vvp/config.h config.h: stamp-config-h -install: all installdirs $(bindir)/vvp$(suffix)@EXEEXT@ $(libdir)/libvpi$(suffix).a $(INSTALL_DOC) +install: all installdirs $(bindir)/vvp$(suffix)@EXEEXT@ $(INSTALL_DOC) $(bindir)/vvp$(suffix)@EXEEXT@: ./vvp@EXEEXT@ $(INSTALL_PROGRAM) ./vvp@EXEEXT@ "$(DESTDIR)$(bindir)/vvp$(suffix)@EXEEXT@" -$(libdir)/libvpi$(suffix).a : ./libvpi.a - $(INSTALL_DATA) libvpi.a "$(DESTDIR)$(libdir)/libvpi$(suffix).a" - $(mandir)/man1/vvp$(suffix).1: vvp.man $(INSTALL_DATA) vvp.man "$(DESTDIR)$(mandir)/man1/vvp$(suffix).1" @@ -227,7 +202,6 @@ installdirs: $(srcdir)/../mkinstalldirs uninstall: $(UNINSTALL32) rm -f "$(DESTDIR)$(bindir)/vvp$(suffix)@EXEEXT@" - rm -f "$(DESTDIR)$(libdir)/libvpi$(suffix).a" rm -f "$(DESTDIR)$(mandir)/man1/vvp$(suffix).1" "$(DESTDIR)$(prefix)/vvp$(suffix).pdf" -include $(patsubst %.o, dep/%.d, $O) diff --git a/vvp/cppcheck.sup b/vvp/cppcheck.sup index 049c11041..911e1cb0a 100644 --- a/vvp/cppcheck.sup +++ b/vvp/cppcheck.sup @@ -2,10 +2,6 @@ // pool is defined there. uninitVar:vvp_net.cc:167 -// These functions are not used by Icarus -// __libvpi_c_dummy_function() -unusedFunction:libvpi.c:24 - // These functions are not used by Icarus // vpi_chk_error() unusedFunction:vpi_priv.cc:193 diff --git a/vvp/vpi_modules.cc b/vvp/vpi_modules.cc index e91bebe0a..e7e189878 100644 --- a/vvp/vpi_modules.cc +++ b/vvp/vpi_modules.cc @@ -30,6 +30,7 @@ static ivl_dll_t*dll_list = 0; static unsigned dll_list_cnt = 0; +typedef void (*vpip_set_callback_t)(vpip_routines_s*); typedef void (*vlog_startup_routines_t)(void); # define VPIP_MODULE_PATH_MAX 64 @@ -215,6 +216,13 @@ void vpip_load_module(const char*name) return; } + vpip_set_callback_t set_callback = (vpip_set_callback_t)ivl_dlsym(dll, "vpip_set_callback"); + if (set_callback == 0) { + fprintf(stderr, "%s: no vpip_set_callback\n", name); + ivl_dlclose(dll); + return; + } + set_callback(&vpi_routines); #ifdef __MINGW32__ /* For this check MinGW does not want the leading underscore! */ diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 5d1fb4f95..ba9476f9a 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1634,3 +1634,47 @@ extern "C" void vpip_count_drivers(vpiHandle ref, unsigned idx, assert(rfp); rfp->node->count_drivers(idx, counts); } + +vpip_routines_s vpi_routines = { + .register_cb = vpi_register_cb, + .remove_cb = vpi_remove_cb, + .register_systf = vpi_register_systf, + .get_systf_info = vpi_get_systf_info, + .handle_by_name = vpi_handle_by_name, + .handle_by_index = vpi_handle_by_index, + .handle = vpi_handle, + .iterate = vpi_iterate, + .scan = vpi_scan, + .get = vpi_get, + .get_str = vpi_get_str, + .get_delays = vpi_get_delays, + .put_delays = vpi_put_delays, + .get_value = vpi_get_value, + .put_value = vpi_put_value, + .get_time = vpi_get_time, + .get_userdata = vpi_get_userdata, + .put_userdata = vpi_put_userdata, + .mcd_open = vpi_mcd_open, + .mcd_close = vpi_mcd_close, + .mcd_flush = vpi_mcd_flush, + .mcd_name = vpi_mcd_name, + .mcd_printf = vpi_mcd_printf, + .mcd_vprintf = vpi_mcd_vprintf, + .flush = vpi_flush, + .printf = vpi_printf, + .vprintf = vpi_vprintf, + .chk_error = vpi_chk_error, + .compare_objects = vpi_compare_objects, + .free_object = vpi_free_object, + .get_vlog_info = vpi_get_vlog_info, + .control = vpi_control, + .sim_control = vpi_sim_control, + .fopen = vpi_fopen, + .get_file = vpi_get_file, + .calc_clog2 = vpip_calc_clog2, + .count_drivers = vpip_count_drivers, + .format_strength = vpip_format_strength, + .make_systf_system_defined = vpip_make_systf_system_defined, + .mcd_rawwrite = vpip_mcd_rawwrite, + .set_return_value = vpip_set_return_value, +}; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 3a841f3a0..d183135e5 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -48,6 +48,8 @@ typedef struct __vpiArray* vvp_array_t; * header file elsewhere. */ +extern vpip_routines_s vpi_routines; + /* * Routines/definitions used to build the file/line number tracing object. */ diff --git a/vvp/vvp.def b/vvp/vvp.def deleted file mode 100644 index c49f79400..000000000 --- a/vvp/vvp.def +++ /dev/null @@ -1,45 +0,0 @@ -EXPORTS - -vpi_chk_error -vpi_compare_objects -vpi_control -vpi_flush -vpi_fopen -vpi_free_object -vpi_get -vpi_get_delays -vpi_get_file -vpi_get_str -vpi_get_systf_info -vpi_get_time -vpi_get_userdata -vpi_get_value -vpi_get_vlog_info -vpi_handle -vpi_handle_by_index -vpi_handle_by_name -vpi_iterate -vpi_mcd_close -vpi_mcd_flush -vpi_mcd_name -vpi_mcd_open -vpi_mcd_printf -vpi_mcd_vprintf -vpi_printf -vpi_put_delays -vpi_put_userdata -vpi_put_value -vpi_register_cb -vpi_register_systf -vpi_remove_cb -vpi_scan -vpi_sim_control -vpi_sim_vcontrol -vpi_vprintf - -vpip_calc_clog2 -vpip_count_drivers -vpip_format_strength -vpip_make_systf_system_defined -vpip_mcd_rawwrite -vpip_set_return_value