Add Xilinx virtex as a reference EDIF device.
This commit is contained in:
parent
4a3f1a3641
commit
bfabeab6b9
|
|
@ -24,7 +24,7 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.1.2.2 2005/09/25 16:35:36 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
|
@ -61,7 +61,7 @@ dep:
|
|||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
D = d-lpm.o
|
||||
D = d-lpm.o d-virtex.o xilinx.o
|
||||
O = edif.o device.o target.o gates.o generic.o $D
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,872 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams (steve@icarus.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-virtex.c,v 1.1.2.1 2005/09/25 16:35:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the driver for Xilinx Virtex style FPGA devices. The device
|
||||
* table structure at the bottom of this file lists all the various
|
||||
* functions that are used to generate code for virtex devices. In
|
||||
* some cases this table uses entries that are common to all Xilinx
|
||||
* devices, and in some cases Virtex specific entries are used. The
|
||||
* Virtex specific functions are given here, the xilinx_* common
|
||||
* functions are in the xilinx.{hc} source files.
|
||||
*/
|
||||
|
||||
# include "device.h"
|
||||
# include "edif.h"
|
||||
# include "generic.h"
|
||||
# include "xilinx.h"
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* This is a table of cell types that are accessible via the cellref
|
||||
* attribute to a gate.
|
||||
*/
|
||||
const static struct edif_xlib_celltable virtex_celltable[] = {
|
||||
{ "BUFG", xilinx_cell_bufg },
|
||||
{ "MULT_AND", xilinx_cell_mult_and },
|
||||
{ 0, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* The show_header function is called before any of the devices of the
|
||||
* netlist are scanned.
|
||||
*
|
||||
* In this function, we look at the ports of the root module to decide
|
||||
* if they are to be made into ports. Modules that have PAD attributes
|
||||
* are *not* to be used as ports, they will be connected to special
|
||||
* PAD devices instead.
|
||||
*/
|
||||
static void virtex_show_header(ivl_design_t des)
|
||||
{
|
||||
const char*part_str = 0;
|
||||
|
||||
xilinx_common_header(des);
|
||||
|
||||
xlib = edif_xlibrary_create(edf, "VIRTEX");
|
||||
edif_xlibrary_set_celltable(xlib, virtex_celltable);
|
||||
|
||||
|
||||
if ( (part_str = ivl_design_flag(des, "part")) && (part_str[0] != 0) ) {
|
||||
edif_pstring(edf, "PART", part_str);
|
||||
}
|
||||
|
||||
cell_0 = edif_xcell_create(xlib, "GND", 1);
|
||||
edif_cell_portconfig(cell_0, 0, "GROUND", IVL_SIP_OUTPUT);
|
||||
|
||||
cell_1 = edif_xcell_create(xlib, "VCC", 1);
|
||||
edif_cell_portconfig(cell_1, 0, "VCC", IVL_SIP_OUTPUT);
|
||||
|
||||
}
|
||||
|
||||
static void virtex_or_wide(ivl_net_logic_t net)
|
||||
{
|
||||
edif_cell_t cell_muxcy_l = xilinx_cell_muxcy_l(xlib);
|
||||
edif_cell_t cell_muxcy = xilinx_cell_muxcy(xlib);
|
||||
edif_cell_t cell_lut4 = xilinx_cell_lut4(xlib);
|
||||
|
||||
edif_cellref_t true_out, false_out;
|
||||
edif_cellref_t lut, muxcy, muxcy_down=NULL;
|
||||
edif_joint_t jnt;
|
||||
|
||||
unsigned idx, inputs, lut4_cnt;
|
||||
|
||||
if (ivl_logic_type(net) == IVL_LO_OR) {
|
||||
true_out = edif_cellref_create(edf, cell_1);
|
||||
false_out = edif_cellref_create(edf, cell_0);
|
||||
} else {
|
||||
true_out = edif_cellref_create(edf, cell_0);
|
||||
false_out = edif_cellref_create(edf, cell_1);
|
||||
}
|
||||
|
||||
inputs = ivl_logic_pins(net) - 1;
|
||||
lut4_cnt = (inputs-1)/4;
|
||||
|
||||
for (idx = 0 ; idx < lut4_cnt ; idx += 1) {
|
||||
muxcy = edif_cellref_create(edf, cell_muxcy_l);
|
||||
lut = edif_cellref_create(edf, cell_lut4);
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "0001");
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, true_out, 0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+2));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+3));
|
||||
edif_add_to_joint(jnt, lut, LUT_I3);
|
||||
|
||||
if (idx > 0) {
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, muxcy_down, MUXCY_O);
|
||||
} else {
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, false_out, 0);
|
||||
}
|
||||
|
||||
muxcy_down = muxcy;
|
||||
}
|
||||
|
||||
muxcy = edif_cellref_create(edf, cell_muxcy);
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, true_out, 0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, muxcy_down, MUXCY_O);
|
||||
|
||||
switch (ivl_logic_pins(net) - 1 - lut4_cnt*4) {
|
||||
|
||||
case 1:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_inv(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, BUF_I);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "1");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "01");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
lut = edif_cellref_create(edf, cell_lut4);
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "0001");
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+3));
|
||||
edif_add_to_joint(jnt, lut, LUT_I3);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_O);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick off the cases where there is a Virtex specific implementation
|
||||
* that is better then the generic Xilinx implementation. Route the
|
||||
* remaining to the base xilinx_logic implementation.
|
||||
*/
|
||||
void virtex_logic(ivl_net_logic_t net)
|
||||
{
|
||||
/* Nothing I can do if the user expresses a specific
|
||||
opinion. The cellref attribute forces me to let the base
|
||||
xilinx_logic take care of it. */
|
||||
if (ivl_logic_attr(net, "cellref")) {
|
||||
xilinx_logic(net);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ivl_logic_type(net)) {
|
||||
|
||||
case IVL_LO_OR:
|
||||
case IVL_LO_NOR:
|
||||
if (ivl_logic_pins(net) <= 5) {
|
||||
xilinx_logic(net);
|
||||
|
||||
} else {
|
||||
virtex_or_wide(net);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
xilinx_logic(net);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void virtex_generic_dff(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
ivl_nexus_t aclr = ivl_lpm_async_clr(net);
|
||||
ivl_nexus_t aset = ivl_lpm_async_set(net);
|
||||
ivl_nexus_t sclr = ivl_lpm_sync_clr(net);
|
||||
ivl_nexus_t sset = ivl_lpm_sync_set(net);
|
||||
const char*abits = 0;
|
||||
|
||||
if (aset) {
|
||||
ivl_expr_t avalue = ivl_lpm_aset_value(net);
|
||||
assert(avalue);
|
||||
abits = ivl_expr_bits(avalue);
|
||||
assert(abits);
|
||||
}
|
||||
|
||||
/* XXXX Can't handle both synchronous and asynchronous clear. */
|
||||
assert( ! (aclr && sclr) );
|
||||
/* XXXX Can't handle synchronous set at all. */
|
||||
assert( ! sset );
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
edif_cellref_t obj;
|
||||
ivl_nexus_t nex;
|
||||
edif_joint_t jnt;
|
||||
|
||||
/* If there is a preset, then select an FDCPE instead of
|
||||
an FDCE device. */
|
||||
if (aset && (abits[idx] == '1')) {
|
||||
obj = edif_cellref_create(edf, xilinx_cell_fdcpe(xlib));
|
||||
} else if (aclr) {
|
||||
obj = edif_cellref_create(edf, xilinx_cell_fdce(xlib));
|
||||
} else if (sclr) {
|
||||
obj = edif_cellref_create(edf, xilinx_cell_fdre(xlib));
|
||||
} else {
|
||||
obj = edif_cellref_create(edf, xilinx_cell_fdce(xlib));
|
||||
}
|
||||
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, obj, FDCE_Q);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, obj, FDCE_D);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net));
|
||||
edif_add_to_joint(jnt, obj, FDCE_C);
|
||||
|
||||
if ( (nex = ivl_lpm_enable(net)) ) {
|
||||
jnt = edif_joint_of_nexus(edf, nex);
|
||||
edif_add_to_joint(jnt, obj, FDCE_CE);
|
||||
}
|
||||
|
||||
if (aclr) {
|
||||
jnt = edif_joint_of_nexus(edf, aclr);
|
||||
edif_add_to_joint(jnt, obj, FDCE_CLR);
|
||||
} else if (sclr) {
|
||||
jnt = edif_joint_of_nexus(edf, sclr);
|
||||
edif_add_to_joint(jnt, obj, FDCE_CLR);
|
||||
}
|
||||
|
||||
if (aset) {
|
||||
if (abits[idx] == '1') {
|
||||
jnt = edif_joint_of_nexus(edf, aset);
|
||||
edif_add_to_joint(jnt, obj, FDCE_PRE);
|
||||
} else {
|
||||
assert(aclr == 0);
|
||||
jnt = edif_joint_of_nexus(edf, aset);
|
||||
edif_add_to_joint(jnt, obj, FDCE_CLR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 significant 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. The LUT
|
||||
* expressions for the chained compare are configured for ==, with the
|
||||
* changed CI/DI inputs performing the inversion.
|
||||
*/
|
||||
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:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
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:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
|
||||
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:
|
||||
{ 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, xilinx_cell_muxcy(xlib));
|
||||
if (subwid == 2) {
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "9009");
|
||||
} else {
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "9");
|
||||
}
|
||||
|
||||
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
|
||||
* span LUT devices.
|
||||
*/
|
||||
void virtex_ge(ivl_lpm_t net)
|
||||
{
|
||||
edif_cellref_t muxcy_prev;
|
||||
edif_cellref_t lut;
|
||||
edif_joint_t jnt;
|
||||
unsigned idx;
|
||||
|
||||
if (ivl_lpm_width(net) == 1) {
|
||||
|
||||
/* If the comparator is a single bit, then use a LUT2
|
||||
with this truth table:
|
||||
|
||||
Q A B
|
||||
--+----
|
||||
1 | 0 0
|
||||
0 | 0 1
|
||||
1 | 1 0
|
||||
1 | 1 1
|
||||
|
||||
Connect the A value to I1 and the B value to I0. */
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "D");
|
||||
|
||||
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_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
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. */
|
||||
|
||||
assert(ivl_lpm_width(net) >= 2);
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
|
||||
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) {
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
return;
|
||||
}
|
||||
|
||||
/* The general case requires that we make the >= comparator
|
||||
from slices. This is an iterative design. Each slice has
|
||||
the truth table:
|
||||
|
||||
An Bn | A >= B
|
||||
------+-------
|
||||
0 0 | CI
|
||||
0 1 | 0
|
||||
1 0 | 1
|
||||
1 1 | CI
|
||||
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
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. */
|
||||
|
||||
|
||||
muxcy_prev = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
|
||||
jnt = edif_joint_create(edf);
|
||||
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, muxcy_prev, MUXCY_S);
|
||||
{ edif_cellref_t p0 = edif_cellref_create(edf, cell_0);
|
||||
edif_cellref_t p1 = edif_cellref_create(edf, cell_1);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for (idx = 2 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
edif_cellref_t muxcy;
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", "9");
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
muxcy_prev = muxcy;
|
||||
}
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
void virtex_mux(ivl_lpm_t net)
|
||||
{
|
||||
|
||||
switch (ivl_lpm_selects(net)) {
|
||||
|
||||
case 2:
|
||||
virtex_mux4(net);
|
||||
break;
|
||||
|
||||
default:
|
||||
xilinx_mux(net);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function generates ADD/SUB devices for Virtex devices,
|
||||
* based on the documented implementations of ADD8/ADD16, etc., from
|
||||
* the Libraries Guide.
|
||||
*
|
||||
* Each slice of the ADD/SUB device is made from a LUT2 device, an
|
||||
* XORCY device that mixes with the LUT2 to make a full adder, and a
|
||||
* MUXCY_L to propagate the carry. The most significant slice does not
|
||||
* have a carry to propagate, so has no MUXCY_L.
|
||||
*
|
||||
* If the device is a wide adder, then the LUT2 devices are configured
|
||||
* to implement an XOR function and a zero is pumped into the least
|
||||
* significant carry input.
|
||||
*
|
||||
* If the device is really an adder, then the input is turned into an
|
||||
* XNOR, which takes a 1-s complement of the B input. Pump a 1 into
|
||||
* the LSB carry input to finish converting the B input into the 2s
|
||||
* complement.
|
||||
*/
|
||||
void virtex_add(ivl_lpm_t net)
|
||||
{
|
||||
const char*ha_init = 0;
|
||||
edif_cellref_t lut, xorcy, muxcy, pad;
|
||||
edif_joint_t jnt;
|
||||
|
||||
unsigned idx;
|
||||
|
||||
if (ivl_lpm_width(net) < 2) {
|
||||
xilinx_add(net);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_ADD:
|
||||
ha_init = "6";
|
||||
break;
|
||||
case IVL_LPM_SUB:
|
||||
ha_init = "9";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
assert(ivl_lpm_width(net) > 1);
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
xorcy = edif_cellref_create(edf, xilinx_cell_xorcy(xlib));
|
||||
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", ha_init);
|
||||
|
||||
/* The bottom carry-in takes a constant that primes the add or
|
||||
subtract. */
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_ADD:
|
||||
pad = edif_cellref_create(edf, cell_0);
|
||||
break;
|
||||
|
||||
case IVL_LPM_SUB:
|
||||
pad = edif_cellref_create(edf, cell_1);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_CI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_O);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_LI);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
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);
|
||||
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
for (idx = 1 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
edif_cellref_t muxcy0 = muxcy;
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
xorcy = edif_cellref_create(edf, xilinx_cell_xorcy(xlib));
|
||||
edif_cellref_pstring(lut, "INIT", ha_init);
|
||||
|
||||
/* If this is the last bit, then there is no further
|
||||
propagation in the carry chain, and I can skip the
|
||||
carry mux MUXCY. */
|
||||
if ((idx+1) < ivl_lpm_width(net))
|
||||
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
|
||||
else
|
||||
muxcy = 0;
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, muxcy0, MUXCY_O);
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_CI);
|
||||
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_CI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_O);
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_add_to_joint(jnt, xorcy, XORCY_LI);
|
||||
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_S);
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_DI);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const struct device_s d_virtex_edif = {
|
||||
virtex_show_header,
|
||||
xilinx_show_footer,
|
||||
xilinx_show_scope,
|
||||
xilinx_pad,
|
||||
virtex_logic,
|
||||
virtex_generic_dff,
|
||||
virtex_eq,
|
||||
virtex_eq,
|
||||
virtex_ge,
|
||||
0, /* show_cmp_gt */
|
||||
virtex_mux,
|
||||
virtex_add,
|
||||
virtex_add,
|
||||
xilinx_shiftl,
|
||||
0, /* show_shiftr */
|
||||
0, /* show_mult */
|
||||
0 /* show_constant */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: d-virtex.c,v $
|
||||
* Revision 1.1.2.1 2005/09/25 16:35:36 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: edif.h,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
|
||||
#ident "$Id: edif.h,v 1.1.2.2 2005/09/25 16:35:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -239,8 +239,21 @@ extern void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex);
|
|||
*/
|
||||
extern void edif_print(FILE*fd, edif_t design);
|
||||
|
||||
/*
|
||||
* This is the fd that should be passed to the edif_print
|
||||
* function. The name "xnf" is historical. This function is opened and
|
||||
* closed automatically by the edif core (the target_design function)
|
||||
* so generally there is no other use then the edif_print for this
|
||||
* exposed fd.
|
||||
*/
|
||||
extern FILE*xnf;
|
||||
|
||||
|
||||
/*
|
||||
* $Log: edif.h,v $
|
||||
* Revision 1.1.2.2 2005/09/25 16:35:36 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -27,16 +27,12 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: edif_priv.h,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
|
||||
#ident "$Id: edif_priv.h,v 1.1.2.2 2005/09/25 16:35:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
# include "device.h"
|
||||
|
||||
/* This is the opened xnf file descriptor. It is the output that this
|
||||
code generator writes to, whether the format is XNF or EDIF. */
|
||||
extern FILE*xnf;
|
||||
|
||||
extern int show_scope_gates(ivl_scope_t net, void*x);
|
||||
|
||||
|
||||
|
|
@ -61,6 +57,9 @@ extern const char*xnf_mangle_nexus_name(ivl_nexus_t net);
|
|||
|
||||
/*
|
||||
* $Log: edif_priv.h,v $
|
||||
* Revision 1.1.2.2 2005/09/25 16:35:36 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: tables.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
|
||||
#ident "$Id: tables.c,v 1.1.2.2 2005/09/25 16:35:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "device.h"
|
||||
|
|
@ -39,14 +39,19 @@
|
|||
* it via the -parch=<foo> command line switch.
|
||||
*/
|
||||
extern const struct device_s d_lpm_edif;
|
||||
extern const struct device_s d_virtex_edif;
|
||||
|
||||
const struct device_table_s edif_device_table[] = {
|
||||
{ "lpm", &d_lpm_edif },
|
||||
{ "virtex",&d_virtex_edif },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: tables.c,v $
|
||||
* Revision 1.1.2.2 2005/09/25 16:35:37 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
|
||||
* Add the tgt-edif target.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,980 @@
|
|||
/*
|
||||
* Copyright (c) 2005 Stephen Williams (steve at icarus.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: xilinx.c,v 1.1.2.1 2005/09/25 16:35:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This source file contains common functions used by Xilinx
|
||||
* devices. The functions here do not support any specific Xilinx part
|
||||
* fimily, but instead provide some core functions that are used by
|
||||
* specific devices.
|
||||
*
|
||||
* For example, some xilinx_* functions are suitable for placing
|
||||
* directly in a device_s table, but there is no "xilinx"
|
||||
* device. These functions can be placed in the tables for devices
|
||||
* that have no better way to handle the device_s function, or these
|
||||
* functions can be called by device specific device_s functions that
|
||||
* fall back on the generic handling in certain cases. For an example
|
||||
* of both cases, see d-virtex.c.
|
||||
*/
|
||||
|
||||
# include "edif.h"
|
||||
# include "generic.h"
|
||||
# include "xilinx.h"
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <assert.h>
|
||||
|
||||
edif_cell_t xilinx_cell_buf(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "BUF", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "BUFE", 3);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, BUF_T, "E", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "BUFG", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "BUFT", 3);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, BUF_T, "T", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "IBUF", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_inv(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "INV", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MUXF5", 4);
|
||||
edif_cell_portconfig(cell, MUXF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MUXF_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXF_I1, "I1", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXF_S, "S", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MUXF6", 4);
|
||||
edif_cell_portconfig(cell, MUXF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MUXF_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXF_I1, "I1", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXF_S, "S", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "OBUF", 2);
|
||||
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "LUT2", 3);
|
||||
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "LUT3", 4);
|
||||
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I2, "I2", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "LUT4", 5);
|
||||
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I2, "I2", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, LUT_I3, "I3", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "FDCE", 5);
|
||||
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CLR,"CLR", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "FDCPE", 6);
|
||||
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CLR,"CLR", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_PRE,"PRE", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "FDRE", 5);
|
||||
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, FDCE_CLR,"R", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MULT_AND", 3);
|
||||
edif_cell_portconfig(cell, MULT_AND_LO, "LO", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MULT_AND_I0, "I0", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MULT_AND_I1, "I1", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MUXCY", 4);
|
||||
edif_cell_portconfig(cell, MUXCY_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_DI, "DI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_CI, "CI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_S, "S", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "MUXCY_L", 4);
|
||||
edif_cell_portconfig(cell, MUXCY_O, "LO", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_DI, "DI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_CI, "CI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, MUXCY_S, "S", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib)
|
||||
{
|
||||
static edif_cell_t cell = 0;
|
||||
if (cell != 0) return cell;
|
||||
|
||||
cell = edif_xcell_create(xlib, "XORCY", 3);
|
||||
edif_cell_portconfig(cell, XORCY_O, "O", IVL_SIP_OUTPUT);
|
||||
edif_cell_portconfig(cell, XORCY_CI, "CI", IVL_SIP_INPUT);
|
||||
edif_cell_portconfig(cell, XORCY_LI, "LI", IVL_SIP_INPUT);
|
||||
return cell;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function does a lot of the stuff common to the header
|
||||
* functions of various Xilinx familes. This includes creating the edf
|
||||
* object that holds the netlist.
|
||||
*/
|
||||
void xilinx_common_header(ivl_design_t des)
|
||||
{
|
||||
unsigned idx;
|
||||
ivl_scope_t root = ivl_design_root(des);
|
||||
unsigned sig_cnt = ivl_scope_sigs(root);
|
||||
unsigned nports = 0, pidx;
|
||||
|
||||
/* Count the ports I'm going to use. */
|
||||
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
|
||||
ivl_signal_t sig = ivl_scope_sig(root, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_attr(sig, "PAD") != 0)
|
||||
continue;
|
||||
|
||||
nports += ivl_signal_pins(sig);
|
||||
}
|
||||
|
||||
edf = edif_create(ivl_scope_basename(root), nports);
|
||||
|
||||
pidx = 0;
|
||||
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
ivl_signal_t sig = ivl_scope_sig(root, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_attr(sig, "PAD") != 0)
|
||||
continue;
|
||||
|
||||
if (ivl_signal_pins(sig) == 1) {
|
||||
edif_portconfig(edf, pidx, ivl_signal_basename(sig),
|
||||
ivl_signal_port(sig));
|
||||
|
||||
assert(ivl_signal_pins(sig) == 1);
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
|
||||
edif_port_to_joint(jnt, edf, pidx);
|
||||
|
||||
} else {
|
||||
const char*name = ivl_signal_basename(sig);
|
||||
ivl_signal_port_t dir = ivl_signal_port(sig);
|
||||
char buf[128];
|
||||
unsigned bit;
|
||||
for (bit = 0 ; bit < ivl_signal_pins(sig) ; bit += 1) {
|
||||
const char*tmp;
|
||||
sprintf(buf, "%s[%u]", name, bit);
|
||||
tmp = strdup(buf);
|
||||
edif_portconfig(edf, pidx+bit, tmp, dir);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit));
|
||||
edif_port_to_joint(jnt, edf, pidx+bit);
|
||||
}
|
||||
}
|
||||
|
||||
pidx += ivl_signal_pins(sig);
|
||||
}
|
||||
|
||||
assert(pidx == nports);
|
||||
}
|
||||
|
||||
void xilinx_show_footer(ivl_design_t des)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0 ; idx < ivl_design_consts(des) ; idx += 1) {
|
||||
unsigned pin;
|
||||
ivl_net_const_t net = ivl_design_const(des, idx);
|
||||
const char*val = ivl_const_bits(net);
|
||||
|
||||
for (pin = 0 ; pin < ivl_const_pins(net) ; pin += 1) {
|
||||
edif_joint_t jnt;
|
||||
edif_cellref_t pad;
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_const_pin(net, pin));
|
||||
switch (val[pin]) {
|
||||
case '0':
|
||||
pad = edif_cellref_create(edf, cell_0);
|
||||
break;
|
||||
case '1':
|
||||
pad = edif_cellref_create(edf, cell_1);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
}
|
||||
}
|
||||
|
||||
edif_print(xnf, edf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make (or retrieve) a cell in the external library that reflects the
|
||||
* scope with its ports.
|
||||
*/
|
||||
void xilinx_show_scope(ivl_scope_t scope)
|
||||
{
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
|
||||
unsigned port, idx;
|
||||
|
||||
cell = edif_xlibrary_scope_cell(xlib, scope);
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
ivl_signal_t sig = ivl_scope_sig(scope, idx);
|
||||
|
||||
if (ivl_signal_port(sig) == IVL_SIP_NONE)
|
||||
continue;
|
||||
|
||||
port = edif_cell_port_byname(cell, ivl_signal_basename(sig));
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
|
||||
edif_add_to_joint(jnt, ref, port);
|
||||
}
|
||||
}
|
||||
|
||||
void xilinx_pad(ivl_signal_t sig, const char*str)
|
||||
{
|
||||
unsigned idx;
|
||||
char**pins;
|
||||
|
||||
if (cell_ipad == 0) {
|
||||
cell_ipad = edif_xcell_create(xlib, "IPAD", 1);
|
||||
edif_cell_portconfig(cell_ipad, 0, "IPAD", IVL_SIP_OUTPUT);
|
||||
}
|
||||
|
||||
if (cell_opad == 0) {
|
||||
cell_opad = edif_xcell_create(xlib, "OPAD", 1);
|
||||
edif_cell_portconfig(cell_opad, 0, "OPAD", IVL_SIP_INPUT);
|
||||
}
|
||||
|
||||
if (cell_iopad == 0) {
|
||||
cell_iopad = edif_xcell_create(xlib, "IOPAD", 1);
|
||||
edif_cell_portconfig(cell_iopad, 0, "IOPAD", IVL_SIP_INOUT);
|
||||
}
|
||||
|
||||
/* Collect an array of pin assignments from the attribute
|
||||
string passed in as str. The format is a comma separated
|
||||
list of location names. */
|
||||
pins = calloc(ivl_signal_pins(sig), sizeof(char*));
|
||||
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||
const char*tmp = strchr(str, ',');
|
||||
if (tmp == 0) tmp = str+strlen(str);
|
||||
|
||||
pins[idx] = malloc(tmp-str+1);
|
||||
strncpy(pins[idx], str, tmp-str);
|
||||
pins[idx][tmp-str] = 0;
|
||||
|
||||
if (*tmp != 0)
|
||||
tmp += 1;
|
||||
|
||||
str = tmp;
|
||||
}
|
||||
|
||||
/* Now go through the pins of the signal, creating pads and
|
||||
bufs and joining them to the signal nexus. */
|
||||
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||
edif_joint_t jnt;
|
||||
edif_cellref_t pad, buf;
|
||||
|
||||
const char*name_str = ivl_signal_basename(sig);
|
||||
if (ivl_signal_pins(sig) > 1) {
|
||||
char name_buf[128];
|
||||
sprintf(name_buf, "%s[%u]", name_str, idx);
|
||||
name_str = strdup(name_buf);
|
||||
}
|
||||
|
||||
switch (ivl_signal_port(sig)) {
|
||||
case IVL_SIP_INPUT:
|
||||
pad = edif_cellref_create(edf, cell_ipad);
|
||||
buf = edif_cellref_create(edf, xilinx_cell_ibuf(xlib));
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_joint_rename(jnt, name_str);
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
edif_add_to_joint(jnt, buf, BUF_I);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
|
||||
edif_add_to_joint(jnt, buf, BUF_O);
|
||||
break;
|
||||
|
||||
case IVL_SIP_OUTPUT:
|
||||
pad = edif_cellref_create(edf, cell_opad);
|
||||
buf = edif_cellref_create(edf, xilinx_cell_obuf(xlib));
|
||||
|
||||
jnt = edif_joint_create(edf);
|
||||
edif_joint_rename(jnt, name_str);
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
edif_add_to_joint(jnt, buf, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
|
||||
edif_add_to_joint(jnt, buf, BUF_I);
|
||||
break;
|
||||
|
||||
case IVL_SIP_INOUT:
|
||||
pad = edif_cellref_create(edf, cell_iopad);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
|
||||
edif_add_to_joint(jnt, pad, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (pins[idx])
|
||||
edif_cellref_pstring(pad, "LOC", pins[idx]);
|
||||
|
||||
}
|
||||
|
||||
/* Don't free the allocated pad name strings. The
|
||||
edif_cellref_pstring function attached the string to the
|
||||
LOC attribute, so the reference is permanent. */
|
||||
|
||||
free(pins);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the case where the user specifies the cell to
|
||||
* use by attribute.
|
||||
*/
|
||||
static void edif_cellref_logic(ivl_net_logic_t net, const char*def)
|
||||
{
|
||||
char*str = strdup(def);
|
||||
char*pins;
|
||||
edif_cell_t cell;
|
||||
edif_cellref_t ref;
|
||||
edif_joint_t jnt;
|
||||
unsigned idx, port;
|
||||
|
||||
pins = strchr(str, ':');
|
||||
assert(pins);
|
||||
*pins++ = 0;
|
||||
|
||||
/* Locate the cell in the library, lookup by name. */
|
||||
cell = edif_xlibrary_findcell(xlib, str);
|
||||
assert(cell);
|
||||
|
||||
ref = edif_cellref_create(edf, cell);
|
||||
|
||||
for (idx = 0 ; idx < ivl_logic_pins(net) ; idx += 1) {
|
||||
char*tmp;
|
||||
|
||||
assert(pins);
|
||||
tmp = strchr(pins,',');
|
||||
if (tmp != 0)
|
||||
*tmp++ = 0;
|
||||
else
|
||||
tmp = 0;
|
||||
|
||||
port = edif_cell_port_byname(cell, pins);
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx));
|
||||
edif_add_to_joint(jnt, ref, port);
|
||||
|
||||
pins = tmp;
|
||||
}
|
||||
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void lut_logic(ivl_net_logic_t net, const char*init3,
|
||||
const char*init4, const char*init5)
|
||||
{
|
||||
edif_cellref_t lut = NULL; /* initialization shuts up gcc -Wall */
|
||||
edif_joint_t jnt;
|
||||
const char* init = NULL; /* ditto */
|
||||
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
|
||||
switch (ivl_logic_pins(net)) {
|
||||
case 3:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
init = init3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
|
||||
init = init4;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void xilinx_logic(ivl_net_logic_t net)
|
||||
{
|
||||
edif_cellref_t obj;
|
||||
edif_joint_t jnt;
|
||||
|
||||
{ const char*cellref_attribute = ivl_logic_attr(net, "cellref");
|
||||
if (cellref_attribute != 0) {
|
||||
edif_cellref_logic(net, cellref_attribute);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ivl_logic_type(net)) {
|
||||
|
||||
case IVL_LO_BUF:
|
||||
case IVL_LO_BUFZ:
|
||||
assert(ivl_logic_pins(net) == 2);
|
||||
|
||||
obj = edif_cellref_create(edf, xilinx_cell_buf(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, obj, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, obj, BUF_I);
|
||||
break;
|
||||
|
||||
case IVL_LO_BUFIF0:
|
||||
/* The Xilinx BUFT devices is a BUF that adds a T
|
||||
input. The output is tri-stated if the T input is
|
||||
1. In other words, it acts just like bufif0. */
|
||||
assert(ivl_logic_pins(net) == 3);
|
||||
|
||||
obj = edif_cellref_create(edf, xilinx_cell_buft(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, obj, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, obj, BUF_I);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
|
||||
edif_add_to_joint(jnt, obj, BUF_T);
|
||||
break;
|
||||
|
||||
case IVL_LO_BUFIF1:
|
||||
/* The Xilinx BUFE devices is a BUF that adds an enable
|
||||
input. The output is tri-stated if the E input is 0.
|
||||
In other words, it acts just like bufif1. */
|
||||
assert(ivl_logic_pins(net) == 3);
|
||||
|
||||
obj = edif_cellref_create(edf, xilinx_cell_bufe(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, obj, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
edif_add_to_joint(jnt, obj, BUF_I);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
|
||||
edif_add_to_joint(jnt, obj, BUF_T);
|
||||
break;
|
||||
|
||||
case IVL_LO_NOT:
|
||||
assert(ivl_logic_pins(net) == 2);
|
||||
|
||||
obj = edif_cellref_create(edf, xilinx_cell_inv(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
|
||||
edif_add_to_joint(jnt, obj, BUF_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
|
||||
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;
|
||||
|
||||
case IVL_LO_XNOR:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
lut_logic(net, "9", "69", "9669");
|
||||
break;
|
||||
|
||||
case IVL_LO_XOR:
|
||||
assert(ivl_logic_pins(net) <= 5);
|
||||
assert(ivl_logic_pins(net) >= 3);
|
||||
lut_logic(net, "6", "96", "6996");
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n",
|
||||
ivl_logic_type(net));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A fully generic Xilinx MUX is implemented entirely from LUT
|
||||
* devices.
|
||||
*/
|
||||
void xilinx_mux(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
edif_cellref_t lut;
|
||||
edif_joint_t jnt;
|
||||
|
||||
assert(ivl_lpm_selects(net) == 1);
|
||||
|
||||
/* A/B Mux devices are made from LUT3 devices. I0 is connected
|
||||
to A, I1 to B, and I2 to the Select input. Create as many
|
||||
as are needed to implement the requested width.
|
||||
|
||||
S B A | Q
|
||||
------+--
|
||||
0 0 0 | 0
|
||||
0 0 1 | 1
|
||||
0 1 0 | 0
|
||||
0 1 1 | 1
|
||||
1 0 0 | 0
|
||||
1 0 1 | 0
|
||||
1 1 0 | 1
|
||||
1 1 1 | 1
|
||||
|
||||
INIT = "CA" */
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_O);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 0, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I0);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 1, idx));
|
||||
edif_add_to_joint(jnt, lut, LUT_I1);
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 0));
|
||||
edif_add_to_joint(jnt, lut, LUT_I2);
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", "CA");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Any Xilinx device works with this adder.
|
||||
* Generic Xilinx add only works for single bit slices.
|
||||
*/
|
||||
void xilinx_add(ivl_lpm_t net)
|
||||
{
|
||||
const char*ha_init = 0;
|
||||
edif_cellref_t lut;
|
||||
edif_joint_t jnt;
|
||||
|
||||
switch (ivl_lpm_type(net)) {
|
||||
case IVL_LPM_ADD:
|
||||
ha_init = "6";
|
||||
break;
|
||||
case IVL_LPM_SUB:
|
||||
ha_init = "9";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* If this is a single bit wide, then generate only a
|
||||
half-adder. Normally this is an XOR, but if this is a SUB
|
||||
then it is an XNOR. */
|
||||
if (ivl_lpm_width(net) == 1) {
|
||||
|
||||
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
|
||||
|
||||
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);
|
||||
|
||||
edif_cellref_pstring(lut, "INIT", ha_init);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The left shift is implemented as a matrix of MUX2_1 devices. The
|
||||
* matrix has as many rows as the device width, and a column for each
|
||||
* select.
|
||||
*/
|
||||
void xilinx_shiftl(ivl_lpm_t net)
|
||||
{
|
||||
unsigned width = ivl_lpm_width(net);
|
||||
unsigned nsel = 0, swid = 0;
|
||||
unsigned sdx, qdx;
|
||||
|
||||
edif_cellref_t* cells;
|
||||
edif_cellref_t**table;
|
||||
|
||||
edif_cellref_t pad0_cell;
|
||||
edif_joint_t pad0;
|
||||
|
||||
|
||||
/* First, find out how many select inputs we really need. We
|
||||
can only use the selects that are enough to shift out the
|
||||
entire width of the device. The excess can be used as an
|
||||
enable for the last column. When disabled, the last column
|
||||
emits zeros. */
|
||||
|
||||
while (nsel < ivl_lpm_selects(net)) {
|
||||
|
||||
nsel += 1;
|
||||
|
||||
swid = 1 << nsel;
|
||||
if (swid >= width)
|
||||
break;
|
||||
}
|
||||
|
||||
assert(nsel > 0);
|
||||
|
||||
/* Allocate a matrix of edif_cellref_t variables. A devices
|
||||
will be addressed by the expression table[sdx][qdx];
|
||||
This should make the algorighm code easier to read. */
|
||||
cells = calloc(nsel * width, sizeof(edif_cellref_t));
|
||||
table = calloc(nsel, sizeof(edif_cellref_t*));
|
||||
|
||||
for (sdx = 0 ; sdx < nsel ; sdx += 1)
|
||||
table[sdx] = cells + sdx*width;
|
||||
|
||||
/* Make a 0 valued pad bit. I wlil use this for all the shifin
|
||||
values that are beyond the input. */
|
||||
pad0_cell = edif_cellref_create(edf, cell_0);
|
||||
pad0 = edif_joint_create(edf);
|
||||
edif_add_to_joint(pad0, pad0_cell, 0);
|
||||
|
||||
/* The LUT matrix is <nsel> columns of <width> devices, with
|
||||
the last column a LUT4 devices. The extra input of the
|
||||
LUT4s in the last column are used as an enable to collect
|
||||
all the excess select inputs. */
|
||||
|
||||
/* Allocate the LUT devices of the matrix, and connect the
|
||||
select inputs to I2 of all the devices of the column. */
|
||||
for (sdx = 0 ; sdx < nsel ; sdx += 1) {
|
||||
const char*init_string = 0;
|
||||
ivl_nexus_t nex = ivl_lpm_select(net,sdx);
|
||||
edif_joint_t sdx_jnt = edif_joint_of_nexus(edf, nex);
|
||||
|
||||
edif_cell_t lut;
|
||||
|
||||
if (((sdx+1) == nsel) && (nsel < ivl_lpm_selects(net))) {
|
||||
lut = xilinx_cell_lut4(xlib);
|
||||
init_string = "00CA";
|
||||
} else {
|
||||
lut = xilinx_cell_lut3(xlib);
|
||||
init_string = "CA";
|
||||
}
|
||||
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1) {
|
||||
table[sdx][qdx] = edif_cellref_create(edf, lut);
|
||||
edif_add_to_joint(sdx_jnt, table[sdx][qdx], LUT_I2);
|
||||
|
||||
edif_cellref_pstring(table[sdx][qdx], "INIT", init_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect the inputs of the SHIFTL device to the column 0 LUT
|
||||
inputs. The slice on the low end shifts in a 0 for a select
|
||||
input. */
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1) {
|
||||
ivl_nexus_t nex0, nex1;
|
||||
edif_joint_t jnt0;
|
||||
edif_joint_t jnt1;
|
||||
|
||||
nex0 = ivl_lpm_data(net,qdx);
|
||||
jnt0 = edif_joint_of_nexus(edf, nex0);
|
||||
|
||||
if (qdx > 0) {
|
||||
nex1 = ivl_lpm_data(net,qdx-1);
|
||||
jnt1 = edif_joint_of_nexus(edf, nex1);
|
||||
} else {
|
||||
jnt1 = pad0;
|
||||
}
|
||||
|
||||
edif_add_to_joint(jnt0, table[0][qdx], LUT_I0);
|
||||
edif_add_to_joint(jnt1, table[0][qdx], LUT_I1);
|
||||
}
|
||||
|
||||
/* Make the inner connections between LUT devices. Each column
|
||||
connects to the previous column, shifted by the power of
|
||||
the column value. If the shifted input falls off the end,
|
||||
then pad with zero. */
|
||||
for (sdx = 1 ; sdx < nsel ; sdx += 1) {
|
||||
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1) {
|
||||
unsigned shift = 1 << sdx;
|
||||
edif_joint_t jnt0 = edif_joint_create(edf);
|
||||
edif_joint_t jnt1 = (qdx >= shift)
|
||||
? edif_joint_create(edf)
|
||||
: pad0;
|
||||
|
||||
edif_add_to_joint(jnt0, table[sdx][qdx], LUT_I0);
|
||||
edif_add_to_joint(jnt1, table[sdx][qdx], LUT_I1);
|
||||
|
||||
edif_add_to_joint(jnt0, table[sdx-1][qdx], LUT_O);
|
||||
if (qdx >= shift)
|
||||
edif_add_to_joint(jnt1, table[sdx-1][qdx-shift], LUT_O);
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect the output of the last column to the output of the
|
||||
SHIFTL device. */
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1) {
|
||||
ivl_nexus_t nex = ivl_lpm_q(net,qdx);
|
||||
edif_joint_t jnt = edif_joint_of_nexus(edf, nex);
|
||||
|
||||
edif_add_to_joint(jnt, table[nsel-1][qdx], LUT_O);
|
||||
}
|
||||
|
||||
/* Connect the excess select inputs to the enable inputs of
|
||||
the LUT4 devices in the last column. */
|
||||
if (nsel < ivl_lpm_selects(net)) {
|
||||
edif_joint_t jnt;
|
||||
|
||||
/* XXXX Only support 1 excess bit for now. */
|
||||
assert((nsel + 1) == ivl_lpm_selects(net));
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net,nsel));
|
||||
for (qdx = 0 ; qdx < width ; qdx += 1)
|
||||
edif_add_to_joint(jnt, table[nsel-1][qdx], LUT_I3);
|
||||
}
|
||||
|
||||
free(cells);
|
||||
free(table);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: xilinx.c,v $
|
||||
* Revision 1.1.2.1 2005/09/25 16:35:37 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
#ifndef __xilinx_H
|
||||
#define __xilinx_H
|
||||
/*
|
||||
* Copyright (c) 2005 Stephen Williams (steve at icarus.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: xilinx.h,v 1.1.2.1 2005/09/25 16:35:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This header file includes XILINX library support functions. They
|
||||
* manage the creation and reference of cells from the library. Use
|
||||
* the xililx_cell_* functions to get an edif_cell_t from the
|
||||
* library. The function will create the cell in the library if
|
||||
* needed, or will return the existing cell if it was already called.
|
||||
*
|
||||
* Note that these functions are *not* part of the baseline EDIF. They
|
||||
* are intended to be Xilinx specific and sometimes do things that
|
||||
* would be flat-out wrong for non-xilinx devices.
|
||||
*/
|
||||
# include "edif.h"
|
||||
|
||||
|
||||
/* === BUF Devices === */
|
||||
|
||||
/* Buffer types of devices have the BUF_O and BUF_I pin
|
||||
assignments. The BUF, INV, and certain specialized devices fit in
|
||||
this category. */
|
||||
extern edif_cell_t xilinx_cell_buf (edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_inv (edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib);
|
||||
#define BUF_O 0
|
||||
#define BUF_I 1
|
||||
/* Only bufe and buft buffers have this input. */
|
||||
#define BUF_T 2
|
||||
|
||||
/* === LUT Devices === */
|
||||
|
||||
/* Most Xilinx devices have LUT2/3/4 devices that take, respectively,
|
||||
2, 3 or 4 inputs. All forms have a single bit output. Also, the
|
||||
real behavior of the device will need to be specified by an INIT
|
||||
parameter string. */
|
||||
extern edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib);
|
||||
#define LUT_O 0
|
||||
#define LUT_I0 1
|
||||
#define LUT_I1 2
|
||||
#define LUT_I2 3
|
||||
#define LUT_I3 4
|
||||
|
||||
|
||||
/* === Flip-Flop Devices === */
|
||||
|
||||
/*
|
||||
* These are flip-flops of various sort, but similar pinouts.
|
||||
*/
|
||||
extern edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib);
|
||||
#define FDCE_Q 0
|
||||
#define FDCE_C 1
|
||||
#define FDCE_D 2
|
||||
#define FDCE_CE 3
|
||||
#define FDCE_CLR 4
|
||||
#define FDCE_PRE 5
|
||||
|
||||
|
||||
/* === Virtex/Virtex2 Carry Chain Logic === */
|
||||
|
||||
extern edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib);
|
||||
#define MULT_AND_LO 0
|
||||
#define MULT_AND_I0 1
|
||||
#define MULT_AND_I1 2
|
||||
|
||||
extern edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib);
|
||||
#define MUXCY_O 0
|
||||
#define MUXCY_DI 1
|
||||
#define MUXCY_CI 2
|
||||
#define MUXCY_S 3
|
||||
|
||||
extern edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib);
|
||||
#define XORCY_O 0
|
||||
#define XORCY_CI 1
|
||||
#define XORCY_LI 2
|
||||
|
||||
/* === Virtex/Virtex2 MUX devices */
|
||||
extern edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_muxf7(edif_xlibrary_t xlib);
|
||||
extern edif_cell_t xilinx_cell_muxf8(edif_xlibrary_t xlib);
|
||||
#define MUXF_O 0
|
||||
#define MUXF_I0 1
|
||||
#define MUXF_I1 2
|
||||
#define MUXF_S 3
|
||||
|
||||
/* === Inheritable Methods === */
|
||||
|
||||
extern void virtex_logic(ivl_net_logic_t net);
|
||||
extern void virtex_generic_dff(ivl_lpm_t net);
|
||||
extern void virtex_eq(ivl_lpm_t net);
|
||||
extern void virtex_ge(ivl_lpm_t net);
|
||||
extern void virtex_mux(ivl_lpm_t net);
|
||||
extern void virtex_add(ivl_lpm_t net);
|
||||
|
||||
extern void xilinx_common_header(ivl_design_t des);
|
||||
extern void xilinx_show_footer(ivl_design_t des);
|
||||
extern void xilinx_show_scope(ivl_scope_t scope);
|
||||
extern void xilinx_pad(ivl_signal_t, const char*str);
|
||||
extern void xilinx_logic(ivl_net_logic_t net);
|
||||
extern void xilinx_mux(ivl_lpm_t net);
|
||||
extern void xilinx_add(ivl_lpm_t net);
|
||||
extern void xilinx_shiftl(ivl_lpm_t net);
|
||||
|
||||
/*
|
||||
* $Log: xilinx.h,v $
|
||||
* Revision 1.1.2.1 2005/09/25 16:35:37 steve
|
||||
* Add Xilinx virtex as a reference EDIF device.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
Loading…
Reference in New Issue