Remove last vestiges of XNF.
XNF hasn't been supported in a while. Xilinx doesn't put any effort into it either, for that matter.
This commit is contained in:
parent
1944f372c5
commit
456fffa7ed
10
Makefile.in
10
Makefile.in
|
|
@ -230,8 +230,6 @@ else
|
|||
WIN32_INSTALL = $(bindir)/iverilog-vpi
|
||||
endif
|
||||
|
||||
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/include/constants.vams $(libdir)/ivl/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
|
|
@ -249,12 +247,6 @@ $(libdir)/ivl/include/constants.vams: $(srcdir)/constants.vams
|
|||
$(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams
|
||||
$(INSTALL_DATA) $(srcdir)/disciplines.vams $(DESTDIR)$(libdir)/ivl/include/disciplines.vams
|
||||
|
||||
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(DESTDIR)$(libdir)/ivl/xnf-s.conf
|
||||
|
||||
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf.conf $(DESTDIR)$(libdir)/ivl/xnf.conf
|
||||
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(DESTDIR)$(includedir)/ivl_target.h
|
||||
|
||||
|
|
@ -304,7 +296,7 @@ uninstall:
|
|||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
for f in xnf.conf xnf-s.conf ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
|
||||
for f in ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
|
||||
do rm -f $(DESTDIR)$(libdir)/ivl/$$f; done
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl/include
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl
|
||||
|
|
|
|||
|
|
@ -12,10 +12,7 @@ home page at <http://www.icarus.com/eda/verilog>.
|
|||
|
||||
Icarus Verilog is not aimed at being a simulator in the traditional
|
||||
sense, but a compiler that generates code employed by back-end
|
||||
tools. These back-end tools currently include a simulator engine
|
||||
called VVP, an XNF (Xilinx Netlist Format) generator and an EDIF FPGA
|
||||
netlist generator. In the future, backends are expected for EDIF/LPM,
|
||||
structural Verilog, VHDL, etc.
|
||||
tools.
|
||||
|
||||
For instructions on how to run Icarus Verilog,
|
||||
see the ``iverilog'' man page.
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ iverilog - Icarus Verilog compiler
|
|||
\fIiverilog\fP is a compiler that translates Verilog source code into
|
||||
executable programs for simulation, or other netlist formats for
|
||||
further processing. The currently supported targets are \fIvvp\fP for
|
||||
simulation, and \fIxnf\fP and \fIfpga\fP for synthesis. Other target
|
||||
simulation, and \fIfpga\fP for synthesis. Other target
|
||||
types are added as code generators are implemented.
|
||||
|
||||
.SH OPTIONS
|
||||
|
|
@ -212,11 +212,6 @@ This is the default. The vvp target generates code for the vvp
|
|||
runtime. The output is a complete program that simulates the design
|
||||
but must be run by the \fBvvp\fP command.
|
||||
.TP 8
|
||||
.B xnf
|
||||
This is the Xilinx Netlist Format used by many tools for placing
|
||||
devices in FPGAs or other programmable devices. This target is
|
||||
obsolete, use the \fBfpga\fP target instead.
|
||||
.TP 8
|
||||
.B fpga
|
||||
This is a synthesis target that supports a variety of fpga devices,
|
||||
mostly by EDIF format output. The Icarus Verilog fpga code generator
|
||||
|
|
@ -418,11 +413,6 @@ To compile and run explicitly using the vvp runtime:
|
|||
|
||||
iverilog -ohello.vvp -tvvp hello.v
|
||||
|
||||
To compile hello.v to a file in XNF-format called hello.xnf
|
||||
|
||||
iverilog -txnf -ohello.xnf hello.v
|
||||
|
||||
|
||||
.SH "AUTHOR"
|
||||
.nf
|
||||
Steve Williams (steve@icarus.com)
|
||||
|
|
|
|||
6
main.cc
6
main.cc
|
|
@ -161,9 +161,6 @@ extern void synth(Design*des);
|
|||
extern void synth2(Design*des);
|
||||
extern void syn_rules(Design*des);
|
||||
extern void nodangle(Design*des);
|
||||
#ifdef WITH_T_XNF
|
||||
extern void xnfio(Design*des);
|
||||
#endif
|
||||
|
||||
typedef void (*net_func)(Design*);
|
||||
static struct net_func_map {
|
||||
|
|
@ -175,9 +172,6 @@ static struct net_func_map {
|
|||
{ "synth", &synth },
|
||||
{ "synth2", &synth2 },
|
||||
{ "syn-rules", &syn_rules },
|
||||
#ifdef WITH_T_XNF
|
||||
{ "xnfio", &xnfio },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
|||
54
targets.cc
54
targets.cc
|
|
@ -16,68 +16,14 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: targets.cc,v 1.12 2004/12/11 02:31:28 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "target.h"
|
||||
|
||||
extern const struct target tgt_dll;
|
||||
#ifdef WITH_T_XNF
|
||||
extern const struct target tgt_xnf;
|
||||
#endif
|
||||
|
||||
const struct target *target_table[] = {
|
||||
&tgt_dll,
|
||||
#ifdef WITH_T_XNF
|
||||
&tgt_xnf,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: targets.cc,v $
|
||||
* Revision 1.12 2004/12/11 02:31:28 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.11 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.10 2002/08/11 23:39:33 steve
|
||||
* Remove VVM option.
|
||||
*
|
||||
* Revision 1.9 2002/02/16 03:18:54 steve
|
||||
* Make vvm optional, normally off.
|
||||
*
|
||||
* Revision 1.8 2001/07/25 03:10:50 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.7 2000/12/02 04:50:32 steve
|
||||
* Make the null target into a loadable target.
|
||||
*
|
||||
* Revision 1.6 2000/08/12 16:34:37 steve
|
||||
* Start stub for loadable targets.
|
||||
*
|
||||
* Revision 1.5 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 1999/05/01 02:57:53 steve
|
||||
* Handle much more complex event expressions.
|
||||
*
|
||||
* Revision 1.3 1999/01/24 01:35:36 steve
|
||||
* Support null target for generating no output.
|
||||
*
|
||||
* Revision 1.2 1998/11/16 05:03:53 steve
|
||||
* Add the sigfold function that unlinks excess
|
||||
* signal nodes, and add the XNF target.
|
||||
*
|
||||
* Revision 1.1 1998/11/03 23:29:07 steve
|
||||
* Introduce verilog to CVS.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:xnfio
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:xnf
|
||||
6
xnf.conf
6
xnf.conf
|
|
@ -1,6 +0,0 @@
|
|||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:xnfio
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:xnf
|
||||
298
xnf.txt
298
xnf.txt
|
|
@ -1,298 +0,0 @@
|
|||
|
||||
WHAT IS XNF
|
||||
|
||||
XNF is the Xilinx Netlist Format. This is somewhat specific to the
|
||||
Xilinx tool chain, but it is sufficiently ubiquitous that it's still
|
||||
worth it. This format can be fed to place and route tools and
|
||||
simulators. Since some third party simulators accept XNF, the format
|
||||
may be useful even independent of Xilinx parts.
|
||||
|
||||
Icarus Verilog supports XNF as specified by the Xilinx Netlist Format
|
||||
Specification, Version 6.1.
|
||||
|
||||
GENERATE XNF OUTPUT -- THE SHORT STORY
|
||||
|
||||
The easiest way to compile for XNF output is with the "verilog"
|
||||
command (man verilog) and the -X switch:
|
||||
|
||||
% iverilog -fpart=4010e -fncf=prog.ncf -txnf prog.v
|
||||
|
||||
This generates from the prog.v Verilog source file the prog.xnf output
|
||||
and the prog.ncf netlist constraints file. The Verilog program
|
||||
arranges to call the preprocessor and the ivl compiler with all the
|
||||
correct switches for generating XNF.
|
||||
|
||||
GENERATING XNF MACROS
|
||||
|
||||
Icarus Verilog can be used to generate XNF implementations of devices
|
||||
that are written in Verilog and used by schematic editors such as
|
||||
OrCAD. The trick here is that the code generator automatically notices
|
||||
ports to the root module and generates the PIN= attributes needed so
|
||||
that external tools can link to the generated XNF.
|
||||
|
||||
Icarus Verilog chooses a name for the pin. The name it chooses is the
|
||||
port name of the module. If the port is a vector, a pin is generated
|
||||
for all the bits of the vector with the bit number appended. For
|
||||
example:
|
||||
|
||||
module foo(in);
|
||||
input [3:0] in;
|
||||
|
||||
causes the single bit ports ``in0'' through ``in3'' be
|
||||
generated. Internally, the XNF file uses the bussed names instead of
|
||||
the pin name.
|
||||
|
||||
The implication of this is that there is a chance of name collision
|
||||
with the generated XNF macro if the port names are chosen badly. It is
|
||||
best to not end a port name with decimal digits, as that can cause
|
||||
trouble at link time. Also, XNF is not case sensitive and that should
|
||||
be accounted for as well.
|
||||
|
||||
XNF PADS IN VERILOG SOURCE
|
||||
|
||||
You can assign wires to pads using the Icarus Verilog $attribute
|
||||
extension. Attach to a scalar signal (wire or register) the PAD
|
||||
attribute with the value that specifies the direction and pin
|
||||
number. For example:
|
||||
|
||||
wire foo, bar, bid;
|
||||
$attribute(foo, "PAD", "i1"); // Input pad on pin 1
|
||||
$attribute(bar, "PAD", "o2"); // Output pad on pin 2
|
||||
$attribute(bid, "PAD", "b3"); // Bi-directional pad on pin 3
|
||||
|
||||
The XNFIO function uses these attributes to locate signals that are
|
||||
connected to pads, and generates XNF I/O block devices to connect to
|
||||
the pad to do the FPGA pin buffering that is needed. So the Verilog
|
||||
programmer need not in general specify the IBUF/OBUF buffers.
|
||||
|
||||
If the programmer does connect buffers to pads, the compiler will
|
||||
notice them and convert them to I/OBUFs automatically. For example:
|
||||
|
||||
buf b1 (sig, foo);
|
||||
|
||||
connects to pad foo, so will be converted into an XNF IBUF
|
||||
device. Also:
|
||||
|
||||
bufif1 bt (bar, value, en);
|
||||
|
||||
connects to pad bar so will automatically be converted into an OBUFT
|
||||
device. Icarus Verilog understands OBUF, IBUF and OBUFT (with optionally
|
||||
inverted enable) devices and will convert Verilog devices from the
|
||||
source, or generate missing devices.
|
||||
|
||||
In addition, the Verilog programmer may explicitly declare a device as
|
||||
an I/OBUF by attaching an attribute to the device, like so:
|
||||
|
||||
buf b1 (sig, foo);
|
||||
$attribute(b1, "XNF-LCA", "OBUF:O,I");
|
||||
|
||||
This latter feature is not entirely recommended as it expects that the
|
||||
programmer really knows how the pins of the XNF device are to be
|
||||
connected. It also bypasses the efforts of the compiler, so is not
|
||||
checked for correctness.
|
||||
|
||||
XNF STORAGE ELEMENTS
|
||||
|
||||
Storage elements in XNF include flip-flops, latches and CLB
|
||||
rams. These devices are generated from the LPM equivalents that the
|
||||
-Fsynth functor synthesizes from behavioral descriptions.
|
||||
|
||||
Flip-flops, or more specifically DFF devices, are generated to
|
||||
implement behavioral code like this:
|
||||
|
||||
reg Q;
|
||||
always @(posedge clk) Q <= <expr>;
|
||||
|
||||
The edge can be positive or negative, and the expression can be any
|
||||
synthesizable expression. Furthermore, the register "Q" can have
|
||||
width, which will cause the appropriate number of flip-flops to be
|
||||
created. A clock enable expression can also be added like so:
|
||||
|
||||
reg Q;
|
||||
always @(posedge clk) if (<ce>) Q <= <expr>;
|
||||
|
||||
The <ce> expression can be any synthesizable expression.
|
||||
|
||||
With or without the CE, the generated DFF devices are written into the
|
||||
XNF output one bit at a time, with the clock input inverted if necessary.
|
||||
|
||||
Xilinx parts also support CLB circuitry as synchronous RAMS. These
|
||||
devices are created from Verilog memories if the properties are
|
||||
right. The behavioral description that the -Fsynth functor matches to
|
||||
get a synchronous RAM looks very similar to that for a DFF:
|
||||
|
||||
reg [15:0] M;
|
||||
always @(posedge clk) if (<we>) M[<addr>] <= <expr>;
|
||||
|
||||
Note that in this case the l-value of the assignment is an addressed
|
||||
memory. This statement models writes into the memory. Reads from the
|
||||
device can be modeled with ordinary structural code, i.e.:
|
||||
|
||||
assign foo <= M[<addr>];
|
||||
|
||||
For the memory to be synthesizable in the XNF target, the address
|
||||
lines for writes and reads must be connected. This corresponds to the
|
||||
limitations of the real hardware.
|
||||
|
||||
OTHER XNF SPECIAL DEVICES
|
||||
|
||||
There are certain special devices in XNF that Verilog does not
|
||||
naturally represent, although there are similar more generic Verilog
|
||||
devices. The most obvious and useful example is the clock driver,
|
||||
otherwise known as the global buffer BUFG. As with pads, Icarus
|
||||
Verilog uses the $attribute extension to allow you to specify special
|
||||
devices.
|
||||
|
||||
The $attribute statement can be applied to devices much the same way
|
||||
one applies them to wires. For example, to turn a buffer into a clock
|
||||
buffer:
|
||||
|
||||
wire iclk, clk;
|
||||
buf BUFG (clk, iclk);
|
||||
$attribute(iclk, "PAD", "i1");
|
||||
$attribute(BUFG, "XNF-LCA", "BUFG:O,I");
|
||||
|
||||
The above statements cause the buffer BUFG to be emitted in the XNF
|
||||
output as a BUFG device with the first signal called "O" and the
|
||||
second called "I". The rest of this example connects the input of the
|
||||
BUFG to a signal from the input pin #1 and connects the output to the
|
||||
internal wire "clk". Incidentally, this example will cause an IBUF to
|
||||
be generated to connect the iclk signal to input pin #1.
|
||||
|
||||
SUMMARY OF IVL SUPPORT FOR XNF
|
||||
|
||||
Icarus Verilog has a code generator and synthesis functions that
|
||||
support generation of XNF netlists. The XNF modules also allow the
|
||||
programmer to use $attributes to control certain aspects of code
|
||||
generation.
|
||||
|
||||
XNF code generation is enabled with the ``-t xnf'' flag on the command
|
||||
line. The code generator needs to know the type of part to generate
|
||||
code for, so the ``-fpart=<type>'' flag is also needed. For example,
|
||||
to generate code for the 4010E the command line might start out as:
|
||||
|
||||
ivl -txnf -fpart=4010e -Fsynth -Fnodangle -Fxnfio [...]
|
||||
|
||||
Icarus Verilog includes the functions ``synth'' and ``xnfio'' to
|
||||
perform transformations and optimizations on the design before code is
|
||||
generated. The ``synth'' function matches certain behavioral constructs
|
||||
to structural components, and the xnfio function generates pads and
|
||||
fills the IOBs.
|
||||
|
||||
SUPPORTED FLAGS
|
||||
|
||||
-fpart=<part>
|
||||
Specify the type of part to target. This string is written
|
||||
literally into the PART, record of the XNF, and may also be
|
||||
used to control synthesis and placement.
|
||||
|
||||
-fncf=<path>
|
||||
Cause the code generator to write into <path> the netlist
|
||||
constraints needed for controlling placement and timing. This
|
||||
switch is required if pin assignments are assigned in the
|
||||
Verilog source.
|
||||
|
||||
THE SYNTH FUNCTION
|
||||
|
||||
This function does synthesis transformations on the entered design,
|
||||
making it possible to generate XNF netlist components from certain
|
||||
behavioral constructs. This is needed in Verilog for example to model
|
||||
some of the synchronous components of the XNF library.
|
||||
|
||||
It is a bit much to expect a Verilog compiler in general to generate
|
||||
components from arbitrary behavioral descriptions, so the synth
|
||||
function works by matching statements that have some documented
|
||||
structure, and substituting them for the equivalent XNF component. A
|
||||
fully synthesize-able design, then, is one where the behavioral
|
||||
statements can all be matched and substituted by the synth function.
|
||||
|
||||
THE XNFIO FUNCTION
|
||||
|
||||
The "xnfio" function transforms the netlist where the IOBs are
|
||||
concerned. The signals with PAD attributes are checked, and
|
||||
surrounding circuitry generated to conform to the logic available in
|
||||
the IOB.
|
||||
|
||||
If the pad is an OPAD, the function will look for an existing buf or
|
||||
not gate connected to the PAD signal. If the gate is appropriately
|
||||
connected, the buf or not gate will be turned into an OBUF. This pulls
|
||||
the buf or inverter into the IOB, freeing a CLB and providing the
|
||||
required pin circuitry.
|
||||
|
||||
If the pad is an IPAD, the function will look for a buf, and convert
|
||||
that to an IBUF. Since Xilinx IOBs cannot invert the output from an
|
||||
IBUF, NOT gates cannot be absorbed as in the OPAD case.
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998-1999 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
|
||||
*/
|
||||
|
||||
|
||||
$Log: xnf.txt,v $
|
||||
Revision 1.16 2003/07/15 03:49:22 steve
|
||||
Spelling fixes.
|
||||
|
||||
Revision 1.15 2003/01/30 16:23:08 steve
|
||||
Spelling fixes.
|
||||
|
||||
Revision 1.14 2000/08/01 21:32:40 steve
|
||||
Use the iverilog command in documentation.
|
||||
|
||||
Revision 1.13 2000/08/01 02:48:42 steve
|
||||
Support <= in synthesis of DFF and ram devices.
|
||||
|
||||
Revision 1.12 2000/07/25 22:49:32 steve
|
||||
memory is not a data type in verilog.
|
||||
|
||||
Revision 1.11 2000/04/23 23:03:13 steve
|
||||
automatically generate macro interface code.
|
||||
|
||||
Revision 1.10 1999/12/05 19:30:43 steve
|
||||
Generate XNF RAMS from synthesized memories.
|
||||
|
||||
Revision 1.9 1999/11/18 03:52:20 steve
|
||||
Turn NetTmp objects into normal local NetNet objects,
|
||||
and add the nodangle functor to clean up the local
|
||||
symbols generated by elaboration and other steps.
|
||||
|
||||
Revision 1.8 1999/11/06 04:51:42 steve
|
||||
Support writing some XNF things into an NCF file.
|
||||
|
||||
Revision 1.7 1999/11/03 05:18:18 steve
|
||||
XNF synthesis now uses the synth functor.
|
||||
|
||||
Revision 1.6 1999/11/02 01:43:55 steve
|
||||
Fix iobuf and iobufif handling.
|
||||
|
||||
Revision 1.5 1999/10/09 17:52:27 steve
|
||||
support XNF OBUFT devices.
|
||||
|
||||
Revision 1.4 1999/08/14 22:48:21 steve
|
||||
Mention the sigfold function.
|
||||
|
||||
Revision 1.3 1999/07/22 02:05:20 steve
|
||||
is_constant method for PEConcat.
|
||||
|
||||
Revision 1.2 1999/07/18 21:17:51 steve
|
||||
Add support for CE input to XNF DFF, and do
|
||||
complete cleanup of replaced design nodes.
|
||||
|
||||
Revision 1.1 1999/05/01 02:57:11 steve
|
||||
XNF target documentation.
|
||||
|
||||
26
xnf2pcf.sh
26
xnf2pcf.sh
|
|
@ -1,26 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# xnf2pcf
|
||||
|
||||
# Converts perfectly good EXT records from an XNF file to
|
||||
# a .pcf file for the "par" step of the Xilinx toolchain.
|
||||
# Why on earth is this needed? Oh, well, the joys of working
|
||||
# with black-box-ware.
|
||||
|
||||
# Usage: xnf2pcf <design.xnf >design.pcf
|
||||
|
||||
# Refer to the resulting .pcf file in the invocation of "par", syntax:
|
||||
# par [options] infile[.ncd] outfile pcf_file[.pcf]
|
||||
|
||||
# Tested (successfully!) with XNF from Icarus Verilog, see
|
||||
# http://www.geda.seul.org/tools/verilog/index.html
|
||||
# and Xilinx back end tools from Foundation 1.5
|
||||
|
||||
# Author: Larry Doolittle <LRDoolittle@lbl.gov>
|
||||
# Date: August 19, 1999
|
||||
|
||||
echo "SCHEMATIC START ;"
|
||||
echo "SCHEMATIC END ;"
|
||||
echo
|
||||
|
||||
awk '/^EXT/{gsub(",",""); printf("COMP \"%s\" LOCATE = SITE \"P%s\" ;\n", $2, $4)}'
|
||||
478
xnfio.cc
478
xnfio.cc
|
|
@ -1,478 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2000 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
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: xnfio.cc,v 1.30 2007/03/22 16:08:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
class xnfio_f : public functor_t {
|
||||
|
||||
public:
|
||||
void signal(Design*des, NetNet*sig);
|
||||
void lpm_compare(Design*des, NetCompare*dev);
|
||||
|
||||
private:
|
||||
bool compare_sideb_const(Design*des, NetCompare*dev);
|
||||
};
|
||||
|
||||
static bool is_a_pad(const NetNet*net)
|
||||
{
|
||||
if (net->attribute(perm_string::literal("PAD")) == verinum())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The xnfio function looks for the PAD signals in the design, and
|
||||
* generates the needed IOB devices to handle being connected to the
|
||||
* actual FPGA PAD. This will add items to the netlist if needed.
|
||||
*
|
||||
* FIXME: If there is a DFF connected to the pad, try to convert it
|
||||
* to an IO DFF instead. This would save a CLB, and it is
|
||||
* really lame to not do the obvious optimization.
|
||||
*/
|
||||
|
||||
static NetLogic* make_obuf(Design*des, NetNet*net)
|
||||
{
|
||||
NetScope* scope = net->scope();
|
||||
assert(scope);
|
||||
|
||||
assert(net->pin_count() == 1);
|
||||
|
||||
/* FIXME: If there is nothing internally driving this PAD, I
|
||||
can connect the PAD to a pullup and disconnect it from the
|
||||
rest of the circuit. This would save routing resources. */
|
||||
if (count_outputs(net->pin(0)) <= 0) {
|
||||
cerr << net->get_line() << ":warning: No outputs to OPAD: "
|
||||
<< net->name() << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(count_outputs(net->pin(0)) > 0);
|
||||
|
||||
/* Look for an existing OBUF connected to this signal. If it
|
||||
is there, then no need to add one. */
|
||||
Nexus*nex = net->pin(0).nexus();
|
||||
for (Link*idx = nex->first_nlink()
|
||||
; idx ; idx = idx->next_nlink()) {
|
||||
NetLogic*tmp;
|
||||
if ((tmp = dynamic_cast<NetLogic*>(idx->get_obj())) == 0)
|
||||
continue;
|
||||
|
||||
// Try to use an existing BUF as an OBUF. This moves the
|
||||
// BUF into the IOB.
|
||||
if ((tmp->type() == NetLogic::BUF)
|
||||
&& (count_inputs(tmp->pin(0)) == 0)
|
||||
&& (count_outputs(tmp->pin(0)) == 1)
|
||||
&& (idx->get_pin() == 0) ) {
|
||||
tmp->attribute(perm_string::literal("XNF-LCA"),
|
||||
verinum("OBUF:O,I"));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Try to use an existing INV as an OBUF. Certain
|
||||
// technologies support inverting the input of an OBUF,
|
||||
// which looks just like an inverter. This uses the
|
||||
// available resources of an IOB to optimize away an
|
||||
// otherwise expensive inverter.
|
||||
if ((tmp->type() == NetLogic::NOT)
|
||||
&& (count_inputs(tmp->pin(0)) == 0)
|
||||
&& (count_outputs(tmp->pin(0)) == 1)
|
||||
&& (idx->get_pin() == 0) ) {
|
||||
tmp->attribute(perm_string::literal("XNF-LCA"),
|
||||
verinum("OBUF:O,~I"));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Try to use an existing bufif1 as an OBUFT. Of course
|
||||
// this will only work if the output of the bufif1 is
|
||||
// connected only to the pad. Handle bufif0 the same
|
||||
// way, but the T input is inverted.
|
||||
if ((tmp->type() == NetLogic::BUFIF1)
|
||||
&& (count_inputs(tmp->pin(0)) == 0)
|
||||
&& (count_outputs(tmp->pin(0)) == 1)
|
||||
&& (idx->get_pin() == 0) ) {
|
||||
tmp->attribute(perm_string::literal("XNF-LCA"),
|
||||
verinum("OBUFT:O,I,~T"));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if ((tmp->type() == NetLogic::BUFIF0)
|
||||
&& (count_inputs(tmp->pin(0)) == 0)
|
||||
&& (count_outputs(tmp->pin(0)) == 1)
|
||||
&& (idx->get_pin() == 0) ) {
|
||||
tmp->attribute(perm_string::literal("XNF-LCA"),
|
||||
verinum("OBUFT:O,I,T"));
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't seem to find a way to rearrange the existing netlist,
|
||||
// so I am stuck creating a new buffer, the OBUF.
|
||||
NetLogic*buf = new NetLogic(scope, scope->local_symbol(),
|
||||
2, NetLogic::BUF);
|
||||
des->add_node(buf);
|
||||
|
||||
buf->attribute(perm_string::literal("XNF-LCA"), verinum("OBUF:O,I"));
|
||||
|
||||
// Put the buffer between this signal and the rest of the
|
||||
// netlist.
|
||||
connect(net->pin(0), buf->pin(1));
|
||||
net->pin(0).unlink();
|
||||
connect(net->pin(0), buf->pin(0));
|
||||
|
||||
// It is possible, in putting an OBUF between net and the rest
|
||||
// of the netlist, to create a ring without a signal. Detect
|
||||
// this case and create a new signal.
|
||||
if (count_signals(buf->pin(1)) == 0) {
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE);
|
||||
tmp->local_flag(true);
|
||||
connect(buf->pin(1), tmp->pin(0));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void absorb_OFF(Design*des, NetLogic*buf)
|
||||
{
|
||||
/* If the nexus connects is not a simple point-to-point link,
|
||||
then I can't drag it into the IOB. Give up. */
|
||||
if (count_outputs(buf->pin(1)) != 1)
|
||||
return;
|
||||
if (count_inputs(buf->pin(1)) != 1)
|
||||
return;
|
||||
/* For now, only support OUTFF. */
|
||||
if (buf->type() != NetLogic::BUF)
|
||||
return;
|
||||
|
||||
Link*drv = find_next_output(&buf->pin(1));
|
||||
assert(drv);
|
||||
|
||||
/* Make sure the device is a FF with width 1. */
|
||||
NetFF*ff = dynamic_cast<NetFF*>(drv->get_obj());
|
||||
if (ff == 0)
|
||||
return;
|
||||
if (ff->width() != 1)
|
||||
return;
|
||||
if (ff->attribute(perm_string::literal("LPM_FFType")) != verinum("DFF"))
|
||||
return;
|
||||
|
||||
/* Connect the flip-flop output to the buffer output and
|
||||
delete the buffer. The XNF OUTFF can buffer the pin. */
|
||||
connect(ff->pin_Q(0), buf->pin(0));
|
||||
delete buf;
|
||||
|
||||
/* Finally, build up an XNF-LCA value that defines this
|
||||
devices as an OUTFF and gives each pin an XNF name. */
|
||||
char**names = new char*[ff->pin_count()];
|
||||
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1)
|
||||
names[idx] = "";
|
||||
|
||||
if (ff->attribute(perm_string::literal("Clock:LPM_Polarity")) == verinum("INVERT"))
|
||||
names[ff->pin_Clock().get_pin()] = "~C";
|
||||
else
|
||||
names[ff->pin_Clock().get_pin()] = "C";
|
||||
|
||||
names[ff->pin_Data(0).get_pin()] = "D";
|
||||
names[ff->pin_Q(0).get_pin()] = "Q";
|
||||
|
||||
string lname = string("OUTFF:") + names[0];
|
||||
for (unsigned idx = 1 ; idx < ff->pin_count() ; idx += 1)
|
||||
lname = lname + "," + names[idx];
|
||||
delete[]names;
|
||||
|
||||
ff->attribute(perm_string::literal("XNF-LCA"), lname);
|
||||
}
|
||||
|
||||
static void make_ibuf(Design*des, NetNet*net)
|
||||
{
|
||||
NetScope*scope = net->scope();
|
||||
assert(scope);
|
||||
|
||||
assert(net->pin_count() == 1);
|
||||
// XXXX For now, require at least one input.
|
||||
assert(count_inputs(net->pin(0)) > 0);
|
||||
|
||||
/* Look for an existing BUF connected to this signal and
|
||||
suitably connected that I can use it as an IBUF. */
|
||||
|
||||
Nexus*nex = net->pin(0).nexus();
|
||||
for (Link*idx = nex->first_nlink()
|
||||
; idx ; idx = idx->next_nlink()) {
|
||||
NetLogic*tmp;
|
||||
if ((tmp = dynamic_cast<NetLogic*>(idx->get_obj())) == 0)
|
||||
continue;
|
||||
|
||||
if (tmp->attribute(perm_string::literal("XNF-LCA")) != verinum())
|
||||
continue;
|
||||
|
||||
// Found a BUF, it is only usable if the only input is
|
||||
// the signal and there are no other inputs.
|
||||
if ((tmp->type() == NetLogic::BUF) &&
|
||||
(count_inputs(tmp->pin(1)) == 1) &&
|
||||
(count_outputs(tmp->pin(1)) == 0)) {
|
||||
tmp->attribute(perm_string::literal("XNF-LCA"), verinum("IBUF:O,I"));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// I give up, create an IBUF.
|
||||
NetLogic*buf = new NetLogic(scope, scope->local_symbol(),
|
||||
2, NetLogic::BUF);
|
||||
des->add_node(buf);
|
||||
|
||||
buf->attribute(perm_string::literal("XNF-LCA"), verinum("IBUF:O,I"));
|
||||
|
||||
// Put the buffer between this signal and the rest of the
|
||||
// netlist.
|
||||
connect(net->pin(0), buf->pin(0));
|
||||
net->pin(0).unlink();
|
||||
connect(net->pin(0), buf->pin(1));
|
||||
|
||||
// It is possible, in putting an OBUF between net and the rest
|
||||
// of the netlist, to create a ring without a signal. Detect
|
||||
// this case and create a new signal.
|
||||
if (count_signals(buf->pin(0)) == 0) {
|
||||
NetNet*tmp = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::WIRE);
|
||||
connect(buf->pin(0), tmp->pin(0));
|
||||
}
|
||||
}
|
||||
|
||||
void xnfio_f::signal(Design*des, NetNet*net)
|
||||
{
|
||||
if (! is_a_pad(net))
|
||||
return;
|
||||
|
||||
assert(net->pin_count() == 1);
|
||||
string pattr = net->attribute(perm_string::literal("PAD")).as_string();
|
||||
|
||||
switch (pattr[0]) {
|
||||
case 'i':
|
||||
case 'I':
|
||||
make_ibuf(des, net);
|
||||
break;
|
||||
case 'o':
|
||||
case 'O': {
|
||||
NetLogic*buf = make_obuf(des, net);
|
||||
if (buf == 0) break;
|
||||
absorb_OFF(des, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: Only IPAD and OPAD supported. Need to
|
||||
// add support for IOPAD.
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt some XNF specific optimizations on comparators.
|
||||
*/
|
||||
void xnfio_f::lpm_compare(Design*des, NetCompare*dev)
|
||||
{
|
||||
if (compare_sideb_const(des, dev))
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool xnfio_f::compare_sideb_const(Design*des, NetCompare*dev)
|
||||
{
|
||||
/* Even if side B is all constant, if there are more than 4
|
||||
signals on side A we will not be able to fit the operation
|
||||
into a function unit, so we might as well accept a
|
||||
comparator. Give up. */
|
||||
if (dev->width() > 4)
|
||||
return false;
|
||||
|
||||
NetScope*scope = dev->scope();
|
||||
|
||||
verinum side (verinum::V0, dev->width());
|
||||
|
||||
/* Is the B side all constant? */
|
||||
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1) {
|
||||
|
||||
if (! dev->pin_DataB(idx).nexus()->drivers_constant())
|
||||
return false;
|
||||
|
||||
side.set(idx, dev->pin_DataB(idx).nexus()->driven_value());
|
||||
}
|
||||
|
||||
/* Handle the special case of comparing A to 0. Use an N-input
|
||||
NOR gate to return 0 if any of the bits is not 0. */
|
||||
if ((side.as_ulong() == 0) && (count_inputs(dev->pin_AEB()) > 0)) {
|
||||
NetLogic*sub = new NetLogic(scope, dev->name(), dev->width()+1,
|
||||
NetLogic::NOR);
|
||||
connect(sub->pin(0), dev->pin_AEB());
|
||||
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
|
||||
connect(sub->pin(idx+1), dev->pin_DataA(idx));
|
||||
delete dev;
|
||||
des->add_node(sub);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle the special case of comparing A to 0. Use an N-input
|
||||
NOR gate to return 0 if any of the bits is not 0. */
|
||||
if ((side.as_ulong() == 0) && (count_inputs(dev->pin_ANEB()) > 0)) {
|
||||
NetLogic*sub = new NetLogic(scope, dev->name(), dev->width()+1,
|
||||
NetLogic::OR);
|
||||
connect(sub->pin(0), dev->pin_ANEB());
|
||||
for (unsigned idx = 0 ; idx < dev->width() ; idx += 1)
|
||||
connect(sub->pin(idx+1), dev->pin_DataA(idx));
|
||||
delete dev;
|
||||
des->add_node(sub);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void xnfio(Design*des)
|
||||
{
|
||||
xnfio_f xnfio_obj;
|
||||
des->functor(&xnfio_obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: xnfio.cc,v $
|
||||
* Revision 1.30 2007/03/22 16:08:18 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.29 2004/02/20 18:53:36 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.28 2004/02/18 17:11:58 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.27 2003/06/24 01:38:03 steve
|
||||
* Various warnings fixed.
|
||||
*
|
||||
* Revision 1.26 2003/03/06 00:28:42 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.25 2003/01/30 16:23:08 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.24 2003/01/14 21:16:18 steve
|
||||
* Move strstream to ostringstream for compatibility.
|
||||
*
|
||||
* Revision 1.23 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.22 2002/06/25 01:33:22 steve
|
||||
* Cache calculated driven value.
|
||||
*
|
||||
* Revision 1.21 2002/06/24 01:49:39 steve
|
||||
* Make link_drive_constant cache its results in
|
||||
* the Nexus, to improve cprop performance.
|
||||
*
|
||||
* Revision 1.20 2002/05/23 03:08:52 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.19 2001/10/20 05:21:51 steve
|
||||
* Scope/module names are char* instead of string.
|
||||
*
|
||||
* Revision 1.18 2001/07/25 03:10:50 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.17 2000/11/20 00:58:40 steve
|
||||
* Add support for supply nets (PR#17)
|
||||
*
|
||||
* Revision 1.16 2000/10/07 19:45:43 steve
|
||||
* Put logic devices into scopes.
|
||||
*
|
||||
* Revision 1.15 2000/06/25 19:59:42 steve
|
||||
* Redesign Links to include the Nexus class that
|
||||
* carries properties of the connected set of links.
|
||||
*
|
||||
* Revision 1.14 2000/05/07 04:37:56 steve
|
||||
* Carry strength values from Verilog source to the
|
||||
* pform and netlist for gates.
|
||||
*
|
||||
* Change vvm constants to use the driver_t to drive
|
||||
* a constant value. This works better if there are
|
||||
* multiple drivers on a signal.
|
||||
*
|
||||
* Revision 1.13 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.12 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
* Revision 1.11 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.10 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.9 1999/11/27 19:07:58 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.8 1999/11/19 05:02:15 steve
|
||||
* Handle inverted clock into OUTFF.
|
||||
*
|
||||
* Revision 1.7 1999/11/19 03:02:25 steve
|
||||
* Detect flip-flops connected to opads and turn
|
||||
* them into OUTFF devices. Inprove support for
|
||||
* the XNF-LCA attribute in the process.
|
||||
*
|
||||
* Revision 1.6 1999/11/18 02:58:37 steve
|
||||
* Handle (with a warning) unconnected opads.
|
||||
*
|
||||
* Revision 1.5 1999/11/02 04:55:01 steve
|
||||
* repair the sense of T from bufif01
|
||||
*
|
||||
* Revision 1.4 1999/11/02 01:43:55 steve
|
||||
* Fix iobuf and iobufif handling.
|
||||
*
|
||||
* Revision 1.3 1999/10/09 17:52:27 steve
|
||||
* support XNF OBUFT devices.
|
||||
*
|
||||
* Revision 1.2 1999/07/17 22:01:14 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
*
|
||||
* Revision 1.1 1998/12/07 04:53:17 steve
|
||||
* Generate OBUF or IBUF attributes (and the gates
|
||||
* to garry them) where a wire is a pad. This involved
|
||||
* figuring out enough of the netlist to know when such
|
||||
* was needed, and to generate new gates and signales
|
||||
* to handle what's missing.
|
||||
*
|
||||
*/
|
||||
|
||||
Loading…
Reference in New Issue