diff options
author | Marlon James <marlon.james@gmail.com> | 2021-03-03 10:33:56 -0800 |
---|---|---|
committer | tgingold <tgingold@users.noreply.github.com> | 2021-03-04 07:49:28 +0100 |
commit | 783cbac7ba4c14aa7e27f28755dccd7e4ee4d54e (patch) | |
tree | 929ab92aac895ec39b5e7780e1fe8cea3edf3be1 /src/grt/grt-cvhpi.c | |
parent | a03aedddf650f923b06ebacb441a713930cd63e1 (diff) | |
download | ghdl-783cbac7ba4c14aa7e27f28755dccd7e4ee4d54e.tar.gz ghdl-783cbac7ba4c14aa7e27f28755dccd7e4ee4d54e.tar.bz2 ghdl-783cbac7ba4c14aa7e27f28755dccd7e4ee4d54e.zip |
VHPI: add initial minimal implementation
Minimal implementation of VHPI provides library loading and
error support. Calling most vhpi_* functions will raise a
VHPI error condition.
Incorporates VHPI thunks into libghdlvpi for linking.
Diffstat (limited to 'src/grt/grt-cvhpi.c')
-rw-r--r-- | src/grt/grt-cvhpi.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/src/grt/grt-cvhpi.c b/src/grt/grt-cvhpi.c new file mode 100644 index 000000000..57abd996d --- /dev/null +++ b/src/grt/grt-cvhpi.c @@ -0,0 +1,256 @@ +/* GRT VHPI C helpers. + Copyright (C) 2021 Marlon James + + 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: VHPI interface for GRT runtime, "C" helpers +// for loading VHPI foreign applications +// and libraries of foreign models, +// and implementing variadic functions in vhpi_user.h +//----------------------------------------------------------------------------- + +#include <stdio.h> +#include <stdlib.h> + +// Define PLI_PROTOTYPES so that vhpi_user.h does not import functions. +#define PLI_PROTOTYPES +#define XXTERN extern + +#include "vhpi_user.h" +#include "vhpi_thunk.h" +#include "grt-cdynload.h" + +// See grt-vhpi.ads +extern int Vhpi_Control_Internal (int command, int status); +extern int Vhpi_Assert_Internal (int severity, const char *msg); + +// Forward declaration +int vhpi_vassert (vhpiSeverityT severity, char *formatmsg, + va_list args); + +static vhpi_thunk __ghdl_vhpi_thunk_v1 = +{ + vhpi_vassert, + vhpi_register_cb, + vhpi_remove_cb, + vhpi_disable_cb, + vhpi_enable_cb, + vhpi_get_cb_info, + 0, //vhpi_sens_first, + 0, //vhpi_sens_zero, + 0, //vhpi_sens_clr, + 0, //vhpi_sens_set, + 0, //vhpi_sens_isset, + vhpi_handle_by_name, + vhpi_handle_by_index, + vhpi_handle, + vhpi_iterator, + vhpi_scan, + vhpi_get, + vhpi_get_str, + vhpi_get_real, + vhpi_get_phys, + vhpi_protected_call, + vhpi_get_value, + vhpi_put_value, + vhpi_schedule_transaction, + vhpi_format_value, + vhpi_get_time, + vhpi_get_next_time, + Vhpi_Control_Internal, + vhpi_vprintf, + vhpi_is_printable, + vhpi_compare_handles, + vhpi_check_error, + vhpi_release_handle, + vhpi_create, + vhpi_register_foreignf, + vhpi_get_foreignf_info, + vhpi_get_data, + vhpi_put_data +}; + +//----------------------------------------------------------------------------- +// VHPI module load & startup + +// VHPI thunks are combined into libghdlvpi +#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 +loadVhpiModule (const char* libname, const char* entrypoint) +{ + static void *libghdlvpi_mod; + int i; + void *vhpimod; + + fprintf (stderr, "loading VHPI library '%s'", libname); + if (entrypoint) + { + fprintf (stderr, " with registration function '%s'", entrypoint); + } + fprintf (stderr, "\n"); + + // TODO: on windows, use SetDllDirectory with: + // - install dir (libdir) => add -DLIBDIR=xxx + // - exec path\lib => see windows_default_path + + vhpimod = grt_dynload_open (libname); + + if (vhpimod == 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 pointer. + // No need to load the library several times. + if (libghdlvpi_mod == NULL) + { + libghdlvpi_mod = grt_dynload_open (libghdlvpi_name); + if (libghdlvpi_mod != NULL) + { + vhpi_thunk **vhpi_thunk_ptr; + + for (i = 0; i < 2; i++) + { + vhpi_thunk_ptr = grt_dynload_symbol (libghdlvpi_mod, &"_VHPI_THUNK"[i]); + + if (vhpi_thunk_ptr != NULL) + { + *vhpi_thunk_ptr = &__ghdl_vhpi_thunk_v1; + break; + } + } + if (vhpi_thunk_ptr == NULL) + fprintf (stderr, "warning: VHPI_THUNK not found in %s\n", + libghdlvpi_name); + } + } + + if (entrypoint) + { + void *regfunc = grt_dynload_symbol (vhpimod, entrypoint); + + if (regfunc) + { + ((vhpiRegistrationFctT)regfunc)(); + fprintf (stderr, "VHPI module loaded and registration function called!\n"); + return 0; // successfully registered VHPI module + } + fprintf (stderr, "registration function '%s' not found\n", entrypoint); + return -1; // failed to register VHPI module + } + + for (i = 0; i < 2; i++) // try with and w/o leading underscores + { + void *vhpitable = + grt_dynload_symbol (vhpimod, &"_vhpi_startup_routines"[i]); + + if (vhpitable) + { + unsigned int idx; + vhpiRegistrationFctT *vhpifuncs; + + vhpifuncs = (vhpiRegistrationFctT*)vhpitable; + for (idx = 0; vhpifuncs[idx]; idx++) + { + vhpifuncs[idx](); + } + + fprintf (stderr, "VHPI module loaded and vhpi_startup_routines functions called!\n"); + return 0; // successfully registered VHPI module + } + } + fprintf (stderr, "vhpi_startup_routines not found\n"); + return -1; // failed to register VHPI module +} + +//----------------------------------------------------------------------------- +// VHPI functions + +#define ASSERTMSG_SIZE 512 +static char assertmsg_buff[ASSERTMSG_SIZE]; +static const char* default_msg = "VHPI foreign application error"; + +int vhpi_vassert (vhpiSeverityT severity, char *formatmsg, + va_list args) +{ + if (formatmsg == NULL) { + return Vhpi_Assert_Internal(severity, default_msg); + } + + // construct assert message in the buffer + vsnprintf(assertmsg_buff, ASSERTMSG_SIZE, formatmsg, args); + + return Vhpi_Assert_Internal(severity, assertmsg_buff); +} + +int +vhpi_assert (vhpiSeverityT severity, char *formatmsg, ...) +{ + va_list args; + int res; + + va_start (args, formatmsg); + res = vhpi_vassert (severity, formatmsg, args); + va_end(args); + + return res; +} + +int +vhpi_control (vhpiSimControlT command, ...) +{ + va_list args; + int status; + int res; + + va_start (args, command); + status = va_arg (args, int); + res = Vhpi_Control_Internal (command, status); + va_end (args); + + return res; +} + +int +vhpi_printf (const char *format, ...) +{ + va_list args; + int res; + + va_start (args, format); + res = vprintf (format, args); + va_end (args); + + return res; +} + +int +vhpi_vprintf (const char *format, va_list args) +{ + return vprintf (format, args); +} |