Example #1
0
static PLI_INT32 size_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv;
      vpiHandle arg;

      (void)name; /* Parameter is not used. */

      argv = vpi_iterate(vpiArgument, callh);
      assert(argv);
      arg = vpi_scan(argv);
      assert(arg);
      vpi_free_object(argv);

      int res = vpi_get(vpiSize, arg);

      s_vpi_value value;
      value.format = vpiIntVal;
      value.value.integer = res;

      vpi_put_value(callh, &value, 0, vpiNoDelay);

      return 0;
}
Example #2
0
static PLI_INT32 sys_fopenrwa_calltf(PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      s_vpi_value val;
      char *mode, *fname;
      errno = 0;

	/* Get the mode. */
      mode = name + strlen(name) - 1;

	/* Get the file name. */
      fname = get_filename(callh, name, vpi_scan(argv));
      vpi_free_object(argv);
      if (fname == 0) return 0;

	/* Open the file and return the result. */
      val.format = vpiIntVal;
      val.value.integer = vpi_fopen(fname, mode);
      vpi_put_value(callh, &val, 0, vpiNoDelay);
      free(fname);

      return 0;
}
Example #3
0
static PLI_INT32 sys_mti_dist_uniform_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      vpiHandle callh, argv, seed, start, end;
      s_vpi_value val;
      long i_seed, i_start, i_end;

      (void)name; /* Parameter is not used. */

	/* Get the argument handles and convert them. */
      callh = vpi_handle(vpiSysTfCall, 0);
      argv = vpi_iterate(vpiArgument, callh);
      seed = vpi_scan(argv);
      start = vpi_scan(argv);
      end = vpi_scan(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;

	/* Calculate and return the result. */
      val.value.integer = mti_dist_uniform(&i_seed, i_start, i_end);
      vpi_put_value(callh, &val, 0, vpiNoDelay);

	/* Return the seed. */
      val.value.integer = i_seed;
      vpi_put_value(seed, &val, 0, vpiNoDelay);

      vpi_free_object(argv);
      return 0;
}
Example #4
0
PLI_INT32 CompileTF(PLI_BYTE8 *user_data)
#endif
{
	s_cb_data cb_data;
	vpiHandle call_h=vpi_handle(vpiSysTfCall,NULL);
	vpiHandle arg_i,arg_h;

	(void)user_data;  /* Parameter is not used. */

	// Get First Argument and Setup Value Change Callback
	arg_i=vpi_iterate(vpiArgument,call_h);
	arg_h=vpi_scan(arg_i);
	vpi_free_object(arg_i);

	cb_data.reason    = cbValueChange;
	cb_data.cb_rtn    = ValueChange;
	cb_data.value     = NULL;
	cb_data.time      = NULL;
	cb_data.user_data = NULL;
	cb_data.obj       = arg_h;
	vpi_register_cb(&cb_data);

	return(0);
}
Example #5
0
PLI_INT32 cmt_init_comp(PLI_BYTE8 * user_data) {
    (void) user_data;

    vpiHandle systf_handle, arg_handle, arg_iter = NULL;
    PLI_INT32 arg_type;
    bool err = false;

    systf_handle = vpi_handle(vpiSysTfCall, NULL);
    arg_iter = vpi_iterate(vpiArgument, systf_handle);

    if (arg_iter == NULL) {
        vpi_printf("ERROR: $cmt_init takes exactly 2 arguments\n");
        err = true;
        goto INIT_COMP_FINISH;
    }

    //scan for first argument
    arg_handle = vpi_scan(arg_iter);
    arg_type = vpi_get(vpiType, arg_handle);


    if ( (arg_type != vpiConstant) && (arg_type != vpiIntegerVar) && (arg_type != vpiParameter) ) {
        vpi_printf("first argument to $cmt_init should be an integer specifying the maximum width of the cmt circuit.\n");
        err = true;
        goto INIT_COMP_FINISH;
    }

    //scan for second arguement
    arg_handle = vpi_scan(arg_iter);
    if (arg_handle == NULL) {
        arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
        vpi_printf("ERROR: $cmt_init takes exactly 2 arguments\n");
        err = true;
        goto INIT_COMP_FINISH;
    }


    arg_type = vpi_get(vpiType, arg_handle);
    if ( (arg_type != vpiConstant) && (arg_type != vpiIntegerVar) && (arg_type != vpiParameter) ) {
        vpi_printf("ERROR: Second argument to $cmt_init should be an integer specifying the depth of the cmt cricuit.\n");
        err = true;
        goto INIT_COMP_FINISH;
    }

    if (vpi_scan(arg_iter) != NULL) {
        vpi_printf("ERROR: $cmt_init takes exactly 2 arguments");
        err = true;
        goto INIT_COMP_FINISH;
    } else {    // vpi_scan(arg_iter) returned NULL, so arg_iter was automatically freed
        arg_iter = NULL;
    }

INIT_COMP_FINISH:
    // free the iterator unless it's already been freed
    if ( (arg_iter != NULL) && (vpi_scan(arg_iter) != NULL) ) {
        vpi_free_object(arg_iter);
    }

    if (err) {
        vpi_control(vpiFinish, 1);
    }

    return 0;
}
Example #6
0
/*
 * Check that the given $table_model() call has valid arguments.
 */
static PLI_INT32 sys_table_model_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle arg;
      p_table_mod table = create_table();

	/* See if there are any table model arguments. */
      check_command_line_flags();

	/* 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 two arguments.\n", name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

	/* The first N (dimensions) arguments must be numeric. */
      for (arg = vpi_scan(argv);
           arg && is_numeric_obj(arg);
           arg = vpi_scan(argv)) {
	    table->dims += 1;
	    table->indep = (vpiHandle *)realloc(table->indep,
	                                        sizeof(vpiHandle)*table->dims);
	    table->indep[table->dims-1] = arg;
      }

	/* We must have a data file. */
      if (arg == 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;
      }

	/* For now we only allow a constant string (file name). */
      if (! is_const_string_obj(arg)) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s file name argument must be a constant string.\n",
	               name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }
      table->file.arg = arg;

	/* There may be an optional constant string (control string). */
      arg = vpi_scan(argv);
      if (arg) {
	    if (! is_const_string_obj(arg)) {
		  vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
		            (int)vpi_get(vpiLineNo, callh));
		  vpi_printf("%s control string argument must be a constant "
		             "string.\n", name);
		  vpi_control(vpiFinish, 1);
		  return 0;
	    }
	    check_for_extra_args(argv, callh, name, "N numeric and 1 or 2 "
	                         " constant string arguments", 0);
	    table->control.arg = arg;
      }

	/* Save the table data information. */
      vpi_put_userdata(callh, table);

      return 0;
}
Example #7
0
static PLI_INT32 xxx_calltf(PLI_BYTE8 *user_data)
#endif
{
  vpiHandle             systf_h;
  s_vpi_value		vpival; /* get/set register values */
  s_vpi_time		t;
  vpiHandle	arg_iterator;
  int		i;
  vpiHandle	argi[100];

  (void)user_data;  /* Parameter is not used. */

  /* Get handle to this instance, look up our workarea */
  systf_h = vpi_handle(vpiSysTfCall, NULL);
  chkvpierr();

  arg_iterator = vpi_iterate(vpiArgument, systf_h);
  chkvpierr();
  i = 0;

  if (arg_iterator == NULL) {
    fprintf(stderr, "ERROR: missing argument list to $example(...)");
  }

  /* Copy args pointers into argi array */
  while ((argi[i] = vpi_scan(arg_iterator)) != NULL) {
    chkvpierr();
    i++;
  }
  /* iterator is exhausted, no need to free */

  /* Fill in the time struct */
  t.type = vpiScaledRealTime;
  t.high = 0;
  t.low = 0;
  t.real = 10.0;

  /* Fill in the value struct */
  vpival.format = vpiBinStrVal;
  vpival.value.str = charbuf;

  /*
   * This is where the real work happens.  We are called in an intial
   * block and we schedule three "set-values" at times 10, 20 and 30
   * to args 0, 1 and 2.  The charbuf gets shared among the three
   * calls, even though it shouldn't and the values are not distinct.
   */

  /* Write this value to argi[0] at time 10.0 */
  strcpy(charbuf, "01010101");
  vpi_put_value(argi[0], &vpival, &t, vpiTransportDelay);

  /* Write this value to argi[1] at time 20.0 */
  strcpy(charbuf, "x1x1x1x1");
  t.real = 20.0;
  vpi_put_value(argi[1], &vpival, &t, vpiTransportDelay);

  /* Write this value to argi[2] at time 30.0 */
  strcpy(charbuf, "0xz101xz");
  t.real = 30.0;
  vpi_put_value(argi[2], &vpival, &t, vpiTransportDelay);

  return 0;
}
Example #8
0
static PLI_INT32 sys_writemem_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      int addr;
      FILE*file;
      char*fname = 0;
      unsigned cnt;
      s_vpi_value value;
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle mitem = 0;
      vpiHandle start_item = 0;
      vpiHandle stop_item = 0;

      int start_addr, stop_addr, addr_incr;
      int min_addr, max_addr; // Not used in this routine.

      /*======================================== Get parameters */

      get_mem_params(argv, callh, name,
                     &fname, &mitem, &start_item, &stop_item);

      if (fname == 0) return 0;

      /*======================================== Process parameters */

      if (process_params(mitem, start_item, stop_item, callh, name,
                         &start_addr, &stop_addr, &addr_incr,
                         &min_addr, &max_addr)) {
	    free(fname);
	    return 0;
      }

      /* Open the data file. */
      file = fopen(fname, "w");
      if (file == 0) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s: Unable to open %s for writing.\n", name, fname);
	    free(fname);
	    return 0;
      }

      if (strcmp(name,"$writememb")==0) value.format = vpiBinStrVal;
      else value.format = vpiHexStrVal;

      /*======================================== Write memory file */

      cnt = 0;
      for(addr=start_addr; addr!=stop_addr+addr_incr; addr+=addr_incr, ++cnt) {
	  vpiHandle word_index;

	  if (cnt%16 == 0) fprintf(file, "// 0x%08x\n", cnt);

	  word_index = vpi_handle_by_index(mitem, addr);
	  assert(word_index);
	  vpi_get_value(word_index, &value);
	  fprintf(file, "%s\n", value.value.str);
      }

      fclose(file);
      free(fname);
      return 0;
}
Example #9
0
static PLI_INT32 sys_readmem_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      int code, wwid, addr;
      FILE*file;
      char *fname = 0;
      s_vpi_value value;
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle mitem = 0;
      vpiHandle start_item = 0;
      vpiHandle stop_item = 0;

      /* start_addr and stop_addr are the parameters given to $readmem in the
	 Verilog code. When not specified, start_addr is equal to the lower of
	 the [left,right]_addr and stop_addr is equal to the higher of the
	 [left,right]_addr. */
      int start_addr, stop_addr, addr_incr;

      /* min_addr and max_addr are equal to start_addr and stop_addr if
	 start_addr<stop_addr or vice versa if not... */
      int min_addr, max_addr;

      /* This is the number of words that we need from the memory. */
      unsigned word_count;

      /*======================================== Get parameters */

      get_mem_params(argv, callh, name,
                     &fname, &mitem, &start_item, &stop_item);
      if (fname == 0) return 0;

      /*======================================== Process parameters */

      if (process_params(mitem, start_item, stop_item, callh, name,
                         &start_addr, &stop_addr, &addr_incr,
                         &min_addr, &max_addr)) {
	    free(fname);
	    return 0;
      }

	/* Open the data file. */
      file = fopen(fname, "r");
	/* Check to see if we have other directories to look for this file. */
      if (file == 0 && sl_count > 0 && fname[0] != '/') {
	    unsigned idx;
	    char path[4096];

	    for (idx = 0; idx < sl_count; idx += 1) {
		  snprintf(path, sizeof(path), "%s/%s",
		           search_list[idx], fname);
		  path[sizeof(path)-1] = 0;
		  if ((file = fopen(path, "r"))) break;
	    }
      }
      if (file == 0) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s: Unable to open %s for reading.\n", name, fname);
	    free(fname);
	    return 0;
      }

	/* We need this many words from the file. */
      word_count = max_addr-min_addr+1;

      wwid = vpi_get(vpiSize, vpi_handle_by_index(mitem, min_addr));

      /* variable that will be used by the lexer to pass values
	 back to this code */
      value.format = vpiVectorVal;
      value.value.vector = calloc((wwid+31)/32, sizeof(s_vpi_vecval));

      /* Configure the readmem lexer */
      if (strcmp(name,"$readmemb") == 0)
	  sys_readmem_start_file(file, 1, wwid, value.value.vector);
      else
	  sys_readmem_start_file(file, 0, wwid, value.value.vector);

      /*======================================== Read memory file */

      /* Run through the input file and store the new contents in the memory */
      addr = start_addr;
      while ((code = readmemlex()) != 0) {
	  switch (code) {
	  case MEM_ADDRESS:
	      addr = value.value.vector->aval;
	      if (addr < min_addr || addr > max_addr) {
		  vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
		             (int)vpi_get(vpiLineNo, callh));
		  vpi_printf("%s(%s): address (0x%x) is out of range "
		             "[0x%x:0x%x]\n",
			     name, fname, addr, start_addr, stop_addr);
		  goto bailout;
	      }
		/* if there is an address in the memory file, then
		   turn off any possible warnings about not having
		   enough words to load the memory. This is standard
		   behavior from 1364-2005. */
	      word_count = 0;
	      break;

	  case MEM_WORD:
	      if (addr >= min_addr && addr <= max_addr) {
		  vpiHandle word_index;
		  word_index = vpi_handle_by_index(mitem, addr);
		  assert(word_index);
		  vpi_put_value(word_index, &value, 0, vpiNoDelay);

		  if (word_count > 0) word_count -= 1;
	      } else {
		  vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
		             (int)vpi_get(vpiLineNo, callh));
		  vpi_printf("%s(%s): Too many words in the file for the "
		             "requested range [%d:%d].\n",
			     name, fname, start_addr, stop_addr);
		  goto bailout;
	      }

	      addr += addr_incr;
	      break;

	  case MEM_ERROR:
	      vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	                 (int)vpi_get(vpiLineNo, callh));
	      vpi_printf("%s(%s): Invalid input character: %s\n", name,
	                 fname, readmem_error_token);
	      goto bailout;
	      break;

	  default:
	      assert(0);
	      break;
	  }
      }

	/* Print a warning if there are not enough words in the data file. */
      if (word_count > 0) {
	    vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s(%s): Not enough words in the file for the "
		       "requested range [%d:%d].\n", name, fname,
		       start_addr, stop_addr);
      }

 bailout:
      free(value.value.vector);
      free(fname);
      fclose(file);
      destroy_readmem_lexor();
      return 0;
}
Example #10
0
static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      s_vpi_value val;
      int fail = 0;
      char *mode_string = 0;
      unsigned idx;
      vpiHandle item = vpi_scan(argv);
      vpiHandle mode = vpi_scan(argv);
      unsigned len;

	/* Get the mode handle if it exists. */
      if (mode) {
            val.format = vpiStringVal;
            vpi_get_value(mode, &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 mode argument is not a valid string.\n",
		             name);
		  fail = 1;
	    }

	      /* Make sure the mode string is correct. */
	    if (strlen(val.value.str) > 3) {
		  vpi_printf("WARNING: %s:%d: ",
		             vpi_get_str(vpiFile, callh),
		             (int)vpi_get(vpiLineNo, callh));
		  vpi_printf("%s's mode argument (%s) is too long.\n",
		             name, val.value.str);
		  fail = 1;
	    } else {
		  unsigned bin = 0, plus = 0;
		  switch (val.value.str[0]) {
		      case 'r':
		      case 'w':
		      case 'a':
			for (idx = 1; idx < 3 ; idx++) {
			      if (val.value.str[idx] == '\0') break;
			      switch (val.value.str[idx]) {
				    case 'b':
				      if (bin) fail = 1;
				      bin = 1;
				      break;
				    case '+':
				      if (plus) fail = 1;
				      plus = 1;
				      break;
				    default:
				      fail = 1;
				      break;
			      }
			}
			if (! fail) break;

		      default:
			vpi_printf("WARNING: %s:%d: ",
			           vpi_get_str(vpiFile, callh),
			           (int)vpi_get(vpiLineNo, callh));
			vpi_printf("%s's mode argument (%s) is invalid.\n",
			name, val.value.str);
			fail = 1;
			break;
		  }
	    }

            mode_string = strdup(val.value.str);

	    vpi_free_object(argv);
      }

	/* Get the string form of the file name from the file name
	   argument. */
      val.format = vpiStringVal;
      vpi_get_value(item, &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);
	    fail = 1;
	    if (mode) free(mode_string);
      }

	/*
	 * 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);
		  fail = 1;
		  if (mode) free(mode_string);
	    }
      }

	/* If either the mode or file name are not valid just return. */
      if (fail) return 0;

      val.format = vpiIntVal;
      if (mode) {
	    val.value.integer = vpi_fopen(val.value.str, mode_string);
	    free(mode_string);
      } else
	    val.value.integer = vpi_mcd_open(val.value.str);

      vpi_put_value(callh, &val, 0, vpiNoDelay);

      return 0;
}
Example #11
0
int VpiSignalObjHdl::initialise(std::string &name, std::string &fq_name) {
    int32_t type = vpi_get(vpiType, GpiObjHdl::get_handle<vpiHandle>());
    if ((vpiIntVar == type) ||
        (vpiIntegerVar == type) ||
        (vpiIntegerNet == type )) {
        m_num_elems = 1;
    } else {
        m_num_elems = vpi_get(vpiSize, GpiObjHdl::get_handle<vpiHandle>());

        if (GpiObjHdl::get_type() == GPI_STRING) {
            m_indexable   = false; // Don't want to iterate over indices
            m_range_left  = 0;
            m_range_right = m_num_elems-1;
        } else if (GpiObjHdl::get_type() == GPI_REGISTER) {
            vpiHandle hdl = GpiObjHdl::get_handle<vpiHandle>();

            m_indexable   = vpi_get(vpiVector, hdl);

            if (m_indexable) {
                s_vpi_value val;
                vpiHandle iter;

                val.format = vpiIntVal;

                iter = vpi_iterate(vpiRange, hdl);

                /* Only ever need the first "range" */
                if (iter != NULL) {
                    vpiHandle rangeHdl = vpi_scan(iter);

                    vpi_free_object(iter);

                    if (rangeHdl != NULL) {
                        vpi_get_value(vpi_handle(vpiLeftRange,rangeHdl),&val);
                        check_vpi_error();
                        m_range_left = val.value.integer;

                        vpi_get_value(vpi_handle(vpiRightRange,rangeHdl),&val);
                        check_vpi_error();
                        m_range_right = val.value.integer;
                    } else {
                        LOG_CRITICAL("Unable to get Range for indexable object");
                    }
                }
                else {
                    vpi_get_value(vpi_handle(vpiLeftRange,hdl),&val);
                    check_vpi_error();
                    m_range_left = val.value.integer;

                    vpi_get_value(vpi_handle(vpiRightRange,hdl),&val);
                    check_vpi_error();
                    m_range_right = val.value.integer;
                }

                LOG_DEBUG("VPI: Indexable Object initialised with range [%d:%d] and length >%d<", m_range_left, m_range_right, m_num_elems);
            }
        }
    }
    LOG_DEBUG("VPI: %s initialised with %d elements", name.c_str(), m_num_elems);
    return GpiObjHdl::initialise(name, fq_name);
}
Example #12
0
int VpiArrayObjHdl::initialise(std::string &name, std::string &fq_name) {
    vpiHandle hdl = GpiObjHdl::get_handle<vpiHandle>();

    m_indexable   = true;

    int range_idx = 0;

    /* Need to determine if this is a pseudo-handle to be able to select the correct range */
    std::string hdl_name = vpi_get_str(vpiName, hdl);

    /* Removing the hdl_name from the name will leave the psuedo-indices */
    if (hdl_name.length() < name.length()) {
        std::string idx_str = name.substr(hdl_name.length());

        while (idx_str.length() > 0) {
            std::size_t found = idx_str.find_first_of("]");

            if (found != std::string::npos) {
                ++range_idx;
                idx_str = idx_str.substr(found+1);
            } else {
                break;
            }
        }
    }

    /* After determining the range_idx, get the range and set the limits */
    vpiHandle iter = vpi_iterate(vpiRange, hdl);

    s_vpi_value val;
    val.format = vpiIntVal;

    if (iter != NULL) {
        vpiHandle rangeHdl;
        int idx = 0;

        while ((rangeHdl = vpi_scan(iter)) != NULL) {
            if (idx == range_idx) {
                break;
            }
            ++idx;
        }

        if (rangeHdl == NULL) {
            LOG_CRITICAL("Unable to get Range for indexable object");
        } else {
            vpi_free_object(iter); // Need to free iterator since exited early

            vpi_get_value(vpi_handle(vpiLeftRange,rangeHdl),&val);
            check_vpi_error();
            m_range_left = val.value.integer;

            vpi_get_value(vpi_handle(vpiRightRange,rangeHdl),&val);
            check_vpi_error();
            m_range_right = val.value.integer;
        }
    } else if (range_idx == 0) {
        vpi_get_value(vpi_handle(vpiLeftRange,hdl),&val);
        check_vpi_error();
        m_range_left = val.value.integer;

        vpi_get_value(vpi_handle(vpiRightRange,hdl),&val);
        check_vpi_error();
        m_range_right = val.value.integer;
    } else {
        LOG_CRITICAL("Unable to get Range for indexable object");
    }

    /* vpiSize will return a size that is incorrect for multi-dimensional arrays so use the range
     * to calculate the m_num_elems.
     *
     *    For example:
     *       wire [7:0] sig_t4 [0:3][7:4]
     *
     *    The size of "sig_t4" will be reported as 16 through the vpi interface.
     */
    if (m_range_left > m_range_right) {
        m_num_elems = m_range_left - m_range_right + 1;
    } else {
        m_num_elems = m_range_right - m_range_left + 1;
    }

    return GpiObjHdl::initialise(name, fq_name);
}
Example #13
0
static void scan_item(unsigned depth, vpiHandle item, int skip)
{
      struct t_cb_data cb;
      struct vcd_info* info;

      const char* name;
      const char* ident;
      int nexus_id;

      /* list of types to iterate upon */
      int i;
      static int types[] = {
	    /* Value */
	    vpiNet,
	    vpiReg,
	    vpiVariables,
	    /* Scope */
	    vpiFunction,
	    vpiModule,
	    vpiNamedBegin,
	    vpiNamedFork,
	    vpiTask,
	    -1
      };

      switch (vpi_get(vpiType, item)) {

	  case vpiMemoryWord:
	    if (vpi_get(vpiConstantSelect, item) == 0) {
		    /* Turn a non-constant array word select into a
		     * constant word select. */
		  vpiHandle array = vpi_handle(vpiParent, item);
		  PLI_INT32 idx = vpi_get(vpiIndex, item);
		  item = vpi_handle_by_index(array, idx);
	    }
	  case vpiIntegerVar:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiIntVar:
	  case vpiLongIntVar:
	  case vpiTimeVar:
	  case vpiReg:
	  case vpiNet:

	      /* An array word is implicitly escaped so look for an
	       * escaped identifier that this could conflict with. */
            if (vpi_get(vpiType, item) == vpiMemoryWord &&
                vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) {
		  vpi_printf("LXT2 warning: dumping array word %s will "
		             "conflict with an escaped identifier.\n",
		             vpi_get_str(vpiFullName, item));
            }

            if (skip || vpi_get(vpiAutomatic, item)) break;

	    name = vpi_get_str(vpiName, item);
	    nexus_id = vpi_get(_vpiNexusId, item);
	    if (nexus_id) {
		  ident = find_nexus_ident(nexus_id);
	    } else {
		  ident = 0;
	    }

	    if (!ident) {
		  char*tmp = create_full_name(name);
		  ident = strdup_sh(&name_heap, tmp);
		  free(tmp);

		  if (nexus_id) set_nexus_ident(nexus_id, ident);

		  info = new_vcd_info();

		  info->item  = item;
		  info->sym   = lxt2_wr_symbol_add(dump_file, ident,
		                                   0 /* array rows */,
		                                   vpi_get(vpiLeftRange, item),
		                                   vpi_get(vpiRightRange, item),
		                                   LXT2_WR_SYM_F_BITS);
		  info->dmp_next = 0;

		  cb.time      = 0;
		  cb.user_data = (char*)info;
		  cb.value     = NULL;
		  cb.obj       = item;
		  cb.reason    = cbValueChange;
		  cb.cb_rtn    = variable_cb_1;

		  info->cb    = vpi_register_cb(&cb);

	    } else {
		  char *n = create_full_name(name);
		  lxt2_wr_symbol_alias(dump_file, ident, n,
				       vpi_get(vpiSize, item)-1, 0);
		  free(n);
            }

	    break;

	  case vpiRealVar:

            if (skip || vpi_get(vpiAutomatic, item)) break;

	    name = vpi_get_str(vpiName, item);
	    { char*tmp = create_full_name(name);
	      ident = strdup_sh(&name_heap, tmp);
	      free(tmp);
	    }
	    info = new_vcd_info();

	    info->item = item;
	    info->sym  = lxt2_wr_symbol_add(dump_file, ident,
	                                    0 /* array rows */,
	                                    vpi_get(vpiSize, item)-1,
	                                    0, LXT2_WR_SYM_F_DOUBLE);
	    info->dmp_next = 0;

	    cb.time      = 0;
	    cb.user_data = (char*)info;
	    cb.value     = NULL;
	    cb.obj       = item;
	    cb.reason    = cbValueChange;
	    cb.cb_rtn    = variable_cb_1;

	    info->cb    = vpi_register_cb(&cb);

	    break;

	  case vpiModule:
	  case vpiNamedBegin:
	  case vpiTask:
	  case vpiFunction:
	  case vpiNamedFork:

	    if (depth > 0) {
		  int nskip;
		  vpiHandle argv;

		  const char* fullname =
			vpi_get_str(vpiFullName, item);

#if 0
		  vpi_printf("LXT2 info: scanning scope %s, %u levels\n",
		             fullname, depth);
#endif
		  nskip = vcd_scope_names_test(fullname);

		  if (!nskip)
			vcd_scope_names_add(fullname);
		  else
		    vpi_printf("LXT2 warning: ignoring signals in "
		               "previously scanned scope %s\n", fullname);

		  name = vpi_get_str(vpiName, item);

                  push_scope(name);

		  for (i=0; types[i]>0; i++) {
			vpiHandle hand;
			argv = vpi_iterate(types[i], item);
			while (argv && (hand = vpi_scan(argv))) {
			      scan_item(depth-1, hand, nskip);
			}
		  }

                  pop_scope();
	    }
	    break;

	  default:
	    vpi_printf("LXT2 warning: $dumpvars: Unsupported parameter "
	               "type (%s)\n", vpi_get_str(vpiType, item));
      }

}
Example #14
0
int checkRetireInst_calltf(char *user_data)
{
  db_t * db_ptr;
  unsigned int FS_PC;
  unsigned int V_PC;
  SS_WORD_TYPE FS_rdst_value;
  SS_WORD_TYPE V_rdst_value;
  vpiHandle systf_handle, arg_iterator, arg_handle, reg_handle;
  s_vpi_value arg1;
  s_vpi_value arg2;
  // s_vpi_value value_s;
  //unsigned long long instruction;

  /* obtain a handle to the system task instance. */
  systf_handle  = vpi_handle(vpiSysTfCall, 0);

  /* obtain handle to system task argument. */
  arg_iterator  = vpi_iterate(vpiArgument, systf_handle);
  reg_handle    = vpi_scan(arg_iterator);


  /* read current value */
  arg1.format = vpiIntVal;  /* read value as a integer */
  vpi_get_value(reg_handle, &arg1);
  V_PC = (unsigned int) arg1.value.integer;

  // Next value
  reg_handle    = vpi_scan(arg_iterator);
  arg2.format = vpiIntVal;  /* read value as a integer */
  vpi_get_value(reg_handle, &arg2);
  V_rdst_value = (SS_WORD_TYPE) arg2.value.integer;

  // Pop from DB (head) 
  db_ptr = THREAD[0]->get_instr();
  FS_PC = (unsigned int) db_ptr->a_pc;
  if (db_ptr->a_num_rdst > 1) {
    vpi_printf("Double Word destination!!\n");
    vpi_printf("Bye !!\n");
    assert(0);
  }
  if (db_ptr->a_num_rdst == 1)
    FS_rdst_value = db_ptr->a_rdst[0].value;

  // Do the check
  if (V_PC != FS_PC) {
    vpi_printf("Retire PC Error!! ");
    vpi_printf("PC:%x Actual:%x\n",V_PC, FS_PC);
    assert(0);
  }

  if (db_ptr->a_num_rdst == 1) {
    if (V_rdst_value != FS_rdst_value) {
      vpi_printf("Rdst Value Error!! ");
      vpi_printf("Rdst:%x Actual:%x\n",V_rdst_value, FS_rdst_value);
      assert(0);
    }
  }

  /* free iterator memory */
  vpi_free_object(arg_iterator);

  return(0);

}
Example #15
0
static PLI_INT32 ivl_method_next_calltf(PLI_BYTE8*data)
{
      vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, sys);
      vpiHandle arg_enum = vpi_scan(argv);
      vpiHandle arg_item = vpi_scan(argv);
      vpiHandle arg_extra = vpi_scan(argv);

      vpiHandle enum_list = 0;
      vpiHandle memb = 0, first_memb = 0;
      long use_width = 0;
      long item_width = vpi_get(vpiSize, arg_item);

      s_vpi_value memb_value, item_value;

      assert(arg_extra == 0);

      item_value.format = vpiObjTypeVal;
      vpi_get_value(arg_item, &item_value);

	/* If this value is a vector value, then make a safe copy of
	   the vector so that other vpi functions don't trash it. */
      if (item_value.format == vpiVectorVal) {
	    unsigned idx;
	    unsigned hwid = (item_width - 1)/32 + 1;
	    s_vpi_vecval*op = calloc(hwid, sizeof(s_vpi_vecval));
	    for (idx = 0 ; idx < hwid ; idx += 1) {
		  op[idx].aval = item_value.value.vector[idx].aval;
		  op[idx].bval = item_value.value.vector[idx].bval;
	    }
	    item_value.value.vector = op;
      }

      enum_list = vpi_iterate(vpiMember, arg_enum);
      assert(enum_list);

	/* Search for the current value in the member list. */
      do {
	    memb = vpi_scan(enum_list);
	    if (first_memb == 0) {
		  first_memb = memb;
		  use_width = vpi_get(vpiSize, first_memb);
		  assert(use_width == vpi_get(vpiSize, arg_item));
	    }
	    if (memb == 0) break;

	    memb_value.format = vpiObjTypeVal;
	    vpi_get_value(memb, &memb_value);

      } while (! compare_value_eequal(&item_value, &memb_value, use_width));

      if (memb != 0)
	    memb = vpi_scan(enum_list);

      if (memb != 0)
	    vpi_free_object(enum_list);

      if (memb == 0) {
	    memb = first_memb;
	    memb_value.format = vpiIntVal;
      }

	/* Free any stached copy of the vector. */
      if (item_value.format == vpiVectorVal)
	    free(item_value.value.vector);

      vpi_get_value(memb, &memb_value);
      vpi_put_value(sys, &memb_value, 0, vpiNoDelay);

      return 0;
}
Example #16
0
static PLI_INT32 sys_fseek_compiletf(PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle arg;

	/* Check that there are three numeric arguments. */
      if (argv == 0) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s requires three arguments.\n", name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

	/* Check that the first argument is numeric. */
      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 first argument must be numeric.\n", name);
	    vpi_control(vpiFinish, 1);
      }

	/* Check that the second argument exists and is numeric. */
      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 (!arg || !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);
      }

	/* Check that the third argument exists and is numeric. */
      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 third (numeric) argument.\n", name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

      if (!arg || !is_numeric_obj(arg)) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s's third 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 three arguments.\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;
}
Example #17
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;
}
Example #18
0
static void scan_item(unsigned depth, vpiHandle item, int skip)
{
      struct t_cb_data cb;
      struct vcd_info* info;

      enum fstVarType type = FST_VT_MAX;
      enum fstScopeType stype = FST_ST_MAX;
      enum fstVarDir dir;
      const char *name;
      const char *fullname;
      char *escname;
      const char *ident;
      fstHandle new_ident;
      int nexus_id;
      unsigned size;
      PLI_INT32 item_type;

	/* Get the displayed type for the various $var and $scope types. */
	/* Not all of these are supported now, but they should be in a
	 * future development version. */
      item_type = vpi_get(vpiType, item);
      switch (item_type) {
	  case vpiNamedEvent: type = FST_VT_VCD_EVENT; break;
	  case vpiIntVar:
	  case vpiIntegerVar: type = FST_VT_VCD_INTEGER; break;
	  case vpiParameter:  type = FST_VT_VCD_PARAMETER; break;
	    /* Icarus converts realtime to real. */
	  case vpiRealVar:    type = FST_VT_VCD_REAL; break;
	  case vpiMemoryWord:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiLongIntVar:
	  case vpiReg:        type = FST_VT_VCD_REG; break;
	    /* Icarus converts a time to a plain register. */
	  case vpiTimeVar:    type = FST_VT_VCD_TIME; break;
	  case vpiNet:
	    switch (vpi_get(vpiNetType, item)) {
		case vpiWand:    type = FST_VT_VCD_WAND; break;
		case vpiWor:     type = FST_VT_VCD_WOR; break;
		case vpiTri:     type = FST_VT_VCD_TRI; break;
		case vpiTri0:    type = FST_VT_VCD_TRI0; break;
		case vpiTri1:    type = FST_VT_VCD_TRI1; break;
		case vpiTriReg:  type = FST_VT_VCD_TRIREG; break;
		case vpiTriAnd:  type = FST_VT_VCD_TRIAND; break;
		case vpiTriOr:   type = FST_VT_VCD_TRIOR; break;
		case vpiSupply1: type = FST_VT_VCD_SUPPLY1; break;
		case vpiSupply0: type = FST_VT_VCD_SUPPLY0; break;
		default:         type = FST_VT_VCD_WIRE; break;
	    }
	    break;

	  case vpiNamedBegin: stype = FST_ST_VCD_BEGIN; break;
	  case vpiNamedFork:  stype = FST_ST_VCD_FORK; break;
	  case vpiFunction:   stype = FST_ST_VCD_FUNCTION; break;
	  case vpiGenScope:   stype = FST_ST_VCD_GENERATE; break;
	  case vpiModule:     stype = FST_ST_VCD_MODULE; break;
	  case vpiTask:       stype = FST_ST_VCD_TASK; break;

	  default:
	    vpi_printf("FST warning: $dumpvars: Unsupported argument "
	               "type (%s)\n", vpi_get_str(vpiType, item));
	    return;
      }

	/* Do some special processing/checking on array words. Dumping
	 * array words is an Icarus extension. */
      if (item_type == vpiMemoryWord) {
	      /* Turn a non-constant array word select into a constant
	       * word select. */
	    if (vpi_get(vpiConstantSelect, item) == 0) {
		  vpiHandle array = vpi_handle(vpiParent, item);
		  PLI_INT32 idx = vpi_get(vpiIndex, item);
		  item = vpi_handle_by_index(array, idx);
	    }

	      /* An array word is implicitly escaped so look for an
	       * escaped identifier that this could conflict with. */
	      /* This does not work as expected since we always find at
	       * least the array word. We likely need a custom routine. */
            if (vpi_get(vpiType, item) == vpiMemoryWord &&
                vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) {
		  vpi_printf("FST warning: array word %s will conflict "
		             "with an escaped identifier.\n",
		             vpi_get_str(vpiFullName, item));
            }
      }

      fullname = vpi_get_str(vpiFullName, item);

	/* Generate the $var or $scope commands. */
      switch (item_type) {
	  case vpiParameter:
	    vpi_printf("FST sorry: $dumpvars: can not dump parameters.\n");
	    break;

	  case vpiNamedEvent:
	  case vpiIntegerVar:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiIntVar:
	  case vpiLongIntVar:
	  case vpiRealVar:
	  case vpiMemoryWord:
	  case vpiReg:
	  case vpiTimeVar:
	  case vpiNet:

	      /* If we are skipping all signal or this is in an automatic
	       * scope then just return. */
            if (skip || vpi_get(vpiAutomatic, item)) return;

	      /* Skip this signal if it has already been included.
	       * This can only happen for implicitly given signals. */
	    if (vcd_names_search(&fst_var, fullname)) return;

	      /* Declare the variable in the FST file. */
	    name = vpi_get_str(vpiName, item);
	    if (is_escaped_id(name)) {
		  escname = malloc(strlen(name) + 2);
		  sprintf(escname, "\\%s", name);
	    } else escname = strdup(name);

	      /* Some signals can have an alias so handle that. */
	    nexus_id = vpi_get(_vpiNexusId, item);

	    ident = 0;
	    if (nexus_id) ident = find_nexus_ident(nexus_id);

	      /* Named events do not have a size, but other tools use
	       * a size of 1 and some viewers do not accept a width of
	       * zero so we will also use a width of one for events. */
	    if (item_type == vpiNamedEvent) size = 1;
	    else size = vpi_get(vpiSize, item);
	      /* The FST format supports a port direction so if the net
	       * is a port set the direction to one of the following:
	       *   FST_VD_INPUT, FST_VD_OUTPUT or FST_VD_INOUT */
	    dir = FST_VD_IMPLICIT;

	    if (size > 1 || vpi_get(vpiLeftRange, item) != 0) {
		  char *buf = malloc(strlen(escname) + 65);
		  sprintf(buf, "%s [%i:%i]", escname,
                            (int)vpi_get(vpiLeftRange, item),
                            (int)vpi_get(vpiRightRange, item));

		  new_ident = fstWriterCreateVar(dump_file, type,
		                                 dir, size, buf,
		                                 (fstHandle)(long)ident);
		  free(buf);
	    } else {
		  new_ident = fstWriterCreateVar(dump_file, type,
		                                 dir, size, escname,
		                                 (fstHandle)(long)ident);
	    }
	    free(escname);

	    if (!ident) {
		  if (nexus_id) set_nexus_ident(nexus_id,
		                                (const char *)(long)new_ident);

		    /* Add a callback for the signal. */
		  info = malloc(sizeof(*info));

		  info->time.type = vpiSimTime;
		  info->item  = item;
		  info->handle = new_ident;
		  info->scheduled = 0;

		  cb.time      = &info->time;
		  cb.user_data = (char*)info;
		  cb.value     = NULL;
		  cb.obj       = item;
		  cb.reason    = cbValueChange;
		  cb.cb_rtn    = variable_cb_1;

		  info->dmp_next = 0;
		  info->next  = vcd_list;
		  vcd_list    = info;

		  info->cb    = vpi_register_cb(&cb);
	    }

	    break;

	  case vpiModule:
	  case vpiGenScope:
	  case vpiFunction:
	  case vpiTask:
	  case vpiNamedBegin:
	  case vpiNamedFork:

	    if (depth > 0) {
		  char *instname;
		  char *defname = NULL;
		  /* list of types to iterate upon */
		  static int types[] = {
			/* Value */
			vpiNamedEvent,
			vpiNet,
			/* vpiParameter, */
			vpiReg,
			vpiVariables,
			/* Scope */
			vpiFunction,
			vpiGenScope,
			vpiModule,
			vpiNamedBegin,
			vpiNamedFork,
			vpiTask,
			-1
		  };
		  int i;
		  int nskip = (vcd_names_search(&fst_tab, fullname) != 0);

		    /* We have to always scan the scope because the
		     * depth could be different for this call. */
		  if (nskip) {
			vpi_printf("FST warning: ignoring signals in "
			           "previously scanned scope %s.\n", fullname);
		  } else {
			vcd_names_add(&fst_tab, fullname);
		  }

		    /* Set the file and line information for this scope.
		     * Everything has instance information. Only a module
		     * has separate definition information. */
		  instname = vpi_get_str(vpiFile, item);
		  fstWriterSetSourceInstantiationStem(dump_file, instname,
		      (int)vpi_get(vpiLineNo, item), 0);
		  if (item_type == vpiModule) {
			fstWriterSetSourceStem(dump_file,
			    vpi_get_str(vpiDefFile, item),
			    (int)vpi_get(vpiDefLineNo, item), 0);
		  } else {
			fstWriterSetSourceStem(dump_file, instname,
			    (int)vpi_get(vpiLineNo, item), 0);
		  }

		    /* This must be done before the other name is fetched
		     * and the string must always be freed */
		  if (item_type == vpiModule) {
			defname = strdup(vpi_get_str(vpiDefName, item));
		  }
		  name = vpi_get_str(vpiName, item);
		    /* If the two names match only use the vpiName. */
		  if (defname && (strcmp(defname, name) == 0)) {
			free(defname);
			defname = NULL;
		  }
		  fstWriterSetScope(dump_file, stype, name, defname);
		  free(defname);

		  for (i=0; types[i]>0; i++) {
			vpiHandle hand;
			vpiHandle argv = vpi_iterate(types[i], item);
			while (argv && (hand = vpi_scan(argv))) {
			      scan_item(depth-1, hand, nskip);
			}
		  }

		    /* Sort any signals that we added above. */
		  fstWriterSetUpscope(dump_file);
	    }
	    break;
      }
}
Example #19
0
static PLI_INT32 sys_mem_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle arg;

      /* Check that there is 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 two arguments.\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 first argument must be a file name (string).\n",
	               name);
	    vpi_control(vpiFinish, 1);
      }

      /* Check that there is a memory argument. */
      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 (memory) argument.\n", name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

      if (vpi_get(vpiType, arg) != vpiMemory) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s's second argument must be a memory.\n", name);
	    vpi_control(vpiFinish, 1);
      }

      /* Check if there is a starting address argument. */
      arg = vpi_scan(argv);
      if (! arg) 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 third argument must be a start address "
	               "(numeric).\n", name);
	    vpi_control(vpiFinish, 1);
      }

      /* Check if there is a finish address argument. */
      arg = vpi_scan(argv);
      if (! arg) 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 fourth argument must be a finish address "
	               "(numeric).\n", name);
	    vpi_control(vpiFinish, 1);
      }

      /* Make sure there are no extra arguments. */
      check_for_extra_args(argv, callh, name, "four arguments", 1);

      return 0;
}
Example #20
0
static PLI_INT32 sys_dumpvars_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle item;
      s_vpi_value value;
      unsigned depth = 0;

      (void)name; /* Parameter is not used. */

      if (dump_file == 0) {
	    open_dumpfile(callh);
	    if (dump_file == 0) {
		  if (argv) vpi_free_object(argv);
		  return 0;
	    }
      }

      if (install_dumpvars_callback()) {
	    if (argv) vpi_free_object(argv);
	    return 0;
      }

        /* Get the depth if it exists. */
      if (argv) {
	    value.format = vpiIntVal;
	    vpi_get_value(vpi_scan(argv), &value);
	    depth = value.value.integer;
      }
      if (!depth) depth = 10000;

        /* This dumps all the modules in the design if none are given. */
      if (!argv || !(item = vpi_scan(argv))) {
	    argv = vpi_iterate(vpiModule, 0x0);
	    assert(argv);  /* There must be at least one top level module. */
	    item = vpi_scan(argv);
      }

      for ( ; item; item = vpi_scan(argv)) {
	    char *scname;
	    const char *fullname;
	    int add_var = 0;
	    int dep;
	    PLI_INT32 item_type = vpi_get(vpiType, item);

	      /* If this is a signal make sure it has not already
	       * been included. */
	    switch (item_type) {
	        case vpiIntegerVar:
		case vpiBitVar:
		case vpiByteVar:
		case vpiShortIntVar:
		case vpiIntVar:
		case vpiLongIntVar:
	        case vpiMemoryWord:
	        case vpiNamedEvent:
	        case vpiNet:
	        case vpiParameter:
	        case vpiRealVar:
	        case vpiReg:
	        case vpiTimeVar:
		    /* Warn if the variables scope (which includes the
		     * variable) or the variable itself was already
		     * included. A scope does not automatically include
		     * memory words so do not check the scope for them.  */
		  scname = strdup(vpi_get_str(vpiFullName,
		                              vpi_handle(vpiScope, item)));
		  fullname = vpi_get_str(vpiFullName, item);
		  if (((item_type != vpiMemoryWord) &&
		       vcd_names_search(&fst_tab, scname)) ||
		      vcd_names_search(&fst_var, fullname)) {
		        vpi_printf("FST warning: skipping signal %s, "
		                   "it was previously included.\n",
		                   fullname);
		        free(scname);
		        continue;
		  } else {
		        add_var = 1;
		  }
		  free(scname);
	    }

	    dep = draw_scope(item, callh);

	    scan_item(depth, item, 0);
	      /* The scope list must be sorted after we scan an item.  */
	    vcd_names_sort(&fst_tab);

	    while (dep--) fstWriterSetUpscope(dump_file);

	      /* Add this signal to the variable list so we can verify it
	       * is not included twice. This must be done after it has
	       * been added */
	    if (add_var) {
		  vcd_names_add(&fst_var, vpi_get_str(vpiFullName, item));
		  vcd_names_sort(&fst_var);
	    }
      }

      return 0;
}
Example #21
0
static PLI_INT32 sys_readmempath_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle paths = vpi_scan(argv);
      s_vpi_value val;
      unsigned len, idx;
      char *path;

      vpi_free_object(argv);

	/* Get the search path string. */
      val.format = vpiStringVal;
      vpi_get_value(paths, &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 argument (%s) is not a valid string.\n",
	               name, vpi_get_str(vpiType, paths));
	    return 0;
      }

	/*
	 * Verify that the search path 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_path = 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 argument contains non-printable "
		             "characters.\n", msg, name);
		  vpi_printf("%*s \"%s\"\n", (int) strlen(msg), " ", esc_path);
		  free(esc_path);
		  return 0;
	    }
      }

	/* Clear the old list before creating the new list. */
      free_readmempath(NULL);

	/*
	 * Break the string into individual paths and add them to the list.
	 * Print a warning if the path is not valid.
	 */
      for (path = strtok(val.value.str, ":"); path; path = strtok(NULL, ":")) {
	    int res;
	    struct stat sb;

	      /* Warn the user if the path is not valid. */
	    res = stat(path, &sb);
	    if (res == 0) {
		  if (!S_ISDIR(sb.st_mode)) {
			vpi_printf("WARNING: %s:%d: ",
			           vpi_get_str(vpiFile, callh),
			           (int)vpi_get(vpiLineNo, callh));
			vpi_printf("%s's path element \"%s\" is not a "
			           "directory!\n", name, path);
			continue;
		  }
	    } else {
		  vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
		             (int)vpi_get(vpiLineNo, callh));
		  vpi_printf("%s could not find directory \"%s\"!\n",
		             name, path);
		  continue;
	    }

	      /* Add a valid search path element to the list. */
	    sl_count += 1;
	    search_list = (char **) realloc(search_list,
	                                    sizeof(char **)*sl_count);
	    search_list[sl_count-1] = strdup(path);
      }

      return 0;
}
Example #22
0
/* $dumpvars takes a variety of arguments. */
PLI_INT32 sys_dumpvars_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle arg;

      /* No arguments is OK, dump everything. */
      if (argv == 0) return 0;

      /* The first argument is the numeric level. */
      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);
      }

      /* The rest of the arguments are either a module or a variable. */
      while ((arg=vpi_scan(argv)) != NULL) {
        switch(vpi_get(vpiType, arg)) {
          case vpiMemoryWord:
/*
 * We need to allow non-constant selects to support the following:
 *
 * for (lp = 0; lp < max ; lp = lp + 1) $dumpvars(0, array[lp]);
 *
 * We need to do a direct callback on the selected element vs using
 * the &A<> structure. The later will not give us what we want.
 * This is implemented in the calltf routine.
 */
#if 0
            if (vpi_get(vpiConstantSelect, arg) == 0) {
		  vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
		             (int)vpi_get(vpiLineNo, callh));
		  vpi_printf("%s cannot dump a non-constant select %s.\n", name,
		             vpi_get_str(vpiType, arg));
		  vpi_control(vpiFinish, 1);
            }
#endif
          /* The module types. */
          case vpiModule:
          case vpiTask:
          case vpiFunction:
          case vpiNamedBegin:
          case vpiNamedFork:
          /* The variable types. */
#if 0
          case vpiParameter: /* A constant! */
#endif
          case vpiNet:
          case vpiReg:
          case vpiIntegerVar:
          case vpiTimeVar:
          case vpiRealVar:
          case vpiNamedEvent:
            break;

          case vpiParameter: /* A constant! */
            vpi_printf("SORRY: %s:%d: ", vpi_get_str(vpiFile, callh),
                       (int)vpi_get(vpiLineNo, callh));
            vpi_printf("%s cannot currently dump a parameter.\n", name);
            break;

          default:
            vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
                       (int)vpi_get(vpiLineNo, callh));
            vpi_printf("%s cannot dump a %s.\n", name,
                       vpi_get_str(vpiType, arg));
            vpi_control(vpiFinish, 1);
        }
      }

      return 0;
}
Example #23
0
static int process_params(vpiHandle mitem,
                          vpiHandle start_item, vpiHandle stop_item,
                          vpiHandle callh, const char *name,
                          int *start_addr, int *stop_addr, int *addr_incr,
                          int *min_addr, int *max_addr)
{
      s_vpi_value val;
      int left_addr, right_addr;

	/* Get left addr of memory */
      val.format = vpiIntVal;
      vpi_get_value(vpi_handle(vpiLeftRange, mitem), &val);
      left_addr = val.value.integer;

	/* Get right addr of memory */
      val.format = vpiIntVal;
      vpi_get_value(vpi_handle(vpiRightRange, mitem), &val);
      right_addr = val.value.integer;

	/* Get start_addr, stop_addr and addr_incr */
      if (! start_item) {
	  *start_addr = left_addr<right_addr ? left_addr  : right_addr;
	  *stop_addr  = left_addr<right_addr ? right_addr : left_addr;
	  *addr_incr = 1;
      } else {
	  val.format = vpiIntVal;
	  vpi_get_value(start_item, &val);
	  *start_addr = val.value.integer;

	  if (! stop_item) {
	      *stop_addr = left_addr<right_addr ? right_addr : left_addr;
	      *addr_incr = 1;
	  } else {
	      val.format = vpiIntVal;
	      vpi_get_value(stop_item, &val);
	      *stop_addr = val.value.integer;

	      *addr_incr = *start_addr<*stop_addr ? 1 : -1;
	  }
      }

	/* Find the minimum and maximum address. */
      *min_addr = *start_addr<*stop_addr ? *start_addr : *stop_addr ;
      *max_addr = *start_addr<*stop_addr ? *stop_addr  : *start_addr;

	/* If the range is not fully specified and the left address is
	 * greater than the right address. Print a warning that this
	 * code follows 1364-2005.
	 *
	 * If we passed a generation flag we could do the correct thing
	 * for 1364-1995 and 1364-2001 instead of this general warning
	 * or we could only show the warning when using 2001/1995.
	 */
      if (!stop_item && (left_addr > right_addr)) {
	    vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s: Standard inconsistency, following 1364-2005.\n",
	               name);
      }

	/* Check that start_addr and stop_addr are within the memory
	   range */
      if (left_addr < right_addr) {
	  if (*start_addr < left_addr || *start_addr > right_addr) {
	      vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	                 (int)vpi_get(vpiLineNo, callh));
	      vpi_printf("%s: Start address %d is out of bounds for memory "
	                 "\'%s[%d:%d]\'!\n", name, *start_addr,
	                 vpi_get_str(vpiFullName, mitem),
	                 left_addr, right_addr);
	      return 1;
	  }

	  if (*stop_addr < left_addr || *stop_addr > right_addr) {
	      vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	                 (int)vpi_get(vpiLineNo, callh));
	      vpi_printf("%s: Finish address %d is out of bounds for memory "
	                 "\'%s[%d:%d]\'!\n", name, *stop_addr,
	                 vpi_get_str(vpiFullName, mitem),
	                 left_addr, right_addr);
	      return 1;
	  }
      } else {
	  if (*start_addr < right_addr || *start_addr > left_addr) {
	      vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	                 (int)vpi_get(vpiLineNo, callh));
	      vpi_printf("%s: Start address %d is out of bounds for memory "
	                 "\'%s[%d:%d]\'!\n", name, *start_addr,
	                 vpi_get_str(vpiFullName, mitem),
	                 left_addr, right_addr);
	      return 1;
	  }

	  if (*stop_addr < right_addr || *stop_addr > left_addr) {
	      vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	                 (int)vpi_get(vpiLineNo, callh));
	      vpi_printf("%s: Finish address %d is out of bounds for memory "
	                 "\'%s[%d:%d]\'!\n", name, *stop_addr,
	                 vpi_get_str(vpiFullName, mitem),
	                 left_addr, right_addr);
	      return 1;
	  }
      }
      return 0;
}
Example #24
0
/*
 * The runtime code for $countdrivers().
 */
static PLI_INT32 sys_countdrivers_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle arg;
      unsigned idx;
      unsigned counts[4];
      unsigned num_drivers;
      s_vpi_value val;

        /* All returned values are integers. */
      val.format = vpiIntVal;

        /* Get the base net reference and bit select */
      idx = 0;
      arg = vpi_scan(argv);
      assert(arg);
      if (vpi_get(vpiType, arg) == vpiPartSelect) {
            idx = vpi_get(vpiLeftRange, arg);
            arg = vpi_handle(vpiParent, arg);
            assert(arg);
      }

        /* Get the net driver counts from the runtime. */
      vpip_count_drivers(arg, idx, counts);
      num_drivers = counts[0] + counts[1] + counts[2];

        /* Handle optional net_is_forced argument. */
      arg = vpi_scan(argv);
      if (arg == 0) goto args_done;
      val.value.integer = counts[3];
      vpi_put_value(arg, &val, 0, vpiNoDelay);

        /* Handle optional number_of_01x_drivers argument. */
      arg = vpi_scan(argv);
      if (arg == 0) goto args_done;
      val.value.integer = num_drivers;
      vpi_put_value(arg, &val, 0, vpiNoDelay);

        /* Handle optional number_of_0_drivers argument. */
      arg = vpi_scan(argv);
      if (arg == 0) goto args_done;
      val.value.integer = counts[0];
      vpi_put_value(arg, &val, 0, vpiNoDelay);

        /* Handle optional number_of_1_drivers argument. */
      arg = vpi_scan(argv);
      if (arg == 0) goto args_done;
      val.value.integer = counts[1];
      vpi_put_value(arg, &val, 0, vpiNoDelay);

        /* Handle optional number_of_x_drivers argument. */
      arg = vpi_scan(argv);
      if (arg == 0) goto args_done;
      val.value.integer = counts[2];
      vpi_put_value(arg, &val, 0, vpiNoDelay);

        /* Free the argument iterator. */
      vpi_free_object(argv);

args_done:
      val.value.integer = (num_drivers > 1) ? 1 : 0;
      vpi_put_value(callh, &val, 0, vpiNoDelay);
      return 0;
}
static int sys_dumpvars_calltf(char*name)
{
      unsigned depth;
      s_vpi_value value;
      vpiHandle item = 0;
      vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv;

      if (dump_file == 0) {
	    open_dumpfile();
	    if (dump_file == 0)
		  return 0;
      }

      if (install_dumpvars_callback()) {
	    return 0;
      }

      argv = vpi_iterate(vpiArgument, sys);

      depth = 0;
      if (argv && (item = vpi_scan(argv)))
	    switch (vpi_get(vpiType, item)) {
		case vpiConstant:
		case vpiNet:
		case vpiReg:
		case vpiIntegerVar:
		case vpiMemoryWord:
		  value.format = vpiIntVal;
		  vpi_get_value(item, &value);
		  depth = value.value.integer;
		  break;
	    }

      if (!depth)
	    depth = 10000;

      if (!argv) {
	    // $dumpvars;
	    // search for the toplevel module
	    vpiHandle parent = vpi_handle(vpiScope, sys);
	    while (parent) {
		  item = parent;
		  parent = vpi_handle(vpiScope, item);
	    }

      } else if (!item  ||  !(item = vpi_scan(argv))) {
	    // $dumpvars(level);
	    // $dumpvars();
	    // dump the current scope
	    item = vpi_handle(vpiScope, sys);
	    argv = 0x0;
      }

      for ( ; item; item = argv ? vpi_scan(argv) : 0x0) {

	    int dep = draw_scope(item);

	    vcd_names_sort(&vcd_tab);
	    scan_item(depth, item, 0);
	    
	    while (dep--) {
		  fprintf(dump_file, "$upscope $end\n");
	    }
      }

      return 0;
}
Example #26
0
static PLI_INT32 sys_value_plusargs_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      s_vpi_vlog_info info;
      s_vpi_value fmt;
      s_vpi_value res;
      char msg[64];
      char*cp;
      int idx;
      int flag = 0;
      size_t slen, len;

      vpiHandle callh  = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);

      fmt.format = vpiStringVal;
      vpi_get_value(vpi_scan(argv), &fmt);

	/* Check for the start of a format string. */
      cp = strchr(fmt.value.str, '%');
      if (cp == 0) {
	    snprintf(msg, sizeof(msg), "ERROR: %s:%d:",
	             vpi_get_str(vpiFile, callh),
	             (int)vpi_get(vpiLineNo, callh));
	    msg[sizeof(msg)-1] = 0;

	    vpi_printf("%s %s is missing a format code.\n", msg, name);
	    vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

	/* This is the length of string we will look for. */
      slen = cp - fmt.value.str;

	/* Skip a zero. */
      cp += 1;
      if (*cp == '0') cp += 1;

	/* Check the format code. */
      switch (*cp) {
	  case 'd':
	  case 'D':
	  case 'o':
	  case 'O':
	  case 'h':
	  case 'H':
	  case 'x':
	  case 'X':
	  case 'b':
	  case 'B':
	  case 'e':
	  case 'E':
	  case 'f':
	  case 'F':
	  case 'g':
	  case 'G':
	  case 's':
	  case 'S':
	    break;
	  default:
	    snprintf(msg, sizeof(msg), "ERROR: %s:%d:",
	             vpi_get_str(vpiFile, callh),
	             (int)vpi_get(vpiLineNo, callh));
	    msg[sizeof(msg)-1] = 0;

	    vpi_printf("%s %s has an invalid format string:\n", msg, name);
	    vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

	/* Warn if there is any trailing garbage. */
      if (*(cp+1) != '\0') {
	    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 Skipping trailing garbage in %s's format string:\n",
	               msg, name);
	    vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", fmt.value.str);
	    *(cp+1) = '\0';
      }

      vpi_get_vlog_info(&info);

	/* Look for a +arg that matches the prefix supplied. */
      for (idx = 0 ;  idx < info.argc ;  idx += 1) {
	    char*sp, *tp, *end;
            size_t sp_len;

	      /* Skip arguments that are not +args. */
	    if (info.argv[idx][0] != '+')
		  continue;

	    len = strlen(info.argv[idx]+1);
	    if (len < slen)
		  continue;

	    if (strncmp(fmt.value.str, info.argv[idx]+1, slen) != 0)
		  continue;

	    sp = info.argv[idx]+1+slen;
            sp_len = strlen(sp);
	    switch (*cp) {
		case 'd':
		case 'D':
		  res.format = vpiDecStrVal;
		    /* A decimal string can set the value to "x" or "z". */
		  if (sp_len == strspn(sp, "xX_") ||
		      sp_len == strspn(sp, "zZ_")) {
			res.value.str = sp;
		    /* A decimal string must contain only these characters.
		     * A decimal string can not start with an "_" character.
		     * A "-" can only be at the start of the string. */
		  } else if (sp_len != strspn(sp, "-0123456789_") ||
		             *sp == '_' ||
		             ((tp = strrchr(sp, '-')) && tp != sp)) {
			res.value.str = "x";
			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 Invalid decimal value passed to %s:\n",
			           msg, name);
			vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
		  } else {
			res.value.str = sp;
		  }
		  break;
		case 'o':
		case 'O':
		  res.format = vpiOctStrVal;
		    /* An octal string must contain only these characters.
		     * An octal string can not start with an "_" character.
		     * A "-" can only be at the start of the string. */
		  if (sp_len != strspn(sp, "-01234567_xXzZ") ||
		      *sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
			res.value.str = "x";
			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 Invalid octal value passed to %s:\n",
			           msg, name);
			vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
		  } else {
			res.value.str = sp;
		  }
		  break;
		case 'h':
		case 'H':
		case 'x':
		case 'X':
		  res.format = vpiHexStrVal;
		    /* A hex. string must contain only these characters.
		     * A hex. string can not start with an "_" character.
		     * A "-" can only be at the start of the string. */
		  if (sp_len != strspn(sp, "-0123456789aAbBcCdDeEfF_xXzZ") ||
		      *sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
			res.value.str = "x";
			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 Invalid hex value passed to %s:\n",
			           msg, name);
			vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
		  } else {
			res.value.str = sp;
		  }
		  break;
		case 'b':
		case 'B':
		  res.format = vpiBinStrVal;
		    /* A binary string must contain only these characters.
		     * A binary string can not start with an "_" character.
		     * A "-" can only be at the start of the string. */
		  if (sp_len != strspn(sp, "-01_xXzZ") ||
		      *sp == '_' || ((tp = strrchr(sp, '-')) && tp != sp)) {
			res.value.str = "x";
			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 Invalid binary value passed to %s:\n",
			           msg, name);
			vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ", sp);
		  } else {
			res.value.str = sp;
		  }
		  break;
		case 'e':
		case 'E':
		case 'f':
		case 'F':
		case 'g':
		case 'G':
		  res.format = vpiRealVal;
		  res.value.real = strtod(sp, &end);
		    /* If we didn't get a full conversion print a warning. */
		  if (*end) {
			  /* We had an invalid value passed. */
			if (end == sp) {
			      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 Invalid real value passed to "
			                 "%s:\n", msg, name);
			      vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ",
			                 sp);
			  /* We have extra garbage at the end. */
			} else {
			      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 Extra character(s) \"%s\" found "
			                 "in %s's real string:\n",
			                 msg, end, name);
			      vpi_printf("%*s \"%s\".\n", (int)strlen(msg), " ",
			                 sp);
			}
		  }
		  break;
		case 's':
		case 'S':
		  res.format = vpiStringVal;
		  res.value.str = sp;
		  break;
		default:
		  assert(0);
	    }

	    vpi_put_value(vpi_scan(argv), &res, 0, vpiNoDelay);
	    flag = 1;
	    break;
      }

      res.format = vpiIntVal;
      res.value.integer = flag;
      vpi_put_value(callh, &res, 0, vpiNoDelay);

      vpi_free_object(argv);
      return 0;
}
Example #27
0
PLI_INT32 cmt_send_comp(PLI_BYTE8 *user_data) {
    (void) user_data;

    vpiHandle systf_handle, arg_handle, arg_iter = NULL;
    PLI_INT32 arg_type;
    bool err = false;

    systf_handle = vpi_handle(vpiSysTfCall, NULL);
    arg_iter = vpi_iterate(vpiArgument, systf_handle);

    if (arg_iter == NULL) {
        vpi_printf("ERROR: $cmt_send takes at least 4 arguments\n");
        err = true;
        goto SEND_COMP_FINISH;
    }

    //scan for first argument
    arg_handle = vpi_scan(arg_iter);
    arg_type = vpi_get(vpiType, arg_handle);


    if ( (arg_type != vpiConstant) && (arg_type != vpiIntegerVar) && (arg_type != vpiReg) && (arg_type != vpiNet) ) {
        vpi_printf("first argument to $cmt_send should be the id of the cmt computation.");
        err = true;
        goto SEND_COMP_FINISH;
    }

    //scan for second arguement
    arg_handle = vpi_scan(arg_iter);
    if (arg_handle == NULL) {
        arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
        vpi_printf("ERROR: $cmt_send takes at least 4 arguments\n");
        err = true;
        goto SEND_COMP_FINISH;
    }

    arg_type = vpi_get(vpiType, arg_handle);
    if ( (arg_type != vpiConstant) && (arg_type != vpiIntegerVar) && (arg_type != vpiReg) && (arg_type != vpiNet)) {
        vpi_printf("ERROR: Second argument to $cmt_send should be an integer constant CMT_*\n");
        err = true;
        goto SEND_COMP_FINISH;
    }

    s_vpi_value arg_val = {0,};
    arg_val.format = vpiIntVal;
    vpi_get_value(arg_handle, &arg_val);
    int requestType = arg_val.value.integer;
#ifdef DEBUG
    vpi_printf("requestType in cmt_send: %d\n", requestType);
#endif


    //scan for third arguement
    arg_handle = vpi_scan(arg_iter);
    if (arg_handle == NULL) {
        arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
        vpi_printf("ERROR: $cmt_send takes at least 4 arguments\n");
        err = true;
        goto SEND_COMP_FINISH;
    }

    arg_type = vpi_get(vpiType, arg_handle);
    if ( (arg_type != vpiReg) && (arg_type != vpiMemory) && (arg_type != vpiMemoryWord) && (arg_type != vpiNetArray) && (arg_type != vpiRegArray) ) {
        vpi_printf("ERROR: third argument to $cmt_send should be the field elements to send.\n");
        vpi_printf("arg_type: %d\n", arg_type);
        err = true;
        goto SEND_COMP_FINISH;
    }


    //scan for fourth argument
    arg_handle = vpi_scan(arg_iter);
    if (arg_handle == NULL) {
        arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
        vpi_printf("ERROR: $cmt_request takes at least 4 arguments\n");
        err = true;
        goto SEND_COMP_FINISH;
    }

    arg_type = vpi_get(vpiType, arg_handle);
    if ( (arg_type != vpiConstant) && (arg_type != vpiParameter) ) {
        vpi_printf("ERROR: fourth argument to $cmt_send should be an integer specifying how many elements to send (CMT_OUTPUT, CMT_H) or the layer (CMT_F012).\n");
        err = true;
        goto SEND_COMP_FINISH;
    }

    if (!isValidSend(requestType)) {
        arg_iter = NULL;
        vpi_printf("ERROR: Invalid reuquestType constant in $cmt_send\n");
        err = true;
        goto SEND_COMP_FINISH;
    }


    if ((requestType == CMT_F012) || (requestType == CMT_H)) { //need a 5th argument in this case.

        arg_handle = vpi_scan(arg_iter);
        if (arg_handle == NULL) {
            arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
            vpi_printf("ERROR: $cmt_send: you requested CMT_F012 without specifying a round, or CMT_H, without specifying a layer.\n");
            err = true;
            goto SEND_COMP_FINISH;
        }

        arg_type = vpi_get(vpiType, arg_handle);
        if ( (arg_type != vpiConstant) && (arg_type != vpiParameter) && (arg_type != vpiIntegerVar) && (arg_type != vpiReg) && (arg_type != vpiNet) ) {
            vpi_printf("ERROR: fifth argument to $cmt_send should be an integer specifying round or layer.\n");
            err = true;
            goto SEND_COMP_FINISH;
        }


    }

    if (vpi_scan(arg_iter) != NULL) {
        vpi_printf("ERROR: $cmt_send takes no more than 5 arguments.\n");
        err = true;
        goto SEND_COMP_FINISH;
    } else {    // vpi_scan(arg_iter) returned NULL, so arg_iter was automatically freed
        arg_iter = NULL;
    }

SEND_COMP_FINISH:
    // free the iterator unless it's already been freed
    if ( (arg_iter != NULL) && (vpi_scan(arg_iter) != NULL) ) {
        vpi_free_object(arg_iter);
    }

    if (err) {
        vpi_control(vpiFinish, 1);
    }

    return 0;
}
Example #28
0
static PLI_INT32 sys_value_plusargs_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle arg;

	/* 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 the first argument is a string. */
      arg = vpi_scan(argv);
      assert(arg != 0);
      if ( ! is_string_obj(arg)) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s's first argument must be a string.\n", name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

      arg = vpi_scan(argv);
      if (! arg) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s's requires a second variable argument.\n", name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

      switch (vpi_get(vpiType, arg)) {

	  case vpiReg:
	  case vpiIntegerVar:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiIntVar:
	  case vpiLongIntVar:
	  case vpiRealVar:
	  case vpiTimeVar:
	    break;

	  default:
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s's second argument must be a variable, found a %s.\n",
		       name, vpi_get_str(vpiType, arg));
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

	/* Make sure there are no extra arguments. */
      check_for_extra_args(argv, callh, name, "two arguments", 0);

      return 0;
}
Example #29
0
PLI_INT32 cmt_request_comp(PLI_BYTE8 * user_data) {
    (void) user_data;

    vpiHandle systf_handle, arg_handle, arg_iter = NULL;
    PLI_INT32 arg_type;
    bool err = false;

    systf_handle = vpi_handle(vpiSysTfCall, NULL);
    arg_iter = vpi_iterate(vpiArgument, systf_handle);

    if (arg_iter == NULL) {
        vpi_printf("ERROR: $cmt_request takes at least 3 arguments\n");
        err = true;
        goto REQUEST_COMP_FINISH;
    }

    //scan for first argument
    arg_handle = vpi_scan(arg_iter);
    arg_type = vpi_get(vpiType, arg_handle);

    if ( (arg_type != vpiConstant) && (arg_type != vpiIntegerVar) && (arg_type != vpiReg) && (arg_type != vpiNet) ) {
        vpi_printf("ERROR: First argument to $cmt_request should be the id of the cmt computation.\n");
        err = true;
        goto REQUEST_COMP_FINISH;
    }

    //scan for second argument
    arg_handle = vpi_scan(arg_iter);
    if (arg_handle == NULL) {
        arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
        vpi_printf("ERROR: $cmt_request takes at least 4 arguments\n");
        err = true;
        goto REQUEST_COMP_FINISH;
    }


    arg_type = vpi_get(vpiType, arg_handle);
    if ( (arg_type != vpiConstant) && (vpi_get(vpiConstType, arg_handle) != vpiDecConst ) ) {
        vpi_printf("ERROR: second argument to $cmt_request should be an integer constant CMT_*\n");
        err = true;
        goto REQUEST_COMP_FINISH;
    }

    s_vpi_value arg_val = {0,};
    arg_val.format = vpiIntVal;
    vpi_get_value(arg_handle, &arg_val);
    int requestType = arg_val.value.integer;

    if (!isValidGetRequest(requestType)) {
        arg_iter = NULL;
        vpi_printf("ERROR: Invalid reuquestType constant in $cmt_request\n");
        err = true;
        goto REQUEST_COMP_FINISH;
    }


    //scan for third argument
    arg_handle = vpi_scan(arg_iter);
    if (arg_handle == NULL) {
        arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
        vpi_printf("ERROR: $cmt_request takes at least 4 arguments\n");
        err = true;
        goto REQUEST_COMP_FINISH;
    }

    arg_type = vpi_get(vpiType, arg_handle);

    if ((arg_type != vpiReg) && (arg_type != vpiMemory)   && (arg_type != vpiMemoryWord) && (arg_type != vpiRegArray) && (arg_type != vpiNetArray) ) {
        vpi_printf("ERROR: third argument to $cmt_request should be a vector of registers to send\n");
        err = true;
        goto REQUEST_COMP_FINISH;
    }

    if (requestType == CMT_R || requestType == CMT_TAU) {

        if ((arg_type != vpiMemoryWord) && (arg_type != vpiReg)) {
            vpi_printf("ERROR: if requesting  CMT_R or CMT_TAU, 3rd argument should be a single registor or memory word.\n");
        }

    }


    //scan for fourth argument
    arg_handle = vpi_scan(arg_iter);
    if (arg_handle == NULL) {
        arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
        vpi_printf("ERROR: $cmt_request takes at least 4 arguments\n");
        err = true;
        goto REQUEST_COMP_FINISH;
    }

    arg_type = vpi_get(vpiType, arg_handle);
    if ( (arg_type != vpiConstant) && (arg_type != vpiParameter) ) {
        vpi_printf("ERROR: fourth argument to $cmt_request should be an integer specifying how many elements, or the layer of the computation. (%d) \n", arg_type);
        err = true;
        goto REQUEST_COMP_FINISH;
    }

    if ( (requestType == CMT_R) || (requestType == CMT_QI) ) {
        //scan for fifth argument
        arg_handle = vpi_scan(arg_iter);
        if (arg_handle == NULL) {
            arg_iter = NULL; // according to the standard, once vpi_scan returns NULL, the iterator is freed
            vpi_printf("ERROR: $cmt_request request requires 5 arguments when requesting CMT_R or CMT_QI.\n");
            err = true;
            goto REQUEST_COMP_FINISH;
        }

        arg_type = vpi_get(vpiType, arg_handle);
        if ( (arg_type != vpiConstant) && (arg_type != vpiParameter) && (arg_type != vpiIntegerVar) && (arg_type != vpiReg) && (arg_type != vpiNet) ) {
            vpi_printf("ERROR: fifth argument to $cmt_request should be an integer specifying how many elements of QI, or which round of sumcheck, for R. \n");
            err = true;
            goto REQUEST_COMP_FINISH;
        }

    }


    if (vpi_scan(arg_iter) != NULL) {
        vpi_printf("ERROR: $cmt_request takes four or five arguments");
        err = true;
        goto REQUEST_COMP_FINISH;
    } else {    // vpi_scan(arg_iter) returned NULL, so arg_iter was automatically freed
        arg_iter = NULL;
    }

REQUEST_COMP_FINISH:
    // free the iterator unless it's already been freed
    if ( (arg_iter != NULL) && (vpi_scan(arg_iter) != NULL) ) {
        vpi_free_object(arg_iter);
    }

    if (err) {
        vpi_control(vpiFinish, 1);
    }

    return 0;

}
Example #30
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;
}