static PLI_INT32 sys_ferror_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle reg; s_vpi_value val; char *msg; PLI_INT32 size; unsigned chars; PLI_UINT32 fd_mcd; /* Get the file pointer. */ val.format = vpiIntVal; vpi_get_value(vpi_scan(argv), &val); fd_mcd = val.value.integer; /* Get the register to put the string result and figure out how many * characters it will hold. */ reg = vpi_scan(argv); size = vpi_get(vpiSize, reg); chars = size / 8; vpi_free_object(argv); /* If we do not already have an error check that the fd is valid. * The assumption is that the other routines have set errno to * EBADF when they encounter a bad file descriptor, so we do not * need to check here. We also need to special case this since * $fopen() will return 0 (a bad file descriptor) when it has a * problem (sets errno). */ if (!errno && !vpi_get_file(fd_mcd) ) { 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; } /* Return the error code. */ val.format = vpiIntVal; val.value.integer = errno; vpi_put_value(callh, &val, 0, vpiNoDelay); /* Only return the number of characters that will fit in the reg. */ msg = (char *) malloc(chars); if (errno != 0) strncpy(msg, strerror(errno), chars-1); else strncpy(msg, "", chars-1); msg[chars-1] = '\0'; val.format = vpiStringVal; val.value.str = msg; vpi_put_value(reg, &val, 0, vpiNoDelay); free(msg); 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++) { 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; }
/* * Generic routine to get the filename from the given handle. * The result is duplicated so call free when the name is no * longer needed. Returns 0 (NULL) for an error. */ char *get_filename(vpiHandle callh, const char *name, vpiHandle file) { s_vpi_value val; unsigned len, idx; /* 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 (%s) is not a valid string.\n", name, vpi_get_str(vpiType, file)); 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((int)val.value.str[idx])) { char msg[64]; char *esc_fname = as_escaped(val.value.str); snprintf(msg, sizeof(msg), "WARNING: %s:%d:", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); msg[sizeof(msg)-1] = 0; vpi_printf("%s %s's file name argument contains non-" "printable characters.\n", msg, name); vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_fname); free(esc_fname); return 0; } } return strdup(val.value.str); }
/* For system tasks/functions that take a single numeric argument. */ PLI_INT32 sys_one_numeric_arg_compiletf(PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); /* Check that there is an argument and that it is numeric. */ if (argv == 0) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s requires a single numeric argument.\n", name); vpi_control(vpiFinish, 1); return 0; } if (! is_numeric_obj(vpi_scan(argv))) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's argument must be numeric.\n", name); vpi_control(vpiFinish, 1); } /* Make sure there are no extra arguments. */ 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 %s takes a single numeric argument.\n", msg, name); vpi_printf("%*s Found %u extra argument%s.\n", (int) strlen(msg), " ", argc, argc == 1 ? "" : "s"); vpi_control(vpiFinish, 1); } return 0; }
/* * Implement the $fopen system function. */ static PLI_INT32 sys_fopen_compiletf(PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv; vpiHandle arg; assert(callh != 0); argv = vpi_iterate(vpiArgument, callh); /* Check that there is a file name argument and that it is a string. */ if (argv == 0) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s requires a string 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 argument must be a string.\n", name); vpi_control(vpiFinish, 1); } /* The type argument is optional. */ arg = vpi_scan(argv); if (arg == 0) return 0; /* When provided, the type argument must be a string. */ if (! is_string_obj(arg)) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's type argument must be a string.\n", name); vpi_control(vpiFinish, 1); } /* Make sure there are no extra arguments. */ check_for_extra_args(argv, callh, name, "two string arguments", 1); return 0; }
static void set_handle_to_value(vpiHandle sig, const char*val) { size_t width = strlen(val); size_t vv_count = (width+31)/32; s_vpi_value value; value.value.vector = calloc(vv_count, sizeof(s_vpi_vecval)); int idx; for (idx = 0 ; idx < width ; idx += 1) { int word = idx / 32; int bit = idx % 32; char src = val[width-idx-1]; PLI_INT32 amask = 0; PLI_INT32 bmask = 0; switch (src) { case '0': continue; case '1': amask = 1; bmask = 0; break; case 'x': amask = 1; bmask = 1; break; case 'z': amask = 0; bmask = 1; break; } s_vpi_vecval*vp = value.value.vector+word; vp->aval |= amask << bit; vp->bval |= bmask << bit; } if (vpi_get(vpiSize, sig) != width) { vpi_printf("ERROR: %s is %d bits, got %zu from server\n", vpi_get_str(vpiName, sig), vpi_get(vpiSize, sig), width); vpi_flush(); } assert(vpi_get(vpiSize, sig) == width); assert(vpi_get(vpiType, sig) == vpiReg); value.format = vpiVectorVal; vpi_put_value(sig, &value, 0, vpiNoDelay); free(value.value.vector); }
static void open_dumpfile(vpiHandle callh) { if (dump_path == 0) dump_path = strdup("dump.fst"); dump_file = fstWriterCreate(dump_path, 1); if (dump_file == 0) { vpi_printf("FST Error: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("Unable to open %s for output.\n", dump_path); vpi_control(vpiFinish, 1); free(dump_path); dump_path = 0; return; } else { int prec = vpi_get(vpiTimePrecision, 0); unsigned scale = 1; unsigned udx = 0; time_t walltime; char scale_buf[65]; vpi_printf("FST info: dumpfile %s opened for output.\n", dump_path); time(&walltime); assert(prec >= -15); while (prec < 0) { udx += 1; prec += 3; } while (prec > 0) { scale *= 10; prec -= 1; } fstWriterSetDate(dump_file, asctime(localtime(&walltime))); fstWriterSetVersion(dump_file, "Icarus Verilog"); sprintf(scale_buf, "\t%u%s\n", scale, units_names[udx]); fstWriterSetTimescaleFromString(dump_file, scale_buf); /* Set the faster dump type when requested. */ if ((lxm_optimum_mode == LXM_SPEED) || (lxm_optimum_mode == LXM_BOTH)) { fstWriterSetPackType(dump_file, 1); } /* Set the most effective compression when requested. */ if ((lxm_optimum_mode == LXM_SPACE) || (lxm_optimum_mode == LXM_BOTH)) { fstWriterSetRepackOnClose(dump_file, 1); } } }
/* * print contents of one loads or drivers iterator iter inside instance ihref * * when called to print loads of task variables ihref will be nil */ static void prt_iter(vpiHandle iter, vpiHandle ihref) { int htyp; vpiHandle href, portihref; char *chp, s1[1025]; for (;;) { if ((href = vpi_scan(iter)) == NULL) break; htyp = vpi_get(vpiType, href); /* must handle port as special case because can be module port */ /* or up instance port connection */ if (htyp == vpiModPathIn || htyp == vpiModPathOut) strcpy(s1, "**NONE(0)"); else { if ((chp = vpi_get_str(vpiFile, href)) == NULL) strcpy(s1, "**NONE(0)"); else sprintf(s1, "**%s(%d)", chp, vpi_get(vpiLineNo, href)); } if (htyp == vpiPort) { /* if ld/drv net in same instance as port then module port */ /* else up instance connection */ portihref = vpi_handle(vpiModule, href); if (vpi_compare_objects(ihref, portihref)) { vpi_printf(" Port (vpiLowConn) object at %s\n", s1); } else { sprintf(s1, "**%s(%d)", vpi_get_str(vpiFile, portihref), vpi_get(vpiLineNo, portihref)); vpi_printf(" Port (vpiHighConn) object at %s\n", s1); } } else vpi_printf(" %s object at %s\n", vpi_get_str(vpiType, href), s1); } }
static PLI_INT32 CompileTF(PLI_BYTE8 *x) #endif { vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle arg; int first = 1; vpi_printf("%s (", vpi_get_str(vpiName, sys)); while ((arg = vpi_scan(argv))) { if (!first) vpi_printf(", "); else first = 0; vpi_printf("%s [type = %d]", vpi_get_str(vpiFullName, arg), (int)vpi_get(vpiType, arg)); if (vpi_get(vpiType, arg) == vpiNamedEvent) num++; } vpi_printf(")\n"); if (num == 2) vpi_printf("PASSED\n"); return 0; }
static int sn_calltf(char*user_data) { vpiHandle scope = vpi_handle(vpiScope, 0); (void)user_data; /* Parameter is not used. */ assert(scope); vpi_printf("My scope name: %s (s.b. xor_try)\n", vpi_get_str(vpiFullName, scope)); return 0; }
double acc_fetch_paramval(handle object) { s_vpi_value val; val.format = vpiObjTypeVal; vpi_get_value(object, &val); switch (val.format) { case vpiStringVal: if (pli_trace) { fprintf(pli_trace, "acc_fetch_paramval(%s) --> \"%s\"\n", vpi_get_str(vpiName, object), val.value.str); } return (double) (long)val.value.str; default: vpi_printf("XXXX: parameter %s has type %d\n", vpi_get_str(vpiName, object), (int)val.format); assert(0); return 0.0; } }
static PLI_INT32 sys_sscanf_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle reg; /* 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 at least three argument.\n", name); vpi_control(vpiFinish, 1); return 0; } /* The first argument must be a register or constant string. */ reg = vpi_scan(argv); /* This should never be zero. */ switch(vpi_get(vpiType, reg)) { case vpiReg: break; case vpiConstant: case vpiParameter: if (vpi_get(vpiConstType, reg) == vpiStringConst) break; default: vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's first argument must be a register or constant " "string.\n", name); vpi_control(vpiFinish, 1); vpi_free_object(argv); return 0; } if (sys_check_args(callh, argv, name)) vpi_control(vpiFinish, 1); return 0; }
/* * print all loads and drivers for nets in iter inside instance ihref * * for task variables ihref will be nil since only needed for ports */ static void prt_1iter_drvlds(vpiHandle iter, vpiHandle ihref) { int ntyp; vpiHandle href, lditer, drviter; for (;;) { if ((href = vpi_scan(iter)) == NULL) break; /* can not pass real variable to load/driver iterator or will get err */ /* bits selects form real illegal in Verilog */ if ((ntyp = vpi_get(vpiType, href)) == vpiRealVar) continue; /* print the drives and loads for 1 net */ vpi_printf("... printing drivers and loads for %s:\n", vpi_get_str(vpiFullName, href)); lditer = vpi_iterate(vpiLocalLoad, href); if (lditer != NULL) { vpi_printf(" Loads:\n"); prt_iter(lditer, ihref); } /* regs can only have loads because in CVC force/assign properties */ /* not drivers */ if (ntyp != vpiNet && ntyp != vpiNetBit) continue; drviter = vpi_iterate(vpiLocalDriver, href); if (drviter != NULL) { vpi_printf(" Drivers:\n"); prt_iter(drviter, ihref); } lditer = vpi_iterate(vpiPathTerm, href); if (lditer != NULL) { vpi_printf(" Path terminals:\n"); prt_iter(lditer, ihref); } lditer = vpi_iterate(vpiTchkTerm, href); if (lditer != NULL) { vpi_printf(" Timing check terminals:\n"); prt_iter(lditer, ihref); } } }
static PLI_INT32 watchreal_cb(p_cb_data cb) { s_vpi_value value; vpiHandle arg = (vpiHandle) (cb->user_data); value.format = vpiRealVal; vpi_get_value(arg, &value); assert(value.format == vpiRealVal); vpi_printf("watchreal: %s = %f\n", vpi_get_str(vpiName, arg), value.value.real); 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; }
int _mon_check_varlist() { const char* p; VlVpiHandle vh2 = vpi_handle_by_name((PLI_BYTE8*)"t.sub", NULL); CHECK_RESULT_NZ(vh2); VlVpiHandle vh10 = vpi_iterate(vpiReg, vh2); CHECK_RESULT_NZ(vh10); VlVpiHandle vh11 = vpi_scan(vh10); CHECK_RESULT_NZ(vh11); p = vpi_get_str(vpiFullName, vh11); CHECK_RESULT_CSTR(p, "t.sub.subsig1"); VlVpiHandle vh12 = vpi_scan(vh10); CHECK_RESULT_NZ(vh12); p = vpi_get_str(vpiFullName, vh12); CHECK_RESULT_CSTR(p, "t.sub.subsig2"); VlVpiHandle vh13 = vpi_scan(vh10); CHECK_RESULT(vh13,0); return 0; }
static int draw_scope(vpiHandle item) { int depth; const char *name; vpiHandle scope = vpi_handle(vpiScope, item); if (!scope) return 0; depth = 1 + draw_scope(scope); name = vpi_get_str(vpiName, scope); push_scope(name); return depth; }
/* * 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; }
/* * 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 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_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 next_sim_time_callback(struct t_cb_data*cb) { vpiHandle obj = (vpiHandle)cb->user_data; s_vpi_value val; s_vpi_time tim; val.format = vpiIntVal; vpi_get_value(obj, &val); tim.type = vpiSimTime; vpi_get_time(obj, &tim); vpi_printf("Callback time=%d %s=%d\n", (int)tim.low, vpi_get_str(vpiName, obj), (int)val.value.integer); return 0; }
static void open_dumpfile(vpiHandle callh) { if (dump_path == 0) dump_path = strdup("dump.vcd"); dump_file = fopen(dump_path, "w"); if (dump_file == 0) { vpi_printf("VCD Error: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("Unable to open %s for output.\n", dump_path); vpi_control(vpiFinish, 1); free(dump_path); dump_path = 0; return; } else { int prec = vpi_get(vpiTimePrecision, 0); unsigned scale = 1; unsigned udx = 0; time_t walltime; vpi_printf("VCD info: dumpfile %s opened for output.\n", dump_path); time(&walltime); assert(prec >= -15); while (prec < 0) { udx += 1; prec += 3; } while (prec > 0) { scale *= 10; prec -= 1; } fprintf(dump_file, "$date\n"); fprintf(dump_file, "\t%s",asctime(localtime(&walltime))); fprintf(dump_file, "$end\n"); fprintf(dump_file, "$version\n"); fprintf(dump_file, "\tIcarus Verilog\n"); fprintf(dump_file, "$end\n"); fprintf(dump_file, "$timescale\n"); fprintf(dump_file, "\t%u%s\n", scale, units_names[udx]); fprintf(dump_file, "$end\n"); } }
static char* fetch_strength_value(handle obj) { struct t_vpi_value val; char str[4]; val.format = vpiStrengthVal; vpi_get_value(obj, &val); /* Should this iterate over the bits? It now matches the old code. */ vpip_format_strength(str, &val, 0); if (pli_trace) { fprintf(pli_trace, "acc_fetch_value(<%s>, \"%%v\") --> %s\n", vpi_get_str(vpiFullName,obj), str); } return __acc_newstring(str); }
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; }
/* * Check that the given $countdrivers() call has valid arguments. */ static PLI_INT32 sys_countdrivers_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle arg; unsigned arg_num; /* 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 at least one argument.\n", name); vpi_control(vpiFinish, 1); return 0; } /* The first argument must be a scalar net or a net bit select. */ arg = vpi_scan(argv); check_net_arg(arg, callh, name); /* The optional arguments must be variables. */ for (arg_num = 2; arg_num < 7; arg_num += 1) { char *arg_name = NULL; switch (arg_num) { case 2: arg_name = "second"; break; case 3: arg_name = "third"; break; case 4: arg_name = "fourth"; break; case 5: arg_name = "fifth"; break; case 6: arg_name = "sixth"; break; default: assert(0); } arg = vpi_scan(argv); if (arg == 0) return 0; check_var_arg(arg, callh, name, arg_name); } /* Make sure there are no extra arguments. */ check_for_extra_args(argv, callh, name, "six arguments", 0); return 0; }
int tf_isetdelay(PLI_INT32 delay, void*ss) { vpiHandle sys = (vpiHandle)ss; int unit = vpi_get(vpiTimeUnit, sys); int prec = vpi_get(vpiTimePrecision, 0); struct t_cb_data cb; struct t_vpi_time ct; if (pli_trace) { fprintf(pli_trace, "%s: tf_isetdelay(%d, ...)" " <unit=%d, prec=%d>;\n", vpi_get_str(vpiName, sys), (int)delay, unit, prec); } /* Convert the delay from the UNITS of the specified task/function to the precision of the simulation. */ assert(unit >= prec); while (unit > prec) { PLI_INT32 tmp = delay * 10; assert(tmp > delay); delay = tmp; unit -= 1; } /* Create a VPI callback to schedule the delay. */ ct.type = vpiSimTime; ct.high = 0; ct.low = delay; cb.reason = cbAfterDelay; cb.cb_rtn = delay_callback; cb.obj = 0; cb.time = &ct; cb.value = 0; cb.user_data = 0; vpi_register_cb(&cb); return 0; }
/* For system tasks/functions that take a single optional numeric argument. */ PLI_INT32 sys_one_opt_numeric_arg_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); /* The argument is optional so just return if none are found. */ if (argv == 0) return 0; if (! is_numeric_obj(vpi_scan(argv))) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's argument must be numeric.\n", name); vpi_control(vpiFinish, 1); } /* Make sure there are no extra arguments. */ check_for_extra_args(argv, callh, name, "one numeric argument", 1); return 0; }
GpiIterator::Status VpiSingleIterator::next_handle(std::string &name, GpiObjHdl **hdl, void **raw_hdl) { GpiObjHdl *new_obj; vpiHandle obj; if (NULL == m_iterator) return GpiIterator::END; obj = vpi_scan(m_iterator); if (NULL == obj) return GpiIterator::END; const char *c_name = vpi_get_str(vpiName, obj); if (!c_name) { int type = vpi_get(vpiType, obj); if (type >= VPI_TYPE_MAX) { *raw_hdl = (void*)obj; return GpiIterator::NOT_NATIVE_NO_NAME; } LOG_DEBUG("Unable to get the name for this object of type %d", type); return GpiIterator::NATIVE_NO_NAME; } std::string fq_name = c_name; LOG_DEBUG("vpi_scan found '%s = '%s'", name.c_str(), fq_name.c_str()); VpiImpl *vpi_impl = reinterpret_cast<VpiImpl*>(m_impl); new_obj = vpi_impl->create_gpi_obj_from_handle(obj, name, fq_name); if (new_obj) { *hdl = new_obj; return GpiIterator::NATIVE; } else return GpiIterator::NOT_NATIVE; }