예제 #1
0
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;
}
예제 #2
0
파일: sys_fileio.c 프로젝트: AmkG/iverilog
/*
 * 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;
}
예제 #3
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;
}
예제 #4
0
파일: sys_fileio.c 프로젝트: AmkG/iverilog
/*
 * 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;
}
예제 #5
0
파일: sys_fileio.c 프로젝트: AmkG/iverilog
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;
}
예제 #6
0
파일: sys_fileio.c 프로젝트: AmkG/iverilog
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);
}
예제 #9
0
파일: sys_fileio.c 프로젝트: AmkG/iverilog
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;
}
예제 #11
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;
}
예제 #12
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;
}
예제 #13
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;
}
예제 #14
0
파일: sys_fileio.c 프로젝트: AmkG/iverilog
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;
}
예제 #15
0
파일: sys_fileio.c 프로젝트: AmkG/iverilog
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;
}