Exemplo n.º 1
0
/* This also supports $abstime() from VAMS-2.3. */
static PLI_INT32 sys_realtime_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      s_vpi_value val;
      s_vpi_time  now;
      vpiHandle callh;
      vpiHandle mod;

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

      mod = sys_func_module(callh);

      now.type = vpiScaledRealTime;
      vpi_get_time(mod, &now);

	/* For $abstime() we return the time in second. */
      if (strcmp(name, "$abstime") == 0) {
	    PLI_INT32 scale = vpi_get(vpiTimeUnit, mod);
	    if (scale >= 0) now.real *= pow(10.0, scale);
	    else now.real /= pow(10.0, -scale);
      }

      val.format = vpiRealVal;
      val.value.real = now.real;
      vpi_put_value(callh, &val, 0, vpiNoDelay);

      return 0;
}
Exemplo n.º 2
0
static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      s_vpi_time now;
      PLI_UINT64 now64;

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

      if (dump_is_off) return 0;
      if (dump_file == 0) return 0;
      if (dump_header_pending()) return 0;

      now.type = vpiSimTime;
      vpi_get_time(0, &now);
      now64 = timerec_to_time64(&now);

      if (now64 > vcd_cur_time) {
	    fprintf(dump_file, "#%" PLI_UINT64_FMT "\n", now64);
	    vcd_cur_time = now64;
      }

      fprintf(dump_file, "$dumpall\n");
      vcd_checkpoint();
      fprintf(dump_file, "$end\n");

      return 0;
}
Exemplo n.º 3
0
static PLI_INT32 sys_dumpon_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      s_vpi_time now;
      PLI_UINT64 now64;

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

      if (!dump_is_off) return 0;

      dump_is_off = 0;

      if (dump_file == 0) return 0;
      if (dump_header_pending()) return 0;

      now.type = vpiSimTime;
      vpi_get_time(0, &now);
      now64 = timerec_to_time64(&now);

      if (now64 > vcd_cur_time) {
	    vcd_work_set_time(now64);
	    vcd_cur_time = now64;
      }

      vcd_work_dumpon();
      vcd_checkpoint();

      return 0;
}
Exemplo n.º 4
0
static PLI_INT32 sys_dumpon_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      s_vpi_time now;
      PLI_UINT64 now64;

      if (!dump_is_off) return 0;

      dump_is_off = 0;

      if (dump_file == 0) return 0;
      if (dump_header_pending()) return 0;

      now.type = vpiSimTime;
      vpi_get_time(0, &now);
      now64 = timerec_to_time64(&now);

      if (now64 > vcd_cur_time) {
	    fstWriterEmitTimeChange(dump_file, now64);
	    vcd_cur_time = now64;
      }

      fstWriterEmitDumpActive(dump_file, 1); /* $dumpon */
      vcd_checkpoint();

      return 0;
}
Exemplo n.º 5
0
static PLI_INT32 from_myhdl_calltf(PLI_BYTE8 *user_data)
{
  vpiHandle reg_iter, reg_handle;
  s_vpi_time verilog_time_s;
  char buf[MAXLINE];
  char s[MAXWIDTH];
  int n;

  static int from_myhdl_flag = 0;

  if (from_myhdl_flag) {
    vpi_printf("ERROR: $from_myhdl called more than once\n");
    vpi_control(vpiFinish, 1);  /* abort simulation */
    return(0);
  }
  from_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: $from_myhdl should be called at time 0\n");
    vpi_control(vpiFinish, 1);  /* abort simulation */
    return(0);
  }
  sprintf(buf, "FROM 0 ");
  pli_time = 0;
  delta = 0;

  from_myhdl_systf_handle = vpi_handle(vpiSysTfCall, NULL);
  reg_iter = vpi_iterate(vpiArgument, from_myhdl_systf_handle);
  while ((reg_handle = vpi_scan(reg_iter)) != NULL) {
    if (vpi_get(vpiType, reg_handle) != vpiReg) {
      vpi_printf("ERROR: $from_myhdl argument %s should be a reg\n",
		 vpi_get_str(vpiName, reg_handle));
      vpi_control(vpiFinish, 1);  /* abort simulation */
      return(0);
    }
    strcat(buf, vpi_get_str(vpiName, reg_handle));
    strcat(buf, " ");
    sprintf(s, "%d ", vpi_get(vpiSize, reg_handle));
    strcat(buf, s);
    vpi_free_object(reg_handle);
  }
  //vpi_free_object(reg_iter);

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

  if ((n = read(rpipe, buf, MAXLINE)) == 0) {
    vpi_printf("Info: MyHDL simulator down\n");
    vpi_control(vpiFinish, 1);  /* abort simulation */
    return(0);
  }
  assert(n > 0);
  buf[n] = '\0';

  return(0);
}
Exemplo n.º 6
0
static PLI_INT32 sys_dumpon_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      s_vpi_time now;
      PLI_UINT64 now64;

      if (!dump_is_off) return 0;

      dump_is_off = 0;

      if (dump_file == 0) return 0;
      if (dump_header_pending()) return 0;

      now.type = vpiSimTime;
      vpi_get_time(0, &now);
      now64 = timerec_to_time64(&now);

      if (now64 > vcd_cur_time) {
	    lt_set_time64(dump_file, now64);
	    vcd_cur_time = now64;
      }

      lt_set_dumpon(dump_file);
      vcd_checkpoint();

      return 0;
}
Exemplo n.º 7
0
static PLI_INT32 sys_dumpall_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      s_vpi_time now;
      PLI_UINT64 now64;

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

      if (dump_is_off) return 0;
      if (dump_file == 0) return 0;
      if (dump_header_pending()) return 0;

      now.type = vpiSimTime;
      vpi_get_time(0, &now);
      now64 = timerec_to_time64(&now);

      if (now64 > vcd_cur_time) {
	    fstWriterEmitTimeChange(dump_file, now64);
	    vcd_cur_time = now64;
      }

      /* nothing to do for $dumpall... */
      vcd_checkpoint();

      return 0;
}
Exemplo n.º 8
0
void update_time(void)
{
  s_vpi_time time_s;
  vpiHandle sys = vpi_handle(vpiSysTfCall, 0);

  time_s.type = vpiScaledRealTime;
  vpi_get_time(sys, &time_s);
  g_time = time_s.real;
}
Exemplo n.º 9
0
void VpiImpl::get_sim_time(uint32_t *high, uint32_t *low)
{
    s_vpi_time vpi_time_s;
    vpi_time_s.type = vpiSimTime;       //vpiSimTime;
    vpi_get_time(NULL, &vpi_time_s);
    check_vpi_error();
    *high = vpi_time_s.high;
    *low = vpi_time_s.low;
}
Exemplo n.º 10
0
static PLI_INT32 sys_time_calltf(ICARUS_VPI_CONST PLI_BYTE8*name)
{
      s_vpi_value val;
      s_vpi_time  now;
      vpiHandle call_handle;
      vpiHandle mod;
      int units, prec;
      long scale;

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

      mod = sys_func_module(call_handle);

      now.type = vpiSimTime;
      vpi_get_time(0, &now);

	/* All the variants but $simtime return the time in units of
	   the local scope. The $simtime function returns the
	   simulation time. */
      if (strcmp(name, "$simtime") == 0)
	    units = vpi_get(vpiTimePrecision, 0);
      else
	    units = vpi_get(vpiTimeUnit, mod);

      prec  = vpi_get(vpiTimePrecision, 0);
      scale = 1;
      while (units > prec) {
	    scale *= 10;
	    units -= 1;
      }

      assert(8*sizeof(long long) >= 64);
      { long frac;
        long long tmp_now = ((long long)now.high) << 32;
        tmp_now += (long long)now.low;
	frac = tmp_now % (long long)scale;
	tmp_now /= (long long)scale;

	  /* Round to the nearest integer, which may be up. */
	if ((scale > 1) && (frac >= scale/2))
	      tmp_now += 1;

	now.low = tmp_now & 0xffffffff;
	now.high = tmp_now >> 32LL;
      }

      val.format = vpiTimeVal;
      val.value.time = &now;

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

      return 0;
}
Exemplo n.º 11
0
PLI_INT32
ValueChange(p_cb_data cb_data)
{
	static s_vpi_time get_time = { vpiSimTime, 0, 0, 0 };

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

	vpi_get_time(NULL,&get_time);
	vpi_printf("%6d: Value Change\n", (int)get_time.low);
	return(0);
}
Exemplo n.º 12
0
static long long get_time()
{
	s_vpi_time time;
	time.type = vpiSimTime;
	vpi_get_time(NULL, &time);
	uint64_t long_time;
	long_time = time.high;
	long_time <<= 32;
	long_time += time.low;
	return (long long)long_time;
}
Exemplo n.º 13
0
static PLI_INT32 next_sim_time_callback(struct t_cb_data*cb)
{
      vpiHandle obj = (vpiHandle)cb->user_data;
      s_vpi_value val;
      s_vpi_time  tim;

      val.format = vpiIntVal;
      vpi_get_value(obj, &val);

      tim.type = vpiSimTime;
      vpi_get_time(obj, &tim);

      vpi_printf("Callback time=%d %s=%d\n", (int)tim.low,
		 vpi_get_str(vpiName, obj),
		 (int)val.value.integer);
      return 0;
}
Exemplo n.º 14
0
static PLI_INT32
Callback(s_cb_data *data)
{
    s_vpi_time t;
    static int count = 0;

    t.type = vpiScaledRealTime;
    vpi_get_time(0, &t);

    vpi_printf("Callback @ %.1f\n", t.real);

    if (count>1) {
	vpi_printf("vpi_remove_cb returned %d @ %.1f\n",
	    (int)vpi_remove_cb(Handle), t.real);
    }

    count++;

    return 0;
}
Exemplo n.º 15
0
static PLI_INT32 ivlh_attribute_event_calltf(ICARUS_VPI_CONST PLI_BYTE8*data)
{
      event_type_t type = (event_type_t) data;
      vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
      struct t_vpi_value rval;
      struct monitor_data*mon;

      rval.format = vpiScalarVal;

      mon = (struct monitor_data*) (vpi_get_userdata(sys));

      if (mon->last_event.type == 0) {
	    rval.value.scalar = vpi0;

      } else {
	    struct t_vpi_time tnow;
	    tnow.type = vpiSimTime;
	    vpi_get_time(0, &tnow);

	    rval.value.scalar = vpi1;

	    // Detect if change occured in this moment
	    if (mon->last_event.high != tnow.high)
		  rval.value.scalar = vpi0;
	    if (mon->last_event.low != tnow.low)
		  rval.value.scalar = vpi0;

	    // Determine the edge, if required
	    if (type == RISING_EDGE && mon->last_value.value.scalar != vpi1)
		  rval.value.scalar = vpi0;
	    else if (type == FALLING_EDGE && mon->last_value.value.scalar != vpi0)
		  rval.value.scalar = vpi0;
      }

      vpi_put_value(sys, &rval, 0, vpiNoDelay);

      return 0;
}
Exemplo n.º 16
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);
}
Exemplo n.º 17
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);
}
Exemplo n.º 18
0
/*
 * This is a VPI callback that notices the value change. This function
 * further dispatches the information about the callback to the
 * consumer function.
 */
static PLI_INT32 vcl_value_callback(struct t_cb_data*cb)
{
      s_vpi_time sim_time;
      s_vpi_value obj_value;
      struct t_vc_record vcr;
      struct vcl_record*cur = (struct vcl_record*)cb->user_data;

      sim_time.type = vpiSimTime;
      vpi_get_time(cur->obj, &sim_time);

      switch (cur->vcl_flag) {
	  case VCL_VERILOG_LOGIC:
	    vpi_printf("XXXX vcl_value_callback(%s=%d);\n",
		       vpi_get_str(vpiName, cur->obj), -1);

	    vcr.vc_reason = logic_value_change;
	    break;

	  case VCL_VERILOG_STRENGTH:
	    vcr.vc_reason = strength_value_change;
	    obj_value.format = vpiStrengthVal;
	    vpi_get_value(cur->obj, &obj_value);
	    assert(obj_value.format == vpiStrengthVal);
	    switch (obj_value.value.strength[0].logic) {
		case vpi0:
		  vcr.out_value.strengths_s.logic_value = acc0;
		  vcr.out_value.strengths_s.strength1 =
			vpi_strength_to_vcl(obj_value.value.strength[0].s0);
		  vcr.out_value.strengths_s.strength2 =
			vpi_strength_to_vcl(obj_value.value.strength[0].s0);
		  break;
		case vpi1:
		  vcr.out_value.strengths_s.logic_value = acc1;
		  vcr.out_value.strengths_s.strength1 =
			vpi_strength_to_vcl(obj_value.value.strength[0].s1);
		  vcr.out_value.strengths_s.strength2 =
			vpi_strength_to_vcl(obj_value.value.strength[0].s1);
		  break;
		case vpiX:
		  vcr.out_value.strengths_s.logic_value = accX;
		  vcr.out_value.strengths_s.strength1 =
			vpi_strength_to_vcl(obj_value.value.strength[0].s1);
		  vcr.out_value.strengths_s.strength2 =
			vpi_strength_to_vcl(obj_value.value.strength[0].s0);
		  break;
		case vpiZ:
		  vcr.out_value.strengths_s.logic_value = accZ;
		  vcr.out_value.strengths_s.strength1 = vclHighZ;
		  vcr.out_value.strengths_s.strength2 = vclHighZ;
		  break;
		default:
		  assert(0);
	    }

	    if (pli_trace) {
		  fprintf(pli_trace,
			  "Call vcl_value_callback(%s=%d <s1=%d,s2=%d>)\n",
			  vpi_get_str(vpiFullName, cur->obj),
			  vcr.out_value.strengths_s.logic_value,
			  vcr.out_value.strengths_s.strength1,
			  vcr.out_value.strengths_s.strength2);
	    }
	    break;

	  default:
	    assert(0);
      }

      vcr.vc_hightime = sim_time.high;
      vcr.vc_lowtime  = sim_time.low;
      vcr.user_data = cur->user_data;

      (cur->consumer) (&vcr);
      return 0;
}
Exemplo n.º 19
0
static PLI_INT32 simbus_ready_calltf(char*my_name)
{
      s_vpi_value value;
      s_vpi_time now;

      vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
	/* vpiHandle scope = vpi_handle(vpiScope, sys); */
      vpiHandle argv = vpi_iterate(vpiArgument, sys);
      vpiHandle arg;
      assert(argv);

      arg = vpi_scan(argv);
      assert(arg);

	/* Get the BUS identifier to use. */
      value.format = vpiIntVal;
      vpi_get_value(arg, &value);
      int bus_id = value.value.integer;
      assert(bus_id < MAX_INSTANCES);
      assert(instance_table[bus_id].fd >= 0);

      DEBUG(SIMBUS_DEBUG_CALLS, "Call $ready(%d...)\n", bus_id);

	/* Get the simulation time. */
      now.type = vpiSimTime;
      vpi_get_time(0, &now);
      uint64_t now_int = ((uint64_t)now.high) << 32;
      now_int += (uint64_t) now.low;

	/* Get the units for the simulation. */
      int scale  = vpi_get(vpiTimePrecision, 0);

	/* Minimize the mantissa by increasing the scale so long as
	   the mantissa is a multiple of 10. This is not a functional
	   requirement, but it does help prevent a runaway precision
	   expansion. */
      while (now_int >= 10 && (now_int%10 == 0)) {
	    now_int /= 10;
	    scale += 1;
      }

      char message[MAX_MESSAGE+1];
      snprintf(message, sizeof message, "READY %" PRIu64 "e%d", now_int, scale);

      char*cp = message + strlen(message);

	/* Send the current state of all the named signals. The format
	   passed in to the argument list is "name", value. Write
	   these values in the proper message format. */
      for (arg = vpi_scan(argv) ; arg ; arg = vpi_scan(argv)) {
	    *cp++ = ' ';

	    value.format = vpiStringVal;
	    vpi_get_value(arg, &value);
	    strcpy(cp, value.value.str);
	    cp += strlen(cp);

	    *cp++ = '=';

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

	    value.format = vpiVectorVal;
	    vpi_get_value(sig, &value);
	    int bit;
	    char*sig_string = cp;
	    for (bit = vpi_get(vpiSize, sig) ; bit > 0 ; bit -= 1) {
		  int word = (bit-1) / 32;
		  int mask = 1 << ((bit-1) % 32);
		  if (value.value.vector[word].aval & mask)
			if (value.value.vector[word].bval & mask)
			      *cp++ = 'x';
			else
			      *cp++ = '1';
		  else
			if (value.value.vector[word].bval & mask)
			      *cp++ = 'z';
			else
			      *cp++ = '0';
	    }

	      /* The second value after the signal name is the drive
		 reference. It is the value that the server is driving
		 (or 'bz if this is output-only). Look at the driver
		 value, and if it is non-z and equal to the value that
		 I see in the verilog, then assume that this is the
		 driver driving the value and subtract it. */
	    vpiHandle drv = vpi_scan(argv);
	    assert(drv);
	    assert(vpi_get(vpiSize,drv) == vpi_get(vpiSize,sig));

	    value.format = vpiVectorVal;
	    vpi_get_value(drv, &value);

	    char*drv_reference = malloc(vpi_get(vpiSize,drv));
	    for (bit = vpi_get(vpiSize,drv) ; bit > 0 ; bit -= 1) {
		  int word = (bit-1) / 32;
		  int mask = 1 << ((bit-1) % 32);
		  if (value.value.vector[word].aval & mask)
			if (value.value.vector[word].bval & mask)
			      drv_reference[bit-1] = 'x';
			else
			      drv_reference[bit-1] = '1';
		  else
			if (value.value.vector[word].bval & mask)
			      drv_reference[bit-1] = 'z';
			else
			      drv_reference[bit-1] = '0';

	    }

	      /* Get the strength values from the signal. */
	    value.format = vpiStrengthVal;
	    vpi_get_value(sig, &value);

	      /* Now given the sig_string that is the current result,
		 and the drive reference that is the value that is
		 being driven by the server, subtract out from the
		 sig_string the server driver, and any pullups from
		 the port. */
	    for (bit = vpi_get(vpiSize,drv); bit > 0; bit -= 1, sig_string+=1) {

		  if (drv_reference[bit-1] == *sig_string) {
			*sig_string = 'z';
			continue;
		  }

		  if (*sig_string == 'z')
			continue;
		  if (*sig_string == 'x')
			continue;

		    /* Do not pass pullup/pulldown values to the
		       server. If the strength of the net is less then
		       a strong drive, then clear it to z. */
		  struct t_vpi_strengthval*str = value.value.strength + bit - 1;
		  if (str->s0 < vpiStrongDrive && str->s1 < vpiStrongDrive)
			*sig_string = 'z';
	    }

	    free(drv_reference);
	    assert(sig_string == cp);
      }

      *cp++ = '\n';
      *cp = 0;

      DEBUG(SIMBUS_DEBUG_PROTOCOL, "Send %s", message);
      int rc = write(instance_table[bus_id].fd, message, strlen(message));
      assert(rc == strlen(message));

      DEBUG(SIMBUS_DEBUG_CALLS, "Return from $ready(%d...)\n", bus_id);

      return 0;
}
Exemplo n.º 20
0
static PLI_INT32 simbus_until_calltf(char*my_name)
{
      s_vpi_time now;
      s_vpi_value value;

      vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
      vpiHandle scope = vpi_handle(vpiScope, sys);
      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);

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

	/* Get a list of the signals and their mapping to a handle. We
	   will use list list to map names from the UNTIL command back
	   to the handle. */
      struct signal_list_cell*signal_list = 0;
      vpiHandle key, sig;
      for (key = vpi_scan(argv) ; key ; key = vpi_scan(argv)) {
	    sig = vpi_scan(argv);
	    assert(sig);

	    struct signal_list_cell*tmp = calloc(1, sizeof(struct signal_list_cell));
	    value.format = vpiStringVal;
	    vpi_get_value(key, &value);
	    assert(value.format == vpiStringVal);
	    assert(value.value.str);
	    tmp->key = strdup(value.value.str);
	    tmp->sig = sig;
	    tmp->next = signal_list;
	    signal_list = tmp;
      }

	/* Now read the command from the server. This will block until
	   the server data actually arrives. */
      char buf[MAX_MESSAGE+1];
      int rc = read_message(bus, buf, sizeof buf);

      if (rc <= 0) {
	    vpi_printf("%s:%d: %s() read from server failed\n",
		       vpi_get_str(vpiFile, sys), (int)vpi_get(vpiLineNo, sys),
		       my_name);

	    vpi_control(vpiStop);

	    free_signal_list(signal_list);

	      /* Set the return value and return. */
	    value.format = vpiIntVal;
	    value.value.integer = 0;
	    vpi_put_value(sys, &value, 0, vpiNoDelay);
	    DEBUG(SIMBUS_DEBUG_CALLS, "Return 0 from $until(%d...)\n", bus);
	    return 0;
      }

      DEBUG(SIMBUS_DEBUG_PROTOCOL, "Recv %s\n", buf);

	/* Chop the message into tokens. */
      int   msg_argc = 0;
      char* msg_argv[MAX_MESSAGE/2];

      char*cp = buf;
      while (*cp != 0) {
	    msg_argv[msg_argc++] = cp;
	    cp += strcspn(cp, " ");
	    if (*cp) {
		  *cp++ = 0;
		  cp += strspn(cp, " ");
	    }
      }
      msg_argv[msg_argc] = 0;

	/* If we get a FINISH command from the server, then $finish
	   the local simulation. */
      if (strcmp(msg_argv[0],"FINISH") == 0) {
	    vpi_printf("Server disconnected with FINISH command\n");
	    vpi_control(vpiFinish);
	    free_signal_list(signal_list);

	      /* Set the return value and return. */
	    value.format = vpiIntVal;
	    value.value.integer = 0;
	    vpi_put_value(sys, &value, 0, vpiNoDelay);
	    DEBUG(SIMBUS_DEBUG_CALLS, "Return 0 from $until(%d...)\n", bus);
	    return 0;
      }

      assert(strcmp(msg_argv[0],"UNTIL") == 0);

      assert(msg_argc >= 2);

      uint64_t until_mant = strtoull(msg_argv[1],&cp,10);
      assert(cp && *cp=='e');
      cp += 1;
      int until_exp = strtol(cp,0,0);

	/* Get the units for the scope */
      int units = vpi_get(vpiTimeUnit, scope);

	/* Put the until time into units of the scope. */
      while (units < until_exp) {
	    until_mant *= 10;
	    until_exp -= 1;
      }
      while (units > until_exp) {
	    until_mant = (until_mant + 5)/10;
	    until_exp += 1;
      }

      	/* Get the simulation time and put it into scope units. */
      now.type = vpiSimTime;
      vpi_get_time(0, &now);
      uint64_t deltatime = ((uint64_t)now.high) << 32;
      deltatime += (uint64_t) now.low;

      int prec  = vpi_get(vpiTimePrecision, 0);
      while (prec < units) {
	    prec += 1;
	    deltatime = (until_mant + 5)/10;
      }

	/* Now we can calculate the delta time. */
      if (deltatime > until_mant)
	    deltatime = 0;
      else
	    deltatime = until_mant - deltatime;

	/* Set the return value and return it. */
      value.format = vpiIntVal;
      value.value.integer = deltatime;
      vpi_put_value(sys, &value, 0, vpiNoDelay);

	/* Process the signal values. */
      int idx;
      for (idx = 2 ; idx < msg_argc ; idx += 1) {

	    char*mkey = msg_argv[idx];
	    char*val = strchr(mkey, '=');
	    assert(val && *val=='=');
	    *val++ = 0;

	    struct signal_list_cell*cur = find_key_in_list(signal_list, mkey);
	    if (cur == 0) {
		  vpi_printf("%s:%d: %s() Unexpected signal %s from bus.\n",
			     vpi_get_str(vpiFile, sys),
			     (int)vpi_get(vpiLineNo, sys),
			     my_name, mkey);
		  continue;
	    }

	    set_handle_to_value(cur->sig, val);
      }

      free_signal_list(signal_list);

      DEBUG(SIMBUS_DEBUG_CALLS, "Return %" PRIu64 " from $until(%d...)\n", deltatime, bus);
      return 0;
}