/* GRT VPI C helpers. Copyright (C) 2003, 2004, 2005 Tristan Gingold & Felix Bertram GHDL is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GHDL 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 GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //----------------------------------------------------------------------------- // Description: VPI interface for GRT runtime, "C" helpers // the main purpose of this code is to interface with the // Icarus Verilog Interactive (IVI) simulator GUI //----------------------------------------------------------------------------- #include #include /* Define PLI_PROTOTYPES so that vpi_user.h do not import functions. */ #define PLI_PROTOTYPES #define PROTO_PARAMS(params) params #define XXTERN extern #include "vpi_user.h" #include "vpi_thunk.h" #include "grt-cdynload.h" /* Extension of a shared library. */ #if defined (WINNT) #define DSO_EXT ".dll" #elif defined (__APPLE__) #define DSO_EXT ".dylib" #else #define DSO_EXT ".so" #endif extern PLI_INT32 vpi_control_np (int op, int status); static vpi_thunk __ghdl_vpi_thunk_v1 = { vpi_register_systf, vpi_vprintf, vpi_mcd_close, vpi_mcd_name, vpi_mcd_open, 0, //vpi_mcd_open_x, 0, //vpi_mcd_vprintf, 0, //vpi_mcd_fputc, 0, //vpi_mcd_fgetc, vpi_register_cb, vpi_remove_cb, 0, //vpi_sim_vcontrol, vpi_handle, vpi_iterate, vpi_scan, vpi_handle_by_index, vpi_get_time, vpi_get, vpi_get_str, vpi_get_value, vpi_put_value, vpi_free_object, vpi_get_vlog_info, vpi_chk_error, vpi_handle_by_name, vpi_control_np }; //----------------------------------------------------------------------------- // VPI module load & startup #if defined (__APPLE__) /* On Darwin: look in rpath. */ #define LIBNAME "@rpath/libghdlvpi" DSO_EXT #else #define LIBNAME "libghdlvpi" DSO_EXT #endif static const char libghdlvpi_name[] = LIBNAME; int loadVpiModule (const char* modulename) { static void *libghdlvpi_mod; int i; void *vpimod; fprintf (stderr, "loading VPI module '%s'\n", modulename); /* TODO: on windows, use SetDllDirectory with: - install dir (libdir) => add -DLIBDIR=xxx - exec path\lib => see windows_default_path */ vpimod = grt_dynload_open (modulename); if (vpimod == NULL) { const char *msg = grt_dynload_error (); fprintf (stderr, "%s\n", msg == NULL ? "unknown dlopen error" : msg); return -1; } /* Try to load the libghdlvpi library and set the thunk. No need to load the library several times. */ if (libghdlvpi_mod == NULL) { libghdlvpi_mod = grt_dynload_open (libghdlvpi_name); if (libghdlvpi_mod != NULL) { vpi_thunk **vpi_thunk_ptr; for (i = 0; i < 2; i++) { vpi_thunk_ptr = grt_dynload_symbol (libghdlvpi_mod, &"_VPI_THUNK"[i]); if (vpi_thunk_ptr != NULL) { *vpi_thunk_ptr = &__ghdl_vpi_thunk_v1; break; } } if (vpi_thunk_ptr == NULL) fprintf (stderr, "warning: VPI_THUNK not found in %s\n", libghdlvpi_name); } } for (i = 0; i < 2; i++) // try with and w/o leading underscores { void *vpitable = grt_dynload_symbol (vpimod, &"_vlog_startup_routines"[i]); if (vpitable) { unsigned int j; typedef void (*vlog_startup_routines_t)(void); vlog_startup_routines_t *vpifuns; vpifuns = (vlog_startup_routines_t*)vpitable; for (j = 0; vpifuns[j]; j++) vpifuns[j](); fprintf (stderr, "VPI module loaded!\n"); return 0; // successfully registered VPI module } } fprintf (stderr, "vlog_startup_routines not found\n"); return -1; // failed to register VPI module } PLI_INT32 vpi_vprintf (char *fmt, va_list ap) { return vprintf (fmt, ap); } PLI_INT32 vpi_printf (char *fmt, ...) { va_list params; PLI_INT32 res; va_start (params, fmt); res = vprintf (fmt, params); va_end (params); return res; } PLI_INT32 vpi_control (int op, ...) { va_list params; int status; PLI_INT32 res; va_start (params, op); status = va_arg (params, int); res = vpi_control_np (op, status); va_end (params); return res; }