static ivl_variable_type_t signal_data_type_of_nexus(ivl_nexus_t nex)
{
      unsigned idx;
      ivl_variable_type_t out = IVL_VT_NO_TYPE;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_variable_type_t vtype;
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
	    if (sig == 0) continue;

	    vtype = ivl_signal_data_type(sig);
	    if (out == IVL_VT_NO_TYPE && vtype == IVL_VT_BOOL) {
		  out = vtype;
		  continue;
	    }
	    if (out != IVL_VT_LOGIC && vtype == IVL_VT_LOGIC) {
		  out = vtype;
		  continue;
	    }
	    if (vtype == IVL_VT_REAL) {
		  out = vtype;
		  break;
	    }
      }

      return out;
}
static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex)
{
      unsigned idx;
      ivl_signal_type_t out = IVL_SIT_TRI;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_signal_type_t stype;
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
	    if (sig == 0)
		  continue;

	    stype = ivl_signal_type(sig);
	    if (stype == IVL_SIT_REG)
		  continue;
	    if (stype == IVL_SIT_TRI)
		  continue;
	    if (stype == IVL_SIT_NONE)
		  continue;
	    if (stype == IVL_SIT_UWIRE) return IVL_SIT_UWIRE;
	    out = stype;
      }

      return out;
}
Beispiel #3
0
static unsigned emit_as_input(ivl_scope_t scope, ivl_net_const_t net_const)
{
      ivl_scope_t const_scope = ivl_const_scope(net_const);
      ivl_scope_t parent = ivl_scope_parent(scope);

	/* Look to see if the constant scope is a parent of this scope. */
      while (parent) {
	    if (parent == const_scope) break;
	    parent = ivl_scope_parent(parent);
      }

	/* If the constant scope is a parent then look for an input in
	 * this scope and use that for the name. */
      if (parent) {
	    ivl_nexus_t nex = ivl_const_nex(net_const);
	    unsigned idx, count = ivl_nexus_ptrs(nex);
	    for (idx = 0; idx < count; idx += 1) {
		  ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
		  ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
		  if (sig && (ivl_signal_port(sig) == IVL_SIP_INPUT)) {
			emit_id(ivl_signal_basename(sig));
			return 1;
		  }
	    }
      }

      return 0;
}
static void display_multi_driver_error(ivl_nexus_t nex, unsigned ndrivers,
                                       mdriver_type_t type)
{
      unsigned idx;
      unsigned scope_len = UINT_MAX;
      ivl_signal_t sig = 0;
	/* Find the signal. */
      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t tsig = ivl_nexus_ptr_sig(ptr);
	    if (tsig != 0) {
		  ivl_scope_t scope;
		  unsigned len;
		  if (ivl_signal_local(tsig)) continue;

		    /* If this is not a local signal then find the signal
		     * that has the shortest scope (is the furthest up
		     * the hierarchy). */
		  scope = ivl_signal_scope(tsig);
		  assert(scope);
		  len = strlen(ivl_scope_name(scope));
		  if (len < scope_len) {
			scope_len = len;
			sig = tsig;
		  }
	    }
      }
      assert(sig);

      fprintf(stderr, "%s:%u: vvp.tgt error: ",
                      ivl_signal_file(sig), ivl_signal_lineno(sig));
      switch (type) {
	  case MDRV_UWIRE:
	    if (ivl_signal_type(sig) != IVL_SIT_UWIRE) {
		  fprintf(stderr, "(implicit) ");
	    }
	    fprintf(stderr, "uwire");
	    break;

	  case MDRV_REAL:
	    assert(ivl_signal_type(sig) == IVL_SIT_TRI);
	    if (ivl_signal_data_type(sig) != IVL_VT_REAL) {
		  fprintf(stderr, "(implicit) ");
	    }
	    fprintf(stderr, "wire real");
	    break;

	  default:
	    assert(0);;
      }
      fprintf(stderr, " \"%s\" must have a single driver, found (%u).\n",
                      ivl_signal_basename(sig), ndrivers);
      vvp_errors += 1;
}
Beispiel #5
0
static unsigned find_driving_signal(ivl_scope_t scope, ivl_nexus_t nex)
{
      ivl_signal_t sig = 0;
      unsigned is_array = 0;
      int64_t array_idx = 0;
      unsigned idx, count = ivl_nexus_ptrs(nex);

      for (idx = 0; idx < count; idx += 1) {
	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
	    if (! t_sig) continue;
	    if (ivl_signal_local(t_sig)) continue;
	      /* An output can be used if it is driven by this nexus. */
	    if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
	        (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ) &&
	        (ivl_signal_port(t_sig) != IVL_SIP_OUTPUT)) {
		  continue;
	    }
	      /* We have a signal that can be used to find the name. */
	    if (sig) {
// HERE: Which one should we use? For now it's the first one found.
//       I believe this needs to be solved (see above).
		  fprintf(stderr, "%s:%u: vlog95 warning: Duplicate name (%s",
		          ivl_signal_file(t_sig), ivl_signal_lineno(t_sig),
		          ivl_signal_basename(t_sig));
		  if (ivl_signal_dimensions(t_sig) > 0) {
			int64_t tmp_idx = ivl_nexus_ptr_pin(nex_ptr);
			tmp_idx += ivl_signal_array_base(t_sig);
			fprintf(stderr, "[%"PRId64"]", tmp_idx);
		  }
		  fprintf(stderr, ") found for nexus (%s",
		          ivl_signal_basename(sig));
		  if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx);
		  fprintf(stderr, ")\n");
	    } else {
		  sig = t_sig;
		  if (ivl_signal_dimensions(sig) > 0) {
			is_array = 1;
			array_idx = ivl_nexus_ptr_pin(nex_ptr);
			array_idx += ivl_signal_array_base(sig);
		  }
	    }
      }

      if (sig) {
	    emit_scope_call_path(scope, ivl_signal_scope(sig));
	    emit_id(ivl_signal_basename(sig));
	    if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx);
	    return 1;
      }

      return 0;
}
Beispiel #6
0
ivl_variable_type_t data_type_of_nexus(ivl_nexus_t nex)
{
      unsigned idx;
      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
	    if (sig != 0)
		  return ivl_signal_data_type(sig);
      }

	/* shouldn't happen! */
      return IVL_VT_NO_TYPE;
}
Beispiel #7
0
unsigned width_of_nexus(ivl_nexus_t nex)
{
      unsigned idx;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
	    if (sig != 0)
		  return ivl_signal_width(sig);
      }

      return 0;
}
/*
 * Given a nexus, look for a signal that has module delay
 * paths. Return that signal. (There should be no more than 1.) If we
 * don't find any, then return nil.
 */
static ivl_signal_t find_modpath(ivl_nexus_t nex)
{
      unsigned idx;
      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex,idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
	    if (sig == 0)
		  continue;
	    if (ivl_signal_npath(sig) == 0)
		  continue;

	    return sig;
      }

      return 0;
}
Beispiel #9
0
ivl_signal_t signal_of_nexus(ivl_nexus_t nex, unsigned*word)
{
      unsigned idx;
      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
	    if (sig == 0)
		  continue;
	    if (ivl_signal_local(sig))
		  continue;
	    *word = ivl_nexus_ptr_pin(ptr);
	    return sig;
      }

      return 0;
}
Beispiel #10
0
/*
 * This tests a bufz device against an output receiver, and determines
 * if the device can be skipped. If this function returns true, then a
 * gate will be generated for this node. Otherwise, the code generator
 * will connect its input to its output and skip the gate.
 */
int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr)
{
      ivl_nexus_t in_n;
      unsigned idx;

	/* These are the drives we expect. */
      ivl_drive_t dr0 = ivl_nexus_ptr_drive0(nptr);
      ivl_drive_t dr1 = ivl_nexus_ptr_drive1(nptr);
      int drive_count = 0;

	/* If the gate carries a delay, it must remain. */
      if (ivl_logic_delay(net, 0) != 0)
	    return 0;

	/* If the input is connected to the output, then do not elide
	   the gate. This is some sort of cycle. */
      if (ivl_logic_pin(net, 0) == ivl_logic_pin(net, 1))
	    return 0;

      in_n = ivl_logic_pin(net, 1);
      for (idx = 0 ;  idx < ivl_nexus_ptrs(in_n) ;  idx += 1) {
	    ivl_nexus_ptr_t in_np = ivl_nexus_ptr(in_n, idx);
	    if (ivl_nexus_ptr_log(in_np) == net)
		  continue;

	      /* If the driver for the source does not match the
		 expected drive, then we need to keep the bufz. This
		 test also catches the case that the input device is
		 really also an input, as that device will have a
		 drive of HiZ. We need to keep BUFZ devices in that
		 case in order to prevent back-flow of data. */
	    if (ivl_nexus_ptr_drive0(in_np) != dr0)
		  return 0;
	    if (ivl_nexus_ptr_drive1(in_np) != dr1)
		  return 0;

	    drive_count += 1;
      }

	/* If the BUFZ input has multiple drivers on its input, then
	   we need to keep this device in order to hide the
	   resolution. */
      if (drive_count != 1)
	    return 0;

      return 1;
}
Beispiel #11
0
/*
 * This function finds the vector width of a signal. It relies on the
 * assumption that all the signal inputs to the nexus have the same
 * width. The ivl_target API should assert that condition.
 */
unsigned width_of_nexus(ivl_nexus_t nex)
{
      unsigned idx;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);

	    if (sig != 0) {
		  return ivl_signal_width(sig);
	    }
      }

	/* ERROR: A nexus should have at least one signal to carry
	   properties like width. */
      return 0;
}
Beispiel #12
0
ivl_variable_type_t type_of_nexus(ivl_nexus_t net)
{
      unsigned idx;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(net); idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(net, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);

	    if (sig != 0) {
		  return ivl_signal_data_type(sig);
	    }
      }

	/* ERROR: A nexus should have at least one signal to carry
	   properties like the data type. */
      return IVL_VT_NO_TYPE;
}
Beispiel #13
0
/*
 * An assignment is one of a possible list of l-values to a behavioral
 * assignment. Each l-value is either a part select of a signal or a
 * non-constant bit select.
 */
static void show_assign_lval(ivl_lval_t lval)
{
      ivl_nexus_t nex;
      ivl_signal_t sig=NULL;

      unsigned idx;
      unsigned lsb=0;

      assert(ivl_lval_mux(lval) == 0);
      assert(ivl_lval_mem(lval) == 0);

      nex = ivl_lval_pin(lval, 0);

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    unsigned pin;
	    ivl_nexus_ptr_t ptr;

	    ptr = ivl_nexus_ptr(nex, idx);
	    sig = ivl_nexus_ptr_sig(ptr);
	    if (sig == 0)
		  continue;

	    lsb = ivl_nexus_ptr_pin(ptr);

	    for (pin = 1 ;  pin < ivl_lval_pins(lval) ;  pin += 1) {
		  if (ivl_signal_pin(sig, lsb+pin) != ivl_lval_pin(lval,pin))
			break;
	    }

	    if (pin < ivl_lval_pins(lval))
		  continue;

	    break;
      }

      assert(sig);

      if ((lsb > 0) || (lsb + ivl_lval_pins(lval)) < ivl_signal_pins(sig)) {
	    fprintf(out, "%s[%u:%u]", ivl_signal_name(sig),
		    lsb+ivl_lval_pins(lval)-1, lsb);

      } else {
	    fprintf(out, "%s", ivl_signal_name(sig));

      }
}
Beispiel #14
0
ivl_discipline_t discipline_of_nexus(ivl_nexus_t nex)
{
      unsigned idx;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex); idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);

	    if (sig != 0) {
		  return ivl_signal_discipline(sig);
	    }
      }

	/* ERROR: A nexus should have at least one signal to carry
	   properties like the data type. */
      return 0;
}
Beispiel #15
0
static unsigned find_const_nexus(ivl_scope_t scope, ivl_nexus_t nex)
{
      unsigned idx, count;

      count = ivl_nexus_ptrs(nex);
      for (idx = 0; idx < count; idx += 1) {
	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
	    ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
// HERE: Do we need to check for duplicates?
	    if (net_const) {
		  assert(! ivl_nexus_ptr_pin(nex_ptr));
		  emit_const_nexus(scope, net_const);
		  return 1;
	    }
      }
      return 0;
}
Beispiel #16
0
ivl_nexus_ptr_t ivl_logic_pin_ptr(ivl_net_logic_t net, unsigned pin)
{
      ivl_nexus_t nex = ivl_logic_pin(net, pin);
      unsigned idx;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_net_logic_t tmp = ivl_nexus_ptr_log(ptr);
	    if (tmp == 0)
		  continue;
	    if (tmp != net)
		  continue;
	    if (ivl_nexus_ptr_pin(ptr) != pin)
		  continue;

	    return ptr;
      }
      assert(0);
      return 0;
}
Beispiel #17
0
static unsigned is_local_input(ivl_scope_t scope, ivl_nexus_t nex)
{
      ivl_signal_t sig = 0;
      unsigned idx, count = ivl_nexus_ptrs(nex);

      for (idx = 0; idx < count; idx += 1) {
	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
	    if (! t_sig) continue;
	    if (! ivl_signal_local(t_sig)) continue;
	    if (ivl_signal_port(t_sig) != IVL_SIP_INPUT) continue;
	    assert(! sig);
	    assert(ivl_signal_dimensions(t_sig) == 0);
	    sig = t_sig;
      }
      if (sig) {
	    fprintf(vlog_out, "ivlog%s", ivl_signal_basename(sig));
	    return 1;
      }
      return 0;
}
Beispiel #18
0
static ivl_signal_t find_path_source_port(ivl_delaypath_t path)
{
      unsigned idx;
      ivl_nexus_t nex = ivl_path_source(path);
      ivl_scope_t path_scope = ivl_path_scope(path);

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
	    if (sig == 0)
		  continue;
	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
		  continue;

	      /* The path source scope must match the modpath scope.*/
	    if (ivl_signal_scope(sig) != path_scope)
		  continue;

	    return sig;
      }

      return 0;
}
Beispiel #19
0
/*
 * Given a nexus, this function draws a signal reference. We don't
 * care really whether the signal is a reg or wire, because this may
 * be an input or output of a gate. Just print it. And if this is a
 * bit of a vector, draw the bit select needed to get at the right bit.
 */
static void draw_nexus(ivl_nexus_t nex)
{
      ivl_signal_t sig=NULL;
      ivl_nexus_ptr_t ptr=NULL;
      unsigned idx;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ptr = ivl_nexus_ptr(nex, idx);
	    sig = ivl_nexus_ptr_sig(ptr);
	    if (sig)
		  break;
      }

      assert(sig);

      if (ivl_signal_pins(sig) == 1) {
	    fprintf(out, "%s", ivl_signal_name(sig));

      } else {
	    fprintf(out, "%s[%u]", ivl_signal_name(sig),
		    ivl_nexus_ptr_pin(ptr));
      }
}
Beispiel #20
0
static void draw_net_input_x(ivl_nexus_t nex,
			     struct vvp_nexus_data*nex_data)
{
      ivl_island_t island = 0;
      int island_input_flag = -1;
      ivl_signal_type_t res;
      char result[512];
      unsigned idx;
      char**driver_labels;
      unsigned ndrivers = 0;

      const char*resolv_type;

      char*nex_private = 0;

	/* Accumulate nex_data flags. */
      int nex_flags = 0;

      res = signal_type_of_nexus(nex);
      switch (res) {
	  case IVL_SIT_TRI:
	  case IVL_SIT_UWIRE:
	    resolv_type = "tri";
	    break;
	  case IVL_SIT_TRI0:
	    resolv_type = "tri0";
	    nex_flags |= VVP_NEXUS_DATA_STR;
	    break;
	  case IVL_SIT_TRI1:
	    resolv_type = "tri1";
	    nex_flags |= VVP_NEXUS_DATA_STR;
	    break;
	  case IVL_SIT_TRIAND:
	    resolv_type = "triand";
	    break;
	  case IVL_SIT_TRIOR:
	    resolv_type = "trior";
	    break;
	  default:
	    fprintf(stderr, "vvp.tgt: Unsupported signal type: %d\n", res);
	    assert(0);
	    resolv_type = "tri";
	    break;
      }


      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_switch_t sw = 0;
	    ivl_nexus_ptr_t nptr = ivl_nexus_ptr(nex, idx);

	      /* If this object is part of an island, then we'll be
	         making a port. If this nexus is an output from any
	         switches in the island, then set island_input_flag to
	         false. Save the island cookie. */
	    if ( (sw = ivl_nexus_ptr_switch(nptr)) ) {
		  assert(island == 0 || island == ivl_switch_island(sw));
		  island = ivl_switch_island(sw);
		  if (nex == ivl_switch_a(sw)) {
			nex_flags |= VVP_NEXUS_DATA_STR;
			island_input_flag = 0;
		  } else if (nex == ivl_switch_b(sw)) {
			nex_flags |= VVP_NEXUS_DATA_STR;
			island_input_flag = 0;
		  } else if (island_input_flag == -1) {
			assert(nex == ivl_switch_enable(sw));
			island_input_flag = 1;
		  }
	    }

	      /* Skip input only pins. */
	    if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_HiZ)
		&& (ivl_nexus_ptr_drive1(nptr) == IVL_DR_HiZ))
		  continue;

	      /* Mark the strength-aware flag if the driver can
		 generate values other than the standard "6"
		 strength. */
	    if (nexus_drive_is_strength_aware(nptr))
		  nex_flags |= VVP_NEXUS_DATA_STR;

	      /* Save this driver. */
	    if (ndrivers >= adrivers) {
		  adrivers += 4;
		  drivers = realloc(drivers, adrivers*sizeof(ivl_nexus_ptr_t));
	    }
	    drivers[ndrivers] = nptr;
	    ndrivers += 1;
      }

      if (island_input_flag < 0)
	    island_input_flag = 0;

	/* Save the nexus driver count in the nex_data. */
      assert(nex_data);
      nex_data->drivers_count = ndrivers;
      nex_data->flags |= nex_flags;

	/* If the nexus has no drivers, then send a constant HiZ or
	   0.0 into the net. */
      if (ndrivers == 0) {
	      /* For real nets put 0.0. */
	    if (signal_data_type_of_nexus(nex) == IVL_VT_REAL) {
		  nex_private = draw_Cr_to_string(0.0);
	    } else {
		  unsigned jdx, wid = width_of_nexus(nex);
		  char*tmp = malloc(wid + 5);
		  nex_private = tmp;
		  strcpy(tmp, "C4<");
		  tmp += strlen(tmp);
		  switch (res) {
		      case IVL_SIT_TRI:
		      case IVL_SIT_UWIRE:
			for (jdx = 0 ;  jdx < wid ;  jdx += 1)
			      *tmp++ = 'z';
			break;
		      case IVL_SIT_TRI0:
			for (jdx = 0 ;  jdx < wid ;  jdx += 1)
			      *tmp++ = '0';
			break;
		      case IVL_SIT_TRI1:
			for (jdx = 0 ;  jdx < wid ;  jdx += 1)
			      *tmp++ = '1';
			break;
		      default:
			assert(0);
		  }
		  *tmp++ = '>';
		  *tmp = 0;

		    /* Create an "open" driver to hold the HiZ. We
		       need to do this so that .nets have something to
		       hang onto. */
		  char buf[64];
		  snprintf(buf, sizeof buf, "o%p", nex);
		  fprintf(vvp_out, "%s .functor BUFZ %u, %s; HiZ drive\n",
			  buf, wid, nex_private);
		  nex_private = realloc(nex_private, strlen(buf)+1);
		  strcpy(nex_private, buf);
	    }

	    if (island) {
		  char*tmp2 = draw_island_port(island, island_input_flag, nex, nex_data, nex_private);
		  free(nex_private);
		  nex_private = tmp2;
	    }
	    assert(nex_data->net_input == 0);
	    nex_data->net_input = nex_private;
	    return;
      }

	/* A uwire is a tri with only one driver. */
      if (res == IVL_SIT_UWIRE) {
	    if (ndrivers > 1) {
		  display_multi_driver_error(nex, ndrivers, MDRV_UWIRE);
	    }
	    res = IVL_SIT_TRI;
      }

	/* If the nexus has exactly one driver, then simply draw
	   it. Note that this will *not* work if the nexus is not a
	   TRI type nexus. */
      if (ndrivers == 1 && res == IVL_SIT_TRI) {
	    ivl_signal_t path_sig = find_modpath(nex);
	    if (path_sig) {
		  char*nex_str = draw_net_input_drive(nex, drivers[0]);
		  char modpath_label[64];
		  snprintf(modpath_label, sizeof modpath_label,
			   "V_%p/m", path_sig);
		  nex_private = strdup(modpath_label);
		  draw_modpath(path_sig, nex_str);

	    } else {
		  nex_private = draw_net_input_drive(nex, drivers[0]);
	    }
	    if (island) {
		  char*tmp = draw_island_port(island, island_input_flag, nex, nex_data, nex_private);
		  free(nex_private);
		  nex_private = tmp;
	    }
	    assert(nex_data->net_input == 0);
	    nex_data->net_input = nex_private;
	    return;
      }

	/* We currently only support one driver on real nets. */
      if (ndrivers > 1 && signal_data_type_of_nexus(nex) == IVL_VT_REAL) {
	    display_multi_driver_error(nex, ndrivers, MDRV_REAL);
      }

      driver_labels = malloc(ndrivers * sizeof(char*));
      for (idx = 0; idx < ndrivers; idx += 1) {
            driver_labels[idx] = draw_net_input_drive(nex, drivers[idx]);
      }
      fprintf(vvp_out, "RS_%p .resolv %s", nex, resolv_type);
      for (idx = 0; idx < ndrivers; idx += 1) {
            fprintf(vvp_out, ", %s", driver_labels[idx]);
	    free(driver_labels[idx]);
      }
      fprintf(vvp_out, ";\n");
      free(driver_labels);

      snprintf(result, sizeof result, "RS_%p", nex);

      if (island)
	    nex_private = draw_island_port(island, island_input_flag, nex, nex_data, result);
      else
	    nex_private = strdup(result);

      assert(nex_data->net_input == 0);
      nex_data->net_input = nex_private;
}
Beispiel #21
0
static void draw_logic_in_scope(ivl_net_logic_t lptr)
{
      unsigned pdx;
      const char*ltype = "?";
      const char*lcasc = 0;
      char identity_val = '0';

      int need_delay_flag = ivl_logic_delay(lptr,0)? 1 : 0;

      unsigned vector_width = width_of_nexus(ivl_logic_pin(lptr, 0));

      ivl_drive_t str0, str1;

      int level;
      int ninp = ivl_logic_pins(lptr) - 1;
      typedef const char*const_charp;
      const_charp*input_strings = calloc(ninp, sizeof(const_charp));

      for (pdx = 0 ;  pdx < ninp ;  pdx += 1) {
	    ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
	    if (nex == 0) {
		    /* Only UDPs can have unconnected inputs. */
		  assert(ivl_logic_type(lptr) == IVL_LO_UDP);
		  input_strings[pdx] = 0;
	    } else {
		  input_strings[pdx] = draw_net_input(nex);
	    }
      }

      switch (ivl_logic_type(lptr)) {

          case IVL_LO_UDP:
	    free(input_strings);
	    draw_udp_in_scope(lptr);
	    return;

          case IVL_LO_BUFZ: {
		  /* Draw bufz objects, but only if the gate cannot
		     be elided. If I can elide it, then the
		     draw_nex_input will take care of it for me. */
		ivl_nexus_ptr_t nptr = ivl_logic_pin_ptr(lptr,0);

		ltype = "BUFZ";

		if (can_elide_bufz(lptr, nptr))
		      return;

		break;
	  }

	  case IVL_LO_PULLDOWN:
	  case IVL_LO_PULLUP:
	      /* Skip pullup and pulldown objects. Things that have
		 pull objects as inputs will instead generate the
		 appropriate C<?> symbol. */
	    free(input_strings);
	    return;

	  case IVL_LO_AND:
	    ltype = "AND";
	    identity_val = '1';
	    break;

	  case IVL_LO_BUF:
	    ltype = "BUF";
	    break;

	  case IVL_LO_BUFIF0:
	    ltype = "BUFIF0";
	    break;

	  case IVL_LO_BUFIF1:
	    ltype = "BUFIF1";
	    break;

	  case IVL_LO_NAND:
	    ltype = "NAND";
	    lcasc = "AND";
	    identity_val = '1';
	    break;

	  case IVL_LO_NOR:
	    ltype = "NOR";
	    lcasc = "OR";
	    break;

	  case IVL_LO_NOT:
	    ltype = "NOT";
	    break;

	  case IVL_LO_OR:
	    ltype = "OR";
	    break;

	  case IVL_LO_XNOR:
	    ltype = "XNOR";
	    lcasc = "XOR";
	    break;

	  case IVL_LO_XOR:
	    ltype = "XOR";
	    break;

	  case IVL_LO_CMOS:
	    ltype = "CMOS";
	    break;

	  case IVL_LO_PMOS:
	    ltype = "PMOS";
	    break;

	  case IVL_LO_NMOS:
	    ltype = "NMOS";
	    break;

	  case IVL_LO_RCMOS:
	    ltype = "RCMOS";
	    break;

	  case IVL_LO_RPMOS:
	    ltype = "RPMOS";
	    break;

	  case IVL_LO_RNMOS:
	    ltype = "RNMOS";
	    break;

	  case IVL_LO_NOTIF0:
	    ltype = "NOTIF0";
	    break;

	  case IVL_LO_NOTIF1:
	    ltype = "NOTIF1";
	    break;

	  default:
	    fprintf(stderr, "vvp.tgt: error: Unhandled logic type: %u\n",
		    ivl_logic_type(lptr));
	    ltype = "?";
	    break;
      }

      { ivl_nexus_t nex = ivl_logic_pin(lptr, 0);
        ivl_nexus_ptr_t nptr = 0;
        unsigned idx;
	for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	      nptr = ivl_nexus_ptr(nex,idx);
	      if (ivl_nexus_ptr_log(nptr) != lptr)
		    continue;
	      if (ivl_nexus_ptr_pin(nptr) != 0)
		    continue;
	      break;
	}
        str0 = ivl_nexus_ptr_drive0(nptr);
	str1 = ivl_nexus_ptr_drive1(nptr);
      }

      if (!lcasc)
	lcasc = ltype;

	/* Get all the input label that I will use for parameters to
	   the functor that I create later. */
      ninp = ivl_logic_pins(lptr) - 1;
      input_strings = calloc(ninp, sizeof(char*));
      for (pdx = 0 ;  pdx < ninp ;  pdx += 1)
	    input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));

      level = 0;
      ninp = ivl_logic_pins(lptr) - 1;
      while (ninp) {
	    int inst;
	    for (inst = 0; inst < ninp; inst += 4) {
		  if (ninp > 4)
			fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
				lptr, level, inst, lcasc, vector_width);
		  else {
			fprintf(vvp_out, "L_%p%s .functor %s %u",
				lptr, need_delay_flag? "/d" : "",
				ltype, vector_width);

			if (str0 != IVL_DR_STRONG || str1 != IVL_DR_STRONG)
			      fprintf(vvp_out, " [%u %u]", str0, str1);

		  }
		  for (pdx = inst; pdx < ninp && pdx < inst+4 ; pdx += 1) {
			if (level) {
			      fprintf(vvp_out, ", L_%p/%d/%d",
				      lptr, level - 1, pdx*4);
			} else {
			      fprintf(vvp_out, ", %s", input_strings[pdx]);
			}
		  }
		  for ( ;  pdx < inst+4 ;  pdx += 1) {
			unsigned wdx;
			fprintf(vvp_out, ", C4<");
			for (wdx = 0 ; wdx < vector_width ;  wdx += 1)
			      fprintf(vvp_out, "%c", identity_val);
			fprintf(vvp_out, ">");
		  }

		  fprintf(vvp_out, ";\n");
	    }
	    if (ninp > 4)
		  ninp = (ninp+3) / 4;
	    else
		  ninp = 0;
	    level += 1;
      }

	/* Free the array of char*. The strings themselves are
	   persistent, held by the ivl_nexus_t objects. */
      free(input_strings);

	/* If there are delays, then draw the delay functor to carry
	   that delay. This is the final output. */
      if (need_delay_flag) {
	    ivl_expr_t rise_exp  = ivl_logic_delay(lptr,0);
	    ivl_expr_t fall_exp  = ivl_logic_delay(lptr,1);
	    ivl_expr_t decay_exp = ivl_logic_delay(lptr,2);

	    if (number_is_immediate(rise_exp,64,0)
		&& number_is_immediate(fall_exp,64,0)
		&& number_is_immediate(decay_exp,64,0)) {

		  fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
			  lptr, get_number_immediate(rise_exp),
			  get_number_immediate(rise_exp),
			  get_number_immediate(rise_exp), lptr);
	    } else {
		  ivl_signal_t sig;
		  assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
		  assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
		  assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL);

		  fprintf(vvp_out, "L_%p .delay  L_%p/d", lptr, lptr);

		  sig = ivl_expr_signal(rise_exp);
		  assert(ivl_signal_dimensions(sig) == 0);
		  fprintf(vvp_out, ", v%p_0", sig);

		  sig = ivl_expr_signal(fall_exp);
		  assert(ivl_signal_dimensions(sig) == 0);
		  fprintf(vvp_out, ", v%p_0", sig);

		  sig = ivl_expr_signal(decay_exp);
		  assert(ivl_signal_dimensions(sig) == 0);
		  fprintf(vvp_out, ", v%p_0;\n", sig);
	    }
      }
}
Beispiel #22
0
static void show_nexus_details(ivl_signal_t net, ivl_nexus_t nex)
{
      unsigned idx;

      for (idx = 0 ;  idx < ivl_nexus_ptrs(nex) ;  idx += 1) {
	    ivl_net_const_t con;
	    ivl_net_logic_t logic;
	    ivl_lpm_t lpm;
	    ivl_signal_t sig;
	    ivl_switch_t swt;
	    ivl_branch_t bra;
	    ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);

	    const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
	    const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];

	    if ((sig = ivl_nexus_ptr_sig(ptr))) {
		  fprintf(out, "      SIG %s word=%u (%s0, %s1)",
			  ivl_signal_name(sig), ivl_nexus_ptr_pin(ptr), dr0, dr1);

		  if (ivl_signal_width(sig) != ivl_signal_width(net)) {
			fprintf(out, " (ERROR: Width=%u)",
				ivl_signal_width(sig));
			stub_errors += 1;
		  }

		  if (ivl_signal_data_type(sig) != ivl_signal_data_type(net)) {
			fprintf(out, " (ERROR: data type mismatch)");
			stub_errors += 1;
		  }

		  fprintf(out, "\n");

	    } else if ((logic = ivl_nexus_ptr_log(ptr))) {
		  fprintf(out, "      LOG %s.%s[%u] (%s0, %s1)\n",
			  ivl_scope_name(ivl_logic_scope(logic)),
			  ivl_logic_basename(logic),
			  ivl_nexus_ptr_pin(ptr), dr0, dr1);

	    } else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
		  fprintf(out, "      LPM %s.%s (%s0, %s1)\n",
			  ivl_scope_name(ivl_lpm_scope(lpm)),
			  ivl_lpm_basename(lpm), dr0, dr1);

	    } else if ((swt = ivl_nexus_ptr_switch(ptr))) {
		  fprintf(out, "      SWITCH %s.%s\n",
			  ivl_scope_name(ivl_switch_scope(swt)),
			  ivl_switch_basename(swt));

	    } else if ((con = ivl_nexus_ptr_con(ptr))) {
		  signal_nexus_const(net, ptr, con);

	    } else if ((bra = ivl_nexus_ptr_branch(ptr))) {
		  fprintf(out, "      BRANCH %p terminal %u\n",
			  bra, ivl_nexus_ptr_pin(ptr));

	    } else {
		  fprintf(out, "      ?[%u] (%s0, %s1)\n",
			  ivl_nexus_ptr_pin(ptr), dr0, dr1);
	    }
      }
}
Beispiel #23
0
static unsigned find_signal_in_nexus(ivl_scope_t scope, ivl_nexus_t nex)
{
      ivl_signal_t use_sig = 0;
      unsigned is_driver = 0;
      unsigned is_array = 0;
      int64_t array_idx = 0;
      unsigned idx, count = ivl_nexus_ptrs(nex);

      for (idx = 0; idx < count; idx += 1) {
	    ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
	    ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
	    if (! sig) continue;
	    if (ivl_signal_local(sig)) {
		    /* If the local signal is another receiver skip it. */
		  if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
		      (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) {
			continue;
		  }
	          assert(0);
	    }
	      /* We have a signal that can be used to find the name. */
	    if (scope == ivl_signal_scope(sig)) {
		  if (use_sig) {
			  /* Swap a receiver for a driver. */
			if (is_driver &&
			    (ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
			    (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) {
			      use_sig = sig;
			      is_driver = 0;
			      if (ivl_signal_dimensions(sig) > 0) {
				    is_array = 1;
				    array_idx = ivl_nexus_ptr_pin(nex_ptr);
				    array_idx += ivl_signal_array_base(sig);
			      }
			      continue;
			}
// HERE: Which one should we use? For now it's the first one found.
//       I believe this needs to be solved (see the inout.v test).
			fprintf(stderr, "%s:%u: vlog95 warning: Duplicate "
			                "name (%s",
			                ivl_signal_file(sig),
			                ivl_signal_lineno(sig),
			                ivl_signal_basename(sig));
			if (ivl_signal_dimensions(sig) > 0) {
			      int64_t tmp_idx = ivl_nexus_ptr_pin(nex_ptr);
			      tmp_idx += ivl_signal_array_base(sig);
			      fprintf(stderr, "[%"PRId64"]", tmp_idx);
			}
			fprintf(stderr, ") found for nexus (%s",
			                ivl_signal_basename(use_sig));
			if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx);
			fprintf(stderr, ")\n");
		  } else {
			use_sig = sig;
			  /* This signal is a driver. */
			if ((ivl_nexus_ptr_drive1(nex_ptr) != IVL_DR_HiZ) ||
			    (ivl_nexus_ptr_drive0(nex_ptr) != IVL_DR_HiZ)) {
			      is_driver = 1;
			}
			if (ivl_signal_dimensions(sig) > 0) {
			      is_array = 1;
			      array_idx = ivl_nexus_ptr_pin(nex_ptr);
			      array_idx += ivl_signal_array_base(sig);
			}
		  }
	    }
      }

      if (use_sig) {
	    emit_id(ivl_signal_basename(use_sig));
	    if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx);
	    return 1;
      }

      return 0;
}