Esempio n. 1
0
static PLI_INT32 sys_convert_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 an argument. */
    if (argv == 0) {
	error_message(callh, "%s requires one argument.\n");
	return 0;
    }

    /* In Icarus if we have an argv we have at least one argument. */
    arg  = vpi_scan(argv);

    /* Validate the argument. Only $bitstoreal for now. */
    if (!strcmp("$bitstoreal", name) && vpi_get(vpiSize, arg) != 64) {
	error_message(callh, "%s requires a 64-bit argument.\n");
	return 0;
    }

    /* Save the argument away to make the calltf faster. */
    vpi_put_userdata(callh, (void *) arg);

    /* These functions only take one argument. */
    check_for_extra_args(argv, callh, name, "one argument", 0);

    return 0;
}
static int sys_random_calltf(char*name)
{
      s_vpi_value val;
      vpiHandle call_handle;
      vpiHandle argv;
      vpiHandle seed = 0;
      int i_seed = 0;
      struct context_s *context;

      call_handle = vpi_handle(vpiSysTfCall, 0);
      assert(call_handle);

	/* Get the argument list and look for a seed. If it is there,
	   get the value and reseed the random number generator. */
      argv = vpi_iterate(vpiArgument, call_handle);
      if (argv) {
	    seed = vpi_scan(argv);
	    vpi_free_object(argv);

	    val.format = vpiIntVal;
	    vpi_get_value(seed, &val);
	    i_seed = val.value.integer;

	      /* Since there is a seed use the current 
	         context or create a new one */
	    context = (struct context_s *)vpi_get_userdata(call_handle);
	    if (!context) {
		  context = (struct context_s *)calloc(1, sizeof(*context));
		  context->mti = NP1;
		  assert(context);

		    /* squrrel away context */
		  vpi_put_userdata(call_handle, (void *)context);
	    }

	      /* If the argument is not the Icarus cookie, then
		 reseed context */
	    if (i_seed != COOKIE)
	          sgenrand(context, i_seed);
      } else {
	    /* use global context */
          context = &global_context;
      }

      val.format = vpiIntVal;
      val.value.integer = genrand(context);

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

        /* mark seed with cookie */
      if (seed && i_seed != COOKIE) {
	    val.format = vpiIntVal;
	    val.value.integer = COOKIE;		
	    vpi_put_value(seed, &val, 0, vpiNoDelay);
      }

      return 0;
}
Esempio n. 3
0
static PLI_INT32 ivlh_attribute_event_compiletf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
      event_type_t type = (event_type_t) data;
      vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, sys);
      vpiHandle arg;
      struct monitor_data*mon;
      struct t_cb_data cb;
      struct t_vpi_time tb;
      struct t_vpi_value vb;

	/* Check that there are arguments. */
      if (argv == 0) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
	               (int)vpi_get(vpiLineNo, sys));
	    vpi_printf("(compiler error) %s requires a single argument.\n",
	               func_names[type]);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }

	/* Icarus either returns 0 above or has one argument. */
      arg = vpi_scan(argv);
      assert(arg);

      mon = malloc(sizeof(struct monitor_data));
	/* Add this to the list of data. */
      mdata_count += 1;
      mdata = (struct monitor_data **) realloc(mdata,
                                               sizeof(struct monitor_data **) *
                                               mdata_count);
      mdata[mdata_count-1] = mon;

      tb.type = vpiSimTime;
      vb.format = vpiScalarVal;
      cb.reason = cbValueChange;
      cb.cb_rtn = monitor_events;
      cb.obj = arg;
      cb.time = &tb;
      cb.value = &vb;
      cb.user_data = (char*) (mon);
      vpi_register_cb(&cb);
      vpi_put_userdata(sys, mon);

	/* Check that there is no more than one argument. */
      arg = vpi_scan(argv);
      if (arg != 0) {
	    vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, sys),
	               (int)vpi_get(vpiLineNo, sys));
	    vpi_printf("(compiler error) %s only takes a single argument.\n",
	               func_names[type]);
	    vpi_free_object(argv);
	    vpi_control(vpiFinish, 1);
      }

      return 0;
}
Esempio n. 4
0
/*
 * Routine to check all the double argument math functions.
 */
static PLI_INT32 va_double_argument_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *ud)
{
    vpiHandle callh, argv, arg;
    const t_double_data *data;
    const char *name;
    va_double_t* fun_data;

    assert(ud != 0);
    callh = vpi_handle(vpiSysTfCall, 0);
    assert(callh != 0);
    argv = vpi_iterate(vpiArgument, callh);
    data = (const t_double_data *) ud;
    name = data->name;

    fun_data = malloc(sizeof(va_double_t));

    /* Check that there are arguments. */
    if (argv == 0) {
        va_error_message(callh, "%s requires two arguments.\n", name);
        free(fun_data);
        return 0;
    }

    /* In Icarus if we have an argv we have at least one argument. */
    arg = vpi_scan(argv);
    fun_data->arg1 = va_process_argument(callh, name, arg, " (arg1)");

    /* Check that there are at least two arguments. */
    arg = vpi_scan(argv);
    if (arg == 0) {
        va_error_message(callh, "%s requires two arguments.\n", name);
    }
    fun_data->arg2 = va_process_argument(callh, name, arg, " (arg2)");

    /* These functions only take two arguments. */
    arg = vpi_scan(argv);
    if (arg != 0) {
        va_error_message(callh, "%s takes only two arguments.\n", name);
        vpi_free_object(argv);
    }

    /* Get the function that is to be used by the calltf routine. */
    fun_data->func = data->func;

    vpi_put_userdata(callh, fun_data);
    double_funcs_count += 1;
    double_funcs = (va_double_t **)realloc(double_funcs,
                   double_funcs_count*sizeof(va_double_t **));
    double_funcs[double_funcs_count-1] = fun_data;

    /* vpi_scan() returning 0 (NULL) has already freed argv. */
    return 0;
}
Esempio n. 5
0
static PLI_INT32 sys_mti_random_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      vpiHandle callh, argv, seed = 0;
      s_vpi_value val;
      int i_seed = COOKIE;
      struct context_s *context;

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

	/* Get the argument list and look for a seed. If it is there,
	   get the value and reseed the random number generator. */
      callh = vpi_handle(vpiSysTfCall, 0);
      argv = vpi_iterate(vpiArgument, callh);
      val.format = vpiIntVal;
      if (argv) {
	    seed = vpi_scan(argv);
	    vpi_free_object(argv);
	    vpi_get_value(seed, &val);
	    i_seed = val.value.integer;

	      /* Since there is a seed use the current
	         context or create a new one */
	    context = (struct context_s *)vpi_get_userdata(callh);
	    if (!context) {
		  context = (struct context_s *)calloc(1, sizeof(*context));
		  context->mti = NP1;

		    /* squirrel away context */
		  vpi_put_userdata(callh, (void *)context);
	    }

	      /* If the argument is not the Icarus cookie, then
		 reseed context */
	    if (i_seed != COOKIE) sgenrand(context, i_seed);
      } else {
	    /* use global context */
          context = &global_context;
      }

        /* Calculate and return the result */
      val.value.integer = genrand(context);
      vpi_put_value(callh, &val, 0, vpiNoDelay);

        /* mark seed with cookie */
      if (seed && i_seed != COOKIE) {
	    val.value.integer = COOKIE;
	    vpi_put_value(seed, &val, 0, vpiNoDelay);
      }

      return 0;
}
Esempio n. 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;
}
/*
 * This function calls the veriusertfs checktf and sets up all the
 * callbacks misctf requires.
 */
static PLI_INT32 compiletf(char *data)
{
      p_pli_data pli;
      p_tfcell tf;
      s_cb_data cb_data;
      vpiHandle call_h, arg_i, arg_h;
      p_pli_data dp;
      int rtn = 0;

      /* cast back from opaque */
      pli = (p_pli_data)data;
      tf = pli->tf;

      /* get call handle */
      call_h = vpi_handle(vpiSysTfCall, NULL);

	/* Attach the pli_data structure to the vpi handle of the
	   system task. This is how I manage the map from vpiHandle to
	   PLI1 pli data. We do it here (instead of during register)
	   because this is the first that I have both the vpiHandle
	   and the pli_data. */
      vpi_put_userdata(call_h, pli);

      /* default cb_data */
      memset(&cb_data, 0, sizeof(s_cb_data));
      cb_data.cb_rtn = callback;
      cb_data.user_data = data;

      /* register EOS misctf callback */
      cb_data.reason = cbEndOfSimulation;
      cb_data.obj = call_h;
      vpi_register_cb(&cb_data);

	/* If there is a misctf function, then create a value change
	   callback for all the arguments. In the tf_* API, misctf
	   functions get value change callbacks, controlled by the
	   tf_asyncon and tf_asyncoff functions. */
      if (tf->misctf && ((arg_i = vpi_iterate(vpiArgument, call_h)) != NULL)) {
	    int paramvc = 1;

	    cb_data.reason = cbValueChange;
	    while ((arg_h = vpi_scan(arg_i)) != NULL) {
		  /* replicate user_data for each instance */
		  dp = calloc(1, sizeof(s_pli_data));
		  memcpy(dp, cb_data.user_data, sizeof(s_pli_data));
		  dp->paramvc = paramvc++;
		  cb_data.user_data = (char *)dp;
		  cb_data.obj = arg_h;
		  vpi_register_cb(&cb_data);
	    }
      }

      /*
       * Since we are in compiletf, checktf and misctf need to
       * be executed. Check runs first to match other simulators.
       */
      if (tf->checktf) {
	    if (pli_trace) {
		  fprintf(pli_trace, "Call %s->checktf(reason_checktf)\n",
			  tf->tfname);
	    }

	    rtn = tf->checktf(tf->data, reason_checktf);
      }

      if (tf->misctf) {
	    if (pli_trace) {
		  fprintf(pli_trace, "Call %s->misctf"
			  "(user_data=%d, reason=%d, paramvc=%d)\n",
			  tf->tfname, tf->data, reason_endofcompile, 0);
	    }

	    tf->misctf(tf->data, reason_endofcompile, 0);
      }

      return rtn;
}