diff --git a/vpi/libvpi.c b/vpi/libvpi.c index f77d6cf32..3780521c1 100644 --- a/vpi/libvpi.c +++ b/vpi/libvpi.c @@ -285,9 +285,13 @@ void vpip_set_return_value(int value) vpip_routines->set_return_value(value); } -DLLEXPORT void vpip_set_callback(vpip_routines_s*routines) +DLLEXPORT PLI_UINT32 vpip_set_callback(vpip_routines_s*routines, PLI_UINT32 version) { + if (version != vpip_routines_version) + return 0; + vpip_routines = routines; + return 1; } #else diff --git a/vpi_modules.cc b/vpi_modules.cc index 700edb552..96eeef4a3 100644 --- a/vpi_modules.cc +++ b/vpi_modules.cc @@ -227,7 +227,7 @@ vpip_routines_s vpi_routines = { .set_return_value = vpip_set_return_value, }; -typedef void (*vpip_set_callback_t)(vpip_routines_s*); +typedef PLI_UINT32 (*vpip_set_callback_t)(vpip_routines_s*, PLI_UINT32); #endif typedef void (*vlog_startup_routines_t)(void); @@ -248,7 +248,12 @@ bool load_vpi_module(const char*path) return true; } vpip_set_callback_t set_callback = (vpip_set_callback_t)function; - set_callback(&vpi_routines); + if (!set_callback(&vpi_routines, vpip_routines_version)) { + cerr << "error: Failed to link '" << path << "'. " + "Try rebuilding it with iverilog-vpi." << endl; + ivl_dlclose(dll); + return true; + } #endif void*table = ivl_dlsym(dll, LU "vlog_startup_routines" TU); diff --git a/vpi_user.h b/vpi_user.h index 1e2410e9f..05a3c3c4b 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -683,6 +683,10 @@ extern void vpip_count_drivers(vpiHandle ref, unsigned idx, * 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. */ + +// Increment the version number any time vpip_routines_s is changed. +static const PLI_UINT32 vpip_routines_version = 1; + typedef struct { vpiHandle (*register_cb)(p_cb_data); PLI_INT32 (*remove_cb)(vpiHandle); @@ -724,7 +728,7 @@ typedef struct { void (*set_return_value)(int); } vpip_routines_s; -extern DLLEXPORT void vpip_set_callback(vpip_routines_s*routines); +extern DLLEXPORT PLI_UINT32 vpip_set_callback(vpip_routines_s*routines, PLI_UINT32 version); #endif // defined(__MINGW32__) || defined (__CYGWIN32__) diff --git a/vvp/vpi_modules.cc b/vvp/vpi_modules.cc index ac2450944..fa35dd57f 100644 --- a/vvp/vpi_modules.cc +++ b/vvp/vpi_modules.cc @@ -31,7 +31,7 @@ static ivl_dll_t*dll_list = 0; static unsigned dll_list_cnt = 0; #if defined(__MINGW32__) || defined (__CYGWIN32__) -typedef void (*vpip_set_callback_t)(vpip_routines_s*); +typedef PLI_UINT32 (*vpip_set_callback_t)(vpip_routines_s*, PLI_UINT32); #endif typedef void (*vlog_startup_routines_t)(void); @@ -226,7 +226,11 @@ void vpip_load_module(const char*name) return; } vpip_set_callback_t set_callback = (vpip_set_callback_t)function; - set_callback(&vpi_routines); + if (!set_callback(&vpi_routines, vpip_routines_version)) { + fprintf(stderr, "Failed to link VPI module %s. Try rebuilding it with iverilog-vpi.\n", name); + ivl_dlclose(dll); + return; + } #endif void*table = ivl_dlsym(dll, LU "vlog_startup_routines" TU);