diff options
author | Tristan Gingold <tgingold@free.fr> | 2016-07-10 17:11:31 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2016-07-10 17:11:31 +0200 |
commit | 8fd9e4a314bec9a3dc4a260b00d2ed7f589d74c0 (patch) | |
tree | 217b25f1bf2dd4e5e3877375e43938ac0bda0c13 /src/grt/grt-cvpi.c | |
parent | 769b358b41351f5824dd23151270505835cee6bc (diff) | |
download | ghdl-8fd9e4a314bec9a3dc4a260b00d2ed7f589d74c0.tar.gz ghdl-8fd9e4a314bec9a3dc4a260b00d2ed7f589d74c0.tar.bz2 ghdl-8fd9e4a314bec9a3dc4a260b00d2ed7f589d74c0.zip |
Initial work to support vpi via dll on windows.
Fixes #116
Diffstat (limited to 'src/grt/grt-cvpi.c')
-rw-r--r-- | src/grt/grt-cvpi.c | 237 |
1 files changed, 101 insertions, 136 deletions
diff --git a/src/grt/grt-cvpi.c b/src/grt/grt-cvpi.c index 6f8420dbf..e122e1b4c 100644 --- a/src/grt/grt-cvpi.c +++ b/src/grt/grt-cvpi.c @@ -25,103 +25,53 @@ #include <stdio.h> #include <stdlib.h> -//----------------------------------------------------------------------------- -// VPI callback functions -typedef void *vpiHandle, *p_vpi_time, *p_vpi_value; -typedef struct t_cb_data s_cb_data, *p_cb_data; +/* 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" + +/* 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 -//----------------------------------------------------------------------------- -// vpi thunking a la Icarus Verilog -#include <stdarg.h> -typedef void *s_vpi_time, *p_vpi_vlog_info, *p_vpi_error_info; -#define VPI_THUNK_MAGIC (0x87836BA5) -struct t_vpi_systf_data; -void vpi_register_systf (const struct t_vpi_systf_data*ss); -void vpi_vprintf (const char*fmt, va_list ap); -unsigned int vpi_mcd_close (unsigned int mcd); -char * vpi_mcd_name (unsigned int mcd); -unsigned int vpi_mcd_open (char *name); -unsigned int vpi_mcd_open_x (char *name, char *mode); -int vpi_mcd_vprintf (unsigned int mcd, const char*fmt, va_list ap); -int vpi_mcd_fputc (unsigned int mcd, unsigned char x); -int vpi_mcd_fgetc (unsigned int mcd); -vpiHandle vpi_register_cb (p_cb_data data); -int vpi_remove_cb (vpiHandle ref); -void vpi_sim_vcontrol (int operation, va_list ap); -vpiHandle vpi_handle (int type, vpiHandle ref); -vpiHandle vpi_iterate (int type, vpiHandle ref); -vpiHandle vpi_scan (vpiHandle iter); -vpiHandle vpi_handle_by_index (vpiHandle ref, int index); -void vpi_get_time (vpiHandle obj, s_vpi_time*t); -int vpi_get (int property, vpiHandle ref); -char* vpi_get_str (int property, vpiHandle ref); -void vpi_get_value (vpiHandle expr, p_vpi_value value); -vpiHandle vpi_put_value (vpiHandle obj, p_vpi_value value, - p_vpi_time when, int flags); -int vpi_free_object (vpiHandle ref); -int vpi_get_vlog_info (p_vpi_vlog_info vlog_info_p); -int vpi_chk_error (p_vpi_error_info info); -vpiHandle vpi_handle_by_name (char *name, vpiHandle scope); - -typedef struct { - int magic; - void (*vpi_register_systf) (const struct t_vpi_systf_data*ss); - void (*vpi_vprintf) (const char*fmt, va_list ap); - unsigned int (*vpi_mcd_close) (unsigned int mcd); - char* (*vpi_mcd_name) (unsigned int mcd); - unsigned int (*vpi_mcd_open) (char *name); - unsigned int (*vpi_mcd_open_x) (char *name, char *mode); - int (*vpi_mcd_vprintf) (unsigned int mcd, const char*fmt, va_list ap); - int (*vpi_mcd_fputc) (unsigned int mcd, unsigned char x); - int (*vpi_mcd_fgetc) (unsigned int mcd); - vpiHandle (*vpi_register_cb) (p_cb_data data); - int (*vpi_remove_cb) (vpiHandle ref); - void (*vpi_sim_vcontrol) (int operation, va_list ap); - vpiHandle (*vpi_handle) (int type, vpiHandle ref); - vpiHandle (*vpi_iterate) (int type, vpiHandle ref); - vpiHandle (*vpi_scan) (vpiHandle iter); - vpiHandle (*vpi_handle_by_index)(vpiHandle ref, int index); - void (*vpi_get_time) (vpiHandle obj, s_vpi_time*t); - int (*vpi_get) (int property, vpiHandle ref); - char* (*vpi_get_str) (int property, vpiHandle ref); - void (*vpi_get_value) (vpiHandle expr, p_vpi_value value); - vpiHandle (*vpi_put_value) (vpiHandle obj, p_vpi_value value, - p_vpi_time when, int flags); - int (*vpi_free_object) (vpiHandle ref); - int (*vpi_get_vlog_info) (p_vpi_vlog_info vlog_info_p); - int (*vpi_chk_error) (p_vpi_error_info info); - vpiHandle (*vpi_handle_by_name) (char *name, vpiHandle scope); -} vpi_thunk, *p_vpi_thunk; - -int vpi_register_sim(p_vpi_thunk tp); - -static vpi_thunk thunkTable = -{ VPI_THUNK_MAGIC, - 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 +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 }; //----------------------------------------------------------------------------- @@ -183,19 +133,17 @@ module_error (void) int loadVpiModule (const char* modulename) { + static const char libghdlvpi_name[] = "@executable_path/libghdlvpi" DSO_EXT; + static void *libghdlvpi_mod; + static const char * const vpitablenames[] = { "_vlog_startup_routines", // with leading underscore: MacOSX "vlog_startup_routines" // w/o leading underscore: Linux }; - static const char * const vpithunknames[] = - { - "_vpi_register_sim", // with leading underscore: MacOSX - "vpi_register_sim" // w/o leading underscore: Linux - }; int i; - void* vpimod; + void *vpimod; fprintf (stderr, "loading VPI module '%s'\n", modulename); @@ -203,48 +151,50 @@ loadVpiModule (const char* modulename) if (vpimod == NULL) { - const char *msg; - - msg = module_error (); + const char *msg = module_error (); fprintf (stderr, "%s\n", msg == NULL ? "unknown dlopen error" : msg); return -1; } - for (i = 0; i < 2; i++) // try with and w/o leading underscores + /* Try to load the libghdlvpi library and set the thunk. + No need to load the library several times. */ + if (libghdlvpi_mod == NULL) { - void* vpithunk; - void* vpitable; - - vpitable = module_symbol (vpimod, vpitablenames[i]); - vpithunk = module_symbol (vpimod, vpithunknames[i]); - - if (vpithunk) + libghdlvpi_mod = module_open (libghdlvpi_name); + if (libghdlvpi_mod != NULL) { - typedef int (*funT)(p_vpi_thunk tp); - funT regsim; + vpi_thunk **vpi_thunk_ptr; - regsim = (funT)vpithunk; - regsim (&thunkTable); - } - else - { - // this is not an error, as the register-mechanism - // is not standardized + for (i = 0; i < 2; i++) + { + vpi_thunk_ptr = module_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 = module_symbol (vpimod, &"_vlog_startup_routines"[i]); if (vpitable) { - unsigned int tmp; - //extern void (*vlog_startup_routines[])(); + unsigned int j; typedef void (*vlog_startup_routines_t)(void); vlog_startup_routines_t *vpifuns; vpifuns = (vlog_startup_routines_t*)vpitable; - for (tmp = 0; vpifuns[tmp]; tmp++) - { - vpifuns[tmp](); - } + for (j = 0; vpifuns[j]; j++) + vpifuns[j](); fprintf (stderr, "VPI module loaded!\n"); return 0; // successfully registered VPI module @@ -254,21 +204,36 @@ loadVpiModule (const char* modulename) return -1; // failed to register VPI module } -void -vpi_vprintf (const char*fmt, va_list ap) +PLI_INT32 +vpi_vprintf (char *fmt, va_list ap) { - vprintf (fmt, ap); + return vprintf (fmt, ap); } -void -vpi_printf (const char *fmt, ...) +PLI_INT32 +vpi_printf (char *fmt, ...) { va_list params; + PLI_INT32 res; va_start (params, fmt); - vprintf (fmt, params); + res = vprintf (fmt, params); va_end (params); + + return res; } -//----------------------------------------------------------------------------- -// end of file +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; +} |