diff --git a/Makefile.in b/Makefile.in index 3b16d2dd9..c5432c351 100644 --- a/Makefile.in +++ b/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 diff --git a/README.txt b/README.txt index 2d447a2be..b980e9c1f 100644 --- a/README.txt +++ b/README.txt @@ -12,10 +12,7 @@ home page at . 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. diff --git a/driver/iverilog.man b/driver/iverilog.man index 3c74e9feb..bdadee29e 100644 --- a/driver/iverilog.man +++ b/driver/iverilog.man @@ -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) diff --git a/main.cc b/main.cc index 17235f3cf..026a90b92 100644 --- a/main.cc +++ b/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 } }; diff --git a/t-xnf.cc b/t-xnf.cc deleted file mode 100644 index e6bf20bc8..000000000 --- a/t-xnf.cc +++ /dev/null @@ -1,1151 +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: t-xnf.cc,v 1.52 2004/02/20 18:53:36 steve Exp $" -#endif - -# include "config.h" - -# include - -/* XNF BACKEND - * This target supports generating Xilinx Netlist Format netlists for - * use by Xilinx tools, and other tools that accepts Xilinx designs. - * - * The code generator automatically detects ports to top level modules - * and generates SIG records that make the XNF usable as a schematic. - * - * FLAGS - * The XNF backend uses the following flags from the command line to - * affect the generated file: - * - * part= - * Specify the part type. The part string is written into the - * PART record. Valid types are defined by Xilinx or the - * receiving tools. - * - * ncf= - * Specify the path to a NCF file. This is an OUTPUT file into - * which the code generator will write netlist constraints that - * relate to pin assignments, CLB placement, etc. If this flag is - * not given, no NCF file will be written. - * - * WIRE ATTRIBUTES - * - * PAD = - * Tell the XNF generator that this wire goes to a PAD. The - * is a single character that tells the direction, and is the - * pin number. For example, "o31" is output on pin 31. The PAD - * attribute is not practically connected to a vector, as all the - * bits would go to the same pad. - * - * NODE ATTRIBUTES - * - * XNF-LCA = :,... - * Specify the LCA library part type for the gate. The lname - * is the name of the symbol to use (i.e. DFF) and the comma - * separated list is the names of the pins, in the order they - * appear in the Verilog source. If the name is prefixed with a - * tilde (~) then the pin is inverted, and the proper "INV" token - * will be added to the PIN record. - * - * This attribute can override even the typical generation of - * gates that one might naturally expect of the code generator, - * but may be used by the optimizers for placing parts. - * - * An example is "XNF-LCA=OBUF:O,~I". This attribute means that - * the object is an OBUF. Pin 0 is called "O", and pin 1 is - * called "I". In addition, pin 1 is inverted. - */ - -# include "netlist.h" -# include "target.h" -# include -# include - -verinum::V link_get_ival(const Link&lnk) -{ - const Nexus*nex = lnk.nexus(); - for (const Link*cur = nex->first_nlink() - ; cur ; cur = cur->next_nlink()) { - if (cur == &lnk) - continue; - - if (dynamic_cast(cur->get_obj())) - return cur->nexus()->get_init(); - - } - - return verinum::Vx; -} - -class target_xnf : public target_t { - - public: - bool start_design(const Design*); - int end_design(const Design*); - void memory(const NetMemory*); - void signal(const NetNet*); - - void lpm_add_sub(const NetAddSub*); - void lpm_compare(const NetCompare*); - void lpm_compare_eq_(ostream&os, const NetCompare*); - void lpm_compare_ge_(ostream&os, const NetCompare*); - void lpm_compare_le_(ostream&os, const NetCompare*); - void lpm_ff(const NetFF*); - void lpm_mux(const NetMux*); - void lpm_ram_dq(const NetRamDq*); - - bool net_const(const NetConst*); - void logic(const NetLogic*); - bool bufz(const NetBUFZ*); - void udp(const NetUDP*); - - private: - static string mangle(const string&); - static string mangle(perm_string); - static string choose_sig_name(const Link*lnk); - static void draw_pin(ostream&os, const string&name, - const Link&lnk); - static void draw_sym_with_lcaname(ostream&os, string lca, - const NetNode*net); - static void draw_xor(ostream&os, const NetAddSub*, unsigned idx); - enum adder_type {FORCE0, LOWER, DOUBLE, LOWER_W_CO, EXAMINE_CI }; - static void draw_carry(ostream&os, const NetAddSub*, unsigned idx, - enum adder_type); - - ofstream out_; - ofstream ncf_; -}; - -/* - * This function takes a signal name and mangles it into an equivalent - * name that is suitable to the XNF format. - */ -string target_xnf::mangle(const string&name) -{ - string result; - for (unsigned idx = 0 ; idx < name.length() ; idx += 1) - switch (name[idx]) { - case '.': - result = result + "/"; - break; - default: - result = result + name[idx]; - break; - } - - return result; -} - -string target_xnf::mangle(perm_string name) -{ - return mangle(string(name)); -} - -/* - * This method takes a signal and pin number as a nexus. Scan the - * nexus to decide which name to use if there are lots of attached - * signals. - */ -string target_xnf::choose_sig_name(const Link*lnk) -{ - return mangle( string(lnk->nexus()->name()) ); -} - -void target_xnf::draw_pin(ostream&os, const string&name, - const Link&lnk) -{ - bool inv = false; - string use_name = name; - if (use_name[0] == '~') { - inv = true; - use_name = use_name.substr(1); - } - - char type=0; - switch (lnk.get_dir()) { - case Link::INPUT: - case Link::PASSIVE: - type = 'I'; - break; - case Link::OUTPUT: - type = 'O'; - break; - } - assert(type); - - os << " PIN, " << use_name << ", " << type << ", " << - choose_sig_name(&lnk); - if (inv) os << ",,INV"; - os << endl; -} - -static string scrape_pin_name(string&list) -{ - unsigned idx = list.find(','); - string name = list.substr(0, idx); - list = list.substr(idx+1); - return name; -} - -/* - * This method draws an LCA item based on the XNF-LCA attribute - * given. The LCA attribute gives enough information to completely - * draw the node in XNF, which is pretty handy at this point. - */ -void target_xnf::draw_sym_with_lcaname(ostream&os, string lca, - const NetNode*net) -{ - unsigned idx = lca.find(':'); - string lcaname = lca.substr(0, idx); - lca = lca.substr(idx+1); - - os << "SYM, " << mangle(net->name()) << ", " << lcaname - << ", LIBVER=2.0.0" << endl; - - for (idx = 0 ; idx < net->pin_count() ; idx += 1) { - string usename = scrape_pin_name(lca); - if (usename == "") continue; - draw_pin(os, usename, net->pin(idx)); - } - - os << "END" << endl; -} - -bool target_xnf::start_design(const Design*des) -{ - out_.open(des->get_flag("-o"), ios::out | ios::trunc); - - string ncfpath = des->get_flag("ncf"); - if (ncfpath != "") - ncf_.open(ncfpath.c_str()); - - out_ << "LCANET,6" << endl; - out_ << "PROG,verilog,$Name: $,\"Icarus Verilog\"" << endl; - ncf_ << "# Generated by Icarus Verilog $Name: $" << endl; - - if (des->get_flag("part") != 0) { - out_ << "PART," << des->get_flag("part") << endl; - ncf_ << "CONFIG PART=" << des->get_flag("part") << ";" << endl; - } - - return true; -} - -int target_xnf::end_design(const Design*) -{ - out_ << "EOF" << endl; - ncf_.close(); - return 0; -} - -void scrape_pad_info(string str, char&dir, unsigned&num) -{ - // Get rid of leading white space - while (str[0] == ' ') - str = str.substr(1); - - // Get the direction letter - switch (str[0]) { - case 'b': - case 'B': - dir = 'B'; - break; - case 'o': - case 'O': - dir = 'O'; - break; - case 'i': - case 'I': - dir = 'I'; - break; - case 't': - case 'T': - dir = 'T'; - break; - default: - dir = '?'; - break; - } - - // Get the number part. - str = str.substr(1); - unsigned val = 0; - while (str.size() && isdigit(str[0])) { - val = val * 10 + (str[0]-'0'); - str = str.substr(1); - } - num = val; -} - -/* - * Memories are handled by the lpm_ram_dq method, so there is nothing - * to do here. - */ -void target_xnf::memory(const NetMemory*) -{ -} - -/* - * Look for signals that have attributes that are pertinent to XNF - * files. The most obvious are those that have the PAD attribute. - * - * Individual signals are easy, the pad description is a letter - * followed by a decimal number that is the pin. - * - * The PAD attribute for a vector is a comma separated pin - * descriptions, that enumerate the pins from most significant to - * least significant. - */ -void target_xnf::signal(const NetNet*net) -{ - - /* Look for signals that are ports to the root module. If they - are, the write a SIG record and generate a pin name so that - this module can be used as a macro. */ - - if (const NetScope*scope = net->scope()) do { - - if (scope->parent()) - break; - - if (net->port_type() == NetNet::NOT_A_PORT) - break; - - string mname = mangle(net->name()); - string pname = mname.substr(mname.find('/')+1, mname.length()); - - if (net->pin_count() == 1) { - out_ << "SIG, " << mangle(net->name()) << ", PIN=" - << pname << endl; - - } else for (unsigned idx = 0; idx < net->pin_count(); idx += 1) { - out_ << "SIG, " << mangle(net->name()) << "<" << idx - << ">, PIN=" << pname << idx << endl; - } - - } while (0); - - - /* Now look to see if a PAD attribute is attached, and if so - write out PAD information to the XNF and the ncf files. */ - - string pad = net->attribute(perm_string::literal("PAD")).as_string(); - if (pad == "") - return; - - if (net->pin_count() > 1) { - cerr << "Signal ``" << net->name() << "'' with PAD=" << - pad << " is a vector." << endl; - return; - } - - char dir; - unsigned num; - scrape_pad_info(pad, dir, num); - out_ << "EXT, " << mangle(net->name()) << ", " << dir - << ", " << num << endl; - - ncf_ << "# Assignment to pin " << num << " (DIR=" << dir << - ") by $attribute(" << net->name() << ", \"PAD\", \"" << - pad << "\")" << endl; - ncf_ << "NET " << mangle(net->name()) << " LOC=P" << num << ";" - << endl; -} - -void target_xnf::draw_xor(ostream &os, const NetAddSub*gate, unsigned idx) -{ - string name = mangle(gate->name()); - string name_add = name; - string name_cout = name + "/COUT"; - - // We only need to pick up the - // carry if we are not the 0 bit. (We know it is 0). - os << "SYM, " << name_add << "<" << (idx+0) << ">, XOR, " - "LIBVER=2.0.0" << endl; - draw_pin(os, "O", gate->pin_Result(idx)); - draw_pin(os, "I0", gate->pin_DataA(idx)); - draw_pin(os, "I1", gate->pin_DataB(idx)); - if (idx > 0) { - os << " PIN, I2, I, " << name_cout << "<" << - idx << ">" << endl; - } - os << "END" << endl; -} - -void target_xnf::draw_carry(ostream &os, const NetAddSub*gate, unsigned idx, - enum adder_type type) -{ - string name = mangle(gate->name()); - - string name_cy4 = name + "/CY"; - string name_cym = name + "/CM"; - string name_cout = name + "/COUT"; - - os << "SYM, " << name_cy4 << "<" << idx << ">, CY4, " - "LIBVER=2.0.0" << endl; - - // Less significant bit addends, if any - if ( type == LOWER || type == DOUBLE || type == LOWER_W_CO ) { - draw_pin(os, "A0", gate->pin_DataA(idx)); - draw_pin(os, "B0", gate->pin_DataB(idx)); - } - - // More significant bit addends, if any - if ( type == DOUBLE ) { - draw_pin(os, "A1", gate->pin_DataA(idx+1)); - draw_pin(os, "B1", gate->pin_DataB(idx+1)); - } - - // All but FORCE0 cells have carry input - if ( type != FORCE0 ) { - os << " PIN, CIN, I, " << name_cout << "<" << idx << ">" << endl; - } - - // Connect the Cout0 to a signal so that I can connect - // it to the adder. - switch (type) { - case LOWER: - case DOUBLE: - os << " PIN, COUT0, O, " << name_cout << "<" << (idx+1) << - ">" << endl; - break; - case EXAMINE_CI: - case LOWER_W_CO: - draw_pin(os, "COUT0", gate->pin_Cout()); - break; - - default: - assert(0); - } - - // Connect the Cout, this will connect to the next Cin - if ( type == FORCE0 || type == DOUBLE ) { - unsigned int to = (type==FORCE0)?(0):(idx+2); - os << " PIN, COUT, O, " << name_cout << "<" << to << - ">" << endl; - } - - // These are the mode inputs from the CY_xx pseudo-device - for (unsigned cn = 0 ; cn < 8 ; cn += 1) { - os << " PIN, C" << cn << ", I, " << name << "/C" - << cn << "<" << (idx) << ">" << endl; - } - os << "END" << endl; - - // On to the CY_xx pseudo-device itself - os << "SYM, " << name_cym << "<" << (idx) << ">, "; - switch (type) { - case FORCE0: - os << "CY4_37, CYMODE=FORCE-0" << endl; - break; - case LOWER: - os << "CY4_01, CYMODE=ADD-F-CI" << endl; - break; - case LOWER_W_CO: - os << "CY4_01, CYMODE=ADD-F-CI" << endl; - break; - case DOUBLE: - os << "CY4_02, CYMODE=ADD-FG-CI" << endl; - break; - case EXAMINE_CI: - os << "CY4_42, CYMODE=EXAMINE-CI" << endl; - break; - } - for (unsigned cn = 0 ; cn < 8 ; cn += 1) { - os << " PIN, C" << cn << ", O, " << name << "/C" - << cn << "<" << (idx) << ">" << endl; - } - os << "END" << endl; -} - -/* - * This function makes an adder out of carry logic symbols. It makes - * as many 2 bit adders as are possible, then the top bit is made into - * a 1-bit adder (with carry in) in the F unit. The low carry is - * initialized with the FORCE-0 configuration of a carry unit below - * the 0 bit. This takes up the carry logic of the CLB below, but not - * the G function. - * - * References: - * XNF 6.1 Specification - * Application note XAPP013 - * Xilinx Libraries Guide, Chapter 12 - */ -void target_xnf::lpm_add_sub(const NetAddSub*gate) -{ - unsigned width = gate->width(); - - /* Make the force-0 carry mode object to initialize the bottom - bits of the carry chain. Label this with the width instead - of the bit position so that symbols don't clash. */ - - draw_carry(out_, gate, width+1, FORCE0); - - - /* Now make the 2 bit adders that chain from the cin - initializer and up. Save the tail bits for later. */ - for (unsigned idx = 0 ; idx < width-2 ; idx += 2) - draw_carry(out_, gate, idx, DOUBLE); - - /* Always have one or two tail bits. The situation gets a - little tricky if we want the carry output, so handle that - here. - - If the carry-out is connected, and there are an even number - of data bits, we need to see the cout from the CLB. This is - done by configuring the top CLB CY device as ADD-FG-CI (to - activate cout) and create an extra CLB CY device on top of - the carry chain configured EXAMINE-CI to put the carry into - the G function block. - - IF the carry-out is connected and there are an odd number - of data bits, then the top CLB can be configured to carry - the top bit in the F unit and deliver the carry out through - the G unit. - - If the carry-out is not connected, then configure this top - CLB as ADD-F-CI. The draw_xor for the top bit will include - the F carry if needed. */ - - if (gate->pin_Cout().is_linked()) { - if (width%2 == 0) { - draw_carry(out_, gate, width-2, DOUBLE); - draw_carry(out_, gate, width, EXAMINE_CI); - } else { - draw_carry(out_, gate, width-1, LOWER_W_CO); - } - - } else { - if (width%2 == 0) - draw_carry(out_, gate, width-2, LOWER); - else - draw_carry(out_, gate, width-1, LOWER); - } - - /* Now draw all the single bit (plus carry in) adders from XOR - gates. This puts the F and G units to use. */ - for (unsigned idx = 0 ; idx < width ; idx += 1) - draw_xor(out_, gate, idx); - -} - -/* - * In XNF, comparators are done differently depending on the type of - * comparator being implemented. So, here we dispatch to the correct - * code generator. - */ -void target_xnf::lpm_compare(const NetCompare*dev) -{ - if (dev->pin_AEB().is_linked() || dev->pin_ANEB().is_linked()) { - lpm_compare_eq_(out_, dev); - return; - } - - if (dev->pin_AGEB().is_linked()) { - lpm_compare_ge_(out_, dev); - return; - } - - if (dev->pin_ALEB().is_linked()) { - lpm_compare_le_(out_, dev); - return; - } - - assert(0); -} - -/* - * To compare that vectors are equal (identity comparator) generate - * XNOR gates to compare each pair of bits, then generate an AND gate - * to combine the bitwise results. This is pretty much the best way to - * do an identity compare in Xilinx CLBs. - */ -void target_xnf::lpm_compare_eq_(ostream&os, const NetCompare*dev) -{ - string mname = mangle(dev->name()); - - /* Draw XNOR gates for each bit pair. These gates to the - bitwise comparison. */ - for (unsigned idx = 0 ; idx < dev->width() ; idx += 1) { - os << "SYM, " << mname << "/cmp<" << idx << ">, " - << "XNOR, LIBVER=2.0.0" << endl; - os << " PIN, O, O, " << mname << "/bit<" << idx << ">" - << endl; - draw_pin(os, "I0", dev->pin_DataA(idx)); - draw_pin(os, "I1", dev->pin_DataB(idx)); - os << "END" << endl; - } - - /* Now draw an AND gate to combine all the bitwise - comparisons. If there are more the 5 bits of data, then we - are going to have generate a nested AND to combine the - results. */ - - if (dev->width() > 5) { - for (unsigned idx = 0 ; idx < dev->width() ; idx += 5) { - - if ((idx+1) >= dev->width()) break; - os << "SYM, " << mname << "/nest<" << idx - << ">, AND, LIBVER=2.0.0" << endl; - - os << " PIN, O, O, " << mname << "/nbit<" << idx - << ">" << endl; - - os << " PIN, I0, I, " << mname << "/bit<" << idx+0 - << ">" << endl; - os << " PIN, I1, I, " << mname << "/bit<" << idx+1 - << ">" << endl; - if ((idx+2) >= dev->width()) goto gate_out; - os << " PIN, I2, I, " << mname << "/bit<" << idx+2 - << ">" << endl; - if ((idx+3) >= dev->width()) goto gate_out; - os << " PIN, I3, I, " << mname << "/bit<" << idx+3 - << ">" << endl; - if ((idx+4) >= dev->width()) goto gate_out; - os << " PIN, I4, I, " << mname << "/bit<" << idx+4 - << ">" << endl; - gate_out: - os << "END" << endl; - } - - /* Draw an AND gate if this is an EQ result, or a NAND - gate of this is a NEQ result. */ - - if (dev->pin_AEB().is_linked()) { - assert( ! dev->pin_ANEB().is_linked()); - os << "SYM, " << mname << ", AND, LIBVER=2.0.0" << endl; - draw_pin(os, "O", dev->pin_AEB()); - - } else { - assert( dev->pin_ANEB().is_linked()); - os << "SYM, " << mname << ", NAND, LIBVER=2.0.0" << endl; - draw_pin(os, "O", dev->pin_ANEB()); - } - - for (unsigned idx = 0 ; idx < dev->width() ; idx += 5) { - if ((idx+1) == dev->width()) - os << " PIN, I" << idx/5 << ", I, " << mname - << "/bit<" << idx << ">" << endl; - else - os << " PIN, I" << idx/5 << ", I, " << mname - << "/nbit<" << idx << ">" << endl; - } - os << "END" << endl; - - } else { - if (dev->pin_AEB().is_linked()) { - assert( ! dev->pin_ANEB().is_linked()); - os << "SYM, " << mname << ", AND, LIBVER=2.0.0" << endl; - draw_pin(os, "O", dev->pin_AEB()); - - } else { - assert( dev->pin_ANEB().is_linked()); - os << "SYM, " << mname << ", NAND, LIBVER=2.0.0" << endl; - draw_pin(os, "O", dev->pin_ANEB()); - } - - for (unsigned idx = 0 ; idx < dev->width() ; idx += 1) { - os << " PIN, I" << idx << ", I, " << mname << "/bit<" - << idx << ">" << endl; - } - os << "END" << endl; - } -} - -void target_xnf::lpm_compare_ge_(ostream&os, const NetCompare*dev) -{ - cerr << "XXXX GE not supported yet" << endl; -} - -void target_xnf::lpm_compare_le_(ostream&os, const NetCompare*dev) -{ - cerr << "XXXX LE not supported yet" << endl; -} - -void target_xnf::lpm_ff(const NetFF*net) -{ - string type = net->attribute(perm_string::literal("LPM_FFType")).as_string(); - if (type == "") type = "DFF"; - - // XXXX For now, only support DFF - assert(type == "DFF"); - - string lcaname = net->attribute(perm_string::literal("XNF-LCA")).as_string(); - if (lcaname != "") { - draw_sym_with_lcaname(out_, lcaname, net); - return; - } - - assert(net->attribute(perm_string::literal("XNF-LCA")) == verinum("")); - - /* Create a DFF object for each bit of width. The symbol name - has the index number appended so that read XNF may be able - to buss them. If the NetNet objects connected to the Q - output of the DFF have an initial value, the write an INIT= - parameter to set the power-up value. */ - - for (unsigned idx = 0 ; idx < net->width() ; idx += 1) { - - verinum::V ival = link_get_ival(net->pin_Q(idx)); - - out_ << "SYM, " << mangle(net->name()) << "<" << idx << ">, DFF, "; - - switch (ival) { - case verinum::V0: - out_ << "INIT=R, "; - break; - case verinum::V1: - out_ << "INIT=S, "; - break; - - default: - break; - } - - out_ << "LIBVER=2.0.0" << endl; - draw_pin(out_, "Q", net->pin_Q(idx)); - draw_pin(out_, "D", net->pin_Data(idx)); - - if (net->attribute(perm_string::literal("Clock:LPM_Polarity")) == verinum("INVERT")) - draw_pin(out_, "~C", net->pin_Clock()); - else - draw_pin(out_, "C", net->pin_Clock()); - - if (net->pin_Enable().is_linked()) - draw_pin(out_, "CE", net->pin_Enable()); - - out_ << "END" << endl; - } -} - -/* - * Generate an LPM_MUX. - * - * XXXX NOTE: For now, this only supports combinational LPM_MUX - * devices that have a single select input. These are typically - * generated from ?: expressions. - */ -void target_xnf::lpm_mux(const NetMux*net) -{ - assert(net->sel_width() == 1); - assert(net->size() == 2); - - for (unsigned idx = 0 ; idx < net->width() ; idx += 1) { - - out_ << "SYM, " << mangle(net->name()) << "<" << idx << ">," - << " EQN, EQN=(I0 * I2) + (~I0 * I1)" << endl; - - draw_pin(out_, "I0", net->pin_Sel(0)); - draw_pin(out_, "I1", net->pin_Data(idx,0)); - draw_pin(out_, "I2", net->pin_Data(idx,1)); - draw_pin(out_, "O", net->pin_Result(idx)); - - out_ << "END" << endl; - } - -} - -void target_xnf::lpm_ram_dq(const NetRamDq*ram) -{ - assert(ram->count_partners() == 1); - - for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) { - out_ << "SYM, " << mangle(ram->name()) - << "<" << idx << ">, RAMS" << endl; - - draw_pin(out_, "O", ram->pin_Q(idx)); - draw_pin(out_, "D", ram->pin_Data(idx)); - draw_pin(out_, "WE", ram->pin_WE()); - draw_pin(out_, "WCLK", ram->pin_InClock()); - for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) { - ostringstream tmp; - tmp << "A" << adr; - draw_pin(out_, tmp.str(), ram->pin_Address(adr)); - } - - out_ << "END" << endl; - } -} - -bool target_xnf::net_const(const NetConst*c) -{ - unsigned x_bits = 0; - for (unsigned idx = 0 ; idx < c->pin_count() ; idx += 1) { - verinum::V v=c->value(idx); - const Link& lnk = c->pin(idx); - - switch (v) { - case verinum::V0: - out_ << " PWR, 0, " << choose_sig_name(&lnk) << endl; - break; - case verinum::V1: - out_ << " PWR, 1, " << choose_sig_name(&lnk) << endl; - break; - case verinum::Vz: - break; - default: - x_bits += 1; - if (x_bits == 1) - cerr << "xnf: error: Unknown (x) const bit value" - << " assigned to " << choose_sig_name(&lnk) - << endl; - break; - } - } - - return x_bits == 0; -} - -/* - * The logic gates I know so far can be translated directly into XNF - * standard symbol types. This is a fairly obvious transformation. - */ -void target_xnf::logic(const NetLogic*net) -{ - // The XNF-LCA attribute overrides anything I might guess - // about this object. - string lca = net->attribute(perm_string::literal("XNF-LCA")).as_string(); - if (lca != "") { - draw_sym_with_lcaname(out_, lca, net); - return; - } - - out_ << "SYM, " << mangle(net->name()) << ", "; - switch (net->type()) { - case NetLogic::AND: - out_ << "AND"; - break; - case NetLogic::BUF: - out_ << "BUF"; - break; - case NetLogic::NAND: - out_ << "NAND"; - break; - case NetLogic::NOR: - out_ << "NOR"; - break; - case NetLogic::NOT: - out_ << "INV"; - break; - case NetLogic::OR: - out_ << "OR"; - break; - case NetLogic::XNOR: - out_ << "XNOR"; - break; - case NetLogic::XOR: - out_ << "XOR"; - break; - case NetLogic::BUFIF0: - case NetLogic::BUFIF1: - out_ << "TBUF"; - break; - default: - cerr << "internal error: XNF: Unhandled logic type." << endl; - break; - } - out_ << ", LIBVER=2.0.0" << endl; - - /* All of these kinds of devices have an output on pin 0. */ - draw_pin(out_, "O", net->pin(0)); - - /* Most devices have inputs called I for all the remaining - pins. The TBUF devices are slightly different, but - essentially the same structure. */ - switch (net->type()) { - - case NetLogic::BUFIF0: - assert(net->pin_count() == 3); - draw_pin(out_, "I", net->pin(1)); - draw_pin(out_, "~T", net->pin(2)); - break; - - case NetLogic::BUFIF1: - assert(net->pin_count() == 3); - draw_pin(out_, "I", net->pin(1)); - draw_pin(out_, "T", net->pin(2)); - break; - - default: - if (net->pin_count() == 2) { - draw_pin(out_, "I", net->pin(1)); - } else for (unsigned idx = 1; idx < net->pin_count(); idx += 1) { - string name = "I"; - assert(net->pin_count() <= 11); - name += (char)('0'+idx-1); - draw_pin(out_, name, net->pin(idx)); - } - break; - } - - out_ << "END" << endl; -} - -bool target_xnf::bufz(const NetBUFZ*net) -{ - static int warned_once=0; - if (!warned_once) { - cerr << "0:0: internal warning: BUFZ objects found " - << "in XNF netlist." << endl; - cerr << "0:0: : I'll make BUFs for them." - << endl; - warned_once=1; - } - out_ << "SYM, " << mangle(net->name()) << ", BUF, LIBVER=2.0.0" << endl; - assert(net->pin_count() == 2); - draw_pin(out_, "O", net->pin(0)); - draw_pin(out_, "I", net->pin(1)); - out_ << "END" << endl; - - return true; -} - -void target_xnf::udp(const NetUDP*net) -{ - string lca = net->attribute(perm_string::literal("XNF-LCA")).as_string(); - - // I only know how to draw a UDP if it has the XNF-LCA - // attribute attached to it. - if (lca == "") { - cerr << "I don't understand this UDP." << endl; - return; - } - - draw_sym_with_lcaname(out_, lca, net); -} - -static target_xnf target_xnf_obj; - -extern const struct target tgt_xnf = { "xnf", &target_xnf_obj }; - -/* - * $Log: t-xnf.cc,v $ - * Revision 1.52 2004/02/20 18:53:36 steve - * Addtrbute keys are perm_strings. - * - * Revision 1.51 2004/02/18 17:11:58 steve - * Use perm_strings for named langiage items. - * - * Revision 1.50 2003/11/10 20:59:04 steve - * Design::get_flag returns const char* instead of string. - * - * Revision 1.49 2003/07/05 20:42:08 steve - * Fix some enumeration warnings. - * - * Revision 1.48 2003/06/24 01:38:03 steve - * Various warnings fixed. - * - * Revision 1.47 2003/01/30 16:23:08 steve - * Spelling fixes. - * - * Revision 1.46 2003/01/14 21:16:18 steve - * Move strstream to ostringstream for compatibility. - * - * Revision 1.45 2002/08/12 01:35:01 steve - * conditional ident string using autoconfig. - * - * Revision 1.44 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.43 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.42 2001/06/30 20:11:15 steve - * typo in CYMODE=EXAMINE-CI string. - * - * Revision 1.41 2001/03/27 03:31:06 steve - * Support error code from target_t::end_design method. - * - * Revision 1.40 2001/02/10 03:22:49 steve - * Report errors when XNF code has constant X values. (PR#128) - * - * Revision 1.39 2000/11/29 23:15:54 steve - * More informative BUFZ warning. - * - * Revision 1.38 2000/11/29 02:54:49 steve - * Add XNF support for NE comparators. - * - * Revision 1.37 2000/11/29 01:34:17 steve - * Typo writing I pins to AND gates in compare. - * - * Revision 1.36 2000/11/22 21:18:20 steve - * Connect the CE if it is linked at all. - * - * Revision 1.35 2000/08/14 04:39:57 steve - * add th t-dll functions for net_const, net_bufz and processes. - * - * Revision 1.34 2000/08/09 03:43:45 steve - * Move all file manipulation out of target class. - * - * Revision 1.33 2000/08/08 01:50:42 steve - * target methods need not take a file stream. - * - * Revision 1.32 2000/07/14 06:12:58 steve - * Move inital value handling from NetNet to Nexus - * objects. This allows better propogation of inital - * values. - * - * Clean up constant propagation a bit to account - * for regs that are not really values. - * - * Revision 1.31 2000/06/28 18:38:54 steve - * Use nexus type to get nexus name. - * - * Revision 1.30 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.29 2000/05/14 17:55:04 steve - * Support initialization of FF Q value. - * - * Revision 1.28 2000/05/08 05:29:43 steve - * no need for nobufz functor. - * - * Revision 1.27 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.26 2000/04/23 23:03:13 steve - * automatically generate macro interface code. - * - * Revision 1.25 2000/04/23 21:15:07 steve - * Emit code for the bufif devices. - * - * Revision 1.24 2000/04/20 02:34:47 steve - * Generate code for identity compare. Use gates. - * - * Revision 1.23 2000/02/23 02:56:55 steve - * Macintosh compilers do not support ident. - * - * Revision 1.22 1999/12/17 03:38:46 steve - * NetConst can now hold wide constants. - * - * Revision 1.21 1999/12/16 18:54:32 steve - * Capture the carry out of carry-chain addition. - * - * Revision 1.20 1999/12/16 02:42:15 steve - * Simulate carry output on adders. - * - * Revision 1.19 1999/12/05 19:30:43 steve - * Generate XNF RAMS from synthesized memories. - * - * Revision 1.18 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.17 1999/11/17 18:52:09 steve - * Add algorithm for choosing nexus name from attached signals. - * - * Revision 1.16 1999/11/17 01:31:28 steve - * Clean up warnings that add_sub got from Alliance - * - * Revision 1.15 1999/11/06 04:51:42 steve - * Support writing some XNF things into an NCF file. - * - * Revision 1.14 1999/11/05 18:43:12 steve - * fix syntax of EQN record. - * - * Revision 1.13 1999/11/05 07:10:45 steve - * Include the obvious XOR gates in the adders. - * - * Revision 1.12 1999/11/05 04:40:40 steve - * Patch to synthesize LPM_ADD_SUB from expressions, - * Thanks to Larry Doolittle. Also handle constants - * in expressions. - * - * Synthesize adders in XNF, based on a patch from - * Larry. Accept synthesis of constants from Larry - * as is. - * - * Revision 1.11 1999/11/04 03:53:26 steve - * Patch to synthesize unary ~ and the ternary operator. - * Thanks to Larry Doolittle . - * - * Add the LPM_MUX device, and integrate it with the - * ternary synthesis from Larry. Replace the lpm_mux - * generator in t-xnf.cc to use XNF EQU devices to - * put muxs into function units. - * - * Rewrite elaborate_net for the PETernary class to - * also use the LPM_MUX device. - * - * Revision 1.10 1999/11/02 04:55:34 steve - * Add the synthesize method to NetExpr to handle - * synthesis of expressions, and use that method - * to improve r-value handling of LPM_FF synthesis. - * - * Modify the XNF target to handle LPM_FF objects. - * - * Revision 1.9 1999/08/25 22:22:08 steve - * handle bufz in XNF backend. - * - * Revision 1.8 1999/08/18 04:00:02 steve - * Fixup spelling and some error messages. - * - * Revision 1.7 1999/07/17 03:39:11 steve - * simplified process scan for targets. - * - * Revision 1.6 1998/12/09 02:43:19 steve - * Fix 2pin logic gates. - * - * Revision 1.5 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. - * - * Revision 1.4 1998/12/02 04:37:13 steve - * Add the nobufz function to eliminate bufz objects, - * Object links are marked with direction, - * constant propagation is more careful will wide links, - * Signal folding is aware of attributes, and - * the XNF target can dump UDP objects based on LCA - * attributes. - * - * Revision 1.3 1998/11/23 00:20:24 steve - * NetAssign handles lvalues as pin links - * instead of a signal pointer, - * Wire attributes added, - * Ability to parse UDP descriptions added, - * XNF generates EXT records for signals with - * the PAD attribute. - * - * Revision 1.2 1998/11/18 04:25:22 steve - * Add -f flags for generic flag key/values. - * - * Revision 1.1 1998/11/16 05:03:53 steve - * Add the sigfold function that unlinks excess - * signal nodes, and add the XNF target. - * - */ - diff --git a/targets.cc b/targets.cc index 7b2adb9f9..8df415cf3 100644 --- a/targets.cc +++ b/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. - * - */ - diff --git a/xnf-s.conf b/xnf-s.conf deleted file mode 100644 index ffcd9ae6c..000000000 --- a/xnf-s.conf +++ /dev/null @@ -1,6 +0,0 @@ -functor:synth -functor:syn-rules -functor:xnfio -functor:cprop -functor:nodangle --t:xnf diff --git a/xnf.conf b/xnf.conf deleted file mode 100644 index ffcd9ae6c..000000000 --- a/xnf.conf +++ /dev/null @@ -1,6 +0,0 @@ -functor:synth -functor:syn-rules -functor:xnfio -functor:cprop -functor:nodangle --t:xnf diff --git a/xnf.txt b/xnf.txt deleted file mode 100644 index 483bab0ab..000000000 --- a/xnf.txt +++ /dev/null @@ -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 <= ; - -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 () Q <= ; - -The 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 () M[] <= ; - -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[]; - -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='' 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= - 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= - Cause the code generator to write into 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. - diff --git a/xnf2pcf.sh b/xnf2pcf.sh deleted file mode 100644 index abac1aa9c..000000000 --- a/xnf2pcf.sh +++ /dev/null @@ -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.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 -# Date: August 19, 1999 - -echo "SCHEMATIC START ;" -echo "SCHEMATIC END ;" -echo - -awk '/^EXT/{gsub(",",""); printf("COMP \"%s\" LOCATE = SITE \"P%s\" ;\n", $2, $4)}' diff --git a/xnfio.cc b/xnfio.cc deleted file mode 100644 index 9bf99c727..000000000 --- a/xnfio.cc +++ /dev/null @@ -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 - -# 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(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(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(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. - * - */ -