diff --git a/AStatement.h b/AStatement.h index a1b2085ef..0b1b60396 100644 --- a/AStatement.h +++ b/AStatement.h @@ -22,6 +22,7 @@ # include # include "StringHeap.h" # include "LineInfo.h" +# include "PExpr.h" class PExpr; diff --git a/Makefile.in b/Makefile.in index a45841892..6fb8b38d1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -104,7 +104,7 @@ elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \ elab_sig.o emit.o eval.o eval_attrib.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ load_module.o netlist.o netmisc.o net_assign.o \ -net_design.o net_event.o net_expr.o net_force.o net_func.o \ +net_design.o net_event.o net_expr.o net_func.o \ net_link.o net_modulo.o net_nex_input.o net_nex_output.o \ net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \ parse.o parse_misc.o pform.o pform_analog.o pform_disciplines.o \ @@ -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; \ @@ -244,16 +242,10 @@ $(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@ $(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/include/constants.vams: $(srcdir)/constants.vams - $(INSTALL_DATA) $(srcdir)/constants.vams $@ + $(INSTALL_DATA) $(srcdir)/constants.vams $(DESTDIR)$(libdir)/ivl/include/constants.vams $(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams - $(INSTALL_DATA) $(srcdir)/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 + $(INSTALL_DATA) $(srcdir)/disciplines.vams $(DESTDIR)$(libdir)/ivl/include/disciplines.vams $(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/Statement.cc b/Statement.cc index 02680d322..a8c9b9627 100644 --- a/Statement.cc +++ b/Statement.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2008 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 @@ -16,9 +16,6 @@ * 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: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $" -#endif # include "config.h" @@ -30,19 +27,19 @@ Statement::~Statement() } PAssign_::PAssign_(PExpr*lval, PExpr*ex) -: event_(0), lval_(lval), rval_(ex) +: event_(0), count_(0), lval_(lval), rval_(ex) { delay_ = 0; } PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex) -: event_(0), lval_(lval), rval_(ex) +: event_(0), count_(0), lval_(lval), rval_(ex) { delay_ = de; } -PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex) -: event_(ev), lval_(lval), rval_(ex) +PAssign_::PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*ev, PExpr*ex) +: event_(ev), count_(cnt), lval_(lval), rval_(ex) { delay_ = 0; } @@ -63,8 +60,8 @@ PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex) { } -PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex) -: PAssign_(lval, d, ex) +PAssign::PAssign(PExpr*lval, PExpr*cnt, PEventStatement*d, PExpr*ex) +: PAssign_(lval, cnt, d, ex) { } @@ -82,6 +79,11 @@ PAssignNB::PAssignNB(PExpr*lval, PExpr*d, PExpr*ex) { } +PAssignNB::PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*d, PExpr*ex) +: PAssign_(lval, cnt, d, ex) +{ +} + PAssignNB::~PAssignNB() { } @@ -298,38 +300,3 @@ PWhile::~PWhile() delete cond_; delete statement_; } - -/* - * $Log: Statement.cc,v $ - * Revision 1.30 2007/05/24 04:07:11 steve - * Rework the heirarchical identifier parse syntax and pform - * to handle more general combinations of heirarch and bit selects. - * - * Revision 1.29 2004/02/18 17:11:54 steve - * Use perm_strings for named langiage items. - * - * Revision 1.28 2002/08/12 01:34:58 steve - * conditional ident string using autoconfig. - * - * Revision 1.27 2002/04/21 22:31:02 steve - * Redo handling of assignment internal delays. - * Leave it possible for them to be calculated - * at run time. - * - * Revision 1.26 2002/04/21 04:59:07 steve - * Add support for conbinational events by finding - * the inputs to expressions and some statements. - * Get case and assignment statements working. - * - * Revision 1.25 2001/12/03 04:47:14 steve - * Parser and pform use hierarchical names as hname_t - * objects instead of encoded strings. - * - * Revision 1.24 2001/11/22 06:20:59 steve - * Use NetScope instead of string for scope path. - * - * Revision 1.23 2001/07/25 03:10:48 steve - * Create a config.h.in file to hold all the config - * junk, and support gcc 3.0. (Stephan Boettcher) - */ - diff --git a/Statement.h b/Statement.h index bdf4e07f4..961e4f71d 100644 --- a/Statement.h +++ b/Statement.h @@ -93,7 +93,7 @@ class PAssign_ : public Statement { public: explicit PAssign_(PExpr*lval, PExpr*ex); explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex); - explicit PAssign_(PExpr*lval, PEventStatement*de, PExpr*ex); + explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex); virtual ~PAssign_() =0; const PExpr* lval() const { return lval_; } @@ -105,6 +105,7 @@ class PAssign_ : public Statement { PExpr* delay_; PEventStatement*event_; + PExpr* count_; private: PExpr* lval_; @@ -116,7 +117,7 @@ class PAssign : public PAssign_ { public: explicit PAssign(PExpr*lval, PExpr*ex); explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex); - explicit PAssign(PExpr*lval, PEventStatement*de, PExpr*ex); + explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex); ~PAssign(); virtual void dump(ostream&out, unsigned ind) const; @@ -130,6 +131,7 @@ class PAssignNB : public PAssign_ { public: explicit PAssignNB(PExpr*lval, PExpr*ex); explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex); + explicit PAssignNB(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex); ~PAssignNB(); virtual void dump(ostream&out, unsigned ind) const; @@ -334,6 +336,9 @@ class PEventStatement : public Statement { void set_statement(Statement*st); virtual void dump(ostream&out, unsigned ind) const; + // Call this with a NULL statement only. It is used to print + // the event expression for inter-assignment event controls. + virtual void dump_inline(ostream&out) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*scope) const; virtual void elaborate_sig(Design*des, NetScope*scope) const; @@ -349,6 +354,8 @@ class PEventStatement : public Statement { Statement*statement_; }; +ostream& operator << (ostream&o, const PEventStatement&obj); + class PForce : public Statement { public: diff --git a/cadpli/Makefile.in b/cadpli/Makefile.in index 9d8885847..2d4f81c0f 100644 --- a/cadpli/Makefile.in +++ b/cadpli/Makefile.in @@ -76,13 +76,13 @@ distclean: clean install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32) $(vpidir)/cadpli.vpl: ./cadpli.vpl - $(INSTALL_PROGRAM) ./cadpli.vpl $(vpidir)/cadpli.vpl + $(INSTALL_PROGRAM) ./cadpli.vpl $(DESTDIR)$(vpidir)/cadpli.vpl installdirs: ../mkinstalldirs - $(srcdir)/../mkinstalldirs $(vpidir) + $(srcdir)/../mkinstalldirs $(DESTDIR)$(vpidir) uninstall: $(UNINSTALL32) - rm -f $(vpidir)/cadpli.vpl + rm -f $(DESTDIR)$(vpidir)/cadpli.vpl uninstall32: diff --git a/driver/Makefile.in b/driver/Makefile.in index 254b65dfd..e3b91d3e4 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -100,17 +100,17 @@ endif install: all installdirs $(bindir)/iverilog@EXEEXT@ $(INSTALL_DOC) $(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@ - $(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@ + $(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(DESTDIR)$(bindir)/iverilog@EXEEXT@ $(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man - $(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1 + $(INSTALL_DATA) $(srcdir)/iverilog.man $(DESTDIR)$(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf: iverilog.pdf $(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog.pdf installdirs: ../mkinstalldirs - $(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR) + $(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(INSTALL_DOCDIR) uninstall: - rm -f $(bindir)/iverilog@EXEEXT@ - rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf + rm -f $(DESTDIR)$(bindir)/iverilog@EXEEXT@ + rm -f $(DESTDIR)$(mandir)/man1/iverilog.1 $(DESTDIR)$(prefix)/iverilog.pdf 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/dup_expr.cc b/dup_expr.cc index ad4bb7b0a..c6bf13416 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -21,6 +21,7 @@ # include "netlist.h" # include +# include # include "ivl_assert.h" NetEAccess* NetEAccess::dup_expr() const diff --git a/elab_scope.cc b/elab_scope.cc index 5df05b7bc..8e104b5da 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -621,9 +621,6 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container) return false; } - // The name of the scope to generate, whatever that item is. - hname_t use_name (scope_name); - if (debug_scopes) cerr << get_fileline() << ": debug: Generate case " << "switch value=" << case_value_co->value() << endl; @@ -673,6 +670,9 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container) << "Generate case matches item at " << item->get_fileline() << endl; + // The name of the scope to generate, whatever that item is. + hname_t use_name (item->scope_name); + NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK); scope->set_line(get_file(), get_lineno()); diff --git a/elaborate.cc b/elaborate.cc index 363239052..43b3c860f 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1702,6 +1702,9 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const /* Elaborate the r-value expression, then try to evaluate it. */ NetExpr*rv = elaborate_rval_(des, scope, count_lval_width(lv)); if (rv == 0) return 0; + assert(rv); + + if (count_) assert(event_); /* Rewrite delayed assignments as assignments that are delayed. For example, a = # b; becomes: @@ -1754,19 +1757,58 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const /* Generate the delay statement with the final assignment attached to it. If this is an event delay, elaborate the PEventStatement. Otherwise, create the - right NetPDelay object. */ + right NetPDelay object. For a repeat event control + repeat the event and then do the final assignment. */ NetProc*st; if (event_) { - st = event_->elaborate_st(des, scope, a2); - if (st == 0) { - cerr << event_->get_fileline() << ": error: " - "unable to elaborate event expression." - << endl; - des->errors += 1; - return 0; - } - assert(st); + if (count_) { + NetExpr*count = elab_and_eval(des, scope, count_, -1); + if (count == 0) { + cerr << get_fileline() << ": Unable to " + "elaborate repeat expression." << endl; + des->errors += 1; + return 0; + } + st = event_->elaborate(des, scope); + if (st == 0) { + cerr << event_->get_fileline() << ": error: " + "unable to elaborate event expression." + << endl; + des->errors += 1; + return 0; + } + // If the expression is a constant, handle + // certain special iteration counts. + if (NetEConst*ce = dynamic_cast(count)) { + long val = ce->value().as_long(); + // We only need the real statement. + if (val <= 0) { + delete count; + delete st; + st = 0; + + // We don't need the repeat statement. + } else if (val == 1) { + delete count; + + // We need a repeat statement. + } else { + st = new NetRepeat(count, st); + } + } else { + st = new NetRepeat(count, st); + } + } else { + st = event_->elaborate_st(des, scope, a2); + if (st == 0) { + cerr << event_->get_fileline() << ": error: " + "unable to elaborate event expression." + << endl; + des->errors += 1; + return 0; + } + } } else { NetPDelay*de = new NetPDelay(delay, a2); de->set_line(*this); @@ -1776,7 +1818,8 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const /* And build up the complex statement. */ NetBlock*bl = new NetBlock(NetBlock::SEQU, 0); bl->append(a1); - bl->append(st); + if (st) bl->append(st); + if (count_) bl->append(a2); return bl; } @@ -1842,6 +1885,34 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const if (delay_ != 0) delay = elaborate_delay_expr(delay_, des, scope); + if (count_ != 0 || event_ != 0) { + NetExpr*count = 0; + if (count_ != 0) { + assert(event_ != 0); + count = elab_and_eval(des, scope, count_, -1); + if (count == 0) { + cerr << get_fileline() << ": Unable to elaborate " + "repeat expression." << endl; + des->errors += 1; +// return 0; + } + } + + NetProc* event = event_->elaborate(des, scope); + if (event == 0) { + cerr << get_fileline() << ": unable to elaborate " + "event expression." << endl; + des->errors += 1; +// return 0; + } + + cerr << get_fileline() << ": sorry: non blocking "; + if (count_) cerr << "repeat "; + cerr << "event controls are not supported." << endl; + des->errors += 1; + return 0; + } + /* All done with this node. Mark its line number and check it in. */ NetAssignNB*cur = new NetAssignNB(lv, rv); cur->set_delay(delay); @@ -3089,17 +3160,14 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const // If the expression is a constant, handle certain special // iteration counts. if (NetEConst*ce = dynamic_cast(expr)) { - verinum val = ce->value(); - switch (val.as_ulong()) { - case 0: + long val = ce->value().as_long(); + if (val <= 0) { delete expr; delete stat; return new NetBlock(NetBlock::SEQU, 0); - case 1: + } else if (val == 1) { delete expr; return stat; - default: - break; } } diff --git a/eval_tree.cc b/eval_tree.cc index 1ccea7463..37ce9d6c7 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -581,7 +581,7 @@ NetEConst* NetEBComp::eval_eqeq_real_(NetExpr*le, NetExpr*ri, bool ne_flag) assert(0); } - verinum result((lv == rv ^ ne_flag) ? verinum::V1 : verinum::V0, 1); + verinum result(((lv == rv) ^ ne_flag) ? verinum::V1 : verinum::V0, 1); vtmp = new NetEConst(result); vtmp->set_line(*this); @@ -1788,7 +1788,7 @@ NetExpr* evaluate_abs(NetExpr*arg) NetEConst*tmpi = dynamic_cast(arg); if (tmpi) { verinum arg = tmpi->value(); - if (arg.has_sign()) { + if (arg.is_negative()) { arg = v_not(arg) + verinum(1); } return new NetEConst(arg); diff --git a/ivlpp/Makefile.in b/ivlpp/Makefile.in index b55b5c7ac..b66ed207a 100644 --- a/ivlpp/Makefile.in +++ b/ivlpp/Makefile.in @@ -63,13 +63,13 @@ lexor.c: lexor.lex install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@ - $(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@ + $(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivlpp@EXEEXT@ installdirs: ../mkinstalldirs - $(srcdir)/../mkinstalldirs $(libdir)/ivl + $(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl uninstall: - rm -f $(libdir)/ivl/ivlpp@EXEEXT@ + rm -f $(DESTDIR)$(libdir)/ivl/ivlpp@EXEEXT@ lexor.o: lexor.c globals.h main.o: main.c globals.h diff --git a/libveriuser/Makefile.in b/libveriuser/Makefile.in index c8a56679c..7fc807e84 100644 --- a/libveriuser/Makefile.in +++ b/libveriuser/Makefile.in @@ -89,12 +89,12 @@ distclean: clean install:: all installdirs $(libdir)/libveriuser.a $(INSTALL32) $(libdir)/libveriuser.a: ./libveriuser.a - $(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a + $(INSTALL_DATA) ./libveriuser.a $(DESTDIR)$(libdir)/libveriuser.a installdirs: mkinstalldirs - $(srcdir)/mkinstalldirs $(includedir) $(libdir) + $(srcdir)/mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(libdir) uninstall:: - rm -f $(libdir)/libveriuser.a + rm -f $(DESTDIR)$(libdir)/libveriuser.a -include $(patsubst %.o, dep/%.d, $O) 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/net_force.cc b/net_force.cc deleted file mode 100644 index 3707bab39..000000000 --- a/net_force.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2000-2004 Stephen Williams (steve@picturel.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: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $" -#endif - -# include "config.h" -# include "compiler.h" - -/* - * This file contains implementation of the NetForce, NetRelease, - * NetCAssign and NetDeassign classes. These are similar or related in - * that they handle the procedural continuous assign and force - * statements. - */ - -# include "netlist.h" -# include - - -/* - * $Log: net_force.cc,v $ - * Revision 1.13 2004/12/11 02:31:26 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.12 2004/02/18 17:11:56 steve - * Use perm_strings for named langiage items. - * - * Revision 1.11 2003/03/06 00:28:41 steve - * All NetObj objects have lex_string base names. - * - * Revision 1.10 2003/01/27 05:09:17 steve - * Spelling fixes. - * - * Revision 1.9 2002/08/19 00:06:12 steve - * Allow release to handle removal of target net. - * - * Revision 1.8 2002/08/12 01:34:59 steve - * conditional ident string using autoconfig. - * - * Revision 1.7 2002/01/19 19:02:08 steve - * Pass back target errors processing conditionals. - * - * Revision 1.6 2001/11/14 03:28:49 steve - * DLL target support for force and release. - * - * Revision 1.5 2001/10/31 05:24:52 steve - * ivl_target support for assign/deassign. - * - * Revision 1.4 2001/10/28 01:14:53 steve - * NetObj constructor finally requires a scope. - * - * Revision 1.3 2001/07/25 03:10:49 steve - * Create a config.h.in file to hold all the config - * junk, and support gcc 3.0. (Stephan Boettcher) - * - * Revision 1.2 2000/05/12 01:22:41 steve - * NetCAssign needs to incr_eref its lval to lock it down. - * - * Revision 1.1 2000/05/11 23:37:27 steve - * Add support for procedural continuous assignment. - * - */ - diff --git a/netlist.cc b/netlist.cc index 9e10d52db..abe72999b 100644 --- a/netlist.cc +++ b/netlist.cc @@ -426,7 +426,8 @@ const Link& NetDelaySrc::condit_pin() const NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins) : NetObj(s, n, 1), sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), - signed_(false), isint_(false), msb_(npins-1), lsb_(0), dimensions_(0), + signed_(false), isint_(false), discipline_(0), msb_(npins-1), lsb_(0), + dimensions_(0), s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0) { assert(s); @@ -466,7 +467,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, : NetObj(s, n, 1), sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false), - isint_(false), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0), + isint_(false), discipline_(0), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0) { assert(s); @@ -514,7 +515,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, : NetObj(s, n, calculate_count(array_s, array_e)), sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false), - msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e), + discipline_(0), msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e), local_flag_(false), eref_count_(0), lref_count_(0) { assert(s); diff --git a/parse.y b/parse.y index 015034559..4f02bafc7 100644 --- a/parse.y +++ b/parse.y @@ -3648,28 +3648,23 @@ statement $$ = tmp; } | lpvalue '=' event_control expression ';' - { PAssign*tmp = new PAssign($1,$3,$4); + { PAssign*tmp = new PAssign($1,0,$3,$4); FILE_NAME(tmp, @1); $$ = tmp; } | lpvalue '=' K_repeat '(' expression ')' event_control expression ';' - { PAssign*tmp = new PAssign($1,$7,$8); + { PAssign*tmp = new PAssign($1,$5,$7,$8); FILE_NAME(tmp,@1); tmp->set_lineno(@1.first_line); - yyerror(@3, "sorry: repeat event control not supported."); - delete $5; $$ = tmp; } | lpvalue K_LE event_control expression ';' - { yyerror(@1, "sorry: Event controls not supported here."); - PAssignNB*tmp = new PAssignNB($1,$4); + { PAssignNB*tmp = new PAssignNB($1,0,$3,$4); FILE_NAME(tmp, @1); $$ = tmp; } | lpvalue K_LE K_repeat '(' expression ')' event_control expression ';' - { yyerror(@1, "sorry: Event controls not supported here."); - delete $5; - PAssignNB*tmp = new PAssignNB($1,$8); + { PAssignNB*tmp = new PAssignNB($1,$5,$7,$8); FILE_NAME(tmp, @1); $$ = tmp; } diff --git a/pform_dump.cc b/pform_dump.cc index e9d65044f..f2f85e733 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -40,6 +40,12 @@ ostream& operator << (ostream&out, const PExpr&obj) return out; } +ostream& operator << (ostream&out, const PEventStatement&obj) +{ + obj.dump_inline(out); + return out; +} + ostream& operator << (ostream&o, const PDelays&d) { d.dump_delays(o); @@ -557,16 +563,20 @@ void AContrib::dump(ostream&out, unsigned ind) const void PAssign::dump(ostream&out, unsigned ind) const { - out << setw(ind) << ""; - out << *lval() << " = " << delay_ << " " << *rval() << ";"; - out << " /* " << get_fileline() << " */" << endl; + out << setw(ind) << "" << *lval() << " = "; + if (delay_) out << "#" << *delay_ << " "; + if (count_) out << "repeat(" << *count_ << ") "; + if (event_) out << *event_ << " "; + out << *rval() << ";" << " /* " << get_fileline() << " */" << endl; } void PAssignNB::dump(ostream&out, unsigned ind) const { - out << setw(ind) << ""; - out << *lval() << " <= " << delay_ << " " << *rval() << ";"; - out << " /* " << get_fileline() << " */" << endl; + out << setw(ind) << "" << *lval() << " <= "; + if (delay_) out << "#" << *delay_ << " "; + if (count_) out << "repeat(" << *count_ << ") "; + if (event_) out << *event_ << " "; + out << *rval() << ";" << " /* " << get_fileline() << " */" << endl; } void PBlock::dump(ostream&out, unsigned ind) const @@ -716,6 +726,23 @@ void PEventStatement::dump(ostream&out, unsigned ind) const } } +void PEventStatement::dump_inline(ostream&out) const +{ + assert(statement_ == 0); + + if (expr_.count() == 0) { + out << "@* "; + + } else { + out << "@(" << *(expr_[0]); + if (expr_.count() > 1) + for (unsigned idx = 1 ; idx < expr_.count() ; idx += 1) + out << " or " << *(expr_[idx]); + + out << ")"; + } +} + void PForce::dump(ostream&out, unsigned ind) const { out << setw(ind) << "" << "force " << *lval_ << " = " << *expr_ diff --git a/t-dll.cc b/t-dll.cc index 98ade6c15..8cec7bac7 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1921,6 +1921,7 @@ void dll_target::lpm_mult(const NetMult*net) unsigned wid = net->width_r(); obj->width = wid; + obj->u_.arith.signed_flag = 0; const Nexus*nex; @@ -2204,6 +2205,7 @@ bool dll_target::net_const(const NetConst*net) assert(net->pin_count() == 1); obj->width_ = net->width(); + obj->signed_ = 0; if (obj->width_ <= sizeof(obj->b.bit_)) { bits = obj->b.bit_; 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/tgt-null/Makefile.in b/tgt-null/Makefile.in index 204e6a00c..426d35230 100644 --- a/tgt-null/Makefile.in +++ b/tgt-null/Makefile.in @@ -75,22 +75,22 @@ check: all install: all installdirs $(libdir)/ivl/null.tgt $(INSTALL_DOC) $(libdir)/ivl/null.conf $(libdir)/ivl/null-s.conf $(libdir)/ivl/null.tgt: ./null.tgt - $(INSTALL_PROGRAM) ./null.tgt $(libdir)/ivl/null.tgt + $(INSTALL_PROGRAM) ./null.tgt $(DESTDIR)$(libdir)/ivl/null.tgt $(libdir)/ivl/null.conf: $(srcdir)/null.conf - $(INSTALL_DATA) $(srcdir)/null.conf $(libdir)/ivl/null.conf + $(INSTALL_DATA) $(srcdir)/null.conf $(DESTDIR)$(libdir)/ivl/null.conf $(libdir)/ivl/null-s.conf: $(srcdir)/null-s.conf - $(INSTALL_DATA) $(srcdir)/null-s.conf $(libdir)/ivl/null-s.conf + $(INSTALL_DATA) $(srcdir)/null-s.conf $(DESTDIR)$(libdir)/ivl/null-s.conf installdirs: ../mkinstalldirs - $(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl + $(srcdir)/../mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(bindir) $(DESTDIR)$(libdir)/ivl uninstall: - rm -f $(libdir)/ivl/null.tgt - rm -f $(libdir)/ivl/null.conf - rm -f $(libdir)/ivl/null-s.conf + rm -f $(DESTDIR)$(libdir)/ivl/null.tgt + rm -f $(DESTDIR)$(libdir)/ivl/null.conf + rm -f $(DESTDIR)$(libdir)/ivl/null-s.conf -include $(patsubst %.o, dep/%.d, $O) diff --git a/tgt-stub/Makefile.in b/tgt-stub/Makefile.in index 679226758..20d0136f9 100644 --- a/tgt-stub/Makefile.in +++ b/tgt-stub/Makefile.in @@ -76,21 +76,21 @@ install: all installdirs $(libdir)/ivl/stub.tgt \ $(libdir)/ivl/stub.conf $(libdir)/ivl/stub-s.conf $(libdir)/ivl/stub.tgt: ./stub.tgt - $(INSTALL_PROGRAM) ./stub.tgt $(libdir)/ivl/stub.tgt + $(INSTALL_PROGRAM) ./stub.tgt $(DESTDIR)$(libdir)/ivl/stub.tgt $(libdir)/ivl/stub.conf: stub.conf - $(INSTALL_DATA) $< $(libdir)/ivl/stub.conf + $(INSTALL_DATA) $< $(DESTDIR)$(libdir)/ivl/stub.conf $(libdir)/ivl/stub-s.conf: stub-s.conf - $(INSTALL_DATA) $< $(libdir)/ivl/stub-s.conf + $(INSTALL_DATA) $< $(DESTDIR)$(libdir)/ivl/stub-s.conf installdirs: ../mkinstalldirs - $(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl + $(srcdir)/../mkinstalldirs $(DESTDIR)$(includedir) $(DESTDIR)$(bindir) $(DESTDIR)$(libdir)/ivl uninstall: - rm -f $(libdir)/ivl/stub.tgt - rm -f $(libdir)/ivl/stub.conf - rm -f $(libdir)/ivl/stub-s.conf + rm -f $(DESTDIR)$(libdir)/ivl/stub.tgt + rm -f $(DESTDIR)$(libdir)/ivl/stub.conf + rm -f $(DESTDIR)$(libdir)/ivl/stub-s.conf -include $(patsubst %.o, dep/%.d, $O) diff --git a/tgt-vhdl/Makefile.in b/tgt-vhdl/Makefile.in index bbd0cfeaf..7b76b1936 100644 --- a/tgt-vhdl/Makefile.in +++ b/tgt-vhdl/Makefile.in @@ -77,16 +77,16 @@ check: all install: all installdirs $(libdir)/ivl/vhdl.tgt $(libdir)/ivl/vhdl.conf $(libdir)/ivl/vhdl.tgt: ./vhdl.tgt - $(INSTALL_PROGRAM) ./vhdl.tgt $(libdir)/ivl/vhdl.tgt + $(INSTALL_PROGRAM) ./vhdl.tgt $(DESTDIR)$(libdir)/ivl/vhdl.tgt $(libdir)/ivl/vhdl.conf: vhdl.conf - $(INSTALL_DATA) $< $(libdir)/ivl/vhdl.conf + $(INSTALL_DATA) $< $(DESTDIR)$(libdir)/ivl/vhdl.conf installdirs: ../mkinstalldirs - $(srcdir)/../mkinstalldirs $(libdir)/ivl + $(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl uninstall: - rm -f $(libdir)/ivl/vhdl.tgt $(libdir)/ivl/vhdl.conf + rm -f $(DESTDIR)$(libdir)/ivl/vhdl.tgt $(DESTDIR)$(libdir)/ivl/vhdl.conf -include $(patsubst %.o, dep/%.d, $O) diff --git a/tgt-vvp/Makefile.in b/tgt-vvp/Makefile.in index 323212332..f3e8b9b0d 100644 --- a/tgt-vvp/Makefile.in +++ b/tgt-vvp/Makefile.in @@ -88,20 +88,20 @@ check: all install: all installdirs $(libdir)/ivl/vvp.tgt $(libdir)/ivl/vvp.conf $(libdir)/ivl/vvp-s.conf $(libdir)/ivl/vvp.tgt: ./vvp.tgt - $(INSTALL_PROGRAM) ./vvp.tgt $(libdir)/ivl/vvp.tgt + $(INSTALL_PROGRAM) ./vvp.tgt $(DESTDIR)$(libdir)/ivl/vvp.tgt $(libdir)/ivl/vvp.conf: vvp.conf - $(INSTALL_DATA) $< $(libdir)/ivl/vvp.conf + $(INSTALL_DATA) $< $(DESTDIR)$(libdir)/ivl/vvp.conf $(libdir)/ivl/vvp-s.conf: vvp-s.conf - $(INSTALL_DATA) $< $(libdir)/ivl/vvp-s.conf + $(INSTALL_DATA) $< $(DESTDIR)$(libdir)/ivl/vvp-s.conf installdirs: ../mkinstalldirs - $(srcdir)/../mkinstalldirs $(libdir)/ivl + $(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir)/ivl uninstall: - rm -f $(libdir)/ivl/vvp.tgt $(libdir)/ivl/vvp.conf $(libdir)/ivl/vvp-s.conf + rm -f $(DESTDIR)$(libdir)/ivl/vvp.tgt $(DESTDIR)$(libdir)/ivl/vvp.conf $(DESTDIR)$(libdir)/ivl/vvp-s.conf -include $(patsubst %.o, dep/%.d, $O) diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 41220c832..302c1e3c4 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1402,10 +1402,11 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope) unsigned lab_top = local_count++, lab_out = local_count++; ivl_expr_t exp = ivl_stmt_cond_expr(net); struct vector_info cnt = draw_eval_expr(exp, 0); + char *sign = ivl_expr_signed(exp) ? "s" : "u"; /* Test that 0 < expr */ - fprintf(vvp_out, "T_%u.%u %%cmp/u 0, %u, %u;\n", thread_count, - lab_top, cnt.base, cnt.wid); + fprintf(vvp_out, "T_%u.%u %%cmp/%s 0, %u, %u;\n", thread_count, + lab_top, sign, cnt.base, cnt.wid); clear_expression_lookaside(); fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, lab_out); /* This adds -1 (all ones in 2's complement) to the count. */ diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index e018166bb..89cc691a9 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1193,13 +1193,10 @@ static void draw_lpm_array(ivl_lpm_t net) { ivl_nexus_t nex; ivl_signal_t mem = ivl_lpm_array(net); - - fprintf(vvp_out, "L_%p .array/port v%p, ", net, mem); - nex = ivl_lpm_select(net); - fprintf(vvp_out, "%s", draw_net_input(nex)); + const char*tmp = draw_net_input(nex); - fprintf(vvp_out, ";\n"); + fprintf(vvp_out, "L_%p .array/port v%p, %s;\n", net, mem, tmp); } static void draw_lpm_cmp(ivl_lpm_t net) diff --git a/verilog.spec b/verilog.spec index ed747afae..a96b1100d 100644 --- a/verilog.spec +++ b/verilog.spec @@ -1,6 +1,6 @@ #norootforbuild # -%define rev_date 20080429 +%define rev_date 20080830 # # Summary: Icarus Verilog @@ -41,11 +41,10 @@ rm -rf $RPM_BUILD_ROOT %files -%attr(-,root,root) %doc COPYING README.txt BUGS.txt QUICK_START.txt ieee1364-notes.txt mingw.txt swift.txt netlist.txt t-dll.txt vpi.txt xnf.txt tgt-fpga/fpga.txt cadpli/cadpli.txt xilinx-hint.txt +%attr(-,root,root) %doc COPYING README.txt BUGS.txt QUICK_START.txt ieee1364-notes.txt mingw.txt swift.txt netlist.txt t-dll.txt vpi.txt tgt-fpga/fpga.txt cadpli/cadpli.txt %attr(-,root,root) %doc examples/* %attr(-,root,root) %{_mandir}/man1/iverilog.1.gz -#%attr(-,root,root) /usr/man/man1/iverilog-fpga.1.gz %attr(-,root,root) %{_mandir}/man1/iverilog-vpi.1.gz %attr(-,root,root) %{_mandir}/man1/vvp.1.gz @@ -63,16 +62,19 @@ rm -rf $RPM_BUILD_ROOT %attr(-,root,root) %{_libdir}/ivl/vvp.tgt %attr(-,root,root) %{_libdir}/ivl/vvp.conf %attr(-,root,root) %{_libdir}/ivl/vvp-s.conf -#%attr(-,root,root) %{_libdir}/ivl/fpga.tgt -#%attr(-,root,root) %{_libdir}/ivl/fpga.conf -#%attr(-,root,root) %{_libdir}/ivl/fpga-s.conf -#%attr(-,root,root) %{_libdir}/ivl/xnf.conf -#%attr(-,root,root) %{_libdir}/ivl/xnf-s.conf +%attr(-,root,root) %{_libdir}/ivl/vhdl.tgt +%attr(-,root,root) %{_libdir}/ivl/vhdl.conf %attr(-,root,root) %{_libdir}/ivl/system.sft %attr(-,root,root) %{_libdir}/ivl/system.vpi +%attr(-,root,root) %{_libdir}/ivl/va_math.sft +%attr(-,root,root) %{_libdir}/ivl/va_math.vpi +%attr(-,root,root) %{_libdir}/ivl/v2005_math.sft +%attr(-,root,root) %{_libdir}/ivl/v2005_math.vpi %attr(-,root,root) %{_libdir}/ivl/cadpli.vpl %attr(-,root,root) %{_libdir}/libvpi.a %attr(-,root,root) %{_libdir}/libveriuser.a +%attr(-,root,root) %{_libdir}/ivl/include/constants.vams +%attr(-,root,root) %{_libdir}/ivl/include/disciplines.vams %attr(-,root,root) /usr/include/ivl_target.h %attr(-,root,root) /usr/include/vpi_user.h %attr(-,root,root) /usr/include/acc_user.h @@ -80,6 +82,10 @@ rm -rf $RPM_BUILD_ROOT %attr(-,root,root) /usr/include/_pli_types.h %changelog -n verilog +* Sat Aug 30 2008 - steve@icarus.com +- Add vhdl target files +- Add V/AMS header files. + * Fri Jan 25 2008 - steve@icarus.com - Removed vvp32 support for x86_64 build. diff --git a/vpi/Makefile.in b/vpi/Makefile.in index 0b5c703ed..29701d77b 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -116,36 +116,35 @@ check: all install: all installdirs \ $(vpidir)/system.vpi $(libdir)/ivl/system.sft \ $(vpidir)/va_math.vpi $(libdir)/ivl/va_math.sft \ - $(vpidir)/v2005_math.vpi $(libdir)/ivl/v2005_math.sft \ - $(vpidir)/include/ + $(vpidir)/v2005_math.vpi $(libdir)/ivl/v2005_math.sft $(vpidir)/system.vpi: ./system.vpi - $(INSTALL_PROGRAM) ./system.vpi $(vpidir)/system.vpi + $(INSTALL_PROGRAM) ./system.vpi $(DESTDIR)$(vpidir)/system.vpi $(libdir)/ivl/system.sft: system.sft - $(INSTALL_DATA) $< $@ + $(INSTALL_DATA) $< $(DESTDIR)$@ $(vpidir)/va_math.vpi: ./va_math.vpi - $(INSTALL_PROGRAM) ./va_math.vpi $(vpidir)/va_math.vpi + $(INSTALL_PROGRAM) ./va_math.vpi $(DESTDIR)$(vpidir)/va_math.vpi $(libdir)/ivl/va_math.sft: va_math.sft - $(INSTALL_DATA) $< $@ + $(INSTALL_DATA) $< $(DESTDIR)$@ $(vpidir)/v2005_math.vpi: ./v2005_math.vpi - $(INSTALL_PROGRAM) ./v2005_math.vpi $(vpidir)/v2005_math.vpi + $(INSTALL_PROGRAM) ./v2005_math.vpi $(DESTDIR)$(vpidir)/v2005_math.vpi $(libdir)/ivl/v2005_math.sft: v2005_math.sft - $(INSTALL_DATA) $< $@ + $(INSTALL_DATA) $< $(DESTDIR)$@ installdirs: ../mkinstalldirs - $(srcdir)/../mkinstalldirs $(vpidir) + $(srcdir)/../mkinstalldirs $(DESTDIR)$(libdir) $(DESTDIR)$(vpidir) uninstall: - rm -f $(vpidir)/system.vpi - rm -f $(libdir)/ivl/system.sft - rm -f $(vpidir)/va_math.vpi - rm -f $(libdir)/ivl/va_math.sft - rm -f $(vpidir)/v2005_math.vpi - rm -f $(libdir)/ivl/v2005_math.sft + rm -f $(DESTDIR)$(vpidir)/system.vpi + rm -f $(DESTDIR)$(libdir)/ivl/system.sft + rm -f $(DESTDIR)$(vpidir)/va_math.vpi + rm -f $(DESTDIR)$(libdir)/ivl/va_math.sft + rm -f $(DESTDIR)$(vpidir)/v2005_math.vpi + rm -f $(DESTDIR)$(libdir)/ivl/v2005_math.sft -include $(patsubst %.o, dep/%.d, $O) diff --git a/vvp/Makefile.in b/vvp/Makefile.in index ab1e8b227..a65994e6b 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -161,24 +161,24 @@ Makefile: Makefile.in config.status install: all installdirs $(bindir)/vvp@EXEEXT@ $(libdir)/libvpi.a $(INSTALL_DOC) $(bindir)/vvp@EXEEXT@: ./vvp@EXEEXT@ - $(INSTALL_PROGRAM) ./vvp@EXEEXT@ $(bindir)/vvp@EXEEXT@ + $(INSTALL_PROGRAM) ./vvp@EXEEXT@ $(DESTDIR)$(bindir)/vvp@EXEEXT@ $(libdir)/libvpi.a : ./libvpi.a - $(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a + $(INSTALL_DATA) libvpi.a $(DESTDIR)$(libdir)/libvpi.a $(mandir)/man1/vvp.1: $(srcdir)/vvp.man - $(INSTALL_DATA) $(srcdir)/vvp.man $(mandir)/man1/vvp.1 + $(INSTALL_DATA) $(srcdir)/vvp.man $(DESTDIR)$(mandir)/man1/vvp.1 $(prefix)/vvp.pdf: vvp.pdf - $(INSTALL_DATA) vvp.pdf $(prefix)/vvp.pdf + $(INSTALL_DATA) vvp.pdf $(DESTDIR)$(prefix)/vvp.pdf installdirs: $(srcdir)/mkinstalldirs - $(srcdir)/mkinstalldirs $(bindir) $(libdir) $(libdir) $(INSTALL_DOCDIR) + $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(libdir) $(DESTDIR)$(INSTALL_DOCDIR) uninstall: $(UNINSTALL32) - rm -f $(bindir)/vvp@EXEEXT@ - rm -f $(libdir)/libvpi.a - rm -f $(mandir)/man1/vvp.1 $(prefix)/vvp.pdf + rm -f $(DESTDIR)$(bindir)/vvp@EXEEXT@ + rm -f $(DESTDIR)$(libdir)/libvpi.a + rm -f $(DESTDIR)$(mandir)/man1/vvp.1 $(DESTDIR)$(prefix)/vvp.pdf -include $(patsubst %.o, dep/%.d, $O) diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 9e2f7f28e..fa869bf0a 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1557,8 +1557,26 @@ vvp_vector2_t& vvp_vector2_t::operator >>= (unsigned shift) } // Cleanup the tail bits. - unsigned long mask = -1UL >> (BITS_PER_WORD - wid_%BITS_PER_WORD); - vec_[words-1] &= mask; + + unsigned use_words = words; + // Mask_shift is the number of high bits of the top word + // that are to be masked off. We start with the number + // of bits that are not included even in the original, + // then we include the bits of the shift, that are to be + // masked to zero. + unsigned long mask_shift = BITS_PER_WORD - wid_%BITS_PER_WORD; + mask_shift %= BITS_PER_WORD; + mask_shift += oshift; + while (mask_shift >= BITS_PER_WORD) { + vec_[use_words-1] = 0; + use_words -= 1; + mask_shift -= BITS_PER_WORD; + } + if (mask_shift > 0) { + assert(use_words > 0); + unsigned long mask = -1UL >> mask_shift; + vec_[use_words-1] &= mask; + } } return *this; 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. - * - */ -