/* * 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"); } }
// Concat lpm_data2 unsigned create_concat_lpm_data2(ivl_lpm_t lpm, unsigned select) { unsigned width = ivl_lpm_width(lpm); unsigned id; unsigned i; id = id_of_nexus(ivl_lpm_data2(lpm, select, 0), 0); for (i = 1; i < width; i++) { id = create_bit_concat(id, i, ivl_lpm_data2(lpm, select, i)); } return id; }
/* * 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); } }
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); } } }