Пример #1
0
/*
 * tf_getp and friends, implemented using VPI interface
 */
PLI_INT32 tf_igetp(PLI_INT32 n, void *obj)
{
      vpiHandle sys_h, sys_i, arg_h = 0;
      s_vpi_value value;
      int rtn = 0;

      assert(n > 0);

      /* get task/func handle */
      sys_h = (vpiHandle)obj;
      sys_i = vpi_iterate(vpiArgument, sys_h);

      /* find nth arg */
      while (n > 0) {
	    if (!(arg_h = vpi_scan(sys_i))) { goto out; }
	    n--;
      }

      /* If it is a constant string, return a pointer to it else int value */
      if (vpi_get(vpiType, arg_h) == vpiConstant &&
	  vpi_get(vpiConstType, arg_h) == vpiStringConst)
      {
	    value.format = vpiStringVal;
	    vpi_get_value(arg_h, &value);
	    rtn = (int) value.value.str;	/* Oh my */
      } else {
	    value.format = vpiIntVal;
	    vpi_get_value(arg_h, &value);
	    rtn = value.value.integer;
      }

      vpi_free_object(sys_i);

out:
      if (pli_trace) {
	    fprintf(pli_trace, "tf_igetp(n=%d, obj=%p) --> %d\n",
		  n, obj, rtn);
      }

      return rtn;
}
Пример #2
0
GpiIterator::Status VpiSingleIterator::next_handle(std::string &name,
                                                   GpiObjHdl **hdl,
                                                   void **raw_hdl)
{
    GpiObjHdl *new_obj;
    vpiHandle obj;

    if (NULL == m_iterator)
        return GpiIterator::END;

    obj = vpi_scan(m_iterator);
    if (NULL == obj)
        return GpiIterator::END;

    const char *c_name = vpi_get_str(vpiName, obj);
    if (!c_name) {
        int type = vpi_get(vpiType, obj);

        if (type >= VPI_TYPE_MAX) {
            *raw_hdl = (void*)obj;
            return GpiIterator::NOT_NATIVE_NO_NAME;
        }

        LOG_DEBUG("Unable to get the name for this object of type %d", type);

        return GpiIterator::NATIVE_NO_NAME;
    }

    std::string fq_name = c_name;

    LOG_DEBUG("vpi_scan found '%s = '%s'", name.c_str(), fq_name.c_str());

    VpiImpl *vpi_impl = reinterpret_cast<VpiImpl*>(m_impl);
    new_obj = vpi_impl->create_gpi_obj_from_handle(obj, name, fq_name);
    if (new_obj) {
        *hdl = new_obj;
        return GpiIterator::NATIVE;
    }
    else
        return GpiIterator::NOT_NATIVE;
}
Пример #3
0
/*
 * print the loads and drivers for all wires in instance ihref
 */
int prt_drvlds(vpiHandle ihref)
{
 vpiHandle iter, thref;
 
 /* first all instance regs, wires, and variables */ 
 iter = vpi_iterate(vpiNet, ihref);
 if (iter != NULL) prt_1iter_drvlds(iter, ihref);
 iter = vpi_iterate(vpiReg, ihref);
 if (iter != NULL) prt_1iter_drvlds(iter, ihref);
 iter = vpi_iterate(vpiVariables, ihref);
 if (iter != NULL) prt_1iter_drvlds(iter, ihref);

 /* also monitor in scopes */
 iter = vpi_iterate(vpiInternalScope, ihref);
 for (;;)
  {
   if ((thref = vpi_scan(iter)) == NULL) break;
   prt_1task_drvlds(thref);
  }
 return(0);
}
Пример #4
0
static PLI_INT32 finish_and_return_calltf(ICARUS_VPI_CONST PLI_BYTE8* name)
{
    vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
    vpiHandle argv = vpi_iterate(vpiArgument, callh);
    vpiHandle arg;
    s_vpi_value val;
    (void) name;  /* Not used! */

    /* Get the return value. */
    arg = vpi_scan(argv);
    vpi_free_object(argv);
    val.format = vpiIntVal;
    vpi_get_value(arg, &val);

    /* Set the return value. */
    vpip_set_return_value(val.value.integer);

    /* Now finish. */
    vpi_control(vpiFinish, 1);
    return 0;
}
Пример #5
0
static void reset_regs(vpiHandle module) {
	vpiHandle reg, i;
	s_vpi_value value;
	int size, j;
	char * charData;

	value.format = vpiBinStrVal;
	i = vpi_iterate(vpiReg, module);

	while (reg = vpi_scan(i)) {
		vpi_get_value(reg, &value);
		charData = value.value.str;
		size = vpi_get(vpiSize, reg);
		for (j = 0; j < size; j++) {
			if (charData[j] == 'x') {
				charData[j] = '0';
			}
		}
		vpi_put_value(reg, &value, NULL, vpiNoDelay);
	}
}
Пример #6
0
/*
 * Routine to return a floating point value (implements %e, %f and %g).
 *
 * Return: 1 for a match, 0 for no match/variable and -1 for a
 *         suppressed match. No variable is fatal.
 */
static int scan_format_float(vpiHandle callh, vpiHandle argv,
                             struct byte_source *src, unsigned width,
                             unsigned suppress_flag, PLI_BYTE8 *name,
                             char code)
{
      vpiHandle arg;
      int match;
      s_vpi_value val;
      double result;

	/* Get the real value. */
      result = get_float(src, width, &match);

	/* Nothing was matched. */
      if (match == 0) return 0;

	/* If this match is being suppressed then return after consuming
	 * the digits and report that no arguments were used. */
      if (suppress_flag) return -1;

	/* We must have a variable to put the double value into. */
      arg = vpi_scan(argv);
      if (! arg) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s() ran out of variables for %%%c format code.",
	               name, code);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

	/* Put the value into the variable. */
      val.format = vpiRealVal;
      val.value.real = result;
      vpi_put_value(arg, &val, 0, vpiNoDelay);

	/* We always consume one variable if it is available. */
      return 1;
}
Пример #7
0
static PLI_INT32 CompileTF(PLI_BYTE8 *x)
#endif
{
	vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
	vpiHandle argv = vpi_iterate(vpiArgument, sys);
	vpiHandle arg;
	int first = 1;

	vpi_printf("%s (", vpi_get_str(vpiName, sys));
	while ((arg = vpi_scan(argv))) {
	    if (!first)
		vpi_printf(", ");
	    else
		first = 0;
	    vpi_printf("%s [type = %d]",
		vpi_get_str(vpiFullName, arg), (int)vpi_get(vpiType, arg));
	    if (vpi_get(vpiType, arg) == vpiNamedEvent) num++;
	}
	vpi_printf(")\n");
	if (num == 2) vpi_printf("PASSED\n");
	return 0;
}
Пример #8
0
/*
 * Routine to return a character value (implements %c).
 *
 * Return: 1 for a match, 0 for no match/variable and -1 for a
 *         suppressed match. No variable is fatal.
 */
static int scan_format_char(vpiHandle callh, vpiHandle argv,
                            struct byte_source *src, unsigned width,
                            unsigned suppress_flag, PLI_BYTE8 *name)
{
      vpiHandle arg;
      s_vpi_value val;
      int ch;

	/* If we are being asked for no digits then return a match fail. */
      if (width == 0) return 0;

	/* Get the character to return. */
      ch = byte_getc(src);

	/* Nothing was matched. */
      if (ch == EOF) return 0;

	/* If this match is being suppressed then return after consuming
	 * the character and report that no arguments were used. */
      if (suppress_flag) return -1;

	/* We must have a variable to put the character value into. */
      arg = vpi_scan(argv);
      if (! arg) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s() ran out of variables for %%c format code.", name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

	/* Put the character into the variable. */
      val.format = vpiIntVal;
      val.value.integer = ch;
      vpi_put_value(arg, &val, 0, vpiNoDelay);

	/* We always consume one variable if it is available. */
      return 1;
}
Пример #9
0
/*
 * print contents of one loads or drivers iterator iter inside instance ihref
 * 
 * when called to print loads of task variables ihref will be nil
 */
static void prt_iter(vpiHandle iter, vpiHandle ihref)
{
 int htyp;
 vpiHandle href, portihref;
 char *chp, s1[1025];

 for (;;)
  {
   if ((href = vpi_scan(iter)) == NULL) break;
  
   htyp = vpi_get(vpiType, href);
   /* must handle port as special case because can be module port */
   /* or up instance port connection */
   if (htyp == vpiModPathIn || htyp == vpiModPathOut) strcpy(s1, "**NONE(0)"); 
   else
    {
     if ((chp = vpi_get_str(vpiFile, href)) == NULL)
      strcpy(s1, "**NONE(0)"); 
     else sprintf(s1, "**%s(%d)", chp, vpi_get(vpiLineNo, href));
    } 
   if (htyp == vpiPort)
    {
     /* if ld/drv net in same instance as port then module port */ 
     /* else up instance connection */
     portihref = vpi_handle(vpiModule, href);
     if (vpi_compare_objects(ihref, portihref))
      {
       vpi_printf("   Port (vpiLowConn) object at %s\n", s1);
      }
     else
      {
       sprintf(s1, "**%s(%d)", vpi_get_str(vpiFile, portihref),
        vpi_get(vpiLineNo, portihref));
       vpi_printf("   Port (vpiHighConn) object at %s\n", s1);
      }
    }
   else vpi_printf("    %s object at %s\n", vpi_get_str(vpiType, href), s1);
  }
}
Пример #10
0
int readUnsignedHalf_calltf(char *user_data)
{
  int data;
  vpiHandle systf_handle, arg_iterator, arg_handle, reg_handle;
  s_vpi_value current_value;
  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);

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

  /* read current value */
  current_value.format = vpiIntVal;  /* read value as a integer */
  vpi_get_value(reg_handle, &current_value);

 

  data = (int) VMEM[0]->read_unsigned_half(current_value.value.integer);
  data = (data & 0x0000FFFF);
  //vpi_printf("Data read \t%x\n",data);

  value_s.format    = vpiIntVal;
  value_s.value.integer = data;

  
  vpi_put_value(systf_handle, &value_s, 0, vpiNoDelay);

 
  return(0);    
}
Пример #11
0
double tf_igetrealp(PLI_INT32 n, void *obj)
{
      vpiHandle sys_h, sys_i, arg_h = 0;
      s_vpi_value value;
      double rtn = 0.0;

      assert(n > 0);

      /* get task/func handle */
      sys_h = (vpiHandle)obj;
      sys_i = vpi_iterate(vpiArgument, sys_h);

      /* find nth arg */
      while (n > 0) {
	    if (!(arg_h = vpi_scan(sys_i))) { goto out; }
	    n--;
      }

      if (vpi_get(vpiType, arg_h) == vpiConstant &&
	  vpi_get(vpiConstType, arg_h) == vpiStringConst)
      {
	    rtn = 0.0;
      } else {
	    value.format = vpiRealVal;
	    vpi_get_value(arg_h, &value);
	    rtn = value.value.real;
      }

      vpi_free_object(sys_i);

out:
      if (pli_trace) {
	    fprintf(pli_trace, "tf_igetrealp(n=%d, obj=%p) --> %f\n",
		  n, obj, rtn);
      }

      return rtn;
}
Пример #12
0
static PLI_INT32 memmonitor_compiletf(PLI_BYTE8*name)
#endif
{
      vpiHandle sys = vpi_handle(vpiSysTfCall,0);
      vpiHandle argv = vpi_iterate(vpiArgument, sys);
      vpiHandle arg;

      if (argv == 0) {
	    vpi_printf("ERROR: %s expects at least 1 argument.\n", name);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

      while ( (arg = vpi_scan(argv)) ) {
	    if (vpi_get(vpiType, arg) != vpiMemory) {
		  vpi_printf("ERROR: %s expects only memory arguments\n", name);
		  vpi_control(vpiFinish, 1);
		  return 0;
	    }
      }

      return 0;
}
Пример #13
0
int vpi_input_str(PLI_BYTE8 *d) {

	vpiHandle systfref, argh, argsiter;
	s_vpi_value v;
	systfref = vpi_handle(vpiSysTfCall, NULL);
	argsiter = vpi_iterate(vpiArgument, systfref);
	argh = vpi_scan(argsiter);
	
	if (!argh) {
		vpi_printf("$VPI: missing parameter\n");
		return 0;
	}
	
	v.format = vpiIntVal;
	vpi_get_value(argh, &v);
	
	vpi_printf("VPI: %d\n", v.value.integer);
	// vpi_put_value(systfref, &v, NULL, vpiNoDelay);
	vpi_put_value(systfref, &v, NULL, vpiNoDelay);


	return 0;
}
Пример #14
0
static PLI_INT32 connect_calltf(PLI_BYTE8 *user)
{
	struct migensim_softc *sc = (struct migensim_softc *)user;
	vpiHandle sys;
	vpiHandle argv;
	vpiHandle item;
	s_vpi_value value;
	
	sys = vpi_handle(vpiSysTfCall, 0);
	argv = vpi_iterate(vpiArgument, sys);
	item = vpi_scan(argv);
	value.format = vpiStringVal;
	vpi_get_value(item, &value);
	
	sc->ipc = ipc_connect(value.value.str, h_go, h_write, h_read, sc);
	if(sc->ipc == NULL) {
		perror("ipc_connect");
		vpi_control(vpiFinish, 1);
		return 0;
	}
	
	return 0;
}
/*
 * This function is also used in sys_lxt to check the arguments of the
 * lxt variant of $dumpvars.
 */
int sys_vcd_dumpvars_compiletf(char*name)
{
      vpiHandle sys   = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv  = vpi_iterate(vpiArgument, sys);
      vpiHandle tmp;

      if (argv == 0)
	    return 0;

      tmp = vpi_scan(argv);
      assert(tmp);

      switch (vpi_get(vpiType, tmp)) {
	  case vpiConstant:
	    if (vpi_get(vpiConstType, tmp) == vpiStringConst) {
		  vpi_printf("ERROR: %s argument must be "
			     "a number constant.\n", name);
		  vpi_control(vpiFinish, 1);
	    }
	    break;

	  case vpiNet:
	  case vpiReg:
	  case vpiIntegerVar:
	  case vpiMemoryWord:
	    break;

	  default:
	    vpi_printf("ERROR: %s argument must be "
		       "a number constant.\n", name);
	    vpi_control(vpiFinish, 1);
	    break;
      }

      vpi_free_object(argv);
      return 0;
}
Пример #16
0
static PLI_INT32 sys_sscanf_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle reg;

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

	/* The first argument must be a register or constant string. */
      reg = vpi_scan(argv);  /* This should never be zero. */
      switch(vpi_get(vpiType, reg)) {
	  case vpiReg:
	    break;
	  case vpiConstant:
	  case vpiParameter:
	    if (vpi_get(vpiConstType, reg) == vpiStringConst) break;

	  default:
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("%s's first argument must be a register or constant "
	               "string.\n", name);
	    vpi_control(vpiFinish, 1);
	    vpi_free_object(argv);
	    return 0;
      }

      if (sys_check_args(callh, argv, name)) vpi_control(vpiFinish, 1);
      return 0;
}
Пример #17
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);
}
Пример #18
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;
}
Пример #19
0
// Called at compile time to validate the arguments to the system functions
// we redefine (info, warning, error, fatal).
//
// Expect either no arguments or a single string
static int system_function_compiletf(char *userdata)
{
    vpiHandle systf_handle, arg_iterator, arg_handle;
    int tfarg_type;

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

    if (arg_iterator == NULL)
        return 0;

    arg_handle = vpi_scan(arg_iterator);
    tfarg_type = vpi_get(vpiType, arg_handle);

    // FIXME: HACK for some reason Icarus returns a vpiRealVal type for strings?
    if (vpiStringVal != tfarg_type && vpiRealVal != tfarg_type) {
        vpi_printf("ERROR: $[info|warning|error|fata] argument wrong type: %d\n",
                    tfarg_type);
        vpi_free_object(arg_iterator);
        vpi_control(vpiFinish, 1);
        return -1;
    }
    return 0;
}
Пример #20
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;
}
Пример #21
0
static void dump_object(vpiHandle item)
{
      PLI_INT32 item_type = vpi_get(vpiType, item);
      vpiHandle argv, cur;

      vpi_printf("%s: ", vpi_get_str(vpiFullName, item));
      vpi_printf("vpiType=%s (%d)\n", vpi_get_str(vpiType, item), item_type);

      switch (item_type) {

	      /* These types are themselves scopes and have objects within. */
	  case vpiModule:
	  case vpiGenScope:
	  case vpiFunction:
	  case vpiTask:
	  case vpiNamedBegin:
	  case vpiNamedFork:
	    argv = vpi_iterate(vpiScope, item);
	    for (cur = vpi_scan(argv) ; cur ; cur = vpi_scan(argv))
		  dump_object(cur);
	    break;
#if 0
	  case vpiRegArray:
	  case vpiNetArray:
	    vpi_printf("%s: ", vpi_get_str(vpiFullName, item));
	    vpi_printf("vpiType=%s (%d)\n", vpi_get_str(vpiType, item), item_type);
	    argv = vpi_iterate(vpiMember, item);
	    for (cur = vpi_scan(argv) ; cur ; cur = vpi_scan(argv))
		  dump_object(cur);
	    break;
#endif
	      /* vpiMemory contains words. */
	  case vpiMemory:
	    argv = vpi_iterate(vpiMemoryWord, item);
	    for (cur = vpi_scan(argv) ; cur ; cur = vpi_scan(argv))
		  dump_object(cur);

	    break;

	  default:
	    break;
      }
}
Пример #22
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;
}
Пример #23
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;
}
Пример #24
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;
}
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;
}
static void scan_item(unsigned depth, vpiHandle item, int skip)
{
      struct t_cb_data cb;
      struct vcd_info* info;

      const char* type;
      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 vpiMemory:
	      /* don't know how to watch memories. */
	    break;

	  case vpiNamedEvent:
	      /* There is nothing in named events to dump. */
	    break;

	  case vpiNet:  type = "wire";    if(0){
	  case vpiIntegerVar:
	  case vpiTimeVar:
	  case vpiReg:  type = "reg";    }

	    if (skip)
		  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) {
		  ident = strdup(vcdid);
		  gen_new_vcd_id();
		  
		  if (nexus_id)
			set_nexus_ident(nexus_id, ident);
		  
		  info = malloc(sizeof(*info));

		  info->time.type = vpiSimTime;
		  info->item  = item;
		  info->ident = 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->next      = vcd_list;
		  info->dmp_next  = 0;
		  vcd_list    = info;

		  info->cb    = vpi_register_cb(&cb);
	    }
	    
	    fprintf(dump_file, "$var %s %u %s %s",
		    type, vpi_get(vpiSize, item), ident,
		    name);
      /* FIXME
	    if (vpi_get(vpiVector, item)
      */
	    if (vpi_get(vpiSize, item) > 1
		|| vpi_get(vpiLeftRange, item) != 0) {
		  fprintf(dump_file, "[%i:%i]", vpi_get(vpiLeftRange, item),
			  vpi_get(vpiRightRange, item));
	    }
	    fprintf(dump_file, " $end\n");
	    break;

	  case vpiRealVar:

	    if (skip)
		  break;

	      /* Declare the variable in the VCD file. */
	    name = vpi_get_str(vpiName, item);
	    ident = strdup(vcdid);
	    gen_new_vcd_id();
	    fprintf(dump_file, "$var real 1 %s %s $end\n",
		    ident, name);

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

	    info->time.type = vpiSimTime;
	    info->item  = item;
	    info->ident = 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->next  = vcd_list;
	    info->dmp_next  = 0;
	    vcd_list    = info;

	    info->cb    = vpi_register_cb(&cb);

	    break;

	  case vpiModule:      type = "module";      if(0){
	  case vpiNamedBegin:  type = "begin";      }if(0){
	  case vpiTask:        type = "task";       }if(0){
	  case vpiFunction:    type = "function";   }if(0){
	  case vpiNamedFork:   type = "fork";       }

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

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

#if 0
		  vpi_mcd_printf(1, 
				 "VCD info:"
				 " scanning scope %s, %u levels\n",
				 fullname, depth);
#endif
		  nskip = 0 != vcd_names_search(&vcd_tab, fullname);
		  
		  if (!nskip) 
			vcd_names_add(&vcd_tab, fullname);
		  else 
		    vpi_mcd_printf(1,
				   "VCD warning:"
				   " ignoring signals"
				   " in previously scanned scope %s\n",
				   fullname);

		  name = vpi_get_str(vpiName, item);

		  fprintf(dump_file, "$scope %s %s $end\n", type, 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);
			}
		  }
		  
		  fprintf(dump_file, "$upscope $end\n");
	    }
	    break;
	    
	  default:
	    vpi_mcd_printf(1,
			   "VCD Error: $dumpvars: Unsupported parameter "
			   "type (%d)\n", vpi_get(vpiType, item));
      }
}
Пример #27
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;
}
Пример #28
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;

}
Пример #29
0
GpiIterator::Status VpiIterator::next_handle(std::string &name, GpiObjHdl **hdl, void **raw_hdl)
{
    GpiObjHdl *new_obj;
    vpiHandle obj;
    vpiHandle iter_obj = m_parent->get_handle<vpiHandle>();

    if (!selected)
        return GpiIterator::END;

    do {
        obj = NULL;

        if (m_iterator) {
            obj = vpi_scan(m_iterator);

            if (NULL == obj) {
                /* m_iterator will already be free'd internally here */
                m_iterator = NULL;
            } else {
                break;
            }

            LOG_DEBUG("End of type=%d iteration", *one2many);
        } else {
            LOG_DEBUG("No valid type=%d iterator", *one2many);
        }

        if (++one2many >= selected->end()) {
            obj = NULL;
            break;
        }

        m_iterator = vpi_iterate(*one2many, iter_obj);

    } while (!obj);

    if (NULL == obj) {
        LOG_DEBUG("No more children, all relationships tested");
        return GpiIterator::END;
    }

    /* Simulators vary here. Some will allow the name to be accessed
       across boundary. We can simply return this up and allow
       the object to be created. Others do not. In this case
       we see if the object is in out type range and if not
       return the raw_hdl up */

    const char *c_name = vpi_get_str(vpiName, obj);
    if (!c_name) {
        /* This may be another type */
        int type = vpi_get(vpiType, obj);

        if (type >= VPI_TYPE_MAX) {
            *raw_hdl = (void*)obj;
            return GpiIterator::NOT_NATIVE_NO_NAME;
        }

        LOG_DEBUG("Unable to get the name for this object of type %d", type);

        return GpiIterator::NATIVE_NO_NAME;
    }
    name = c_name;

    /* We try and create a handle internally, if this is not possible we
       return and GPI will try other implementations with the name
       */

    std::string fq_name = m_parent->get_fullname() + "." + name;

    LOG_DEBUG("vpi_scan found '%s'", fq_name.c_str());
    VpiImpl *vpi_impl = reinterpret_cast<VpiImpl*>(m_impl);
    new_obj = vpi_impl->create_gpi_obj_from_handle(obj, name, fq_name);
    if (new_obj) {
        *hdl = new_obj;
        return GpiIterator::NATIVE;
    }
    else
        return GpiIterator::NOT_NATIVE;
}
Пример #30
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;
}