Exemplo n.º 1
0
static void show_lpm_sfunc(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);
      unsigned ports = ivl_lpm_size(net);
      ivl_variable_type_t data_type = type_of_nexus(ivl_lpm_q(net));
      ivl_nexus_t nex;
      unsigned idx;

      fprintf(out, "  LPM_SFUNC %s: <call=%s, width=%u, type=%s, ports=%u>\n",
	      ivl_lpm_basename(net), ivl_lpm_string(net),
	      width, data_type_string(data_type), ports);

      nex = ivl_lpm_q(net);
      if (width != width_of_nexus(nex)) {
	    fprintf(out, "    ERROR: Q output nexus width=%u "
		    " does not match part width\n", width_of_nexus(nex));
	    stub_errors += 1;
      }

      fprintf(out, "    Q: %p\n", nex);
      for (idx = 0 ;  idx < ports ;  idx += 1) {
	    nex = ivl_lpm_data(net, idx);
	    fprintf(out, "    D%u: %p <width=%u, type=%s>\n", idx,
		    nex, width_of_nexus(nex),
		    data_type_string(type_of_nexus(nex)));
      }
}
Exemplo n.º 2
0
static void show_lpm_cast_real(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);
      ivl_nexus_t q, a;

      fprintf(out, "  LPM_CAST_REAL %s: <width=%u>\n",
	      ivl_lpm_basename(net), width);

      q = ivl_lpm_q(net);
      a = ivl_lpm_data(net,0);
      fprintf(out, "    O: %p\n", ivl_lpm_q(net));
      fprintf(out, "    A: %p\n", ivl_lpm_data(net,0));

      if (type_of_nexus(q) != IVL_VT_REAL) {
	    fprintf(out, "    ERROR: Data type of Q is %s, expecting real\n",
		    data_type_string(type_of_nexus(q)));
	    stub_errors += 1;
      }

      if (type_of_nexus(a) == IVL_VT_REAL) {
	    fprintf(out, "    ERROR: Data type of A is %s, expecting !real\n",
		    data_type_string(type_of_nexus(a)));
	    stub_errors += 1;
      }
}
Exemplo n.º 3
0
static void show_lpm_array(ivl_lpm_t net)
{
      ivl_nexus_t nex;
      unsigned width = ivl_lpm_width(net);
      ivl_signal_t array = ivl_lpm_array(net);

      fprintf(out, "  LPM_ARRAY: <width=%u, signal=%s>\n",
	      width, ivl_signal_basename(array));
      nex = ivl_lpm_q(net);
      assert(nex);
      fprintf(out, "    Q: %p\n", nex);
      nex = ivl_lpm_select(net);
      assert(nex);
      fprintf(out, "    Address: %p (address width=%u)\n",
	      nex, ivl_lpm_selects(net));

      if (width_of_nexus(ivl_lpm_q(net)) != width) {
	    fprintf(out, "    ERROR: Data Q width doesn't match "
		    "nexus width=%u\n", width_of_nexus(ivl_lpm_q(net)));
	    stub_errors += 1;
      }

      if (ivl_signal_width(array) != width) {
	    fprintf(out, "    ERROR: Data  width doesn't match "
		    "word width=%u\n", ivl_signal_width(array));
	    stub_errors += 1;
      }
}
Exemplo n.º 4
0
static void show_lpm_abs(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);
      ivl_nexus_t nex;

      fprintf(out, "  LPM_ABS %s: <width=%u>\n",
	      ivl_lpm_basename(net), width);

      nex = ivl_lpm_q(net);
      fprintf(out, "    Q: %p\n", ivl_lpm_q(net));

      nex = ivl_lpm_data(net, 0);
      fprintf(out, "    D: %p\n", nex);
      if (nex == 0) {
	    fprintf(out, "    ERROR: missing input\n");
	    stub_errors += 1;
	    return;
      }

      if (width_of_nexus(nex) != width) {
	    fprintf(out, "    ERROR: D width (%d) is wrong\n",
		    width_of_nexus(nex));
	    stub_errors += 1;
      }
}
Exemplo n.º 5
0
/*
 * The compare-like LPM nodes have input widths that match the
 * ivl_lpm_width() value, and an output width of 1. This function
 * checks that that is so, and indicates errors otherwise.
 */
static void check_cmp_widths(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);

	/* Check that the input widths are as expected. The inputs
	   must be the width of the ivl_lpm_width() for this device,
	   even though the output for this device is 1 bit. */
      if (width != width_of_nexus(ivl_lpm_data(net,0))) {
	    fprintf(out, "    ERROR: Width of A is %u, not %u\n",
		    width_of_nexus(ivl_lpm_data(net,0)), width);
	    stub_errors += 1;
      }

      if (width != width_of_nexus(ivl_lpm_data(net,1))) {
	    fprintf(out, "    ERROR: Width of B is %u, not %u\n",
		    width_of_nexus(ivl_lpm_data(net,1)), width);
	    stub_errors += 1;
      }

      if (width_of_nexus(ivl_lpm_q(net)) != 1) {
	    fprintf(out, "    ERROR: Width of Q is %u, not 1\n",
		    width_of_nexus(ivl_lpm_q(net)));
	    stub_errors += 1;
      }
}
Exemplo n.º 6
0
static void show_lpm_arithmetic_pins(ivl_lpm_t net)
{
      ivl_nexus_t nex;
      nex = ivl_lpm_q(net);
      fprintf(out, "    Q: %p\n", ivl_lpm_q(net));

      nex = ivl_lpm_data(net, 0);
      fprintf(out, "    DataA: %p\n", nex);

      nex = ivl_lpm_data(net, 1);
      fprintf(out, "    DataB: %p\n", nex);
}
Exemplo n.º 7
0
/*
 * The reduction operators have similar characteristics and are
 * displayed here.
 */
static void show_lpm_re(ivl_lpm_t net)
{
      ivl_nexus_t nex;
      const char*type = "?";
      unsigned width = ivl_lpm_width(net);

      switch (ivl_lpm_type(net)) {
	  case IVL_LPM_RE_AND:
	    type = "AND";
	    break;
	  case IVL_LPM_RE_NAND:
	    type = "NAND";
	    break;
	  case IVL_LPM_RE_OR:
	    type = "OR";
	    break;
	  case IVL_LPM_RE_NOR:
	    type = "NOR";
	  case IVL_LPM_RE_XOR:
	    type = "XOR";
	    break;
	  case IVL_LPM_RE_XNOR:
	    type = "XNOR";
	  default:
	    break;
      }

      fprintf(out, "  LPM_RE_%s: %s <width=%u>\n",
	      type, ivl_lpm_name(net),width);

      nex = ivl_lpm_q(net);
      fprintf(out, "    Q: %p\n", nex);

      nex = ivl_lpm_data(net, 0);
      fprintf(out, "    D: %p\n", nex);

      nex = ivl_lpm_q(net);

      if (1 != width_of_nexus(nex)) {
	    fprintf(out, "    ERROR: Width of Q is %u, expecting 1\n",
		    width_of_nexus(nex));
	    stub_errors += 1;
      }

      nex = ivl_lpm_data(net, 0);
      if (width != width_of_nexus(nex)) {
	    fprintf(out, "    ERROR: Width of input is %u, expecting %u\n",
		    width_of_nexus(nex), width);
	    stub_errors += 1;
      }
}
Exemplo n.º 8
0
static void show_lpm_shift(ivl_lpm_t net, const char*shift_dir)
{
      ivl_nexus_t nex;
      unsigned width = ivl_lpm_width(net);

      fprintf(out, "  LPM_SHIFT%s %s: <width=%u, %ssigned>\n", shift_dir,
	      ivl_lpm_basename(net), width,
	      ivl_lpm_signed(net)? "" : "un");

      nex = ivl_lpm_q(net);
      fprintf(out, "    Q: %p\n", nex);

      if (width != width_of_nexus(nex)) {
	    fprintf(out, "    ERROR: Q output nexus width=%u "
		    "does not match part width\n", width_of_nexus(nex));
	    stub_errors += 1;
      }

      nex = ivl_lpm_data(net, 0);
      fprintf(out, "    D: %p\n", nex);

      if (width != width_of_nexus(nex)) {
	    fprintf(out, "    ERROR: Q output nexus width=%u "
		    "does not match part width\n", width_of_nexus(nex));
	    stub_errors += 1;
      }

      nex = ivl_lpm_data(net, 1);
      fprintf(out, "    S: %p <width=%u>\n", nex, width_of_nexus(nex));
}
Exemplo n.º 9
0
/*
 * This function draws N-bit wide binary mux devices. These are so
 * very popular because they are the result of such expressions as:
 *
 *        x = sel? a : b;
 *
 * This code only supports the case where sel is a single bit. It
 * works by drawing for each bit of the width an EQN device that takes
 * as inputs I0 and I1 the alternative inputs, and I2 the select. The
 * select bit is common with all the generated mux devices.
 */
static void generic_show_mux(ivl_lpm_t net)
{
    char name[1024];
    ivl_nexus_t nex, sel;
    unsigned idx;

    xnf_mangle_lpm_name(net, name, sizeof name);

    /* Access the single select bit. This is common to the whole
       width of the mux. */
    assert(ivl_lpm_selects(net) == 1);
    sel = ivl_lpm_select(net, 0);

    for (idx = 0 ;  idx < ivl_lpm_width(net) ;  idx += 1) {
        fprintf(xnf, "SYM, %s/M%u, EQN, "
                "EQN=((I0 * ~I2) + (I1 * I2))\n",
                name, idx);

        nex = ivl_lpm_q(net, idx);
        xnf_draw_pin(nex, "O", 'O');

        nex = ivl_lpm_data2(net, 0, idx);
        xnf_draw_pin(nex, "I0", 'I');

        nex = ivl_lpm_data2(net, 1, idx);
        xnf_draw_pin(nex, "I1", 'I');

        xnf_draw_pin(sel, "I2", 'I');

        fprintf(xnf, "END\n");
    }
}
Exemplo n.º 10
0
// Split lpm_q
void create_split_lpm_q(ivl_lpm_t lpm, unsigned id)
{
  unsigned width = ivl_lpm_width(lpm);
  unsigned i;
  for (i = 0; i < width; i++)
    create_bit_select(id_of_nexus(ivl_lpm_q(lpm, i), 1), width, i, id);
}
Exemplo n.º 11
0
static void show_lpm_ufunc(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);
      unsigned ports = ivl_lpm_size(net);
      ivl_scope_t def = ivl_lpm_define(net);
      ivl_nexus_t nex;
      unsigned idx;

      fprintf(out, "  LPM_UFUNC %s: <call=%s, width=%u, ports=%u>\n",
	      ivl_lpm_basename(net), ivl_scope_name(def), width, ports);

      show_lpm_delays(net);

      nex = ivl_lpm_q(net);
      if (width != width_of_nexus(nex)) {
	    fprintf(out, "    ERROR: Q output nexus width=%u "
		    " does not match part width\n", width_of_nexus(nex));
	    stub_errors += 1;
      }

      fprintf(out, "    Q: %p\n", nex);

      for (idx = 0 ;  idx < ports ;  idx += 1) {
	    nex = ivl_lpm_data(net, idx);
	    fprintf(out, "    D%u: %p <width=%u>\n", idx,
		    nex, width_of_nexus(nex));
      }
}
Exemplo n.º 12
0
static void draw_lpm_sfunc(ivl_lpm_t net)
{
      unsigned idx;

      const char*dly = draw_lpm_output_delay(net);

      fprintf(vvp_out, "L_%p%s .sfunc %u %u \"%s\"", net, dly,
              ivl_file_table_index(ivl_lpm_file(net)), ivl_lpm_lineno(net),
              ivl_lpm_string(net));

	/* Print the function type descriptor string. */
      fprintf(vvp_out, ", \"");

      draw_type_string_of_nex(ivl_lpm_q(net,0));

      for (idx = 0 ;  idx < ivl_lpm_size(net) ;  idx += 1)
	    draw_type_string_of_nex(ivl_lpm_data(net,idx));

      fprintf(vvp_out, "\"");

      for (idx = 0 ;  idx < ivl_lpm_size(net) ;  idx += 1) {
	    fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx)));
      }

      fprintf(vvp_out, ";\n");
}
Exemplo n.º 13
0
static void show_lpm_repeat(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);
      unsigned count = ivl_lpm_size(net);
      ivl_nexus_t nex_q = ivl_lpm_q(net);
      ivl_nexus_t nex_a = ivl_lpm_data(net,0);

      fprintf(out, "  LPM_REPEAT %s: <width=%u, count=%u>\n",
	      ivl_lpm_basename(net), width, count);

      fprintf(out, "    Q: %p\n", nex_q);
      fprintf(out, "    D: %p\n", nex_a);

      if (width != width_of_nexus(nex_q)) {
	    fprintf(out, "    ERROR: Width of Q is %u, expecting %u\n",
		    width_of_nexus(nex_q), width);
	    stub_errors += 1;
      }

      if (count == 0 || count > width || (width%count != 0)) {
	    fprintf(out, "    ERROR: Repeat count not reasonable\n");
	    stub_errors += 1;

      } else if (width/count != width_of_nexus(nex_a)) {
	    fprintf(out, "    ERROR: Width of D is %u, expecting %u\n",
		    width_of_nexus(nex_a), width/count);
	    stub_errors += 1;
      }
}
Exemplo n.º 14
0
/*
 * The LPM_MULT node has a Q output and two data inputs. The width of
 * the Q output must be the width of the node itself.
 */
static void show_lpm_mult(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);

      fprintf(out, "  LPM_MULT %s: <width=%u>\n",
	      ivl_lpm_basename(net), width);

      fprintf(out, "    O: %p\n", ivl_lpm_q(net));
      fprintf(out, "    A: %p <width=%u>\n",
	      ivl_lpm_data(net,0), width_of_nexus(ivl_lpm_data(net,0)));
      fprintf(out, "    B: %p <width=%u>\n",
	      ivl_lpm_data(net,1), width_of_nexus(ivl_lpm_data(net,1)));

      if (width != width_of_nexus(ivl_lpm_q(net))) {
	    fprintf(out, "    ERROR: Width of Q is %u, not %u\n",
		    width_of_nexus(ivl_lpm_q(net)), width);
	    stub_errors += 1;
      }
}
Exemplo n.º 15
0
/*
 * Handle a PART SELECT PV device. Generate a .part/pv node that
 * includes the part input, and the geometry of the part.
 */
static void draw_lpm_part_pv(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);
      unsigned base  = ivl_lpm_base(net);
      unsigned signal_width = width_of_nexus(ivl_lpm_q(net,0));

      fprintf(vvp_out, "L_%p .part/pv %s",
	      net, draw_net_input(ivl_lpm_data(net, 0)));

      fprintf(vvp_out, ", %u, %u, %u;\n", base, width, signal_width);
}
Exemplo n.º 16
0
/* IVL_LPM_CMP_NE
 * This LPM node supports two-input compare. The output width is
 * actually always 1, the lpm_width is the expected width of the inputs.
 */
static void show_lpm_cmp_ne(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);

      fprintf(out, "  LPM_CMP_NE %s: <width=%u>\n",
	      ivl_lpm_basename(net), width);

      fprintf(out, "    O: %p\n", ivl_lpm_q(net));
      fprintf(out, "    A: %p\n", ivl_lpm_data(net,0));
      fprintf(out, "    B: %p\n", ivl_lpm_data(net,1));
      check_cmp_widths(net);
}
Exemplo n.º 17
0
/* IVL_LPM_CMP_EEQ/NEE
 * This LPM node supports two-input compare. The output width is
 * actually always 1, the lpm_width is the expected width of the inputs.
 */
static void show_lpm_cmp_eeq(ivl_lpm_t net)
{
      const char*str = (ivl_lpm_type(net) == IVL_LPM_CMP_EEQ)? "EEQ" : "NEE";
      unsigned width = ivl_lpm_width(net);

      fprintf(out, "  LPM_CMP_%s %s: <width=%u>\n", str,
	      ivl_lpm_basename(net), width);

      fprintf(out, "    O: %p\n", ivl_lpm_q(net));
      fprintf(out, "    A: %p\n", ivl_lpm_data(net,0));
      fprintf(out, "    B: %p\n", ivl_lpm_data(net,1));
      check_cmp_widths(net);
}
Exemplo n.º 18
0
/* IVL_LPM_CMP_GT
 * This LPM node supports two-input compare.
 */
static void show_lpm_cmp_gt(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);

      fprintf(out, "  LPM_CMP_GT %s: <width=%u %s>\n",
	      ivl_lpm_basename(net), width,
	      ivl_lpm_signed(net)? "signed" : "unsigned");

      fprintf(out, "    O: %p\n", ivl_lpm_q(net));
      fprintf(out, "    A: %p\n", ivl_lpm_data(net,0));
      fprintf(out, "    B: %p\n", ivl_lpm_data(net,1));
      check_cmp_widths(net);
}
Exemplo n.º 19
0
/*
 * A 4-input N-wide mux can be made on Virtex devices using MUXF5 and
 * LUT devices. The MUXF5 selects a LUT device (and is connected to
 * S[1]) and the LUT devices, connected to S[0], select the input.
 */
static void virtex_mux4(ivl_lpm_t net)
{
      unsigned idx;
      assert(ivl_lpm_selects(net) == 2);

      for (idx = 0 ;  idx < ivl_lpm_width(net) ;  idx += 1) {
	    edif_joint_t jnt;
	    edif_cellref_t lut01;
	    edif_cellref_t lut23;
	    edif_cellref_t muxf5;

	    lut01 = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
	    edif_cellref_pstring(lut01, "INIT", "CA");

	    lut23 = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
	    edif_cellref_pstring(lut23, "INIT", "CA");

	    muxf5 = edif_cellref_create(edf, xilinx_cell_muxf5(xlib));

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 0, idx));
	    edif_add_to_joint(jnt, lut01, LUT_I0);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 1, idx));
	    edif_add_to_joint(jnt, lut01, LUT_I1);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 2, idx));
	    edif_add_to_joint(jnt, lut23, LUT_I0);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 3, idx));
	    edif_add_to_joint(jnt, lut23, LUT_I1);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 0));
	    edif_add_to_joint(jnt, lut01, LUT_I2);
	    edif_add_to_joint(jnt, lut23, LUT_I2);

	    jnt = edif_joint_create(edf);
	    edif_add_to_joint(jnt, muxf5, MUXF_I0);
	    edif_add_to_joint(jnt, lut01, LUT_O);

	    jnt = edif_joint_create(edf);
	    edif_add_to_joint(jnt, muxf5, MUXF_I1);
	    edif_add_to_joint(jnt, lut23, LUT_O);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
	    edif_add_to_joint(jnt, muxf5, MUXF_O);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 1));
	    edif_add_to_joint(jnt, muxf5, MUXF_S);
      }
}
Exemplo n.º 20
0
int fit_logic(void)
{
      unsigned idx;

      for (idx = 0 ;  idx < pins ;  idx += 1) {
	    ivl_nexus_t cell;

	    struct pal_bind_s*pin = bind_pin + idx;
	    if (pin->sop == 0)
		  continue;

	    cell = pin->nexus;
	    if (cell == 0)
		  continue;


	      /* If there is an enable, then this is a bufifX or a
		 notifX. Build the expression for the enable, and
		 guess that the input to the cell is actually the
		 input to the enable. */
	    if (pin->enable) {
		  ivl_nexus_t en_nex = ivl_logic_pin(pin->enable, 2);
		  assert(cell == ivl_logic_pin(pin->enable, 0));

		  cell = ivl_logic_pin(pin->enable, 1);
		  assert(cell);

		  pin->enable_ex = build_expr(en_nex);
		  dump_expr(pin->enable_ex, ivl_nexus_name(en_nex));
	    }

	      /* If there is a reg, then the input to the cell is
		 really the D input to the ff. */
	    if (pin->reg) {
		  assert(cell == ivl_lpm_q(pin->reg, pin->reg_q));
		  cell = ivl_lpm_data(pin->reg, pin->reg_q);
	    }

	    assert(cell);

	      /* Here we are. Generate the sum-of-products for the
		 input. */
	    pin->sop_ex = build_expr(cell);
	    dump_expr(pin->sop_ex, ivl_nexus_name(cell));
      }

      return 0;
}
Exemplo n.º 21
0
static void show_lpm_sign_ext(ivl_lpm_t net)
{
      unsigned width = ivl_lpm_width(net);
      ivl_nexus_t nex_q = ivl_lpm_q(net);
      ivl_nexus_t nex_a = ivl_lpm_data(net,0);

      fprintf(out, "  LPM_SIGN_EXT %s: <width=%u>\n",
	      ivl_lpm_basename(net), width);

      fprintf(out, "    Q: %p\n", nex_q);
      fprintf(out, "    D: %p <width=%u>\n", nex_a, width_of_nexus(nex_a));

      if (width != width_of_nexus(nex_q)) {
	    fprintf(out, "    ERROR: Width of Q is %u, expecting %u\n",
		    width_of_nexus(nex_q), width);
	    stub_errors += 1;
      }
}
Exemplo n.º 22
0
static void show_lpm_ff(ivl_lpm_t net)
{
      ivl_nexus_t nex;
      unsigned width = ivl_lpm_width(net);

      fprintf(out, "  LPM_FF %s: <width=%u>\n",
	      ivl_lpm_basename(net), width);

      nex = ivl_lpm_clk(net);
      fprintf(out, "    clk: %p\n", nex);
      if (width_of_nexus(nex) != 1) {
	    fprintf(out, "    clk: ERROR: Nexus width is %u\n",
		    width_of_nexus(nex));
	    stub_errors += 1;
      }

      if (ivl_lpm_enable(net)) {
	    nex = ivl_lpm_enable(net);
	    fprintf(out, "    CE: %p\n", nex);
	    if (width_of_nexus(nex) != 1) {
		  fprintf(out, "    CE: ERROR: Nexus width is %u\n",
			  width_of_nexus(nex));
		  stub_errors += 1;
	    }
      }

      nex = ivl_lpm_data(net,0);
      fprintf(out, "    D: %p\n", nex);
      if (width_of_nexus(nex) != width) {
	    fprintf(out, "    D: ERROR: Nexus width is %u\n",
		    width_of_nexus(nex));
	    stub_errors += 1;
      }

      nex = ivl_lpm_q(net);
      fprintf(out, "    Q: %p\n", nex);
      if (width_of_nexus(nex) != width) {
	    fprintf(out, "    Q: ERROR: Nexus width is %u\n",
		    width_of_nexus(nex));
	    stub_errors += 1;
      }

}
Exemplo n.º 23
0
/*
 * Show an IVL_LPM_MUX.
 *
 * The compiler is supposed to make sure that the Q output and data
 * inputs all have the width of the device. The ivl_lpm_select input
 * has its own width.
 */
static void show_lpm_mux(ivl_lpm_t net)
{
      ivl_nexus_t nex;
      unsigned idx;
      unsigned width = ivl_lpm_width(net);
      unsigned size  = ivl_lpm_size(net);
      ivl_drive_t drive0 = ivl_lpm_drive0(net);
      ivl_drive_t drive1 = ivl_lpm_drive1(net);

      fprintf(out, "  LPM_MUX %s: <width=%u, size=%u>\n",
	      ivl_lpm_basename(net), width, size);

      nex = ivl_lpm_q(net);
      fprintf(out, "    Q: %p <drive0/1 = %u/%u>\n", nex, drive0, drive1);
      if (width != width_of_nexus(nex)) {
	    fprintf(out, "    Q: ERROR: Nexus width is %u\n",
		    width_of_nexus(nex));
	    stub_errors += 1;
      }

	/* The select input is a vector with the width from the
	   ivl_lpm_selects function. */
      nex = ivl_lpm_select(net);
      fprintf(out, "    S: %p <width=%u>\n",
	      nex, ivl_lpm_selects(net));
      if (ivl_lpm_selects(net) != width_of_nexus(nex)) {
	    fprintf(out, "    S: ERROR: Nexus width is %u\n",
		    width_of_nexus(nex));
	    stub_errors += 1;
      }

	/* The ivl_lpm_size() method give the number of inputs that
	   can be selected from. */
      for (idx = 0 ;  idx < size ;  idx += 1) {
	    nex = ivl_lpm_data(net,idx);
	    fprintf(out, "    D%u: %p\n", idx, nex);
	    if (width != width_of_nexus(nex)) {
		  fprintf(out, "    D%u: ERROR, Nexus width is %u\n",
			  idx, width_of_nexus(nex));
		  stub_errors += 1;
	    }
      }
}
Exemplo n.º 24
0
static void generic_show_dff(ivl_lpm_t net)
{
    char name[1024];
    ivl_nexus_t nex;

    xnf_mangle_lpm_name(net, name, sizeof name);

    fprintf(xnf, "SYM, %s, DFF, LIBVER=2.0.0\n", name);

    nex = ivl_lpm_q(net, 0);
    xnf_draw_pin(nex, "Q", 'O');

    nex = ivl_lpm_data(net, 0);
    xnf_draw_pin(nex, "D", 'I');

    nex = ivl_lpm_clk(net);
    xnf_draw_pin(nex, "C", 'I');

    if ((nex = ivl_lpm_enable(net)))
        xnf_draw_pin(nex, "CE", 'I');

    fprintf(xnf, "END\n");
}
Exemplo n.º 25
0
/* IVL_LPM_CONCAT
 * The concat device takes N inputs (N=ivl_lpm_size) and generates
 * a single output. The total output is known from the ivl_lpm_width
 * function. The widths of all the inputs are inferred from the widths
 * of the signals connected to the nexus of the inputs. The compiler
 * makes sure the input widths add up to the output width.
 */
static void show_lpm_concat(ivl_lpm_t net)
{
      unsigned idx;

      unsigned width_sum = 0;
      unsigned width = ivl_lpm_width(net);

      fprintf(out, "  LPM_CONCAT %s: <width=%u, inputs=%u>\n",
	      ivl_lpm_basename(net), width, ivl_lpm_size(net));
      fprintf(out, "    O: %p\n", ivl_lpm_q(net));

      for (idx = 0 ;  idx < ivl_lpm_size(net) ;  idx += 1) {
	    ivl_nexus_t nex = ivl_lpm_data(net, idx);
	    unsigned signal_width = width_of_nexus(nex);

	    fprintf(out, "    I%u: %p (width=%u)\n", idx, nex, signal_width);
	    width_sum += signal_width;
      }

      if (width_sum != width) {
	    fprintf(out, "    ERROR! Got %u bits input, expecting %u!\n",
		    width_sum, width);
      }
}
Exemplo n.º 26
0
static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
{
      unsigned nptr_pin = ivl_nexus_ptr_pin(nptr);
      ivl_net_const_t cptr;
      ivl_net_logic_t lptr;
      ivl_signal_t sptr;
      ivl_lpm_t lpm;

      lptr = ivl_nexus_ptr_log(nptr);
      if (lptr
	  && ((ivl_logic_type(lptr)==IVL_LO_BUFZ)||(ivl_logic_type(lptr)==IVL_LO_BUFT))
	  && (nptr_pin == 0))
	    do {
		  if (! can_elide_bufz(lptr, nptr))
			break;

		  return strdup(draw_net_input(ivl_logic_pin(lptr, 1)));
	    } while(0);

	/* If this is a pulldown device, then there is a single pin
	   that drives a constant value to the entire width of the
	   vector. The driver normally drives a pull0 value, so a C8<>
	   constant is appropriate, but if the drive is really strong,
	   then we can draw a C4<> constant instead. */
      if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLDOWN)) {
	    if (ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG) {
		  size_t result_len = ivl_logic_width(lptr) + 5;
		  char*result = malloc(result_len);
		  char*dp = result;
		  strcpy(dp, "C4<");
		  dp += strlen(dp);
		  str_repeat(dp, "0", ivl_logic_width(lptr));
		  dp += ivl_logic_width(lptr);
		  *dp++ = '>';
		  *dp = 0;
		  assert(dp >= result);
		  assert((unsigned)(dp - result) <= result_len);
		  return result;
	    } else {
		  char val[4];
		  size_t result_len = 3*ivl_logic_width(lptr) + 5;
		  char*result = malloc(result_len);
		  char*dp = result;

		  val[0] = "01234567"[ivl_nexus_ptr_drive0(nptr)];
		  val[1] = val[0];
		  val[2] = '0';
		  val[3] = 0;

		  strcpy(dp, "C8<");
		  dp += strlen(dp);
		  str_repeat(dp, val, ivl_logic_width(lptr));
		  dp += 3*ivl_logic_width(lptr);
		  *dp++ = '>';
		  *dp = 0;
		  assert(dp >= result);
		  assert((unsigned)(dp - result) <= result_len);
		  return result;
	    }
      }

      if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLUP)) {
	    char*result;
	    char tmp[32];
	    if (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG) {
		  size_t result_len = 5 + ivl_logic_width(lptr);
		  result = malloc(result_len);
		  char*dp = result;
		  strcpy(dp, "C4<");
		  dp += strlen(dp);
		  str_repeat(dp, "1", ivl_logic_width(lptr));
		  dp += ivl_logic_width(lptr);
		  *dp++ = '>';
		  *dp = 0;
		  assert(dp >= result);
		  assert((unsigned)(dp - result) <= result_len);

	    } else {
		  char val[4];
		  size_t result_len = 5 + 3*ivl_logic_width(lptr);
		  result = malloc(result_len);
		  char*dp = result;

		  val[0] = "01234567"[ivl_nexus_ptr_drive1(nptr)];
		  val[1] = val[0];
		  val[2] = '1';
		  val[3] = 0;

		  strcpy(dp, "C8<");
		  dp += strlen(dp);
		  str_repeat(dp, val, ivl_logic_width(lptr));
		  dp += 3*ivl_logic_width(lptr);
		  *dp++ = '>';
		  *dp = 0;
		  assert(dp >= result);
		  assert((unsigned)(dp - result) <= result_len);

	    }

	      /* Make the constant an argument to a BUFZ, which is
		 what we use to drive the PULLed value. */
	    fprintf(vvp_out, "L_%p .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
		    lptr, result);
	    snprintf(tmp, sizeof tmp, "L_%p", lptr);
	    result = realloc(result, strlen(tmp)+1);
	    strcpy(result, tmp);
	    return result;
      }

      if (lptr && (nptr_pin == 0)) {
	    char tmp[128];
	    snprintf(tmp, sizeof tmp, "L_%p", lptr);
	    return strdup(tmp);
      }

      sptr = ivl_nexus_ptr_sig(nptr);
      if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
	    char tmp[128];
	      /* Input is a .var. This device may be a non-zero pin
	         because it may be an array of reg vectors. */
	    snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin);

	    if (ivl_signal_dimensions(sptr) > 0) {
		  fprintf(vvp_out, "v%p_%u .array/port v%p, %u;\n",
			  sptr, nptr_pin, sptr, nptr_pin);
	    }

	    return strdup(tmp);
      }

      cptr = ivl_nexus_ptr_con(nptr);
      if (cptr) {
	    char *result = 0;
	    ivl_expr_t d_rise, d_fall, d_decay;
            unsigned dly_width = 0;

	      /* Constants should have exactly 1 pin, with a literal value. */
	    assert(nptr_pin == 0);

	    switch (ivl_const_type(cptr)) {
		case IVL_VT_LOGIC:
		case IVL_VT_BOOL:
		case IVL_VT_STRING:
		  if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG)
		      && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG)) {

			result = draw_C4_to_string(cptr);

		  } else {
			result = draw_C8_to_string(cptr,
						   ivl_nexus_ptr_drive0(nptr),
						   ivl_nexus_ptr_drive1(nptr));
		  }
                  dly_width = ivl_const_width(cptr);
		  break;

		case IVL_VT_REAL:
		  result = draw_Cr_to_string(ivl_const_real(cptr));
                  dly_width = 0;
		  break;

		default:
		  assert(0);
		  break;
	    }

	    d_rise = ivl_const_delay(cptr, 0);
	    d_fall = ivl_const_delay(cptr, 1);
	    d_decay = ivl_const_delay(cptr, 2);

	      /* We have a delayed constant, so we need to build some code. */
	    if (d_rise != 0) {
		  char tmp[128];
		  fprintf(vvp_out, "L_%p/d .functor BUFT 1, %s, "
		                   "C4<0>, C4<0>, C4<0>;\n", cptr, result);
		  free(result);

		    /* Is this a fixed or variable delay? */
		  if (number_is_immediate(d_rise, 64, 0) &&
		      number_is_immediate(d_fall, 64, 0) &&
		      number_is_immediate(d_decay, 64, 0)) {

			assert(! number_is_unknown(d_rise));
			assert(! number_is_unknown(d_fall));
			assert(! number_is_unknown(d_decay));

			fprintf(vvp_out, "L_%p .delay %u "
				"(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n",
			                 cptr, dly_width,
			                 get_number_immediate64(d_rise),
			                 get_number_immediate64(d_fall),
			                 get_number_immediate64(d_decay), cptr);

		  } else {
			ivl_signal_t sig;
			// We do not currently support calculating the decay
			// from the rise and fall variable delays.
			assert(d_decay != 0);
			assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL);
			assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL);
			assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL);

			fprintf(vvp_out, "L_%p .delay %u L_%p/d",
                                cptr, dly_width, cptr);

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

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

			sig = ivl_expr_signal(d_decay);
			assert(ivl_signal_dimensions(sig) == 0);
			fprintf(vvp_out, ", v%p_0;\n", sig);
		  }

		  snprintf(tmp, sizeof tmp, "L_%p", cptr);
		  result = strdup(tmp);

	    } else {
		  char tmp[64];
		  fprintf(vvp_out, "L_%p .functor BUFT 1, %s, "
			  "C4<0>, C4<0>, C4<0>;\n", cptr, result);
		  free(result);

		  snprintf(tmp, sizeof tmp, "L_%p", cptr);
		  result = strdup(tmp);
	    }

	    return result;
      }

      lpm = ivl_nexus_ptr_lpm(nptr);
      if (lpm) switch (ivl_lpm_type(lpm)) {

	  case IVL_LPM_FF:
	  case IVL_LPM_ABS:
	  case IVL_LPM_ADD:
	  case IVL_LPM_ARRAY:
	  case IVL_LPM_CAST_INT2:
	  case IVL_LPM_CAST_INT:
	  case IVL_LPM_CAST_REAL:
	  case IVL_LPM_CONCAT:
	  case IVL_LPM_CONCATZ:
	  case IVL_LPM_CMP_EEQ:
	  case IVL_LPM_CMP_EQ:
	  case IVL_LPM_CMP_GE:
	  case IVL_LPM_CMP_GT:
	  case IVL_LPM_CMP_NE:
	  case IVL_LPM_CMP_NEE:
	  case IVL_LPM_RE_AND:
	  case IVL_LPM_RE_OR:
	  case IVL_LPM_RE_XOR:
	  case IVL_LPM_RE_NAND:
	  case IVL_LPM_RE_NOR:
	  case IVL_LPM_RE_XNOR:
	  case IVL_LPM_SFUNC:
	  case IVL_LPM_SHIFTL:
	  case IVL_LPM_SHIFTR:
	  case IVL_LPM_SIGN_EXT:
	  case IVL_LPM_SUB:
	  case IVL_LPM_MULT:
	  case IVL_LPM_MUX:
	  case IVL_LPM_POW:
	  case IVL_LPM_DIVIDE:
	  case IVL_LPM_MOD:
	  case IVL_LPM_UFUNC:
	  case IVL_LPM_PART_VP:
	  case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */
	  case IVL_LPM_REPEAT:
	    if (ivl_lpm_q(lpm) == nex) {
		  char tmp[128];
		  snprintf(tmp, sizeof tmp, "L_%p", lpm);
		  return strdup(tmp);
	    }
	    break;

      }

      fprintf(stderr, "vvp.tgt error: no input to nexus.\n");
      assert(0);
      return strdup("C<z>");
}
Exemplo n.º 27
0
static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
{
      unsigned nptr_pin = ivl_nexus_ptr_pin(nptr);
      ivl_net_const_t cptr;
      ivl_net_logic_t lptr;
      ivl_signal_t sptr;
      ivl_lpm_t lpm;

      lptr = ivl_nexus_ptr_log(nptr);
      if (lptr
	  && ((ivl_logic_type(lptr)==IVL_LO_BUFZ)||(ivl_logic_type(lptr)==IVL_LO_BUFT))
	  && (nptr_pin == 0))
	    do {
		  if (! can_elide_bufz(lptr, nptr))
			break;

		  return strdup(draw_net_input(ivl_logic_pin(lptr, 1)));
	    } while(0);

      if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLDOWN)) {
	    return draw_net_pull(lptr, ivl_nexus_ptr_drive0(nptr), "0");
      }

      if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLUP)) {
	    return draw_net_pull(lptr, ivl_nexus_ptr_drive1(nptr), "1");
      }

      if (lptr && (nptr_pin == 0)) {
	    char tmp[128];
	    snprintf(tmp, sizeof tmp, "L_%p", lptr);
	    return strdup(tmp);
      }

      sptr = ivl_nexus_ptr_sig(nptr);
      if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
	    char tmp[128];
	      /* Input is a .var. This device may be a non-zero pin
	         because it may be an array of reg vectors. */
	    snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin);

	    if (ivl_signal_dimensions(sptr) > 0) {
		  fprintf(vvp_out, "v%p_%u .array/port v%p, %u;\n",
			  sptr, nptr_pin, sptr, nptr_pin);
	    }

	    return strdup(tmp);
      }

      cptr = ivl_nexus_ptr_con(nptr);
      if (cptr) {
	    char tmp[64];
	    char *result = 0;
	    ivl_expr_t d_rise, d_fall, d_decay;
            unsigned dly_width = 0;
	    char *dly;

	      /* Constants should have exactly 1 pin, with a literal value. */
	    assert(nptr_pin == 0);

	    switch (ivl_const_type(cptr)) {
		case IVL_VT_LOGIC:
		case IVL_VT_BOOL:
		case IVL_VT_STRING:
		  if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG)
		      && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG)) {

			result = draw_C4_to_string(cptr);

		  } else {
			result = draw_C8_to_string(cptr,
						   ivl_nexus_ptr_drive0(nptr),
						   ivl_nexus_ptr_drive1(nptr));
		  }
                  dly_width = ivl_const_width(cptr);
		  break;

		case IVL_VT_REAL:
		  result = draw_Cr_to_string(ivl_const_real(cptr));
                  dly_width = 0;
		  break;

		default:
		  assert(0);
		  break;
	    }

	    d_rise = ivl_const_delay(cptr, 0);
	    d_fall = ivl_const_delay(cptr, 1);
	    d_decay = ivl_const_delay(cptr, 2);

	    dly = "";
	    if (d_rise != 0) {
		  draw_delay(cptr, dly_width, 0, d_rise, d_fall, d_decay);
		  dly = "/d";
	    }
	    fprintf(vvp_out, "L_%p%s .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n",
		    cptr, dly, result);
	    free(result);

	    snprintf(tmp, sizeof tmp, "L_%p", cptr);
	    return strdup(tmp);
      }

      lpm = ivl_nexus_ptr_lpm(nptr);
      if (lpm) switch (ivl_lpm_type(lpm)) {

	  case IVL_LPM_FF:
	  case IVL_LPM_LATCH:
	  case IVL_LPM_ABS:
	  case IVL_LPM_ADD:
	  case IVL_LPM_ARRAY:
	  case IVL_LPM_CAST_INT2:
	  case IVL_LPM_CAST_INT:
	  case IVL_LPM_CAST_REAL:
	  case IVL_LPM_CONCAT:
	  case IVL_LPM_CONCATZ:
	  case IVL_LPM_CMP_EEQ:
	  case IVL_LPM_CMP_EQ:
	  case IVL_LPM_CMP_WEQ:
	  case IVL_LPM_CMP_WNE:
	  case IVL_LPM_CMP_EQX:
	  case IVL_LPM_CMP_EQZ:
	  case IVL_LPM_CMP_GE:
	  case IVL_LPM_CMP_GT:
	  case IVL_LPM_CMP_NE:
	  case IVL_LPM_CMP_NEE:
	  case IVL_LPM_RE_AND:
	  case IVL_LPM_RE_OR:
	  case IVL_LPM_RE_XOR:
	  case IVL_LPM_RE_NAND:
	  case IVL_LPM_RE_NOR:
	  case IVL_LPM_RE_XNOR:
	  case IVL_LPM_SFUNC:
	  case IVL_LPM_SHIFTL:
	  case IVL_LPM_SHIFTR:
	  case IVL_LPM_SIGN_EXT:
	  case IVL_LPM_SUB:
	  case IVL_LPM_MULT:
	  case IVL_LPM_MUX:
	  case IVL_LPM_POW:
	  case IVL_LPM_DIVIDE:
	  case IVL_LPM_MOD:
	  case IVL_LPM_UFUNC:
	  case IVL_LPM_PART_VP:
	  case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */
	  case IVL_LPM_REPEAT:
	  case IVL_LPM_SUBSTITUTE:
	    if (ivl_lpm_q(lpm) == nex) {
		  char tmp[128];
		  snprintf(tmp, sizeof tmp, "L_%p", lpm);
		  return strdup(tmp);
	    }
	    break;

      }

      fprintf(stderr, "vvp.tgt error: no input to nexus.\n");
      assert(0);
      return strdup("C<z>");
}
Exemplo n.º 28
0
static void lpm_show_mult(ivl_lpm_t net)
{
      char name[64];
      unsigned idx;

      edif_cell_t cell;
      edif_cellref_t ref;
      edif_joint_t jnt;

      sprintf(name, "mult%u", ivl_lpm_width(net));
      cell = edif_xlibrary_findcell(xlib, name);

      if (cell == 0) {
	    cell = edif_xcell_create(xlib, strdup(name),
				     3 * ivl_lpm_width(net));

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

		  sprintf(name, "Result%u", idx);
		  edif_cell_portconfig(cell, idx*3+0,
				       strdup(name),
				       IVL_SIP_OUTPUT);

		  sprintf(name, "DataA%u", idx);
		  edif_cell_portconfig(cell, idx*3+1,
				       strdup(name),
				       IVL_SIP_INPUT);

		  sprintf(name, "DataB%u", idx);
		  edif_cell_portconfig(cell, idx*3+2,
				       strdup(name),
				       IVL_SIP_INPUT);
	    }

	    edif_cell_pstring(cell,  "LPM_Type",  "LPM_MULT");
	    edif_cell_pinteger(cell, "LPM_WidthP", ivl_lpm_width(net));
	    edif_cell_pinteger(cell, "LPM_WidthA", ivl_lpm_width(net));
	    edif_cell_pinteger(cell, "LPM_WidthB", ivl_lpm_width(net));
      }

      ref = edif_cellref_create(edf, cell);

      for (idx = 0 ;  idx < ivl_lpm_width(net) ;  idx += 1) {
	    unsigned pin;
	    ivl_nexus_t nex;

	    sprintf(name, "Result%u", idx);
	    pin = edif_cell_port_byname(cell, name);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
	    edif_add_to_joint(jnt, ref, pin);

	    if ( (nex = ivl_lpm_data(net, idx)) ) {
		  sprintf(name, "DataA%u", idx);
		  pin = edif_cell_port_byname(cell, name);

		  jnt = edif_joint_of_nexus(edf, nex);
		  edif_add_to_joint(jnt, ref, pin);
	    }

	    if ( (nex = ivl_lpm_datab(net, idx)) ) {
		  sprintf(name, "DataB%u", idx);
		  pin = edif_cell_port_byname(cell, name);

		  jnt = edif_joint_of_nexus(edf, nex);
		  edif_add_to_joint(jnt, ref, pin);
	    }
      }

}
Exemplo n.º 29
0
static void lpm_show_add(ivl_lpm_t net)
{
      unsigned idx;
      unsigned cell_width;
      char cellname[32];
      edif_cell_t cell;
      edif_cellref_t ref;
      edif_joint_t jnt;

      const char*type = "ADD";

      if (ivl_lpm_type(net) == IVL_LPM_SUB)
	    type = "SUB";

	/* Figure out the width of the cell. Normally, it is the LPM
	   width known by IVL. But if the top data input bits are
	   unconnected, then we really have a width one less, and we
	   can use the cout to fill out the output width. */
      cell_width = ivl_lpm_width(net);
      if ( (ivl_lpm_data(net,cell_width-1) == 0)
	   && (ivl_lpm_datab(net,cell_width-1) == 0) )
	    cell_width -= 1;

	/* Find the correct ADD/SUB device in the library, search by
	   name. If the device is not there, then create it and put it
	   in the library. */
      sprintf(cellname, "%s%u", type, cell_width);
      cell = edif_xlibrary_findcell(xlib, cellname);

      if (cell == 0) {
	    unsigned pins = cell_width * 3 + 1;

	    cell = edif_xcell_create(xlib, strdup(cellname), pins);

	    for (idx = 0 ;  idx < cell_width ;  idx += 1) {

		  sprintf(cellname, "Result%u", idx);
		  edif_cell_portconfig(cell, idx*3+0, strdup(cellname),
				       IVL_SIP_OUTPUT);

		  sprintf(cellname, "DataA%u", idx);
		  edif_cell_portconfig(cell, idx*3+1, strdup(cellname),
				       IVL_SIP_INPUT);

		  sprintf(cellname, "DataB%u", idx);
		  edif_cell_portconfig(cell, idx*3+2, strdup(cellname),
				       IVL_SIP_INPUT);
	    }

	    edif_cell_portconfig(cell, pins-1, "Cout", IVL_SIP_OUTPUT);

	    edif_cell_pstring(cell,  "LPM_Type",      "LPM_ADD_SUB");
	    edif_cell_pstring(cell,  "LPM_Direction", type);
	    edif_cell_pinteger(cell, "LPM_Width",     ivl_lpm_width(net));
      }

      ref = edif_cellref_create(edf, cell);

	/* Connect the pins of the instance to the nexa. Access the
	   cell pins by name. */
      for (idx = 0 ;  idx < cell_width ;  idx += 1) {
	    unsigned pin;

	    sprintf(cellname, "Result%u", idx);
	    pin = edif_cell_port_byname(cell, cellname);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
	    edif_add_to_joint(jnt, ref, pin);

	    sprintf(cellname, "DataA%u", idx);
	    pin = edif_cell_port_byname(cell, cellname);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
	    edif_add_to_joint(jnt, ref, pin);

	    sprintf(cellname, "DataB%u", idx);
	    pin = edif_cell_port_byname(cell, cellname);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
	    edif_add_to_joint(jnt, ref, pin);
      }

      if (cell_width < ivl_lpm_width(net)) {
	    unsigned pin = edif_cell_port_byname(cell, "Cout");

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, cell_width));
	    edif_add_to_joint(jnt, ref, pin);
      }
}
Exemplo n.º 30
0
static void lpm_show_mux(ivl_lpm_t net)
{
      edif_cell_t cell;
      edif_cellref_t ref;
      edif_joint_t jnt;

      unsigned idx, rdx;

      char cellname[32];

      unsigned wid_r = ivl_lpm_width(net);
      unsigned wid_s = ivl_lpm_selects(net);
      unsigned wid_z = ivl_lpm_size(net);

      sprintf(cellname, "mux%u_%u_%u", wid_r, wid_s, wid_z);
      cell = edif_xlibrary_findcell(xlib, cellname);

      if (cell == 0) {
	    unsigned pins = wid_r + wid_s + wid_r*wid_z;

	    cell = edif_xcell_create(xlib, strdup(cellname), pins);

	      /* Make the output ports. */
	    for (idx = 0 ;  idx < wid_r ;  idx += 1) {
		  sprintf(cellname, "Result%u", idx);
		  edif_cell_portconfig(cell, idx, strdup(cellname),
				       IVL_SIP_OUTPUT);
	    }

	      /* Make the select ports. */
	    for (idx = 0 ;  idx < wid_s ;  idx += 1) {
		  sprintf(cellname, "Sel%u", idx);
		  edif_cell_portconfig(cell, wid_r+idx, strdup(cellname),
				       IVL_SIP_INPUT);
	    }

	    for (idx = 0 ;  idx < wid_z ; idx += 1) {
		  unsigned base = wid_r + wid_s + wid_r * idx;
		  unsigned rdx;

		  for (rdx = 0 ;  rdx < wid_r ;  rdx += 1) {
			sprintf(cellname, "Data%ux%u", idx, rdx);
			edif_cell_portconfig(cell, base+rdx, strdup(cellname),
					     IVL_SIP_INPUT);
		  }
	    }

	    edif_cell_pstring(cell,  "LPM_Type",   "LPM_MUX");
	    edif_cell_pinteger(cell, "LPM_Width",  wid_r);
	    edif_cell_pinteger(cell, "LPM_WidthS", wid_s);
	    edif_cell_pinteger(cell, "LPM_Size",   wid_z);
      }


      ref = edif_cellref_create(edf, cell);

	/* Connect the pins of the instance to the nexa. Access the
	   cell pins by name. */
      for (idx = 0 ;  idx < wid_r ;  idx += 1) {
	    unsigned pin;

	    sprintf(cellname, "Result%u", idx);
	    pin = edif_cell_port_byname(cell, cellname);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
	    edif_add_to_joint(jnt, ref, pin);
      }

      for (idx = 0 ;  idx < wid_s ;  idx += 1) {
	    unsigned pin;

	    sprintf(cellname, "Sel%u", idx);
	    pin = edif_cell_port_byname(cell, cellname);

	    jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, idx));
	    edif_add_to_joint(jnt, ref, pin);
      }

      for (idx = 0 ;  idx < wid_z ;  idx += 1) {
	    for (rdx = 0 ;  rdx < wid_r ;  rdx += 1) {
		  unsigned pin;

		  sprintf(cellname, "Data%ux%u", idx, rdx);
		  pin = edif_cell_port_byname(cell, cellname);

		  jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, idx, rdx));
		  edif_add_to_joint(jnt, ref, pin);
	    }
      }
}