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; (void) name; /* Not used! */ /* If we have no argument then flush all the streams. */ if (argv == 0) { fflush(NULL); return 0; } /* 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; 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; }
/* * Implement $fclose system function */ static PLI_INT32 sys_fclose_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle fd = vpi_scan(argv); s_vpi_value val; PLI_UINT32 fd_mcd; errno = 0; vpi_free_object(argv); /* Get the file/MC descriptor and verify that it is valid. */ val.format = vpiIntVal; vpi_get_value(fd, &val); fd_mcd = val.value.integer; 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; } /* We need to cancel any active $fstrobe()'s for this FD/MCD. * For now we check in the strobe callback and skip the output * generation when needed. */ vpi_mcd_close(fd_mcd); return 0; }
static PLI_INT32 sys_fscanf_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); s_vpi_value val; struct byte_source src; FILE *fd; errno = 0; val.format = vpiIntVal; vpi_get_value(vpi_scan(argv), &val); fd = vpi_get_file(val.value.integer); if (!fd) { vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("invalid file descriptor (0x%x) given to %s.\n", (int)val.value.integer, name); errno = EBADF; val.format = vpiIntVal; val.value.integer = EOF; vpi_put_value(callh, &val, 0, vpiNoDelay); vpi_free_object(argv); return 0; } src.str = 0; src.fd = fd; scan_format(callh, &src, argv, name); 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 sys_common_fd_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; /* Get the file pointer. */ 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; } val.format = vpiIntVal; switch (name[4]) { case 'l': /* $ftell() */ val.value.integer = ftell(fp); break; case 'f': /* $feof() is from 1264-2005*/ val.value.integer = feof(fp); break; case 'i': /* $rewind() */ val.value.integer = fseek(fp, 0L, SEEK_SET); break; case 't': /* $fgetc() */ val.value.integer = fgetc(fp); break; default: vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s cannot be processed with this routine.\n", name); assert(0); break; } vpi_put_value(callh, &val, 0 , vpiNoDelay); return 0; }
static PLI_INT32 sys_ferror_calltf(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; }
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 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 int sys_ungetc_calltf(char *name) { unsigned int mcd; unsigned char x; s_vpi_value value, xvalue, rval; vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); vpiHandle item = vpi_scan(argv); FILE *fp; rval.format = vpiIntVal; assert(item); value.format = vpiIntVal; vpi_get_value(item, &value); mcd = value.value.integer; if (IS_MCD(mcd)) { rval.value.integer = EOF; vpi_put_value(sys, &rval, 0, vpiNoDelay); return 0; } item = vpi_scan(argv); xvalue.format = vpiIntVal; vpi_get_value(item, &xvalue); x = xvalue.value.integer; fp = vpi_get_file(mcd); if ( !fp ) { rval.value.integer = EOF; vpi_put_value(sys, &rval, 0, vpiNoDelay); return 0; } ungetc(x, fp); rval.value.integer = 0; vpi_put_value(sys, &rval, 0, vpiNoDelay); return 0; }
static PLI_INT32 sys_fputc_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; unsigned char chr; (void) name; /* Not used! */ /* 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; /* Put the character and return the result. */ fp = vpi_get_file(fd_mcd); val.format = vpiIntVal; if (!fp || IS_MCD(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", fd_mcd, name); val.value.integer = EOF; } else val.value.integer = fputc(chr, fp); vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; }
static PLI_INT32 sys_fseek_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; PLI_INT32 offset, oper; FILE *fp; /* Get the file pointer. */ arg = vpi_scan(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); fd_mcd = val.value.integer; /* Get the offset. */ arg = vpi_scan(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); offset = val.value.integer; /* Get the operation. */ arg = vpi_scan(argv); vpi_free_object(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); oper = val.value.integer; /* Check that the operation is in the valid range. */ if ((oper < 0) || (oper > 2)) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's operation must be 0, 1 or 2 given %d.\n", name, oper); val.format = vpiIntVal; val.value.integer = EOF; vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; } /* Return EOF if this is not a valid fd. */ fp = vpi_get_file(fd_mcd); if (!fp || IS_MCD(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", fd_mcd, name); val.format = vpiIntVal; val.value.integer = EOF; vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; } val.format = vpiIntVal; val.value.integer = fseek(fp, offset, oper); vpi_put_value(callh, &val, 0 , vpiNoDelay); return 0; }
static PLI_INT32 sys_fgets_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle regh; vpiHandle arg; s_vpi_value val; PLI_UINT32 fd_mcd; FILE *fp; PLI_INT32 reg_size; char*text; (void) name; /* Not used! */ /* Get the register handle. */ regh = vpi_scan(argv); /* Get the file/MCD descriptor. */ arg = vpi_scan(argv); vpi_free_object(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); fd_mcd = val.value.integer; /* Return zero if this is not a valid fd. */ fp = vpi_get_file(fd_mcd); if (!fp || IS_MCD(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", fd_mcd, name); val.format = vpiIntVal; val.value.integer = 0; vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; } /* Get the register size in bytes and allocate the buffer. */ reg_size = vpi_get(vpiSize, regh) / 8; text = malloc(reg_size + 1); /* Read in the bytes. Return 0 if there was an error. */ if (fgets(text, reg_size+1, fp) == 0) { val.format = vpiIntVal; val.value.integer = 0; vpi_put_value(callh, &val, 0, vpiNoDelay); free(text); return 0; } /* Return the number of character read. */ val.format = vpiIntVal; val.value.integer = strlen(text); vpi_put_value(callh, &val, 0, vpiNoDelay); /* Return the characters to the register. */ val.format = vpiStringVal; val.value.str = text; vpi_put_value(regh, &val, 0, vpiNoDelay); free(text); return 0; }
static PLI_INT32 sys_fseek_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; PLI_INT32 offset, oper; FILE *fp; errno = 0; /* Get the file pointer. */ arg = vpi_scan(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); fd_mcd = val.value.integer; /* Get the offset. */ arg = vpi_scan(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); offset = val.value.integer; /* Get the operation. */ arg = vpi_scan(argv); vpi_free_object(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); oper = val.value.integer; /* Check that the operation is in the valid range. */ switch (oper) { case 0: oper = SEEK_SET; break; case 1: oper = SEEK_CUR; break; case 2: oper = SEEK_END; break; default: vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's operation must be 0, 1 or 2 given %d.\n", name, (int)oper); oper = -1; /* An invalid argument value. */ } /* 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; } val.format = vpiIntVal; val.value.integer = fseek(fp, offset, oper); vpi_put_value(callh, &val, 0 , vpiNoDelay); return 0; }
static PLI_INT32 sys_fread_calltf(PLI_BYTE8*name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); vpiHandle arg, mem_reg; s_vpi_value val; PLI_UINT32 fd_mcd; PLI_INT32 start, count, width, rtn; unsigned is_mem, bpe, words; FILE *fp; s_vpi_vecval *vector; errno = 0; /* Get the register/memory. */ mem_reg = vpi_scan(argv); /* Get the file descriptor. */ arg = vpi_scan(argv); val.format = vpiIntVal; vpi_get_value(arg, &val); fd_mcd = val.value.integer; /* Return 0 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 = 0; vpi_put_value(callh, &val, 0, vpiNoDelay); vpi_free_object(argv); return 0; } /* Are we reading into a memory? */ if (vpi_get(vpiType, mem_reg) == vpiReg) is_mem = 0; else is_mem = 1; /* We only need to get these for memories. */ if (is_mem) { PLI_INT32 left, right, max, min; /* Get the left and right memory address. */ val.format = vpiIntVal; vpi_get_value(vpi_handle(vpiLeftRange, mem_reg), &val); left = val.value.integer; val.format = vpiIntVal; vpi_get_value(vpi_handle(vpiRightRange, mem_reg), &val); right = val.value.integer; max = (left > right) ? left : right; min = (left < right) ? left : right; /* Get the starting address (optional). */ arg = vpi_scan(argv); if (arg) { val.format = vpiIntVal; vpi_get_value(arg, &val); start = val.value.integer; if (start < min || start > max) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's start argument (%d) is outside " "memory range [%d:%d].\n", name, (int)start, (int)left, (int)right); val.format = vpiIntVal; val.value.integer = 0; vpi_put_value(callh, &val, 0, vpiNoDelay); vpi_free_object(argv); return 0; } /* Get the count (optional). */ arg = vpi_scan(argv); if (arg) { val.format = vpiIntVal; vpi_get_value(arg, &val); count = val.value.integer; if (count > max-start) { vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); vpi_printf("%s's count argument (%d) is too " "large for start (%d) and memory " "range [%d:%d].\n", name, (int)count, (int)start, (int)left, (int)right); count = max - start + 1; } vpi_free_object(argv); } else { count = max - start + 1; } } else { start = min; count = max - min + 1; } width = vpi_get(vpiSize, vpi_handle_by_index(mem_reg, start)); } else { start = 0; count = 1; width = vpi_get(vpiSize, mem_reg); vpi_free_object(argv); } words = (width+31)/32; vector = calloc(words, sizeof(s_vpi_vecval)); bpe = (width+7)/8; if (is_mem) { unsigned idx; rtn = 0; for (idx = 0; idx < count; idx += 1) { vpiHandle word; word = vpi_handle_by_index(mem_reg, start+(signed)idx); rtn += fread_word(fp, word, words, bpe, vector); if (feof(fp)) break; } } else { rtn = fread_word(fp, mem_reg, words, bpe, vector); } free(vector); /* Return the number of bytes read. */ val.format = vpiIntVal; val.value.integer = rtn; vpi_put_value(callh, &val, 0, vpiNoDelay); return 0; }