Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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);
	    }
      }
}