Add == and some lut logic.

This commit is contained in:
steve 2003-04-04 06:20:29 +00:00
parent 6495d0bd5d
commit 882c46437c
1 changed files with 240 additions and 65 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: d-virtex2.c,v 1.7 2003/04/04 04:59:03 steve Exp $"
#ident "$Id: d-virtex2.c,v 1.8 2003/04/04 06:20:29 steve Exp $"
#endif
# include "device.h"
@ -85,10 +85,6 @@ const unsigned XORCY_O = 0;
const unsigned XORCY_CI = 1;
const unsigned XORCY_LI = 2;
const unsigned MULT_AND_LO = 0;
const unsigned MULT_AND_I0 = 1;
const unsigned MULT_AND_I1 = 2;
/*
* The check_cell_* functions can be called in front of any reference
* to the matching cell_* variable to make sure the cell type has been
@ -236,6 +232,10 @@ static void check_cell_xorcy(void)
}
const unsigned MULT_AND_LO = 0;
const unsigned MULT_AND_I0 = 1;
const unsigned MULT_AND_I1 = 2;
static edif_cell_t celltable_mult_and(edif_xlibrary_t xlib)
{
edif_cell_t cell = edif_xcell_create(xlib, "MULT_AND", 3);
@ -509,6 +509,57 @@ static void edif_cellref_logic(ivl_net_logic_t net, const char*def)
free(str);
}
static void lut_logic(ivl_net_logic_t net, const char*init3,
const char*init4, const char*init5)
{
edif_cellref_t lut;
edif_joint_t jnt;
const char* init;
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
switch (ivl_logic_pins(net)) {
case 3:
check_cell_lut2();
lut = edif_cellref_create(edf, cell_lut2);
init = init3;
break;
case 4:
check_cell_lut3();
lut = edif_cellref_create(edf, cell_lut3);
init = init4;
break;
case 5:
check_cell_lut4();
lut = edif_cellref_create(edf, cell_lut4);
init = init5;
break;
}
edif_cellref_pstring(lut, "INIT", init);
switch (ivl_logic_pins(net)) {
case 5:
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 4));
edif_add_to_joint(jnt, lut, LUT_I3);
case 4:
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 3));
edif_add_to_joint(jnt, lut, LUT_I2);
case 3:
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, lut, LUT_I1);
}
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
}
static void virtex2_logic(ivl_net_logic_t net)
{
edif_cellref_t obj;
@ -537,69 +588,34 @@ static void virtex2_logic(ivl_net_logic_t net)
edif_add_to_joint(jnt, obj, BUF_I);
break;
case IVL_LO_AND:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "8", "80", "8000");
break;
case IVL_LO_NOR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "1", "01", "0001");
break;
case IVL_LO_OR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "E", "FE", "FFFE");
break;
switch (ivl_logic_pins(net)) {
case IVL_LO_XNOR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "9", "69", "9669");
break;
case 3:
check_cell_lut2();
obj = edif_cellref_create(edf, cell_lut2);
edif_cellref_pstring(obj, "INIT", "E");
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, obj, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, obj, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, obj, LUT_I1);
break;
case 4:
check_cell_lut3();
obj = edif_cellref_create(edf, cell_lut3);
edif_cellref_pstring(obj, "INIT", "FE");
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, obj, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, obj, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, obj, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 3));
edif_add_to_joint(jnt, obj, LUT_I2);
break;
case 5:
check_cell_lut4();
obj = edif_cellref_create(edf, cell_lut4);
edif_cellref_pstring(obj, "INIT", "FFFE");
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, obj, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, obj, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, obj, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 3));
edif_add_to_joint(jnt, obj, LUT_I2);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 4));
edif_add_to_joint(jnt, obj, LUT_I3);
break;
default:
assert(0);
}
case IVL_LO_XOR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "6", "96", "6996");
break;
default:
@ -968,6 +984,162 @@ static void virtex2_add(ivl_lpm_t net)
}
/*
* This method handles both == and != operators, the identity
* comparison operators.
*
* If the identity compare is applied to small enough input vectors,
* it is shoved into a single LUT. Otherwise, it is strung out into a
* row of LUT devices chained together by carry muxes. The output of
* the comparison is the output of the last mux.
*
* When the compare is small, a LUT is generated with the appropriate
* truth table to cause an == or != result.
*
* When the compare is too wide for a single LUT, then it is made into
* a chain connected by a string of carry mux devices. Each LUT
* implements == for up to two pairs of bits, even if the final output
* is supposed to be !=. The LUT output is connected to an associated
* MUX select input. The CO output of each muxcy is passed up to the
* next higher order bits of the compare.
*
* For identity == compare, a != output from the LUT selects the DI
* input of the muxcy, generating a 0 output that is passed up. Since
* the next higher muxcy now gets a 0 input to both DI and CI, the
* output of the next higher muxcy is guaranteed to be 0, and so on to
* the final output of the carry chain. If the output from a LUT is ==,
* then the CI input of the muxcy is selected and the truth of this
* level depends on lower order bits. The least significan muxcy is
* connected to GND and VCC so that its CO follows the least
* significant LUT.
*
* Identity != is the same as == except that the output is
* inverted. To get that effect without putting an inverter on the
* output of the top muxcy pin CO (which would cost a LUT) the DI
* inputs are all connected to VCC instead of GND, and the CI of the
* least significant muxcy is connected to GND instead of VCC.
*/
static void virtex_eq(ivl_lpm_t net)
{
edif_cellref_t lut, mux, mux_prev;
edif_joint_t jnt, jnt_di;
unsigned idx;
/* True if I'm implementing CMP_EQ instead of CMP_NE */
int eq = 1;
assert(ivl_lpm_width(net) >= 1);
if (ivl_lpm_type(net) == IVL_LPM_CMP_NE)
eq = 0;
switch (ivl_lpm_width(net)) {
case 1:
check_cell_lut2();
lut = edif_cellref_create(edf, cell_lut2);
edif_cellref_pstring(lut, "INIT", eq? "9" : "6");
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I1);
return;
case 2:
check_cell_lut4();
lut = edif_cellref_create(edf, cell_lut4);
edif_cellref_pstring(lut, "INIT", eq? "9009" : "6FF6");
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 1));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 1));
edif_add_to_joint(jnt, lut, LUT_I3);
return;
default:
check_cell_lut2();
check_cell_lut4();
check_cell_muxcy();
{ edif_cellref_t di;
di = edif_cellref_create(edf, eq? cell_0 : cell_1);
jnt_di = edif_joint_create(edf);
edif_add_to_joint(jnt_di, di, 0);
}
mux_prev = 0;
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 2) {
int subwid = 2;
if ((idx + 1) == ivl_lpm_width(net))
subwid = 1;
mux = edif_cellref_create(edf, cell_muxcy);
if (subwid == 2) {
lut = edif_cellref_create(edf, cell_lut4);
edif_cellref_pstring(lut, "INIT", eq? "9009" : "6FF6");
} else {
lut = edif_cellref_create(edf, cell_lut2);
edif_cellref_pstring(lut, "INIT", eq? "9" : "6");
}
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, lut, LUT_O);
edif_add_to_joint(jnt, mux, MUXCY_S);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
edif_add_to_joint(jnt, lut, LUT_I1);
if (subwid > 1) {
jnt = edif_joint_of_nexus(edf,
ivl_lpm_data(net, idx+1));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf,
ivl_lpm_datab(net, idx+1));
edif_add_to_joint(jnt, lut, LUT_I3);
}
edif_add_to_joint(jnt_di, mux, MUXCY_DI);
if (mux_prev) {
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, mux, MUXCY_CI);
edif_add_to_joint(jnt, mux_prev, MUXCY_O);
} else {
edif_cellref_t ci;
ci = edif_cellref_create(edf, eq? cell_1 : cell_0);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, ci, 0);
edif_add_to_joint(jnt, mux, MUXCY_CI);
}
mux_prev = mux;
}
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, mux_prev, MUXCY_O);
return;
}
}
/*
* Implement hardware for the device (A >= B). We use LUT devices if
* it can handle the slices, or carry chain logic if the slices must
@ -1139,8 +1311,8 @@ const struct device_s d_virtex2_edif = {
virtex2_pad,
virtex2_logic,
virtex2_generic_dff,
0,
0,
virtex_eq,
virtex_eq,
virtex2_cmp_ge,
0,
virtex2_add,
@ -1152,6 +1324,9 @@ const struct device_s d_virtex2_edif = {
/*
* $Log: d-virtex2.c,v $
* Revision 1.8 2003/04/04 06:20:29 steve
* Add == and some lut logic.
*
* Revision 1.7 2003/04/04 04:59:03 steve
* Add xlibrary celltable.
*