Beispiel #1
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);
      }
}
Beispiel #2
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");
    }
}
Beispiel #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;
      }
}
Beispiel #4
0
/*
* The read port to an array is generated as a single record that takes
* the address as an input.
*/
static void draw_lpm_array(ivl_lpm_t net)
{
      ivl_nexus_t nex;
      ivl_signal_t mem = ivl_lpm_array(net);
      const char*tmp;

      nex = ivl_lpm_select(net);
      tmp = draw_net_input(nex);

      fprintf(vvp_out, "L_%p .array/port v%p, %s;\n", net, mem, tmp);
}
Beispiel #5
0
// Mux tree.
unsigned create_mux(ivl_lpm_t lpm, unsigned select_width, unsigned select_number)
{
  unsigned id;
  if (select_width == 0) {
    id = create_concat_lpm_data2(lpm, select_number);
  }
  else {
    unsigned width = ivl_lpm_width(lpm);
    unsigned select = id_of_nexus(ivl_lpm_select(lpm, select_width - 1), 0);
    unsigned data_0 = create_mux(lpm, select_width - 1, select_number << 1);
    unsigned data_1 = create_mux(lpm, select_width - 1, (select_number << 1) | 1);
    id = new_id();
    indent();
    fprintf(output, "  (mux    %i %i %i %i %i)\n", id, width, select, data_0, data_1);
  }
  return id;
}
Beispiel #6
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;
	    }
      }
}
Beispiel #7
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);
	    }
      }
}