Exemple #1
0
void show_switch(ivl_switch_t net)
{
      const char*name = ivl_switch_basename(net);
      int has_enable = 0;
      ivl_nexus_t nexa, nexb;
      ivl_variable_type_t nex_type_a, nex_type_b;

      switch (ivl_switch_type(net)) {
	  case IVL_SW_TRAN:
	    fprintf(out, "  tran %s", name);
	    break;
	  case IVL_SW_RTRAN:
	    fprintf(out, "  rtran %s", name);
	    break;
	  case IVL_SW_TRANIF0:
	    fprintf(out, "  tranif0 %s", name);
	    has_enable = 1;
	    break;
	  case IVL_SW_RTRANIF0:
	    fprintf(out, "  rtranif0 %s", name);
	    has_enable = 1;
	    break;
	  case IVL_SW_TRANIF1:
	    fprintf(out, "  tranif1 %s", name);
	    has_enable = 1;
	    break;
	  case IVL_SW_RTRANIF1:
	    fprintf(out, "  rtranif1 %s", name);
	    has_enable = 1;
	    break;
	  case IVL_SW_TRAN_VP:
	    fprintf(out, "  tran(VP wid=%u, part=%u, off=%u) %s",
		    ivl_switch_width(net), ivl_switch_part(net),
		    ivl_switch_offset(net), name);
	    break;
      }

      fprintf(out, " island=%p\n", ivl_switch_island(net));

      nexa = ivl_switch_a(net);
      nex_type_a = nexa? type_of_nexus(nexa) : IVL_VT_NO_TYPE;
      fprintf(out, "    A: %p <type=%s>\n", nexa, data_type_string(nex_type_a));

      nexb = ivl_switch_b(net);
      nex_type_b = nexb? type_of_nexus(nexb) : IVL_VT_NO_TYPE;
      fprintf(out, "    B: %p <type=%s>\n", nexb, data_type_string(nex_type_b));

	/* The A/B pins of the switch must be present, and must match. */
      if (nex_type_a == IVL_VT_NO_TYPE) {
	    fprintf(out, "    A: ERROR: Type missing for pin A\n");
	    stub_errors += 1;
      }
      if (nex_type_b == IVL_VT_NO_TYPE) {
	    fprintf(out, "    B: ERROR: Type missing for pin B\n");
	    stub_errors += 1;
      }
      if (nex_type_a != nex_type_b) {
	    fprintf(out, "    A/B: ERROR: Type mismatch between pins A and B\n");
	    stub_errors += 1;
      }

      if (ivl_switch_type(net) == IVL_SW_TRAN_VP) {
	      /* The TRAN_VP nodes are special in that the specific
		 width matters for each port and should be exactly
		 right for both. */
	    if (width_of_nexus(nexa) != ivl_switch_width(net)) {
		  fprintf(out, "    A: ERROR: part vector nexus "
			  "width=%u, expecting width=%u\n",
			  width_of_nexus(nexa), ivl_switch_width(net));
		  stub_errors += 1;
	    }
	    if (width_of_nexus(nexb) != ivl_switch_part(net)) {
		  fprintf(out, "    B: ERROR: part select nexus "
			  "width=%u, expecting width=%u\n",
			  width_of_nexus(nexb), ivl_switch_part(net));
		  stub_errors += 1;
	    }
      } else {
	      /* All other TRAN nodes will have matching vector
		 widths, but the actual value doesn't matter. */
	    if (width_of_nexus(nexa) != width_of_nexus(nexb)) {
		  fprintf(out, "    A/B: ERROR: Width of ports don't match"
			  ": A=%u, B=%u\n",
			  width_of_nexus(nexa), width_of_nexus(nexb));
		  stub_errors += 1;
	    }
      }

      if (has_enable) {
	    ivl_nexus_t nexe = ivl_switch_enable(net);
	    ivl_variable_type_t nexe_type = type_of_nexus(nexe);
	    fprintf(out, "    E: %p <type=%s>\n", nexe, data_type_string(nexe_type));
	    if (width_of_nexus(nexe) != 1) {
		  fprintf(out, "    E: ERROR: Nexus width is %u\n",
			  width_of_nexus(nexe));
	    }
      }
}
void draw_switch_in_scope(ivl_switch_t sw)
{
      ivl_island_t island;
      ivl_nexus_t nex_a, nex_b, enable;
      const char*str_a, *str_b, *str_e;

      ivl_expr_t rise_exp = ivl_switch_delay(sw, 0);
      ivl_expr_t fall_exp = ivl_switch_delay(sw, 1);
      ivl_expr_t decay_exp= ivl_switch_delay(sw, 2);

      if ((rise_exp || fall_exp || decay_exp) &&
          (!number_is_immediate(rise_exp, 64, 0) ||
           number_is_unknown(rise_exp) ||
           !number_is_immediate(fall_exp, 64, 0) ||
           number_is_unknown(fall_exp) ||
	   !number_is_immediate(decay_exp, 64, 0) ||
	   number_is_unknown(decay_exp))) {
	    fprintf(stderr, "%s:%u: error: Invalid tranif delay expression.\n",
	                    ivl_switch_file(sw), ivl_switch_lineno(sw));
	    vvp_errors += 1;
      }

      island = ivl_switch_island(sw);
      if (ivl_island_flag_test(island, 0) == 0)
	    draw_tran_island(island);

      nex_a = ivl_switch_a(sw);
      assert(nex_a);
      str_a = draw_island_net_input(island, nex_a);

      nex_b = ivl_switch_b(sw);
      assert(nex_b);
      str_b = draw_island_net_input(island, nex_b);

      enable = ivl_switch_enable(sw);
      str_e = 0;
      char str_e_buf[4 + 2*sizeof(void*)];

      if (enable && rise_exp) {
	    assert(fall_exp && decay_exp);

	      /* If the enable has a delay, then generate a .delay
		 node to delay the input by the specified amount. Do
		 the delay outside of the island so that the island
		 processing doesn't have to deal with it. */
	    const char*raw = draw_net_input(enable);

	    snprintf(str_e_buf, sizeof str_e_buf, "p%p", sw);
	    str_e = str_e_buf;

	    fprintf(vvp_out, "%s/d .delay 1 "
		    "(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") %s;\n",
		    str_e, get_number_immediate64(rise_exp),
		    get_number_immediate64(fall_exp),
		    get_number_immediate64(decay_exp), raw);

	    fprintf(vvp_out, "%s .import I%p, %s/d;\n", str_e, island, str_e);

      } else if (enable) {
	    str_e = draw_island_net_input(island, enable);
      }

      switch (ivl_switch_type(sw)) {
	  case IVL_SW_TRAN:
	    fprintf(vvp_out, " .tran");
	    break;
	  case IVL_SW_TRANIF0:
	    fprintf(vvp_out, " .tranif0");
	    break;
	  case IVL_SW_TRANIF1:
	    fprintf(vvp_out, " .tranif1");
	    break;
	  case IVL_SW_TRAN_VP:
	    fprintf(vvp_out, " .tranvp %u %u %u,",
		    ivl_switch_width(sw), ivl_switch_part(sw), ivl_switch_offset(sw));
	    break;

	  default:
	    fprintf(stderr, "%s:%u: tgt-vvp sorry: resistive switch modeling "
	                    "is not currently supported.\n",
		            ivl_switch_file(sw), ivl_switch_lineno(sw));
	    vvp_errors += 1;
	    return;
      }

      fprintf(vvp_out, " I%p, %s %s", island, str_a, str_b);
      if (enable) {
	    fprintf(vvp_out, ", %s", str_e);
      }
      fprintf(vvp_out, ";\n");
}