/* * Runtime routine for the $table_model(). */ static PLI_INT32 sys_table_model_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); s_vpi_value val; p_table_mod table; unsigned idx; double result; /* Retrieve the table data. */ table = vpi_get_userdata(callh); /* If this is the first call then build the data structure. */ if ((table->have_fname == 0) && initialize_table_model(callh, name, table)) { vpi_control(vpiFinish, 1); return 0; } /* Load the current argument values into the table structure. */ for (idx = 0; idx < table->dims; idx += 1) { val.format = vpiRealVal; vpi_get_value(table->indep[idx], &val); table->indep_val[idx] = val.value.real; } /* Interpolate/extrapolate the data structure to find the value. */ result = eval_table_model(callh, table); /* Return the calculated value. */ val.format = vpiRealVal; val.value.real = result; vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; }
static PLI_INT32 sys_rtoi_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle arg = (vpiHandle) vpi_get_userdata(callh); s_vpi_value value; static struct t_vpi_vecval res; double val; (void)name; /* Parameter is not used. */ /* get value */ value.format = vpiRealVal; vpi_get_value(arg, &value); /* If the value is NaN or +/- infinity then return 'bx */ val = value.value.real; if (val != val || (val && (val == 0.5*val))) { res.aval = ~(PLI_INT32)0; res.bval = ~(PLI_INT32)0; } else { /* This is not 100% correct since large real values may break this * code. See the verinum code for a more rigorous implementation. */ if (val >= 0.0) res.aval = (PLI_UINT64) val; else res.aval = - (PLI_UINT64) -val; res.bval = 0; } value.format = vpiVectorVal; value.value.vector = &res; /* return converted value */ vpi_put_value(callh, &value, 0, vpiNoDelay); return 0; }
static PLI_INT32 sys_realtobits_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle arg = (vpiHandle) vpi_get_userdata(callh); s_vpi_value value; static struct t_vpi_vecval res[2]; PLI_UINT32 bits[2]; (void)name; /* Parameter is not used. */ /* get value */ value.format = vpiRealVal; vpi_get_value(arg, &value); /* convert */ double2bits(value.value.real, bits); res[0].aval = bits[0]; res[0].bval = 0; res[1].aval = bits[1]; res[1].bval = 0; value.format = vpiVectorVal; value.value.vector = res; /* return converted value */ vpi_put_value(callh, &value, 0, vpiNoDelay); return 0; }
static PLI_INT32 sys_bitstoreal_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle arg = (vpiHandle) vpi_get_userdata(callh); s_vpi_value value; PLI_UINT32 bits[2]; (void)name; /* Parameter is not used. */ /* get value */ value.format = vpiVectorVal; vpi_get_value(arg, &value); /* convert */ bits[0] = (value.value.vector[0]).aval; bits[1] = (value.value.vector[1]).aval; value.value.real = bits2double(bits); value.format = vpiRealVal; /* return converted value */ vpi_put_value(callh, &value, 0, vpiNoDelay); return 0; }
PLI_INT32 tf_isetrealdelay(double dly, void*obj) { vpiHandle sys = (vpiHandle)obj; p_pli_data pli = vpi_get_userdata(sys); s_cb_data cb; s_vpi_time ti = {vpiSimTime}; /* Scale delay to SimTime */ ivl_u64_t delay = ((dly / pow(10, tf_gettimeunit() - tf_gettimeprecision())) + 0.5); ti.high = delay >> 32 & 0xffffffff; ti.low = delay & 0xffffffff; cb.reason = cbAfterDelay; cb.cb_rtn = callback; cb.obj = sys; cb.time = &ti; cb.user_data = (char *)pli; vpi_register_cb(&cb); if (pli_trace) fprintf(pli_trace, "tf_isetrealdelay(%f, %p) --> %d\n", dly, obj, 0); return 0; }
static int sys_random_calltf(char*name) { s_vpi_value val; vpiHandle call_handle; vpiHandle argv; vpiHandle seed = 0; int i_seed = 0; struct context_s *context; call_handle = vpi_handle(vpiSysTfCall, 0); assert(call_handle); /* Get the argument list and look for a seed. If it is there, get the value and reseed the random number generator. */ argv = vpi_iterate(vpiArgument, call_handle); if (argv) { seed = vpi_scan(argv); vpi_free_object(argv); val.format = vpiIntVal; vpi_get_value(seed, &val); i_seed = val.value.integer; /* Since there is a seed use the current context or create a new one */ context = (struct context_s *)vpi_get_userdata(call_handle); if (!context) { context = (struct context_s *)calloc(1, sizeof(*context)); context->mti = NP1; assert(context); /* squrrel away context */ vpi_put_userdata(call_handle, (void *)context); } /* If the argument is not the Icarus cookie, then reseed context */ if (i_seed != COOKIE) sgenrand(context, i_seed); } else { /* use global context */ context = &global_context; } val.format = vpiIntVal; val.value.integer = genrand(context); vpi_put_value(call_handle, &val, 0, vpiNoDelay); /* mark seed with cookie */ if (seed && i_seed != COOKIE) { val.format = vpiIntVal; val.value.integer = COOKIE; vpi_put_value(seed, &val, 0, vpiNoDelay); } return 0; }
static PLI_INT32 sys_mti_random_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { vpiHandle callh, argv, seed = 0; s_vpi_value val; int i_seed = COOKIE; struct context_s *context; (void)name; /* Parameter is not used. */ /* Get the argument list and look for a seed. If it is there, get the value and reseed the random number generator. */ callh = vpi_handle(vpiSysTfCall, 0); argv = vpi_iterate(vpiArgument, callh); val.format = vpiIntVal; if (argv) { seed = vpi_scan(argv); vpi_free_object(argv); vpi_get_value(seed, &val); i_seed = val.value.integer; /* Since there is a seed use the current context or create a new one */ context = (struct context_s *)vpi_get_userdata(callh); if (!context) { context = (struct context_s *)calloc(1, sizeof(*context)); context->mti = NP1; /* squirrel away context */ vpi_put_userdata(callh, (void *)context); } /* If the argument is not the Icarus cookie, then reseed context */ if (i_seed != COOKIE) sgenrand(context, i_seed); } else { /* use global context */ context = &global_context; } /* Calculate and return the result */ val.value.integer = genrand(context); vpi_put_value(callh, &val, 0, vpiNoDelay); /* mark seed with cookie */ if (seed && i_seed != COOKIE) { val.value.integer = COOKIE; vpi_put_value(seed, &val, 0, vpiNoDelay); } return 0; }
PLI_INT32 tf_irosynchronize(void*obj) { vpiHandle sys = (vpiHandle)obj; p_pli_data pli = vpi_get_userdata(sys); s_cb_data cb; s_vpi_time ti = {vpiSuppressTime, 0, 0}; cb.reason = cbReadOnlySynch; cb.cb_rtn = callback; cb.obj = sys; cb.time = &ti; cb.user_data = (char *)pli; vpi_register_cb(&cb); if (pli_trace) fprintf(pli_trace, "tf_irosynchronize(%p) --> %d\n", obj, 0); return 0; }
/* * Routine to implement the single argument math functions. */ static PLI_INT32 va_single_argument_calltf(ICARUS_VPI_CONST PLI_BYTE8 *ud) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); s_vpi_value val; va_single_t* fun_data; (void) ud; /* Not used! */ /* Retrieve the function and argument data. */ fun_data = vpi_get_userdata(callh); /* Calculate the result */ val.format = vpiRealVal; vpi_get_value(fun_data->arg, &val); val.value.real = (fun_data->func)(val.value.real); /* Return the result */ vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; }
static PLI_INT32 sys_itor_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle arg = (vpiHandle) vpi_get_userdata(callh); s_vpi_value value; (void)name; /* Parameter is not used. */ /* get value */ value.format = vpiIntVal; vpi_get_value(arg, &value); /* convert */ value.value.real = value.value.integer; value.format = vpiRealVal; /* return converted value */ vpi_put_value(callh, &value, 0, vpiNoDelay); return 0; }
static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*data) { event_type_t type = (event_type_t) data; vpiHandle sys = vpi_handle(vpiSysTfCall, 0); struct t_vpi_value rval; struct monitor_data*mon; rval.format = vpiScalarVal; mon = (struct monitor_data*) (vpi_get_userdata(sys)); if (mon->last_event.type == 0) { rval.value.scalar = vpi0; } else { struct t_vpi_time tnow; tnow.type = vpiSimTime; vpi_get_time(0, &tnow); rval.value.scalar = vpi1; // Detect if change occured in this moment if (mon->last_event.high != tnow.high) rval.value.scalar = vpi0; if (mon->last_event.low != tnow.low) rval.value.scalar = vpi0; // Determine the edge, if required if (type == RISING_EDGE && mon->last_value.value.scalar != vpi1) rval.value.scalar = vpi0; else if (type == FALLING_EDGE && mon->last_value.value.scalar != vpi0) rval.value.scalar = vpi0; } vpi_put_value(sys, &rval, 0, vpiNoDelay); return 0; }