예제 #1
0
int _mon_check_callbacks() {
    t_cb_data cb_data;
    cb_data.reason = cbEndOfSimulation;
    cb_data.cb_rtn = NULL;
    cb_data.user_data = 0;
    cb_data.value = NULL;

    vpiHandle vh = vpi_register_cb(&cb_data);
    CHECK_RESULT_NZ(vh);

    PLI_INT32 status = vpi_remove_cb(vh);
    CHECK_RESULT_NZ(status);

    return 0;
}
예제 #2
0
파일: vtimcbs.c 프로젝트: kammoh/cvcx
/*
 * ro sync cb routine
 */
int cbwrsync_rtn(p_cb_data cbp)
{
 vpi_printf("*** rw sync time wake up at %d\n", cbp->time->low);

 /* not sure if legal to usurp t_cb_data since removed when event happens */
 cbp->reason = cbReadOnlySynch;
 cbp->cb_rtn = cbrosync_rtn;
 cbp->obj = NULL;
 cbp->time->high = 0;
 cbp->time->low = 0;
 cbp->value = NULL;
 cbp->index = 0;
 vpi_register_cb(cbp); 
 return(0);
}
예제 #3
0
static PLI_INT32 simbus_poll_calltf(char*my_name)
{
      int poll_state;
      s_vpi_value value;

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

      vpiHandle bus_h = vpi_scan(argv);
      assert(bus_h);

      value.format = vpiIntVal;
      vpi_get_value(bus_h, &value);

      int bus = value.value.integer;
      assert(bus >= 0 && bus < MAX_INSTANCES);

      vpiHandle trig = vpi_scan(argv);
      assert(trig);

      vpi_free_object(argv);

      DEBUG(SIMBUS_DEBUG_CALLS, "Call $poll(%d...)\n", bus);

      poll_state = check_readable(bus);

      value.format = vpiScalarVal;
      value.value.scalar = poll_state? vpi1 : vpi0;
      vpi_put_value(trig, &value, 0, vpiNoDelay);

      if (poll_state == 0) {
	    struct t_cb_data cb_data;
	    struct t_vpi_time cb_time;
	    cb_time.type = vpiSuppressTime;
	    cb_data.reason = cbReadWriteSynch;
	    cb_data.cb_rtn = poll_for_simbus_bus;
	    cb_data.time   = &cb_time;
	    vpi_register_cb(&cb_data);

	    instance_table[bus].trig = trig;

      } else {
	    instance_table[bus].trig = 0;
      }

      DEBUG(SIMBUS_DEBUG_CALLS, "return $poll(%d...)\n", bus);
      return 0;
}
예제 #4
0
static void vhdl_register(void)
{
      s_vpi_systf_data tf_data;
      s_cb_data cb;
      vpiHandle res;

      tf_data.type         = vpiSysFunc;
      tf_data.sysfunctype  = vpiSizedFunc;
      tf_data.calltf       = ivlh_attribute_event_calltf;
      tf_data.compiletf    = ivlh_attribute_event_compiletf;
      tf_data.sizetf       = ivlh_attribute_event_sizetf;
      tf_data.tfname       = func_names[EVENT];
      tf_data.user_data    = (PLI_BYTE8*) EVENT;
      res = vpi_register_systf(&tf_data);
      vpip_make_systf_system_defined(res);

      tf_data.type         = vpiSysFunc;
      tf_data.sysfunctype  = vpiSizedFunc;
      tf_data.calltf       = ivlh_attribute_event_calltf;
      tf_data.compiletf    = ivlh_attribute_event_compiletf;
      tf_data.sizetf       = ivlh_attribute_event_sizetf;
      tf_data.tfname       = func_names[RISING_EDGE];
      tf_data.user_data    = (PLI_BYTE8*) RISING_EDGE;
      res = vpi_register_systf(&tf_data);
      vpip_make_systf_system_defined(res);

      tf_data.type         = vpiSysFunc;
      tf_data.sysfunctype  = vpiSizedFunc;
      tf_data.calltf       = ivlh_attribute_event_calltf;
      tf_data.compiletf    = ivlh_attribute_event_compiletf;
      tf_data.sizetf       = ivlh_attribute_event_sizetf;
      tf_data.tfname       = func_names[FALLING_EDGE];
      tf_data.user_data    = (PLI_BYTE8*) FALLING_EDGE;
      res = vpi_register_systf(&tf_data);
      vpip_make_systf_system_defined(res);

	/* Create a callback to clear the monitor data memory when the
	 * simulator finishes. */
      cb.time = NULL;
      cb.reason = cbEndOfSimulation;
      cb.cb_rtn = cleanup_mdata;
      cb.user_data = NULL;
      cb.obj = NULL;

      vpi_register_cb(&cb);
}
예제 #5
0
파일: vfopen1.c 프로젝트: kammoh/cvcx
/*
 * register call backs
 */
void register_cbs(void)
{
 vpiHandle href;
 struct t_cb_data *ecbp;
 struct t_cb_data cbrec;

 /* notice cb records must be in global storage */
 ecbp = &cbrec;
 ecbp->reason = cbPLIError;
 ecbp->cb_rtn = my_error_handler; 
 ecbp->obj = NULL;
 ecbp->time = NULL;
 ecbp->value = NULL; 
 ecbp->user_data = NULL;

 /* probably should check for error here */
 if ((href = vpi_register_cb(ecbp)) == NULL)
  vpi_printf("**ERR: PLI 2.0 can not register error handler callback.\n");
}
예제 #6
0
int tf_isetdelay(PLI_INT32 delay, void*ss)
{
      vpiHandle sys = (vpiHandle)ss;
      int unit = vpi_get(vpiTimeUnit, sys);
      int prec = vpi_get(vpiTimePrecision, 0);

      struct t_cb_data cb;
      struct t_vpi_time ct;

      if (pli_trace) {
	    fprintf(pli_trace, "%s: tf_isetdelay(%d, ...)"
		    " <unit=%d, prec=%d>;\n",
		    vpi_get_str(vpiName, sys), (int)delay, unit, prec);
      }


	/* Convert the delay from the UNITS of the specified
	   task/function to the precision of the simulation. */
      assert(unit >= prec);

      while (unit > prec) {
	    PLI_INT32 tmp = delay * 10;
	    assert(tmp > delay);
	    delay = tmp;
	    unit -= 1;
      }

	/* Create a VPI callback to schedule the delay. */
      ct.type = vpiSimTime;
      ct.high = 0;
      ct.low  = delay;

      cb.reason = cbAfterDelay;
      cb.cb_rtn = delay_callback;
      cb.obj = 0;
      cb.time = &ct;
      cb.value = 0;
      cb.user_data = 0;
      vpi_register_cb(&cb);

      return 0;
}
예제 #7
0
/*
 * Register all the functions with Verilog.
 */
static void va_math_register(void)
{
    s_cb_data cb_data;
    s_vpi_systf_data tf_data;
    vpiHandle res;
    unsigned idx;

    /* Register the single argument functions. */
    tf_data.type        = vpiSysFunc;
    tf_data.sysfunctype = vpiRealFunc;
    tf_data.calltf      = va_single_argument_calltf;
    tf_data.compiletf   = va_single_argument_compiletf;
    tf_data.sizetf      = 0;

    for (idx=0; va_single_data[idx].name != 0; idx++) {
        tf_data.tfname    = va_single_data[idx].name;
        tf_data.user_data = (PLI_BYTE8 *) &va_single_data[idx];
        res = vpi_register_systf(&tf_data);
        vpip_make_systf_system_defined(res);
    }

    /* Register the double argument functions. */
    tf_data.type        = vpiSysFunc;
    tf_data.sysfunctype = vpiRealFunc;
    tf_data.calltf      = va_double_argument_calltf;
    tf_data.compiletf   = va_double_argument_compiletf;
    tf_data.sizetf      = 0;

    for (idx=0; va_double_data[idx].name != 0; idx++) {
        tf_data.tfname    = va_double_data[idx].name;
        tf_data.user_data = (PLI_BYTE8 *) &va_double_data[idx];
        res = vpi_register_systf(&tf_data);
        vpip_make_systf_system_defined(res);
    }

    /* We need to clean up the userdata. */
    cb_data.reason = cbEndOfSimulation;
    cb_data.time = 0;
    cb_data.cb_rtn = sys_end_of_simulation;
    cb_data.user_data = "system";
    vpi_register_cb(&cb_data);
}
예제 #8
0
파일: event2.c 프로젝트: jaredcasper/ivtest
static PLI_INT32
CallbackRegister(s_cb_data *data)
{
    vpiHandle hand;
    s_cb_data cb_data;
    s_vpi_time timerec = { vpiSimTime, 0, 0, 0 };

    hand = vpi_handle_by_name("test.e", 0);
    assert(hand);

    cb_data.time = &timerec;
    cb_data.value = 0;
    cb_data.user_data = (char *)hand;
    cb_data.obj = hand;
    cb_data.reason = cbValueChange;
    cb_data.cb_rtn = Callback;
    Handle = vpi_register_cb(&cb_data);

    return (0);
}
예제 #9
0
PLI_INT32 tf_irosynchronize(void*obj)
{
      vpiHandle sys = (vpiHandle)obj;
      p_pli_data pli = vpi_get_userdata(sys);
      s_cb_data cb;
      s_vpi_time ti = {vpiSuppressTime, 0, 0};

      cb.reason = cbReadOnlySynch;
      cb.cb_rtn = callback;
      cb.obj = sys;
      cb.time = &ti;
      cb.user_data = (char *)pli;

      vpi_register_cb(&cb);

      if (pli_trace)
	    fprintf(pli_trace, "tf_irosynchronize(%p) --> %d\n", obj, 0);

      return 0;
}
static int variable_cb_1(p_cb_data cause)
{
      struct t_cb_data cb;
      struct vcd_info*info = (struct vcd_info*)cause->user_data;

      if (dump_is_off) 		 return 0;
      if (dump_header_pending()) return 0;
      if (info->scheduled)       return 0;

      if (!vcd_dmp_list) {
          cb = *cause;
          cb.reason = cbReadOnlySynch;
          cb.cb_rtn = variable_cb_2;
          vpi_register_cb(&cb);
      } 

      info->scheduled = 1;
      info->dmp_next  = vcd_dmp_list;
      vcd_dmp_list    = info;

      return 0;
}
예제 #11
0
파일: vhelbad.c 프로젝트: kammoh/cvcx
/*
 * check each hello call, in struct as short but passed as int 
 *
 * dynamic nature of PLI 2.0 requires checking just before simulation 
 * because need to wait until simulation data structure is built
 */
PLI_INT32 hello_setup(char *data)
{
 vpiHandle href;
 struct t_cb_data *cbp;
 struct t_cb_data cbrec;
 
 vpi_printf("... executing vpi_ systf compiletf routine.\n");
 cbp = &cbrec;
 cbp->reason = cbEndOfCompile;
 cbp->cb_rtn = hello_chk;
 cbp->obj = NULL;
 cbp->time = NULL;
 cbp->value = NULL; 
 cbp->user_data = NULL;

 /* probably should check for error here */
 if ((href = vpi_register_cb(cbp)) == NULL)
  vpi_printf(
   "**ERR: $hello PLI 2.0 task cannot register end of compile check routine");
 /* if not registered will be no call backs */
 return(0);
}
예제 #12
0
void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record),
		 void*data, PLI_INT32 vcl_flag)
{
      struct vcl_record*cur;
      struct t_cb_data cb;

      switch (vpi_get(vpiType, obj)) {
	  case vpiNet:
	  case vpiReg:
	    cur = malloc(sizeof (struct vcl_record));
	    cur->obj = obj;
	    cur->consumer = consumer;
	    cur->user_data = data;
	    cur->vcl_flag = vcl_flag;
	    cur->next = vcl_list;
	    vcl_list = cur;

	    cb.reason = cbValueChange;
	    cb.cb_rtn = vcl_value_callback;
	    cb.obj = obj;
	    cb.time = 0;
	    cb.value = 0;
	    cb.user_data = (void*)cur;
	    cur->callback = vpi_register_cb(&cb);

	    if (pli_trace) {
		  fprintf(pli_trace, "acc_vcl_add(<%s>, ..., %p, %d)\n",
			  vpi_get_str(vpiFullName, obj), data, (int)vcl_flag);
	    }
	    break;

	  default:
	    vpi_printf("XXXX acc_vcl_add(<type=%d>, ..., %d);\n",
		       (int)vpi_get(vpiType, obj), (int)vcl_flag);
	    break;
      }

}
예제 #13
0
파일: pr686.c 프로젝트: orsonmmz/ivtest
static PLI_INT32 test_next_calltf(PLI_BYTE8 *name)
#endif
{
      vpiHandle sys, argv, value;

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

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

      argv = vpi_iterate(vpiArgument, sys);
      assert(argv);

      for (value = vpi_scan(argv) ;  value ;  value = vpi_scan(argv)) {
	    s_cb_data cb;
	    cb.reason = cbNextSimTime;
	    cb.cb_rtn = next_sim_time_callback;
	    cb.user_data = (char*)value;
	    vpi_register_cb(&cb);
      }

      return 0;
}
예제 #14
0
/**********************************************************************
 * $my_pow Registration Data
 * (add this function name to the vlog_startup_routines array)
 *********************************************************************/
void PLIbook_pow_register(void)
{
  s_vpi_systf_data tf_data;
  s_cb_data        cb_data_s;
  vpiHandle        callback_handle;

  tf_data.type        = vpiSysFunc;
  tf_data.sysfunctype = vpiSysFuncSized;
  tf_data.tfname      = "$my_pow";
  tf_data.calltf      = PLIbook_PowCalltf;
  tf_data.compiletf   = PLIbook_PowCompiletf;
  tf_data.sizetf      = PLIbook_PowSizetf;
  tf_data.user_data   = NULL;
  vpi_register_systf(&tf_data);

  cb_data_s.reason    = cbStartOfSimulation;
  cb_data_s.cb_rtn    = PLIbook_PowStartOfSim;
  cb_data_s.obj       = NULL;
  cb_data_s.time      = NULL;
  cb_data_s.value     = NULL;
  cb_data_s.user_data = NULL;
  callback_handle = vpi_register_cb(&cb_data_s);
  vpi_free_object(callback_handle);  /* don't need callback handle */
}
예제 #15
0
파일: nulls1.c 프로젝트: SuvenduDash/ivtest
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);
}
예제 #16
0
파일: jtag_vpi.c 프로젝트: sifive/jtag_vpi
void setup_finish_callbacks(void)
{
	// here we setup and install callbacks for
	// simulation finish

	static s_vpi_time time_s = {vpiScaledRealTime, 0, 0, 0};
	static s_vpi_value value_s = {.format = vpiBinStrVal};

	static s_cb_data cb_data_s = {
		cbEndOfSimulation, // end of simulation
		(void *)sim_finish_callback,
		NULL,
		&time_s,
		&value_s,
		0,
		NULL
	};

	cb_data_s.obj = NULL;  /* trigger object */
	cb_data_s.user_data = NULL;

	// actual call to register the callback
	vpi_register_cb(&cb_data_s);
}
예제 #17
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));
      }

}
예제 #18
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 *fullname;
      const char *prefix;
      const char *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 = "event"; break;
	  case vpiIntVar:
	  case vpiIntegerVar: type = "integer"; break;
	  case vpiParameter:  type = "parameter"; break;
	    /* Icarus converts realtime to real. */
	  case vpiRealVar:    type = "real"; break;
	  case vpiMemoryWord:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiLongIntVar:
	  case vpiReg:        type = "reg"; break;
	    /* Icarus converts a time to a plain register. */
	  case vpiTimeVar:    type = "time"; break;
	  case vpiNet:
	    switch (vpi_get(vpiNetType, item)) {
		case vpiWand:    type = "wand"; break;
		case vpiWor:     type = "wor"; break;
		case vpiTri:     type = "tri"; break;
		case vpiTri0:    type = "tri0"; break;
		case vpiTri1:    type = "tri1"; break;
		case vpiTriReg:  type = "trireg"; break;
		case vpiTriAnd:  type = "triand"; break;
		case vpiTriOr:   type = "trior"; break;
		case vpiSupply1: type = "supply1"; break;
		case vpiSupply0: type = "supply0"; break;
		default:         type = "wire"; break;
	    }
	    break;

	  case vpiNamedBegin: type = "begin"; break;
	  case vpiGenScope:   type = "begin"; break;
	  case vpiNamedFork:  type = "fork"; break;
	  case vpiFunction:   type = "function"; break;
	  case vpiModule:     type = "module"; break;
	  case vpiTask:       type = "task"; break;

	  default:
	    vpi_printf("VCD 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("VCD 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("VCD 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(&vcd_var, fullname)) return;

	      /* Declare the variable in the VCD file. */
	    name = vpi_get_str(vpiName, item);
	    prefix = is_escaped_id(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);

	    if (!ident) {
		  ident = strdup(vcdid);
		  gen_new_vcd_id();

		  if (nexus_id) set_nexus_ident(nexus_id, ident);

		    /* Add a callback for the signal. */
		  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->dmp_next = 0;
		  info->next  = vcd_list;
		  vcd_list    = info;

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

	      /* 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);

	    fprintf(dump_file, "$var %s %u %s %s%s",
		    type, size, ident, prefix, name);

	      /* Add a range for vectored values. */
	    if (size > 1 || vpi_get(vpiLeftRange, item) != 0) {
		  fprintf(dump_file, " [%i:%i]",
			  (int)vpi_get(vpiLeftRange, item),
			  (int)vpi_get(vpiRightRange, item));
	    }

	    fprintf(dump_file, " $end\n");
	    break;

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

	    if (depth > 0) {
		/* 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(&vcd_tab, fullname) != 0);

		    /* We have to always scan the scope because the
		     * depth could be different for this call. */
		  if (nskip) {
			vpi_printf("VCD warning: ignoring signals in "
			           "previously scanned scope %s.\n", fullname);
		  } else {
			vcd_names_add(&vcd_tab, 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;
			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. */
		  fprintf(dump_file, "$upscope $end\n");
	    }
	    break;
      }
}
예제 #19
0
/*
 * Register veriusertfs routines/wrappers. Iterate over the tfcell
 * array, registering each function.
 */
void veriusertfs_register_table(p_tfcell vtable)
{
      static int need_EOS_cb = 1;
      const char*path;
      p_tfcell tf;
      s_vpi_systf_data tf_data;
      p_pli_data data;
      static char trace_buf[1024];

      if (!pli_trace && (path = getenv("PLI_TRACE"))) {
	    if (strcmp(path,"-") == 0)
		  pli_trace = stdout;
	    else {
		  pli_trace = fopen(path, "w");
		  if (!pli_trace) {
			perror(path);
			exit(1);
		  }
	    }
	    setvbuf(pli_trace, trace_buf, _IOLBF, sizeof(trace_buf));
      }

      for (tf = vtable; tf; tf++) {
	    /* last element */
	    if (tf->type == 0) break;

	    /* force forwref true */
	    if (!tf->forwref) {
		  vpi_printf("veriusertfs: %s, forcing forwref = true\n",
			tf->tfname);
	    }

	    /* squirrel away veriusertfs in persistent user_data */
	    data = calloc(1, sizeof(s_pli_data));
	    udata_count += 1;
	    udata_store = (p_pli_data*)realloc(udata_store,
	                  udata_count*sizeof(p_pli_data*));
	    udata_store[udata_count-1] = data;
	    if (need_EOS_cb) {
		  s_cb_data cb_data;

		  cb_data.reason = cbEndOfSimulation;
		  cb_data.time = 0;
		  cb_data.cb_rtn = sys_end_of_simulation;
		  cb_data.user_data = "system";
		  vpi_register_cb(&cb_data);

		  need_EOS_cb = 0;
	    }
	    data->tf = tf;

	      /* Build a VPI system task/function structure, and point
		 it to the pli_data that represents this
		 function. Supply wrapper functions for the system
		 task actions. */
	    memset(&tf_data, 0, sizeof(s_vpi_systf_data));
	    switch (tf->type) {
		case usertask:
		  tf_data.type = vpiSysTask;
		  break;
		case userfunction:
		  tf_data.sysfunctype = vpiIntFunc;
		  tf_data.type = vpiSysFunc;
		  break;
		case userrealfunction:
		  tf_data.sysfunctype = vpiRealFunc;
		  tf_data.type = vpiSysFunc;
		  break;
		default:
		  vpi_printf("veriusertfs: %s, unsupported type %d\n",
			     tf->tfname, tf->type);
		  continue;
	    }

	    tf_data.tfname = tf->tfname;
	    tf_data.compiletf = compiletf;
	    tf_data.calltf = calltf;
	    tf_data.sizetf = (PLI_INT32 (*)(PLI_BYTE8 *))tf->sizetf;
	    tf_data.user_data = (char *)data;

	    if (pli_trace) {
		  fprintf(pli_trace, "Registering system %s:\n",
			tf->type == usertask ? "task" : "function");
		  fprintf(pli_trace, "  tfname : %s\n", tf->tfname);
		  if (tf->data)
			fprintf(pli_trace, "  data   : %d\n", tf->data);
		  if (tf->checktf)
			fprintf(pli_trace, "  checktf: %p\n", tf->checktf);
		  if (tf->sizetf)
			fprintf(pli_trace, "  sizetf : %p\n", tf->sizetf);
		  if (tf->calltf)
			fprintf(pli_trace, "  calltf : %p\n", tf->calltf);
		  if (tf->misctf)
			fprintf(pli_trace, "  misctf : %p\n", tf->misctf);
	    }

	    /* register */
	    vpi_register_systf(&tf_data);
      }

      return;
}
예제 #20
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;
}
예제 #21
0
static PLI_INT32 readonly_callback(p_cb_data cb_data)
{
  vpiHandle net_iter, net_handle, cb_h;
  s_cb_data cb_data_s;
  s_vpi_time verilog_time_s;
  s_vpi_value value_s;
  s_vpi_time time_s;
  char buf[MAXLINE];
  int n;
  int i;
  char *myhdl_time_string;
  myhdl_time64_t delay;

  static int start_flag = 1;

  if (start_flag) {
    start_flag = 0;
    n = write(wpipe, "START", 5);  
    // vpi_printf("INFO: RO cb at start-up\n");
    if ((n = read(rpipe, buf, MAXLINE)) == 0) {
      vpi_printf("ABORT from RO cb at start-up\n");
      vpi_control(vpiFinish, 1);  /* abort simulation */
    }  
    assert(n > 0);
  }

  buf[0] = '\0';
  verilog_time_s.type = vpiSimTime;
  vpi_get_time(NULL, &verilog_time_s);
  verilog_time = timestruct_to_time(&verilog_time_s);
   if (verilog_time != (pli_time * 1000 + delta)) {
     vpi_printf("%u %u\n", verilog_time_s.high, verilog_time_s.low );
     vpi_printf("%llu %llu %d\n", verilog_time, pli_time, delta);
   }
  /* Icarus 0.7 fails on this assertion beyond 32 bits due to a bug */
  // assert(verilog_time == pli_time * 1000 + delta);
  assert( (verilog_time & 0xFFFFFFFF) == ( (pli_time * 1000 + delta) & 0xFFFFFFFF ) );
  sprintf(buf, "%llu ", pli_time);
  net_iter = vpi_iterate(vpiArgument, to_myhdl_systf_handle);
  value_s.format = vpiHexStrVal;
  i = 0;
  while ((net_handle = vpi_scan(net_iter)) != NULL) {
    if (changeFlag[i]) {
      strcat(buf, vpi_get_str(vpiName, net_handle));
      strcat(buf, " ");
      vpi_get_value(net_handle, &value_s);
      strcat(buf, value_s.value.str);
      strcat(buf, " ");
      changeFlag[i] = 0;
    }
    i++;
    vpi_free_object(net_handle);  // done with this one
  }
  //vpi_free_object(net_iter);
  
  n = write(wpipe, buf, strlen(buf));
  if ((n = read(rpipe, buf, MAXLINE)) == 0) {
    // vpi_printf("ABORT from RO cb\n");
    vpi_control(vpiFinish, 1);  /* abort simulation */
    return(0);
  }
  assert(n > 0);
  buf[n] = '\0';



  /* save copy for later callback */
  strcpy(bufcp, buf);

  myhdl_time_string = strtok(buf, " ");
  myhdl_time = (myhdl_time64_t) strtoull(myhdl_time_string, (char **) NULL, 10);
  delay = (myhdl_time - pli_time) * 1000;
  assert(delay >= 0);
  assert(delay <= 0xFFFFFFFF);
  if (delay > 0) { // schedule cbAfterDelay callback
    assert(delay > delta);
    delay -= delta;
    /* Icarus 20030518 runs RO callbacks when time has already advanced */
    /* Therefore, one had to compensate for the prescheduled delta callback */
    /* delay -= 1; */
    /* Icarus 20031009 has a different scheduler, more correct I believe */
    /* compensation is no longer necessary */
    delta = 0;
    pli_time = myhdl_time;

    // register cbAfterDelay callback //
    time_s.type = vpiSimTime;
    time_s.high = 0;
    time_s.low = (PLI_UINT32) delay;
    cb_data_s.reason = cbAfterDelay;
    cb_data_s.user_data = NULL;
    cb_data_s.cb_rtn = delay_callback;
    cb_data_s.obj = NULL;
    cb_data_s.time = &time_s;
    cb_data_s.value = NULL;
    cb_h = vpi_register_cb(&cb_data_s);
    vpi_free_object(cb_h);
  } else {
    delta++;
    assert(delta < 1000);
  }
  return(0);
}
예제 #22
0
파일: sys_fst.c 프로젝트: bzero/iverilog
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;
      }
}
예제 #23
0
static PLI_INT32 poll_for_simbus_bus(struct t_cb_data*cb)
{
      int nfds = 0;
      int idx;
      int rc;
      fd_set read_set;
      FD_ZERO(&read_set);

      for (idx = 0 ; idx < MAX_INSTANCES ; idx += 1) {
	    if (instance_table[idx].trig == 0)
		  continue;

	    if (instance_table[idx].fd > nfds)
		  nfds = instance_table[idx].fd;

	    FD_SET(instance_table[idx].fd, &read_set);
      }

      if (nfds == 0)
	    return 0;

      rc = select(nfds+1, &read_set, 0, 0, 0);
      assert(rc != 0);
      if (rc < 0) {
	    vpi_printf("ERROR:poll_for_simbus_bus:%s\n", sys_errlist[errno]);
	    vpi_control(vpiFinish, 1);
	    return 0;
      }
      assert(rc > 0);

      for (idx = 0 ; idx < MAX_INSTANCES ; idx += 1) {
	    s_vpi_value value;

	    if (instance_table[idx].trig == 0)
		  continue;

	    if (! FD_ISSET(instance_table[idx].fd, &read_set))
		  continue;

	      /* This fd is readable, so try to read some data, and
		 check if a command is complete. If not, then continue
		 waiting. Otherwise, let this one be completed. */
	    consume_readable_data(idx);
	    if (!check_readable(idx))
		  continue;

	    value.format = vpiScalarVal;
	    value.value.scalar = vpi1;
	    vpi_put_value(instance_table[idx].trig, &value, 0, vpiNoDelay);
	    instance_table[idx].trig = 0;
      }

	/* Check and see if there are still triggers waiting. If so
	   then reschedule this callback. */
      nfds += 1;
      for (idx = 0 ; idx < MAX_INSTANCES ; idx += 1) {
	    if (instance_table[idx].trig == 0)
		  continue;

	    nfds += 1;
      }

      if (nfds > 0) {
	    struct t_cb_data cb_data;
	    struct t_vpi_time cb_time;
	    cb_time.type = vpiSuppressTime;
	    cb_data.reason = cbReadWriteSynch;
	    cb_data.cb_rtn = poll_for_simbus_bus;
	    cb_data.time   = &cb_time;
	    vpi_register_cb(&cb_data);
      }

      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));
      }
}
예제 #25
0
static PLI_INT32 to_myhdl_calltf(PLI_BYTE8 *user_data)
{
  vpiHandle net_iter, net_handle, cb_h;
  char buf[MAXLINE];
  char s[MAXWIDTH];
  int n;
  int i;
  int *id;
  s_cb_data cb_data_s;
  s_vpi_time verilog_time_s;
  s_vpi_time time_s;
  s_vpi_value value_s;
  static int to_myhdl_flag = 0;

  if (to_myhdl_flag) {
    vpi_printf("ERROR: $to_myhdl called more than once\n");
    vpi_control(vpiFinish, 1);  /* abort simulation */
    return(0);
  }
  to_myhdl_flag = 1;

  init_pipes();

  verilog_time_s.type = vpiSimTime;
  vpi_get_time(NULL, &verilog_time_s);
  verilog_time = timestruct_to_time(&verilog_time_s);
  if (verilog_time != 0) {
    vpi_printf("ERROR: $to_myhdl should be called at time 0\n");
    vpi_control(vpiFinish, 1);  /* abort simulation */
    return(0);
  }
  sprintf(buf, "TO 0 ");
  pli_time = 0;
  delta = 0;

  time_s.type = vpiSuppressTime;
  value_s.format = vpiSuppressVal;
  cb_data_s.reason = cbValueChange;
  cb_data_s.cb_rtn = change_callback;
  cb_data_s.time = &time_s;
  cb_data_s.value = &value_s;
  // value_s.format = vpiHexStrVal;
  i = 0;
  to_myhdl_systf_handle = vpi_handle(vpiSysTfCall, NULL);
  net_iter = vpi_iterate(vpiArgument, to_myhdl_systf_handle);
  while ((net_handle = vpi_scan(net_iter)) != NULL) {
    if (i == MAXARGS) {
      vpi_printf("ERROR: $to_myhdl max #args (%d) exceeded\n", MAXARGS);
      vpi_control(vpiFinish, 1);  /* abort simulation */
    }
    strcat(buf, vpi_get_str(vpiName, net_handle));
    strcat(buf, " ");
    sprintf(s, "%d ", vpi_get(vpiSize, net_handle));
    strcat(buf, s);
    changeFlag[i] = 0;
    id = malloc(sizeof(int));
    *id = i;
    cb_data_s.user_data = (PLI_BYTE8 *)id;
    cb_data_s.obj = net_handle;
    cb_h = vpi_register_cb(&cb_data_s);
    vpi_free_object(cb_h);
    i++;
    vpi_free_object(net_handle);
  }
  //vpi_free_object(net_iter);

  n = write(wpipe, buf, strlen(buf));

  if ((n = read(rpipe, buf, MAXLINE)) == 0) {
    vpi_printf("ABORT from $to_myhdl\n");
    vpi_control(vpiFinish, 1);  /* abort simulation */
    return(0);
  }
  buf[n] = '\0';
  assert(n > 0);

  // register read-only callback //
  time_s.type = vpiSimTime;
  time_s.high = 0;
  time_s.low = 0;
  cb_data_s.reason = cbReadOnlySynch;
  cb_data_s.user_data = NULL;
  cb_data_s.cb_rtn = readonly_callback;
  cb_data_s.obj = NULL;
  cb_data_s.time = &time_s;
  cb_data_s.value = NULL;
  cb_h = vpi_register_cb(&cb_data_s);
  vpi_free_object(cb_h);

  // pre-register delta cycle callback //
  delta = 0;
  time_s.type = vpiSimTime;
  time_s.high = 0;
  time_s.low = 1;
  cb_data_s.reason = cbAfterDelay;
  cb_data_s.user_data = NULL;
  cb_data_s.cb_rtn = delta_callback;
  cb_data_s.obj = NULL;
  cb_data_s.time = &time_s;
  cb_data_s.value = NULL;
  cb_h = vpi_register_cb(&cb_data_s);
  vpi_free_object(cb_h);

  return(0);
}