int exm_python_vpi_file(char* arg) { vpiHandle href; vpiHandle arglist; s_vpi_value vpi_value; href = vpi_handle(vpiSysTfCall, 0); arglist = vpi_iterate(vpiArgument, href); vpi_value.format = vpiStringVal; vpi_get_value(vpi_scan(arglist), &vpi_value); return exm_python_file(vpi_value.value.str); }
/* * Routine to check all the double argument math functions. */ static PLI_INT32 va_double_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud) { vpiHandle callh, argv, arg; const t_double_data *data; const char *name; va_double_t* fun_data; assert(ud != 0); callh = vpi_handle(vpiSysTfCall, 0); assert(callh != 0); argv = vpi_iterate(vpiArgument, callh); data = (const t_double_data *) ud; name = data->name; fun_data = malloc(sizeof(va_double_t)); /* Check that there are arguments. */ if (argv == 0) { va_error_message(callh, "%s requires two arguments.\n", name); free(fun_data); return 0; } /* In Icarus if we have an argv we have at least one argument. */ arg = vpi_scan(argv); fun_data->arg1 = va_process_argument(callh, name, arg, " (arg1)"); /* Check that there are at least two arguments. */ arg = vpi_scan(argv); if (arg == 0) { va_error_message(callh, "%s requires two arguments.\n", name); } fun_data->arg2 = va_process_argument(callh, name, arg, " (arg2)"); /* These functions only take two arguments. */ arg = vpi_scan(argv); if (arg != 0) { va_error_message(callh, "%s takes only two arguments.\n", name); vpi_free_object(argv); } /* Get the function that is to be used by the calltf routine. */ fun_data->func = data->func; vpi_put_userdata(callh, fun_data); double_funcs_count += 1; double_funcs = (va_double_t **)realloc(double_funcs, double_funcs_count*sizeof(va_double_t **)); double_funcs[double_funcs_count-1] = fun_data; /* vpi_scan() returning 0 (NULL) has already freed argv. */ return 0; }
static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle file = vpi_scan(argv); s_vpi_value val; char *mode; unsigned idx, len; vpi_free_object(argv); /* Get the mode. */ mode = name + strlen(name) - 1; /* Get the filename. */ val.format = vpiStringVal; vpi_get_value(file, &val); /* Verify that we have a string and that it is not NULL. */ if (val.format != vpiStringVal || !*(val.value.str)) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's file name argument is not a valid string.\n", name); return 0; } /* * Verify that the file name is composed of only printable * characters. */ len = strlen(val.value.str); for (idx = 0; idx < len; idx++) { if (! isprint(val.value.str[idx])) { char msg [64]; snprintf(msg, 64, "WARNING: %s:%d:", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s %s's file name argument contains non-" "printable characters.\n", msg, name); vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", val.value.str); return 0; } } /* Open the file and return the result. */ val.format = vpiIntVal; val.value.integer = vpi_fopen(val.value.str, mode); vpi_put_value(callh, &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; }
static PLI_INT32 sys_dumplimit_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); s_vpi_value val; /* Get the value and set the dump limit. */ val.format = vpiIntVal; vpi_get_value(vpi_scan(argv), &val); dump_limit = val.value.integer; vpi_free_object(argv); return 0; }
static PLI_INT32 poke_calltf(char*xx) { s_vpi_value value; s_vpi_time poke_time; s_cb_data cb_data; vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle dst, val, del, tmp; struct poke_details*poke; (void)xx; /* Parameter is not used. */ assert(argv); dst = vpi_scan(argv); assert(dst); val = vpi_scan(argv); assert(val); del = vpi_scan(argv); assert(del); tmp = vpi_scan(argv); assert(tmp == 0); poke = calloc(1, sizeof (struct poke_details)); assert(poke); poke->dst = dst; value.format = vpiIntVal; vpi_get_value(val, &value); poke->val = value.value.integer; value.format = vpiIntVal; vpi_get_value(del, &value); poke_time.low = value.value.integer; poke_time.high = 0; poke_time.type = vpiSimTime; cb_data.reason = cbAtStartOfSimTime; cb_data.cb_rtn = delayed_poke; cb_data.user_data = (char*)poke; cb_data.time = &poke_time; vpi_register_cb(&cb_data); return 0; }
static int sys_fgets_calltf(char *name) { unsigned int mcd; FILE*fd; s_vpi_value value, rval; char*txt; unsigned txt_len; vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle str = vpi_scan(argv); vpiHandle mch = vpi_scan(argv); value.format = vpiIntVal; vpi_get_value(mch, &value); mcd = value.value.integer; fd = vpi_get_file(mcd); if (!fd || IS_MCD(mcd)) { rval.format = vpiIntVal; rval.value.integer = 0; vpi_put_value(sys, &rval, 0, vpiNoDelay); return 0; } txt_len = vpi_get(vpiSize, str) / 8; txt = malloc(txt_len + 1); if (fgets(txt, txt_len, fd) == 0) { rval.format = vpiIntVal; rval.value.integer = 0; vpi_put_value(sys, &rval, 0, vpiNoDelay); free(txt); return 0; } rval.format = vpiIntVal; rval.value.integer = strlen(txt); vpi_put_value(sys, &rval, 0, vpiNoDelay); value.format = vpiStringVal; value.value.str = txt; vpi_put_value(str, &value, 0, vpiNoDelay); free(txt); return 0; }
static PLI_INT32 calltf(PLI_BYTE8 *data) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle mod = vpi_scan(argv); (void)data; /* Parameter is not used. */ vpi_free_object(argv); vpi_printf("Module instance %s is%s a cell.\n", vpi_get_str(vpiFullName, mod), vpi_get(vpiCellInstance, mod) ? "" : " not"); return 0; }
static PLI_INT32 simbus_poll_calltf(char*my_name) { int poll_state; s_vpi_value value; vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle bus_h = vpi_scan(argv); assert(bus_h); value.format = vpiIntVal; vpi_get_value(bus_h, &value); int bus = value.value.integer; assert(bus >= 0 && bus < MAX_INSTANCES); vpiHandle trig = vpi_scan(argv); assert(trig); vpi_free_object(argv); DEBUG(SIMBUS_DEBUG_CALLS, "Call $poll(%d...)\n", bus); poll_state = check_readable(bus); value.format = vpiScalarVal; value.value.scalar = poll_state? vpi1 : vpi0; vpi_put_value(trig, &value, 0, vpiNoDelay); if (poll_state == 0) { struct t_cb_data cb_data; struct t_vpi_time cb_time; cb_time.type = vpiSuppressTime; cb_data.reason = cbReadWriteSynch; cb_data.cb_rtn = poll_for_simbus_bus; cb_data.time = &cb_time; vpi_register_cb(&cb_data); instance_table[bus].trig = trig; } else { instance_table[bus].trig = 0; } DEBUG(SIMBUS_DEBUG_CALLS, "return $poll(%d...)\n", bus); return 0; }
static int sys_dist_uniform_calltf(char*name) { s_vpi_value val; vpiHandle call_handle; vpiHandle argv; vpiHandle seed = 0, start, end; long i_seed, i_start, i_end; call_handle = vpi_handle(vpiSysTfCall, 0); assert(call_handle); argv = vpi_iterate(vpiArgument, call_handle); if (argv == 0) { vpi_printf("ERROR: %s requires parameters " "(seed, start, end)\n", name); return 0; } seed = vpi_scan(argv); assert(seed); start = vpi_scan(argv); assert(start); end = vpi_scan(argv); assert(end); vpi_free_object(argv); val.format = vpiIntVal; vpi_get_value(seed, &val); i_seed = val.value.integer; vpi_get_value(start, &val); i_start = val.value.integer; vpi_get_value(end, &val); i_end = val.value.integer; val.format = vpiIntVal; val.value.integer = rtl_dist_uniform(&i_seed, i_start, i_end); vpi_put_value(call_handle, &val, 0, vpiNoDelay); val.format = vpiIntVal; val.value.integer = i_seed; vpi_put_value(seed, &val, 0, vpiNoDelay); return 0; }
VpiIterator::VpiIterator(GpiImplInterface *impl, GpiObjHdl *hdl) : GpiIterator(impl, hdl), m_iterator(NULL) { vpiHandle iterator; vpiHandle vpi_hdl = m_parent->get_handle<vpiHandle>(); int type = vpi_get(vpiType, vpi_hdl); if (NULL == (selected = iterate_over.get_options(type))) { LOG_WARN("VPI: Implementation does not know how to iterate over %s(%d)", vpi_get_str(vpiType, vpi_hdl), type); return; } for (one2many = selected->begin(); one2many != selected->end(); one2many++) { /* GPI_GENARRAY are pseudo-regions and all that should be searched for are the sub-regions */ if (m_parent->get_type() == GPI_GENARRAY && *one2many != vpiInternalScope) { LOG_DEBUG("vpi_iterator vpiOneToManyT=%d skipped for GPI_GENARRAY type", *one2many); continue; } iterator = vpi_iterate(*one2many, vpi_hdl); if (iterator) { break; } LOG_DEBUG("vpi_iterate type=%d returned NULL", *one2many); } if (NULL == iterator) { LOG_DEBUG("vpi_iterate return NULL for all relationships on %s (%d) type:%s", vpi_get_str(vpiName, vpi_hdl), type, vpi_get_str(vpiType, vpi_hdl)); selected = NULL; return; } LOG_DEBUG("Created iterator working from type %d %s", *one2many, vpi_get_str(vpiFullName, vpi_hdl)); m_iterator = iterator; }
char *tf_istrgetp(PLI_INT32 n, PLI_INT32 fmt, void *obj) { vpiHandle sys_h, sys_i, arg_h = 0; s_vpi_value value; char *rtn = 0; assert(n > 0); /* get task/func handle */ sys_h = (vpiHandle)obj; sys_i = vpi_iterate(vpiArgument, sys_h); /* find nth arg */ while (n > 0) { if (!(arg_h = vpi_scan(sys_i))) { goto out; } n--; } if (vpi_get(vpiType, arg_h) == vpiConstant && vpi_get(vpiConstType, arg_h) == vpiStringConst) { value.format = vpiStringVal; vpi_get_value(arg_h, &value); rtn = value.value.str; } else { value.format = -1; switch (tolower(fmt)) { case 'b': value.format = vpiBinStrVal; break; case 'o': value.format = vpiOctStrVal; break; case 'd': value.format = vpiDecStrVal; break; case 'h': value.format = vpiHexStrVal; break; } if (value.format > 0) { vpi_get_value(arg_h, &value); rtn = value.value.str; } } vpi_free_object(sys_i); out: if (pli_trace) { fprintf(pli_trace, "tf_istrgetp(n=%d, fmt=%c, obj=%p) --> \"%s\"\n", n, fmt, obj, rtn); } return rtn; }
/* * process one instance and recursively process all under instances * processing is top down depth first */ static void process_inst(vpiHandle up_ihref) { int isiz; vpiHandle iter, ihref; iproc_rtn(up_ihref); if ((iter = vpi_iterate(vpiModule, up_ihref)) == NULL) return; isiz = vpi_get(vpiSize, iter); vpi_printf(" There are %d instances in %s.\n", isiz, vpi_get_str(vpiFullName, up_ihref)); for (;;) { if ((ihref = vpi_scan(iter)) == NULL) break; process_inst(ihref); } }
static vpiHandle find_scope(vpiHandle scope, const char*name) { vpiHandle idx = vpi_iterate(vpiModule, scope); assert(idx); vpiHandle cur; while ( (cur = vpi_scan(idx)) ) { if ( strcmp(name, vpi_get_str(vpiName,cur)) == 0) { vpi_free_object(idx); return cur; } } return 0; }
/* * acc_next_topmod implemented using VPI interface */ handle acc_next_topmod(handle prev_topmod) { static vpiHandle last = NULL; static vpiHandle mod_i = NULL; if (!prev_topmod) { /* start over */ mod_i = vpi_iterate(vpiModule, NULL); } else { /* subsequent time through */ assert(prev_topmod == last); } last = vpi_scan(mod_i); return last; }
/* * Check that the function is called with the correct argument. */ static PLI_INT32 sys_clog2_compiletf(PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv, arg; assert(callh != 0); argv = vpi_iterate(vpiArgument, callh); (void) name; /* Not used! */ /* We must have an argument. */ if (argv == 0) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("$clog2 requires one numeric argument.\n"); vpi_control(vpiFinish, 1); return 0; } /* The argument must be numeric. */ arg = vpi_scan(argv); if (! is_numeric_obj(arg)) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("The first argument to $clog2 must be numeric.\n"); vpi_control(vpiFinish, 1); } /* We can have a maximum of one argument. */ if (vpi_scan(argv) != 0) { char msg [64]; unsigned argc; snprintf(msg, 64, "ERROR: %s:%d:", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); argc = 1; while (vpi_scan(argv)) argc += 1; vpi_printf("%s $clog2 takes at most one argument.\n", msg); vpi_printf("%*s Found %u extra argument%s.\n", (int) strlen(msg), " ", argc, argc == 1 ? "" : "s"); vpi_control(vpiFinish, 1); } return 0; }
/* * Implement $fflush system function */ static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle arg; s_vpi_value val; PLI_UINT32 fd_mcd; FILE *fp; errno = 0; /* If we have no argument then flush all the streams. */ if (argv == 0) { fflush(NULL); return 0; } /* Get the file/MC descriptor and verify that it is valid. */ arg = vpi_scan(argv); vpi_free_object(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); fd_mcd = val.value.integer; /* If the MCD is zero we have nothing to do so just return. */ if (fd_mcd == 0) return 0; if ((! IS_MCD(fd_mcd) && vpi_get_file(fd_mcd) == NULL) || ( IS_MCD(fd_mcd) && vpi_mcd_printf(fd_mcd, "%s", "") == EOF) || (! fd_mcd)) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("invalid file descriptor/MCD (0x%x) given to %s.\n", (unsigned int)fd_mcd, name); errno = EBADF; return 0; } if (IS_MCD(fd_mcd)) { vpi_mcd_flush(fd_mcd); } else { /* If we have a valid file descriptor flush the file. */ fp = vpi_get_file(fd_mcd); if (fp) fflush(fp); } return 0; }
static PLI_INT32 to_vec_compiletf(ICARUS_VPI_CONST PLI_BYTE8*user_data) { (void) user_data; /* Parameter is not used. */ vpiHandle systf_handle, arg_iterator, arg_handle; PLI_INT32 arg_type[2]; /* obtain a handle to the system task instance */ systf_handle = vpi_handle(vpiSysTfCall, NULL); if (systf_handle == NULL) { vpi_printf("ERROR: $ivl_darray_method$to_vec failed to obtain systf handle\n"); vpi_control(vpiFinish,0); /* abort simulation */ return 0; } /* obtain handles to system task arguments */ arg_iterator = vpi_iterate(vpiArgument, systf_handle); if (arg_iterator == NULL) { vpi_printf("ERROR: $ivl_darray_method$to_vec requires 2 arguments\n"); vpi_control(vpiFinish, 0); return 0; } /* check the type of object in system task arguments */ arg_handle = vpi_scan(arg_iterator); for(int i = 0; i < 2; ++i) { arg_type[i] = vpi_get(vpiType, arg_handle); arg_handle = vpi_scan(arg_iterator); } if (arg_handle != NULL) { /* are there more arguments? */ vpi_printf("ERROR: $ivl_darray_method$to_vec can only have 2 arguments\n"); vpi_free_object(arg_iterator); vpi_control(vpiFinish, 0); return 0; } if ((arg_type[0] != vpiRegArray) || (arg_type[1] != vpiNet && arg_type[1] != vpiReg && arg_type[1] != vpiBitVar)) { vpi_printf("ERROR: $ivl_darray_method$to_vec value arguments must be a dynamic array and a net or reg\n"); vpi_free_object(arg_iterator); vpi_control(vpiFinish, 0); return 0; } return 0; }
static PLI_INT32 regfileTestCompileTf() { vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle arg = NULL; init(); /* Check for arguments number */ for (int i=0; i < ARGS_NR; i++) { arg = vpi_scan(argv); assert(arg); args[i].handle = arg; char* name = vpi_get_str(vpiName, arg); if (!(args[i].name = copy_string(args[i].name, name))) bomb(); } return 0; }
static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle arg; /* * Check that there are two arguments and that the first is a * register and that the second is numeric. */ if (argv == 0) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s requires two arguments.\n", name); vpi_control(vpiFinish, 1); return 0; } if (vpi_get(vpiType, vpi_scan(argv)) != vpiReg) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's first argument must be a reg.\n", name); vpi_control(vpiFinish, 1); } arg = vpi_scan(argv); if (! arg) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s requires a second (numeric) argument.\n", name); vpi_control(vpiFinish, 1); return 0; } if (! is_numeric_obj(arg)) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's second argument must be numeric.\n", name); vpi_control(vpiFinish, 1); } /* Make sure there are no extra arguments. */ check_for_extra_args(argv, callh, name, "two arguments", 0); return 0; }
static PLI_INT32 sys_dumplimit_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); s_vpi_value val; (void)name; /* Parameter is not used. */ /* Get the value and set the dump limit. */ val.format = vpiIntVal; vpi_get_value(vpi_scan(argv), &val); dump_limit = val.value.integer; fstWriterSetDumpSizeLimit(dump_file, dump_limit); vpi_free_object(argv); return 0; }
static PLI_INT32 sys_deposit_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle target, value; /* Check that there are arguments. */ if (argv == 0) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s requires two arguments.\n", name); vpi_control(vpiFinish, 1); return 0; } /* Check that there are at least two arguments. */ target = vpi_scan(argv); /* This should never be zero. */ value = vpi_scan(argv); if (value == 0) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s requires two arguments.\n", name); vpi_control(vpiFinish, 1); return 0; } assert(target); /* Check the targets type. It must be a net or a register. */ switch (vpi_get(vpiType, target)) { case vpiNet: case vpiReg: break; default: vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("invalid target type (%s) for %s.\n", vpi_get_str(vpiType, target), name); vpi_control(vpiFinish, 1); } /* Check that there is at most two arguments. */ check_for_extra_args(argv, callh, name, "two arguments", 0); return 0; }
/* * routine to get and zero all delays in design */ int process_all_insts(struct t_cb_data *cbp) { int isiz; vpiHandle topiter, topiref; /* build the iterator for each module */ topiter = vpi_iterate(vpiModule, NULL); isiz = vpi_get(vpiSize, topiter); vpi_printf(" There are %d top level modules.\n", isiz); for (;;) { if ((topiref = vpi_scan(topiter)) == NULL) break; process_inst(topiref); } vpi_printf(" >>> All instances processed - continuing with simulation.\n"); return(0); }
static PLI_INT32 listparams_calltf(PLI_BYTE8*name) #endif { vpiHandle sys = vpi_handle(vpiSysTfCall,0); vpiHandle scope= vpi_handle(vpiScope, sys); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle item; while ( (item = vpi_scan(argv)) ) { s_vpi_value value; value.format = vpiStringVal; vpi_get_value(item, &value); param_by_name(scope, value.value.str); } return 0; }
static int sys_fputc_calltf(char *name) { unsigned int mcd; int type; unsigned char x; s_vpi_value value, xvalue; vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle item = vpi_scan(argv); FILE *fp; if (item == 0) { vpi_printf("%s: mcd parameter missing.\n", name); return 0; } type = vpi_get(vpiType, item); switch (type) { case vpiReg: case vpiRealVal: case vpiIntegerVar: break; default: vpi_printf("ERROR: %s mcd parameter must be of integral", name); vpi_printf(", got vpiType=%d\n", type); vpi_free_object(argv); return 0; } value.format = vpiIntVal; vpi_get_value(item, &value); mcd = value.value.integer; if (IS_MCD(mcd)) return EOF; item = vpi_scan(argv); xvalue.format = vpiIntVal; vpi_get_value(item, &xvalue); x = xvalue.value.integer; fp = vpi_get_file(mcd); if (!fp) return EOF; return fputc(x, fp); }
static PLI_INT32 sys_ungetc_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle arg; s_vpi_value val; PLI_UINT32 fd_mcd; FILE *fp; int chr; errno = 0; /* Get the character. */ arg = vpi_scan(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); chr = val.value.integer; /* Get the file/MC descriptor. */ arg = vpi_scan(argv); vpi_free_object(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); fd_mcd = val.value.integer; /* Return EOF if this is not a valid fd. */ fp = vpi_get_file(fd_mcd); if (!fp) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("invalid file descriptor (0x%x) given to %s.\n", (unsigned int)fd_mcd, name); errno = EBADF; val.format = vpiIntVal; val.value.integer = EOF; vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; } /* ungetc the character and return the result. */ val.format = vpiIntVal; val.value.integer = ungetc(chr, fp); if (val.value.integer != EOF) val.value.integer = 0; vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; }
static PLI_INT32 sys_sdf_annotate_calltf(PLI_BYTE8*name) { s_vpi_value value; vpiHandle sys = vpi_handle(vpiSysTfCall,0); vpiHandle argv = vpi_iterate(vpiArgument, sys); /* The first argument is the path to the SDF file. */ vpiHandle path = vpi_scan(argv); assert(path); value.format = vpiStringVal; vpi_get_value(path, &value); if ((value.format != vpiStringVal) || !value.value.str) { vpi_printf("ERROR: %s: File name argument (type=%d)" " does not have a string value.\n", name, vpi_get(vpiType, path)); vpi_control(vpiFinish, 1); return 0; } char*path_str = strdup(value.value.str); FILE*sdf_fd = fopen(path_str, "r"); if (sdf_fd == 0) { vpi_printf("ERROR: %s: Unable to open SDF file `%s'." " Skipping annotation.\n", name, path_str); return 0; } /* The optional second argument is the scope to annotate. */ sdf_scope = vpi_scan(argv); if (sdf_scope) vpi_free_object(argv); if (sdf_scope == 0) { sdf_scope = vpi_handle(vpiScope,sys); } sdf_cur_cell = 0; sdf_process_file(sdf_fd, path_str); fclose(sdf_fd); free(path_str); return 0; }
static PLI_INT32 sys_sdf_annotate_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall,0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle module; check_command_line_args(); /* Check that we have a file name argument. */ if (argv == 0) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s requires a file name argument.\n", name); vpi_control(vpiFinish, 1); return 0; } if (! is_string_obj(vpi_scan(argv))) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's file name must be a string.\n", name); vpi_control(vpiFinish, 1); } /* The module argument is optional. */ module = vpi_scan(argv); if (module == 0) return 0; if (vpi_get(vpiType, module) != vpiModule) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's second argument must be a module instance.\n", name); vpi_control(vpiFinish, 1); } /* Warn the user that we only use the first two arguments. */ if (vpi_scan(argv) != 0) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s currently only uses the first two argument.\n", name); vpi_free_object(argv); } return 0; }
static vpiHandle find_scope(vpiHandle scope, const char*name) { vpiHandle idx = vpi_iterate(vpiModule, scope); /* If this scope has no modules then it can't have the one we * are looking for so just return 0. */ if (idx == 0) return 0; vpiHandle cur; while ( (cur = vpi_scan(idx)) ) { if ( strcmp(name, vpi_get_str(vpiName,cur)) == 0) { vpi_free_object(idx); return cur; } } return 0; }
/* * Compare the +arguments passed to the simulator with the argument * passed to the $test$plusargs. If there is a simulator argument that * is like this argument, then return true. Otherwise return false. */ static PLI_INT32 sys_test_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { s_vpi_value val; s_vpi_vlog_info info; int idx; int flag = 0; size_t slen, len; (void)name; /* Parameter is not used. */ vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); val.format = vpiStringVal; vpi_get_value(vpi_scan(argv), &val); slen = strlen(val.value.str); vpi_get_vlog_info(&info); /* Look for a +arg that matches the prefix supplied. */ for (idx = 0 ; idx < info.argc ; idx += 1) { /* Skip arguments that are not +args. */ if (info.argv[idx][0] != '+') continue; len = strlen(info.argv[idx]+1); if (len < slen) continue; if (strncmp(val.value.str, info.argv[idx]+1, slen) != 0) continue; flag = 1; break; } val.format = vpiIntVal; val.value.integer = flag; vpi_put_value(callh, &val, 0, vpiNoDelay); vpi_free_object(argv); return 0; }