Proper sliced >= comparator.

This commit is contained in:
steve 2003-03-31 00:04:21 +00:00
parent 3878f3c770
commit 2be1b1a096
1 changed files with 96 additions and 112 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: d-virtex2.c,v 1.3 2003/03/30 03:43:44 steve Exp $" #ident "$Id: d-virtex2.c,v 1.4 2003/03/31 00:04:21 steve Exp $"
#endif #endif
# include "device.h" # include "device.h"
@ -999,144 +999,125 @@ static void virtex2_cmp_ge(ivl_lpm_t net)
return; return;
} }
/* Handle the case where the device is two slices
wide. In this case, we can use a LUT4 to do all
the calculation. Use this truth table:
Q AA BB
--+------
1 | 00 00
0 | 00 01
0 | 00 10
0 | 00 11
1 | 01 00
1 | 01 01
0 | 01 10
0 | 01 11
1 | 10 00
1 | 10 01
1 | 10 10
0 | 10 11
1 | 11 xx
The I3-I0 inputs are A1 A0 B1 B0 in that order. */
check_cell_lut4();
lut = edif_cellref_create(edf, cell_lut4);
edif_cellref_pstring(lut, "INIT", "F731");
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 1));
edif_add_to_joint(jnt, lut, LUT_I3);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 1));
edif_add_to_joint(jnt, lut, LUT_I1);
/* There are only two slices, so this is all we need. */
if (ivl_lpm_width(net) == 2) { if (ivl_lpm_width(net) == 2) {
/* Handle the case where the device is two slices
wide. In this case, we can use a LUT4 to do all
the calculation. Use this truth table:
Q AA BB
--+------
1 | 00 00
0 | 00 01
0 | 00 10
0 | 00 11
1 | 01 00
1 | 01 01
0 | 01 10
0 | 01 11
1 | 10 00
1 | 10 01
1 | 10 10
0 | 10 11
1 | 11 xx
The I3-I0 inputs are A1 A0 B1 B0 in that order. */
check_cell_lut4();
lut = edif_cellref_create(edf, cell_lut4);
edif_cellref_pstring(lut, "INIT", "F731");
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0)); jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, LUT_O); 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_I2);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 1));
edif_add_to_joint(jnt, lut, LUT_I3);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 1));
edif_add_to_joint(jnt, lut, LUT_I1);
return; return;
} }
/* The general case is more complicated, but we can take /* The general case requires that we make the >= comparator
advantage of the MULTAND and MUXCY devices to pack two bit from slices. This is an iterative design. Each slice has
slices of input into each LUT4 device. The logic works like the truth table:
this:
The goal is to calculate: An Bn | A >= B
------+-------
0 0 | CI
0 1 | 0
1 0 | 1
1 1 | CI
A >= B. The CI for each slice is the output of the compare of the
next less significant bits. We get this truth table by
connecting a LUT2 to the S input of a MUXCY. When the S
input is (1), it propagates its CI. This suggests that the
init value for the LUT be "9" (XNOR).
This is the same as the expression: When the MUXCY S input is 0, it propagates a local
input. We connect to that input An, and we get the desired
and complete truth table for a slice.
~(A < B) This iterative definition needs to terminate at the least
significant bits. In fact, we have a non-iterative was to
deal with the two least significant slices. We take the
output of the LUT4 device for the least significant bits,
and use that to generate the initial CI for the chain. */
so the problem is changed to calculating A < B an inverting check_cell_lut2();
the result. In fact, A<B can be further transformed to the check_cell_muxcy();
expression: check_cell_muxcy_l();
B-A > 0 muxcy_prev = edif_cellref_create(edf, cell_muxcy_l);
jnt = edif_joint_create(edf);
This can in fact be implemented using carry chain edif_add_to_joint(jnt, lut, LUT_O);
arithmetic. Each bit slice of a normal subtractor uses a edif_add_to_joint(jnt, muxcy_prev, MUXCY_S);
LUT2, a MUXCY and an XORCY. However, since we do not care { edif_cellref_t p0 = edif_cellref_create(edf, cell_0);
about the result of the subtract (only whether it edif_cellref_t p1 = edif_cellref_create(edf, cell_0);
overflows) then we can skip the XORCY. jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, p0, 0);
edif_add_to_joint(jnt, muxcy_prev, MUXCY_DI);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, p1, 0);
edif_add_to_joint(jnt, muxcy_prev, MUXCY_CI);
}
Furthermore, pairs of LUT2 and MUXCY devices can be reduced for (idx = 2 ; idx < ivl_lpm_width(net) ; idx += 1) {
to a single LUT4, MUXCY and MULTAND device. */ edif_cellref_t muxcy;
/* For now, only support even widths. */ lut = edif_cellref_create(edf, cell_lut2);
assert(ivl_lpm_width(net)%2 == 0);
muxcy_prev = 0;
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 2) {
edif_cellref_t muxcy, multand;
check_cell_lut4();
check_cell_muxcy();
check_cell_mult_and();
lut = edif_cellref_create(edf, cell_lut4);
muxcy = edif_cellref_create(edf, cell_muxcy); muxcy = edif_cellref_create(edf, cell_muxcy);
multand = edif_cellref_create(edf, cell_mult_and); edif_cellref_pstring(lut, "INIT", "9");
edif_cellref_pstring(lut, "INIT", "8421");
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx+0));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx+1));
edif_add_to_joint(jnt, lut, LUT_I3);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx+0));
edif_add_to_joint(jnt, lut, LUT_I0);
edif_add_to_joint(jnt, multand, MULT_AND_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx+1));
edif_add_to_joint(jnt, lut, LUT_I1);
edif_add_to_joint(jnt, multand, MULT_AND_I1);
jnt = edif_joint_create(edf); jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, lut, LUT_O); edif_add_to_joint(jnt, lut, LUT_O);
edif_add_to_joint(jnt, muxcy, MUXCY_S); edif_add_to_joint(jnt, muxcy, MUXCY_S);
jnt = edif_joint_create(edf); jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, multand, MULT_AND_LO); edif_add_to_joint(jnt, muxcy, MUXCY_CI);
edif_add_to_joint(jnt, muxcy, MUXCY_DI); edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
if (idx == 0) { jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
muxcy_prev = edif_cellref_create(edf, cell_1); edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_create(edf); edif_add_to_joint(jnt, muxcy, MUXCY_DI);
edif_add_to_joint(jnt, muxcy_prev, 0);
edif_add_to_joint(jnt, muxcy, MUXCY_CI); jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
} else { edif_add_to_joint(jnt, lut, LUT_I1);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
}
muxcy_prev = muxcy; muxcy_prev = muxcy;
} }
/* At this point, muxcy_prev[MUXCY_O] in the truth of the
expression B-A > 0. Connect an inverter to this and we get
our desired result. */
check_cell_inv();
lut = edif_cellref_create(edf, cell_inv);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
edif_add_to_joint(jnt, lut, BUF_I);
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0)); jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, BUF_O); edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
} }
const struct device_s d_virtex2_edif = { const struct device_s d_virtex2_edif = {
@ -1158,6 +1139,9 @@ const struct device_s d_virtex2_edif = {
/* /*
* $Log: d-virtex2.c,v $ * $Log: d-virtex2.c,v $
* Revision 1.4 2003/03/31 00:04:21 steve
* Proper sliced >= comparator.
*
* Revision 1.3 2003/03/30 03:43:44 steve * Revision 1.3 2003/03/30 03:43:44 steve
* Handle wide ports of macros. * Handle wide ports of macros.
* *