Ejemplo n.º 1
0
static void emit_delay(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
{
	/* A delay in a continuous assignment can also be a continuous
	 * assignment expression. */
      if (ivl_expr_type(expr) == IVL_EX_SIGNAL) {
	    ivl_signal_t sig = ivl_expr_signal(expr);
	    if (ivl_signal_local(sig)) {
		  assert(! is_stmt);
		  emit_nexus_as_ca(scope, ivl_signal_nex(sig, 0), 0);
		  return;
	    }
      }
      emit_expr(scope, expr, 0);
}
Ejemplo n.º 2
0
/*
 * This function draws a net. This is a bit more complicated as we
 * have to find an appropriate functor to connect to the input.
 */
static void draw_net_in_scope(ivl_signal_t sig)
{
      int msb = ivl_signal_msb(sig);
      int lsb = ivl_signal_lsb(sig);

      const char*datatype_flag = ivl_signal_signed(sig)? "/s" : "";
      const char*local_flag = ivl_signal_local(sig)? "*" : "";
      unsigned iword;

      switch (ivl_signal_data_type(sig)) {
	  case IVL_VT_REAL:
	    datatype_flag = "/real";
	    break;
	  default:
	    break;
      }

      for (iword = 0 ;  iword < ivl_signal_array_count(sig); iword += 1) {

	    unsigned word_count = ivl_signal_array_count(sig);
	    unsigned dimensions = ivl_signal_dimensions(sig);
	    struct vvp_nexus_data*nex_data;

	      /* Connect the pin of the signal to something. */
	    ivl_nexus_t nex = ivl_signal_nex(sig, iword);
	    const char*driver = draw_net_input(nex);

	    nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
	    assert(nex_data);

	    if (nex_data->net == 0) {
		  int strength_aware_flag = 0;
		  const char*vec8 = "";
		  if (nex_data->flags&VVP_NEXUS_DATA_STR)
			strength_aware_flag = 1;
		  if (nex_data->drivers_count > 1)
			vec8 = "8";
		  if (strength_aware_flag)
			vec8 = "8";

		  if (iword == 0 && dimensions > 0) {
			int last = ivl_signal_array_base(sig) + word_count-1;
			int first = ivl_signal_array_base(sig);
			fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
				sig, vvp_mangle_name(ivl_signal_basename(sig)),
				last, first);
		  }
		  if (dimensions > 0) {
			/* If this is a word of an array, then use an
			   array reference in place of the net name. */
			fprintf(vvp_out, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
				" %u drivers%s\n",
				sig, iword, vec8, datatype_flag, sig,
				iword, msb, lsb, driver,
				nex_data->drivers_count,
				strength_aware_flag?", strength-aware":"");
		  } else {
			/* If this is an isolated word, it uses its
			   own name. */
			assert(word_count == 1);
			fprintf(vvp_out, "v%p_%u .net%s%s %s\"%s\", %d %d, %s;"
				" %u drivers%s\n",
				sig, iword, vec8, datatype_flag, local_flag,
				vvp_mangle_name(ivl_signal_basename(sig)),
				msb, lsb, driver,
				nex_data->drivers_count,
				strength_aware_flag?", strength-aware":"");
		  }
		  nex_data->net = sig;
		  nex_data->net_word = iword;

	    } else if (dimensions > 0) {

		    /* In this case, we have an alias to an existing
		       signal array. this typically is an instance of
		       port collapsing that the elaborator combined to
		       discover that the entire array can be collapsed,
		       so the word count for the signal and the alias
		       *must* match. */

		  if (word_count == ivl_signal_array_count(nex_data->net)) {
		    if (iword == 0) {
		      fprintf(vvp_out, "v%p .array \"%s\", v%p; Alias to %s\n",
			      sig, vvp_mangle_name(ivl_signal_basename(sig)),
			      nex_data->net,
			      ivl_signal_basename(nex_data->net));
		    }
		    /* An alias for an individual word. */
		  } else {
			if (iword == 0) {
			      int first = ivl_signal_array_base(sig);
			      int last = first + word_count-1;
			      fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
				      sig,
				      vvp_mangle_name(ivl_signal_basename(sig)),
				      last, first);
			}

			fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
			        "v%p_%u; Alias to %s\n", sig, iword,
			        datatype_flag, sig, iword, msb, lsb,
			        nex_data->net, nex_data->net_word,
			        ivl_signal_basename(nex_data->net));
		  }
	    } else {
		    /* Finally, we may have an alias that is a word
		       connected to another word. Again, this is a
		       case of port collapsing. */

		    /* For the alias, create a different kind of node
		       that refers to the alias source data instead of
		       holding our own data. */
		  fprintf(vvp_out, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
			  sig, iword, datatype_flag,
			  vvp_mangle_name(ivl_signal_basename(sig)),
			  msb, lsb, nex_data->net, nex_data->net_word);
	    }
      }
}
Ejemplo n.º 3
0
static void show_signal(ivl_signal_t net)
{
      unsigned idx;

      const char*type = "?";
      const char*port = "";
      const char*data_type = "?";
      const char*sign = ivl_signal_signed(net)? "signed" : "unsigned";

      switch (ivl_signal_type(net)) {
	  case IVL_SIT_REG:
	    type = "reg";
	    break;
	  case IVL_SIT_TRI:
	    type = "tri";
	    break;
	  case IVL_SIT_TRI0:
	    type = "tri0";
	    break;
	  case IVL_SIT_TRI1:
	    type = "tri1";
	    break;
	  case IVL_SIT_UWIRE:
	    type = "uwire";
	    break;
	  default:
	    break;
      }

      switch (ivl_signal_port(net)) {

	  case IVL_SIP_INPUT:
	    port = "input ";
	    break;

	  case IVL_SIP_OUTPUT:
	    port = "output ";
	    break;

	  case IVL_SIP_INOUT:
	    port = "inout ";
	    break;

	  case IVL_SIP_NONE:
	    break;
      }

      switch (ivl_signal_data_type(net)) {

	  case IVL_VT_BOOL:
	    data_type = "bool";
	    break;

	  case IVL_VT_LOGIC:
	    data_type = "logic";
	    break;

	  case IVL_VT_REAL:
	    data_type = "real";
	    break;

	  default:
	    data_type = "?data?";
	    break;
      }

      const char*discipline_txt = "NONE";
      if (ivl_signal_discipline(net)) {
	    ivl_discipline_t dis = ivl_signal_discipline(net);
	    discipline_txt = ivl_discipline_name(dis);
      }

      for (idx = 0 ;  idx < ivl_signal_array_count(net) ; idx += 1) {

	    ivl_nexus_t nex = ivl_signal_nex(net, idx);

	    fprintf(out, "  %s %s %s%s[%d:%d] %s[word=%u, adr=%d]  "
		               "<width=%u%s> <discipline=%s> ",
		    type, sign, port, data_type,
		    ivl_signal_msb(net), ivl_signal_lsb(net),
		    ivl_signal_basename(net),
		    idx, ivl_signal_array_base(net)+idx,
		    ivl_signal_width(net),
		    ivl_signal_local(net)? ", local":"",
		    discipline_txt);
	    if (nex == NULL) {
		  fprintf(out, "nexus=<virtual>\n");
		  continue;
	    } else {
		  fprintf(out, "nexus=%p\n", nex);
	    }

	    show_nexus_details(net, nex);
      }

      for (idx = 0 ;  idx < ivl_signal_npath(net) ;  idx += 1) {
	    ivl_delaypath_t path = ivl_signal_path(net,idx);
	    ivl_nexus_t nex = ivl_path_source(path);
	    ivl_nexus_t con = ivl_path_condit(path);
	    int posedge = ivl_path_source_posedge(path);
	    int negedge = ivl_path_source_negedge(path);

	    fprintf(out, "      path %p", nex);
	    if (posedge) fprintf(out, " posedge");
	    if (negedge) fprintf(out, " negedge");
	    if (con) fprintf(out, " (if %p)", con);
	    else if (ivl_path_is_condit(path)) fprintf(out, " (ifnone)");
	    fprintf(out, " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64
		         " %" PRIu64 ",%" PRIu64 ",%" PRIu64,
		    ivl_path_delay(path, IVL_PE_01),
		    ivl_path_delay(path, IVL_PE_10),
		    ivl_path_delay(path, IVL_PE_0z),
		    ivl_path_delay(path, IVL_PE_z1),
		    ivl_path_delay(path, IVL_PE_1z),
		    ivl_path_delay(path, IVL_PE_z0),
		    ivl_path_delay(path, IVL_PE_0x),
		    ivl_path_delay(path, IVL_PE_x1),
		    ivl_path_delay(path, IVL_PE_1x),
		    ivl_path_delay(path, IVL_PE_x0),
		    ivl_path_delay(path, IVL_PE_xz),
		    ivl_path_delay(path, IVL_PE_zx));
	    fprintf(out, " scope=%s\n", ivl_scope_name(ivl_path_scope(path)));
      }

      for (idx = 0 ;  idx < ivl_signal_attr_cnt(net) ;  idx += 1) {
	    ivl_attribute_t atr = ivl_signal_attr_val(net, idx);

	    switch (atr->type) {
		case IVL_ATT_STR:
		  fprintf(out, "    %s = %s\n", atr->key, atr->val.str);
		  break;
		case IVL_ATT_NUM:
		  fprintf(out, "    %s = %ld\n", atr->key, atr->val.num);
		  break;
		case IVL_ATT_VOID:
		  fprintf(out, "    %s\n", atr->key);
		  break;
	    }
      }

}