Virtex and Virtex2 share much code.
This commit is contained in:
parent
f7162eb538
commit
0e797dc7bc
|
|
@ -16,7 +16,7 @@
|
||||||
# 59 Temple Place - Suite 330
|
# 59 Temple Place - Suite 330
|
||||||
# Boston, MA 02111-1307, USA
|
# Boston, MA 02111-1307, USA
|
||||||
#
|
#
|
||||||
#ident "$Id: Makefile.in,v 1.9 2003/04/05 05:53:34 steve Exp $"
|
#ident "$Id: Makefile.in,v 1.10 2003/06/25 02:55:57 steve Exp $"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
|
|
@ -53,7 +53,7 @@ dep:
|
||||||
mv $*.d dep
|
mv $*.d dep
|
||||||
|
|
||||||
D = d-generic.o d-generic-edif.o d-virtex.o d-virtex2.o
|
D = d-generic.o d-generic-edif.o d-virtex.o d-virtex2.o
|
||||||
O = edif.o fpga.o gates.o mangle.o tables.o xilinx.o $D
|
O = edif.o fpga.o gates.o mangle.o tables.o generic.o xilinx.o $D
|
||||||
|
|
||||||
ifeq (@WIN32@,yes)
|
ifeq (@WIN32@,yes)
|
||||||
TGTLDFLAGS=-L.. -livl
|
TGTLDFLAGS=-L.. -livl
|
||||||
|
|
|
||||||
2316
tgt-fpga/d-virtex.c
2316
tgt-fpga/d-virtex.c
File diff suppressed because it is too large
Load Diff
1045
tgt-fpga/d-virtex2.c
1045
tgt-fpga/d-virtex2.c
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||||
|
*
|
||||||
|
* This source code is free software; you can redistribute it
|
||||||
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
#ifndef HAVE_CVS_IDENT
|
||||||
|
#ident "$Id: generic.c,v 1.1 2003/06/25 02:55:57 steve Exp $"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# include "generic.h"
|
||||||
|
|
||||||
|
edif_t edf = 0;
|
||||||
|
edif_xlibrary_t xlib = 0;
|
||||||
|
|
||||||
|
edif_cell_t cell_0 = 0;
|
||||||
|
edif_cell_t cell_1 = 0;
|
||||||
|
|
||||||
|
edif_cell_t cell_ipad = 0;
|
||||||
|
edif_cell_t cell_opad = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $Log: generic.c,v $
|
||||||
|
* Revision 1.1 2003/06/25 02:55:57 steve
|
||||||
|
* Virtex and Virtex2 share much code.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef __generic_H
|
||||||
|
#define __generic_H
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||||
|
*
|
||||||
|
* This source code is free software; you can redistribute it
|
||||||
|
* and/or modify it in source code form under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software
|
||||||
|
* Foundation; either version 2 of the License, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
|
*/
|
||||||
|
#ifndef HAVE_CVS_IDENT
|
||||||
|
#ident "$Id: generic.h,v 1.1 2003/06/25 02:55:57 steve Exp $"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# include "edif.h"
|
||||||
|
|
||||||
|
extern edif_t edf;
|
||||||
|
extern edif_xlibrary_t xlib;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The cell_* variables below are the various kinds of devices that
|
||||||
|
* this family supports as primitives. If the cell type is used at
|
||||||
|
* least once, then the edif_cell_t is non-zero and will also be
|
||||||
|
* included in the library declaration. The constants underneath are
|
||||||
|
* pin assignments for the cell.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern edif_cell_t cell_0;
|
||||||
|
extern edif_cell_t cell_1;
|
||||||
|
|
||||||
|
extern edif_cell_t cell_ipad;
|
||||||
|
extern edif_cell_t cell_opad;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* $Log: generic.h,v $
|
||||||
|
* Revision 1.1 2003/06/25 02:55:57 steve
|
||||||
|
* Virtex and Virtex2 share much code.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
@ -17,10 +17,18 @@
|
||||||
* 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: xilinx.c,v 1.1 2003/04/05 05:53:34 steve Exp $"
|
#ident "$Id: xilinx.c,v 1.2 2003/06/25 02:55:57 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
# include "edif.h"
|
||||||
|
# include "generic.h"
|
||||||
# include "xilinx.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)
|
edif_cell_t xilinx_cell_buf(edif_xlibrary_t xlib)
|
||||||
{
|
{
|
||||||
|
|
@ -198,10 +206,485 @@ edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib)
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
unsigned*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_OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Collect an array of pin assignments from the attribute
|
||||||
|
string passed in as str. The format is a comma separated
|
||||||
|
list of unsigned decimal integers. */
|
||||||
|
pins = calloc(ivl_signal_pins(sig), sizeof(unsigned));
|
||||||
|
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
|
||||||
|
char*tmp;
|
||||||
|
pins[idx] = strtoul(str, &tmp, 10);
|
||||||
|
switch (*tmp) {
|
||||||
|
case ',':
|
||||||
|
tmp += 1;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
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:
|
||||||
|
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_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 $
|
* $Log: xilinx.c,v $
|
||||||
|
* Revision 1.2 2003/06/25 02:55:57 steve
|
||||||
|
* Virtex and Virtex2 share much code.
|
||||||
|
*
|
||||||
* Revision 1.1 2003/04/05 05:53:34 steve
|
* Revision 1.1 2003/04/05 05:53:34 steve
|
||||||
* Move library cell management to common file.
|
* Move library cell management to common file.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,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: xilinx.h,v 1.1 2003/04/05 05:53:34 steve Exp $"
|
#ident "$Id: xilinx.h,v 1.2 2003/06/25 02:55:57 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -93,8 +93,25 @@ extern edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib);
|
||||||
#define XORCY_CI 1
|
#define XORCY_CI 1
|
||||||
#define XORCY_LI 2
|
#define XORCY_LI 2
|
||||||
|
|
||||||
|
/* === Inheritable Methods === */
|
||||||
|
|
||||||
|
extern void virtex_show_footer(ivl_design_t des);
|
||||||
|
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_add(ivl_lpm_t net);
|
||||||
|
|
||||||
|
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_add(ivl_lpm_t net);
|
||||||
|
extern void xilinx_shiftl(ivl_lpm_t net);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* $Log: xilinx.h,v $
|
* $Log: xilinx.h,v $
|
||||||
|
* Revision 1.2 2003/06/25 02:55:57 steve
|
||||||
|
* Virtex and Virtex2 share much code.
|
||||||
|
*
|
||||||
* Revision 1.1 2003/04/05 05:53:34 steve
|
* Revision 1.1 2003/04/05 05:53:34 steve
|
||||||
* Move library cell management to common file.
|
* Move library cell management to common file.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue