#include #include #include #include /* * This file exercises an error */ static int chkvpierr(void) { s_vpi_error_info info; int level; if ((level = vpi_chk_error(&info)) != 0) { fprintf(stderr, "+++ VPI ERROR +++ level %d\n", level); fprintf(stderr, "+++ MESS: %s\n", info.message); fprintf(stderr, "+++ PROD: %s\n", info.product); fprintf(stderr, "+++ CODE: %s\n", info.code); fprintf(stderr, "+++ FILE: %s\n", info.file); fprintf(stderr, "+++\n"); } return level; } #ifdef IVERILOG_V0_8 static PLI_INT32 xxx_compiletf(char *user_data) #else static PLI_INT32 xxx_compiletf(PLI_BYTE8 *user_data) #endif { (void)user_data; /* Parameter is not used. */ return 0; } char charbuf[100]; #ifdef IVERILOG_V0_8 static PLI_INT32 xxx_calltf(char *user_data) #else static PLI_INT32 xxx_calltf(PLI_BYTE8 *user_data) #endif { vpiHandle systf_h; s_vpi_value vpival; /* get/set register values */ s_vpi_time t; vpiHandle arg_iterator; int i; vpiHandle argi[100]; (void)user_data; /* Parameter is not used. */ /* Get handle to this instance, look up our workarea */ systf_h = vpi_handle(vpiSysTfCall, NULL); chkvpierr(); arg_iterator = vpi_iterate(vpiArgument, systf_h); chkvpierr(); i = 0; if (arg_iterator == NULL) { fprintf(stderr, "ERROR: missing argument list to $example(...)"); } /* Copy args pointers into argi array */ while ((argi[i] = vpi_scan(arg_iterator)) != NULL) { chkvpierr(); i++; } /* iterator is exhausted, no need to free */ /* Fill in the time struct */ t.type = vpiScaledRealTime; t.high = 0; t.low = 0; t.real = 10.0; /* Fill in the value struct */ vpival.format = vpiBinStrVal; vpival.value.str = charbuf; /* * This is where the real work happens. We are called in an intial * block and we schedule three "set-values" at times 10, 20 and 30 * to args 0, 1 and 2. The charbuf gets shared among the three * calls, even though it shouldn't and the values are not distinct. */ /* Write this value to argi[0] at time 10.0 */ strcpy(charbuf, "01010101"); vpi_put_value(argi[0], &vpival, &t, vpiTransportDelay); /* Write this value to argi[1] at time 20.0 */ strcpy(charbuf, "x1x1x1x1"); t.real = 20.0; vpi_put_value(argi[1], &vpival, &t, vpiTransportDelay); /* Write this value to argi[2] at time 30.0 */ strcpy(charbuf, "0xz101xz"); t.real = 30.0; vpi_put_value(argi[2], &vpival, &t, vpiTransportDelay); return 0; } static void xxx_register(void) { s_vpi_systf_data tfdata; vpi_printf("+++ in XXX_REGISTER\n"); tfdata.type = vpiSysFunc; /* * TOM: sysfunctype field seems to be problematic for different simulators! * some simulators simply don't register callback if subtype missing. * * Icarus - doesn't implement vpiSizedFunc, so use vpiIntFunct. * CVER - use vpiIntFunc * MTI - use vpiSizedFunc or vpiIntFunc. * XL/NC - doesn't matter * VCS - doesn't matter * */ tfdata.sysfunctype = vpiIntFunc; /* tfdata.sysfunctype = vpiSizedFunc; */ tfdata.tfname = "$example"; tfdata.calltf = xxx_calltf; tfdata.compiletf = xxx_compiletf; /* tfdata.sizetf = xxx_sizetf; */ tfdata.sizetf = 0; tfdata.user_data = 0; vpi_register_systf(&tfdata); chkvpierr(); } static void xxx_startup(void) { vpi_printf("*** Registering XXX PLI functions.\n"); xxx_register(); } /** * * **/ void (*vlog_startup_routines[])(void) = { xxx_startup, 0 };