Compare commits

...

42 Commits

Author SHA1 Message Date
steve 05e6d51004 Snapshot 0.8.2 2005-09-30 15:13:37 +00:00
steve ae583204e3 Snapshot 0.8.2 2005-09-30 15:01:44 +00:00
steve 018476f7cd More predictable ordering of items in NexusSet. 2005-09-25 23:30:31 +00:00
steve bfabeab6b9 Add Xilinx virtex as a reference EDIF device. 2005-09-25 16:35:36 +00:00
steve 4a3f1a3641 Attach line numbers to NetMux devices. 2005-09-11 02:56:37 +00:00
steve d97560caa7 Fix overly agressive constant propagation through MUX causing lost Z bits. 2005-09-11 02:50:51 +00:00
steve 393102d43a Evaluate magnitude compare with real operands. 2005-09-09 02:17:08 +00:00
steve 8e97a0e4d4 Support b1 edge in primitive tables. 2005-09-09 02:13:15 +00:00
steve 4ea789a2d7 More explicit internal error message. 2005-09-04 15:41:54 +00:00
steve 354f7ad920 More explicit internal error message. 2005-09-04 15:39:19 +00:00
steve f4a6206790 Handle b0 edges in primitives. 2005-09-04 15:33:19 +00:00
steve fd29ba3398 Reduce mux slices that are constant throughout range. 2005-08-28 22:00:39 +00:00
steve 44fbf60885 More thorough constant propagation through MUX devices. 2005-08-28 19:51:02 +00:00
steve a0d69113c3 More thorough constant propagation through MUX devices. 2005-08-28 19:50:03 +00:00
steve 86942ac592 Dump CMP_GE devices. 2005-08-28 17:37:28 +00:00
steve 075f9cbc4b Back-port edif_nexus_to_joint from tgt-edif. 2005-08-27 22:29:30 +00:00
steve 9dab368880 fix configure and build instructions for mingw build. 2005-08-27 22:19:37 +00:00
steve 5f6027fb66 Join cell0 and cell1 instances in LPM target. 2005-08-25 18:52:32 +00:00
steve 53156793fe Add support for implicit defaults in case and conditions. 2005-08-22 01:00:41 +00:00
steve 4644c220e8 Handle statements in blocks overriding previous statement outputs. 2005-08-21 22:49:54 +00:00
steve c30cd9afea Display NOR gates. 2005-08-21 22:27:57 +00:00
steve a8f45a18f0 Fix the comment in the EDIT header. 2005-08-21 22:25:51 +00:00
steve 6828e3e2ea Generate LPM for the CMP_EQ device. 2005-08-21 14:39:33 +00:00
steve 75eb372adf configure tgt-edif subdir. 2005-08-21 02:20:16 +00:00
steve 3b753fe52b Add the tgt-edif target. 2005-08-17 01:17:28 +00:00
steve 8c73fa7840 Fix compilation warnings/errors with newer compilers. 2005-08-13 00:45:53 +00:00
steve d310e656c7 Fix parse errors related to pr766. 2005-07-27 14:48:34 +00:00
steve 0510367b70 Fix compile errors with g++-4. 2005-07-06 22:41:34 +00:00
steve 3e11207a56 Fix gcc4 build issues. 2005-06-14 15:33:54 +00:00
steve 665f31271f popen must be matched by pclose. 2005-03-22 15:53:12 +00:00
steve 9a2b56675c Fix set_width to allow binary logical operands to be self determined. 2005-03-05 01:36:16 +00:00
steve c9f38f5ffa Improve distclean targets. 2005-02-23 18:40:23 +00:00
steve 5ea4152162 Spelling fixes from Larry. 2005-02-23 18:37:52 +00:00
steve 327c897d7e Spellig fixes. 2005-02-19 16:39:30 +00:00
steve 29ebe486b7 Fix multiple delete of an expression. 2005-02-19 16:38:14 +00:00
steve 4af0acb3be Fix (from Tony) for clock compression detection 2005-02-11 17:04:22 +00:00
steve 8435774c26 Fix evaluate of constants in netlist concatenation repeats. 2005-01-29 00:18:23 +00:00
steve 6172748c65 Add stub config files to CVS. 2005-01-28 18:30:11 +00:00
steve ca0ae9040a Add ability to compile real values into index registers. 2005-01-28 18:29:29 +00:00
steve d9cdbde3f6 More robust handling of file name argument to $fopen. 2005-01-01 20:07:41 +00:00
steve 307a97116f Fix leak of word registers in code generator. 2004-12-12 04:25:10 +00:00
steve 83d2c6dfd1 Update for 0.8 files. 2004-10-14 01:12:41 +00:00
78 changed files with 5929 additions and 356 deletions

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $" #ident "$Id: LineInfo.cc,v 1.4.2.1 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -34,12 +34,12 @@ LineInfo::~LineInfo()
{ {
} }
string LineInfo::get_line() const std::string LineInfo::get_line() const
{ {
ostringstream buf; std::ostringstream buf;
buf << (file_? file_ : "") << ":" << lineno_; buf << (file_? file_ : "") << ":" << lineno_;
string res = buf.str(); std::string res = buf.str();
return res; return res;
} }
@ -61,6 +61,9 @@ void LineInfo::set_lineno(unsigned n)
/* /*
* $Log: LineInfo.cc,v $ * $Log: LineInfo.cc,v $
* Revision 1.4.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.4 2003/01/17 05:49:03 steve * Revision 1.4 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf. * Use stringstream in place of sprintf.
* *

View File

@ -19,11 +19,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.h,v 1.7 2003/01/17 05:49:03 steve Exp $" #ident "$Id: LineInfo.h,v 1.7.2.2 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include <string> # include <string>
using namespace std;
/* /*
* This class holds line information for an internal object. * This class holds line information for an internal object.
* *
@ -38,7 +40,7 @@ class LineInfo {
LineInfo(); LineInfo();
~LineInfo(); ~LineInfo();
string get_line() const; std::string get_line() const;
void set_line(const LineInfo&that); void set_line(const LineInfo&that);
@ -52,6 +54,12 @@ class LineInfo {
/* /*
* $Log: LineInfo.h,v $ * $Log: LineInfo.h,v $
* Revision 1.7.2.2 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.7.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.7 2003/01/17 05:49:03 steve * Revision 1.7 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf. * Use stringstream in place of sprintf.
* *

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.169 2004/10/13 22:01:34 steve Exp $" #ident "$Id: Makefile.in,v 1.169.2.2 2005/09/30 15:01:44 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -25,7 +25,7 @@ SHELL = /bin/sh
# by the compiler. It reflects the assigned version number for the # by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token # product as a whole. Most components also print the CVS Name: token
# in order to get a more automatic version stamp as well. # in order to get a more automatic version stamp as well.
VERSION = 0.8 VERSION = 0.8.2
prefix = @prefix@ prefix = @prefix@
exec_prefix = @exec_prefix@ exec_prefix = @exec_prefix@
@ -103,6 +103,7 @@ distclean: clean
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \ for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
do (cd $$dir ; $(MAKE) $@); done do (cd $$dir ; $(MAKE) $@); done
rm -f Makefile config.status config.log config.cache config.h rm -f Makefile config.status config.log config.cache config.h
rm -rf autom4te.cache
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PTask.h,v 1.13 2004/05/31 23:34:36 steve Exp $" #ident "$Id: PTask.h,v 1.13.2.1 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include "LineInfo.h" # include "LineInfo.h"
@ -70,7 +70,7 @@ class PTask : public LineInfo {
// Elaborate the statement to finish off the task definition. // Elaborate the statement to finish off the task definition.
void elaborate(Design*des, NetScope*scope) const; void elaborate(Design*des, NetScope*scope) const;
void dump(ostream&, unsigned) const; void dump(std::ostream&, unsigned) const;
private: private:
svector<PWire*>*ports_; svector<PWire*>*ports_;
@ -106,7 +106,7 @@ class PFunction : public LineInfo {
/* Elaborate the behavioral statement. */ /* Elaborate the behavioral statement. */
void elaborate(Design *des, NetScope*) const; void elaborate(Design *des, NetScope*) const;
void dump(ostream&, unsigned) const; void dump(std::ostream&, unsigned) const;
private: private:
perm_string name_; perm_string name_;
@ -117,6 +117,9 @@ class PFunction : public LineInfo {
/* /*
* $Log: PTask.h,v $ * $Log: PTask.h,v $
* Revision 1.13.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.13 2004/05/31 23:34:36 steve * Revision 1.13 2004/05/31 23:34:36 steve
* Rewire/generalize parsing an elaboration of * Rewire/generalize parsing an elaboration of
* function return values to allow for better * function return values to allow for better

13
PUdp.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PUdp.h,v 1.12 2004/03/08 00:47:44 steve Exp $" #ident "$Id: PUdp.h,v 1.12.2.1 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include <map> # include <map>
@ -55,20 +55,20 @@ class PUdp {
public: public:
explicit PUdp(perm_string n, unsigned nports); explicit PUdp(perm_string n, unsigned nports);
svector<string>ports; svector<std::string>ports;
unsigned find_port(const char*name); unsigned find_port(const char*name);
bool sequential; bool sequential;
svector<string>tinput; svector<std::string>tinput;
svector<char> tcurrent; svector<char> tcurrent;
svector<char> toutput; svector<char> toutput;
verinum::V initial; verinum::V initial;
map<string,PExpr*> attributes; std::map<std::string,PExpr*> attributes;
void dump(ostream&out) const; void dump(std::ostream&out) const;
perm_string name_; perm_string name_;
private: private:
@ -80,6 +80,9 @@ class PUdp {
/* /*
* $Log: PUdp.h,v $ * $Log: PUdp.h,v $
* Revision 1.12.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.12 2004/03/08 00:47:44 steve * Revision 1.12 2004/03/08 00:47:44 steve
* primitive ports can bind bi name. * primitive ports can bind bi name.
* *

View File

@ -114,7 +114,7 @@ configure script that modify its behavior:
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
most out of your install, first make sure you have both 64bit and most out of your install, first make sure you have both 64bit and
32bit development libraries installed. Then configure with this 32bit development libraries installed. Then configure with this
somewhat more compilcated command: somewhat more complex command:
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32 ./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.cc,v 1.6 2004/02/18 17:11:54 steve Exp $" #ident "$Id: StringHeap.cc,v 1.6.2.1 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include "StringHeap.h" # include "StringHeap.h"
@ -131,7 +131,7 @@ perm_string StringHeapLex::make(const char*text)
return perm_string(add(text)); return perm_string(add(text));
} }
perm_string StringHeapLex::make(const string&text) perm_string StringHeapLex::make(const std::string&text)
{ {
return perm_string(add(text.c_str())); return perm_string(add(text.c_str()));
} }
@ -181,6 +181,9 @@ bool operator < (perm_string a, perm_string b)
/* /*
* $Log: StringHeap.cc,v $ * $Log: StringHeap.cc,v $
* Revision 1.6.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.6 2004/02/18 17:11:54 steve * Revision 1.6 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *

View File

@ -19,12 +19,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.h,v 1.5 2004/02/18 17:11:54 steve Exp $" #ident "$Id: StringHeap.h,v 1.5.2.2 2005/08/13 00:45:53 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
# include <string> # include <string>
using namespace std;
class perm_string { class perm_string {
public: public:
@ -101,7 +103,7 @@ class StringHeapLex : private StringHeap {
const char*add(const char*); const char*add(const char*);
perm_string make(const char*); perm_string make(const char*);
perm_string make(const string&); perm_string make(const std::string&);
unsigned add_count() const; unsigned add_count() const;
unsigned add_hit_count() const; unsigned add_hit_count() const;
@ -120,6 +122,12 @@ class StringHeapLex : private StringHeap {
/* /*
* $Log: StringHeap.h,v $ * $Log: StringHeap.h,v $
* Revision 1.5.2.2 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.5.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.5 2004/02/18 17:11:54 steve * Revision 1.5 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *

18
aclocal.m4 vendored
View File

@ -14,7 +14,7 @@
AC_DEFUN([AX_CPP_IDENT], AC_DEFUN([AX_CPP_IDENT],
[AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident, [AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident,
[AC_TRY_COMPILE([ [AC_TRY_COMPILE([
#ident "$Id: aclocal.m4,v 1.6 2004/10/04 01:10:52 steve Exp $" #ident "$Id: aclocal.m4,v 1.6.2.1 2005/08/27 22:19:37 steve Exp $"
],[while (0) {}], ],[while (0) {}],
[AS_VAR_SET(ax_cv_cpp_ident, yes)], [AS_VAR_SET(ax_cv_cpp_ident, yes)],
[AS_VAR_SET(ax_cv_cpp_ident, no)])]) [AS_VAR_SET(ax_cv_cpp_ident, no)])])
@ -91,13 +91,9 @@ AC_MSG_RESULT($WIN32)
AC_DEFUN([AX_LD_EXTRALIBS], AC_DEFUN([AX_LD_EXTRALIBS],
[AC_MSG_CHECKING([for extra libs needed]) [AC_MSG_CHECKING([for extra libs needed])
EXTRALIBS= EXTRALIBS=
case "${host}" in if test "$MINGW32" = "yes"; then
*-*-cygwin* ) EXTRALIBS="-liberty"
if test "$MINGW32" = "yes"; then fi
EXTRALIBS="-liberty"
fi
;;
esac
AC_SUBST(EXTRALIBS) AC_SUBST(EXTRALIBS)
AC_MSG_RESULT($EXTRALIBS) AC_MSG_RESULT($EXTRALIBS)
])# AX_LD_EXTRALIBS ])# AX_LD_EXTRALIBS
@ -109,7 +105,7 @@ AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
[AC_MSG_CHECKING([for shared library link flag]) [AC_MSG_CHECKING([for shared library link flag])
shared=-shared shared=-shared
case "${host}" in case "${host}" in
*-*-cygwin*) *-*-cygwin* | *-*-mingw32*)
shared="-shared -Wl,--enable-auto-image-base" shared="-shared -Wl,--enable-auto-image-base"
;; ;;
@ -138,7 +134,7 @@ AC_DEFUN([AX_C_PICFLAG],
PICFLAG=-fPIC PICFLAG=-fPIC
case "${host}" in case "${host}" in
*-*-cygwin*) *-*-cygwin* | *-*-mingw32*)
PICFLAG= PICFLAG=
;; ;;
@ -173,7 +169,7 @@ case "${host}" in
rdynamic="" rdynamic=""
;; ;;
*-*-cygwin*) *-*-cygwin* | *-*-mingw32*)
rdynamic="" rdynamic=""
;; ;;

View File

@ -9,7 +9,7 @@
echo "Autoconf in root..." echo "Autoconf in root..."
autoconf autoconf
for dir in vpip vpi vvp tgt-vvp tgt-fpga libveriuser cadpli for dir in vpip vpi vvp tgt-vvp tgt-edif tgt-fpga libveriuser cadpli
do do
echo "Autoconf in $dir..." echo "Autoconf in $dir..."
( cd ./$dir ; autoconf --include=.. ) ( cd ./$dir ; autoconf --include=.. )

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.11 2004/10/04 01:09:07 steve Exp $" #ident "$Id: Makefile.in,v 1.11.2.1 2005/02/23 18:40:23 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -86,6 +86,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32) install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)

View File

@ -141,6 +141,6 @@ AC_SUBST(vpidir1)
AC_SUBST(vpidir2) AC_SUBST(vpidir2)
AC_MSG_RESULT(${vpidir1} ${vpidir2}) AC_MSG_RESULT(${vpidir1} ${vpidir2})
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-fpga libveriuser cadpli) AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-edif tgt-fpga libveriuser cadpli)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile) AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)

317
cprop.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: cprop.cc,v 1.47 2004/02/20 18:53:34 steve Exp $" #ident "$Id: cprop.cc,v 1.47.2.4 2005/09/11 02:50:51 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -47,6 +47,7 @@ struct cprop_functor : public functor_t {
virtual void lpm_ff(Design*des, NetFF*obj); virtual void lpm_ff(Design*des, NetFF*obj);
virtual void lpm_logic(Design*des, NetLogic*obj); virtual void lpm_logic(Design*des, NetLogic*obj);
virtual void lpm_mux(Design*des, NetMux*obj); virtual void lpm_mux(Design*des, NetMux*obj);
virtual void lpm_mux_large(Design*des, NetMux*obj);
}; };
void cprop_functor::signal(Design*des, NetNet*obj) void cprop_functor::signal(Design*des, NetNet*obj)
@ -847,77 +848,298 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
*/ */
void cprop_functor::lpm_mux(Design*des, NetMux*obj) void cprop_functor::lpm_mux(Design*des, NetMux*obj)
{ {
if (obj->size() > 2) {
lpm_mux_large(des, obj);
return;
}
if (obj->size() != 2) if (obj->size() != 2)
return; return;
if (obj->sel_width() != 1) if (obj->sel_width() != 1)
return; return;
/* If the first input is all constant Vz, then replace the NetScope*scope = obj->scope();
NetMux with an array of BUFIF1 devices, with the enable
connected to the select input. */
bool flag = true; bool flag = true;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) { for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (! obj->pin_Data(idx, 0).nexus()->drivers_constant()) { bool cflag_a = obj->pin_Data(idx, 0).nexus()->drivers_constant();
flag = false; bool cflag_b = obj->pin_Data(idx, 1).nexus()->drivers_constant();
break;
}
if (obj->pin_Data(idx, 0).nexus()->driven_value() != verinum::Vz) { /* If both data inputs are constant, we'll be able to do
flag = false; a substitution. */
break; if (cflag_a && cflag_b)
} continue;
verinum::V va = cflag_a
? obj->pin_Data(idx, 0).nexus()->driven_value()
: verinum::Vx;
verinum::V vb = cflag_b
? obj->pin_Data(idx, 1).nexus()->driven_value()
: verinum::Vx;
/* If only one Data input is constant, but a constant
HiZ, then we will be able to to a bufif
substitution. */
if (cflag_a && va==verinum::Vz)
continue;
if (cflag_b && vb==verinum::Vz)
continue;
/* Otherwise, we cannot accurately do a substitution. If
one input is non-constant, then that input may have a
HiZ value, and there is no Verilog logic other then a
MUX that can pass a HiZ value. */
flag = false;
} }
if (flag) { if (! flag) {
NetScope*scope = obj->scope(); return;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) { }
NetLogic*tmp = new NetLogic(obj->scope(),
/* We know that every slice has at least one constant. Run
through the slices again, creating boolean devices to
replace the MUX slice. */
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
/* If the Sel==0 input is constant Z, make a bufif1. */
if (obj->pin_Data(idx, 0).nexus()->drivers_constant()
&& obj->pin_Data(idx, 0).nexus()->driven_value()==verinum::Vz) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(), scope->local_symbol(),
3, NetLogic::BUFIF1); 3, NetLogic::BUFIF1);
connect(obj->pin_Result(idx), tmp->pin(0)); connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1)); connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2)); connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp); des->add_node(tmp);
continue;
} }
count += 1; /* If the Sel==1 input is constant Z, make a bufif0. */
delete obj; if (obj->pin_Data(idx, 1).nexus()->drivers_constant()
return; && obj->pin_Data(idx, 1).nexus()->driven_value()==verinum::Vz) {
}
/* If instead the second input is all constant Vz, replace the NetLogic*tmp = new NetLogic(scope,
NetMux with an array of BUFIF0 devices. */
flag = true;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (! obj->pin_Data(idx, 1).nexus()->drivers_constant()) {
flag = false;
break;
}
if (obj->pin_Data(idx, 1).nexus()->driven_value() != verinum::Vz) {
flag = false;
break;
}
}
if (flag) {
NetScope*scope = obj->scope();
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(), scope->local_symbol(),
3, NetLogic::BUFIF0); 3, NetLogic::BUFIF0);
connect(obj->pin_Result(idx), tmp->pin(0)); connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1)); connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2)); connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp); des->add_node(tmp);
continue;
} }
count += 1; /* At this point, the only cases that are left are where
delete obj; the data inputs are both constant, and neither are
HiZ. From this we know how to generate the output
from only the S input. */
assert(obj->pin_Data(idx, 0).nexus()->drivers_constant()
&& obj->pin_Data(idx, 1).nexus()->drivers_constant());
verinum::V a = obj->pin_Data(idx, 0).nexus()->driven_value();
verinum::V b = obj->pin_Data(idx, 1).nexus()->driven_value();
if (a == b) {
connect(obj->pin_Result(idx), obj->pin_Data(idx,0));
continue;
}
if (a == verinum::V0 && b == verinum::V1) {
connect(obj->pin_Result(idx), obj->pin_Sel(0));
continue;
}
if (a == verinum::V1 && b == verinum::V0) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Sel(0), tmp->pin(1));
des->add_node(tmp);
continue;
}
/* A==0: Q = B & S */
if (a == verinum::V0) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::AND);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* B==1: Q = A | S */
if (b == verinum::V1) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::OR);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* A==1: Q = B | ~S */
if (a == verinum::V1) {
NetLogic*inv = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
NetNet*invs = new NetNet(scope,
scope->local_symbol(),
NetNet::TRI, 1);
invs->local_flag(true);
connect(inv->pin(0), invs->pin(0));
connect(inv->pin(1), obj->pin_Sel(0));
des->add_node(inv);
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::OR);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(inv->pin(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* B==0: Q = A & ~S */
if (b == verinum::V0) {
NetLogic*inv = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
NetNet*invs = new NetNet(scope,
scope->local_symbol(),
NetNet::TRI, 1);
invs->local_flag(true);
connect(inv->pin(0), invs->pin(0));
connect(inv->pin(1), obj->pin_Sel(0));
des->add_node(inv);
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::AND);
connect(obj->pin_Result(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(inv->pin(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
assert(0);
}
delete obj;
count += 1;
}
void cprop_functor::lpm_mux_large(Design*des, NetMux*obj)
{
NetScope*scope = obj->scope();
unsigned width = obj->width();
unsigned size = obj->size();
/* This test looks for bit slices that are constant
throughout. If we find any, we can reduce the width of the
MUX to eliminate the fixed value. */
/* After the following for look, this array of bools will
contain "true" for each bit slice that is constant and
identical, and "false" otherwise. The reduce_width will
count the number of true entries in the flags array. */
bool*flags = new bool[width];
unsigned reduce_width = 0;
for (unsigned bit = 0 ; bit < width ; bit += 1) {
flags[bit] = true;
/* If not even the first selection is constant, then the
slice cannot be reduced. */
if (! obj->pin_Data(bit, 0).nexus()->drivers_constant()) {
flags[bit] = false;
continue;
}
/* If any of the remaining selections in non-consant, or
constant with a different value, then this slice
cannot be reduced. */
verinum::V val = obj->pin_Data(bit, 0).nexus()->driven_value();
for (unsigned idx = 1; flags[bit] && idx < size ; idx += 1) {
if (!obj->pin_Data(bit,idx).nexus()->drivers_constant()) {
flags[bit] = false;
break;
}
if (val != obj->pin_Data(bit,idx).nexus()->driven_value()) {
flags[bit] = false;
break;
}
}
if (! flags[bit]) {
/* This bit slice is too complex. Go on. */
continue;
}
reduce_width += 1;
}
/* If no slices can be reduced, then we are finished. */
if (reduce_width == 0) {
delete[]flags;
return; return;
} }
/* Handle the very special case that all the slices can be
reduced. We don't need a MUX at all! */
if (reduce_width == width) {
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(obj->pin_Result(idx), obj->pin_Data(idx,0));
delete obj;
count += 1;
delete[]flags;
return;
}
/* Create a reduced mux with the same name and size, but fewer
slices. Connect all the slices that we are keeping. */
NetMux*tmp = new NetMux(scope, obj->name(),
width-reduce_width, size, obj->sel_width());
tmp->set_line(*obj);
for (unsigned idx = 0 ; idx < obj->sel_width() ; idx += 1)
connect(obj->pin_Sel(idx), tmp->pin_Sel(idx));
unsigned dst_bit = 0;
for (unsigned bit = 0 ; bit < width ; bit += 1) {
if (flags[bit]) {
connect(obj->pin_Result(bit), obj->pin_Data(bit,0));
continue;
}
connect(obj->pin_Result(bit), tmp->pin_Result(dst_bit));
for (unsigned idx = 0 ; idx < size ; idx += 1)
connect(obj->pin_Data(bit,idx), tmp->pin_Data(dst_bit,idx));
dst_bit += 1;
}
/* Add the new node. Delete the old node. Signal that we
change the design and may use a rescan. */
des->add_node(tmp);
delete obj;
delete[]flags;
count += 1;
} }
/* /*
@ -1038,6 +1260,15 @@ void cprop(Design*des)
/* /*
* $Log: cprop.cc,v $ * $Log: cprop.cc,v $
* Revision 1.47.2.4 2005/09/11 02:50:51 steve
* Fix overly agressive constant propagation through MUX causing lost Z bits.
*
* Revision 1.47.2.3 2005/08/28 22:00:39 steve
* Reduce mux slices that are constant throughout range.
*
* Revision 1.47.2.2 2005/08/28 19:51:02 steve
* More thorough constant propagation through MUX devices.
*
* Revision 1.47 2004/02/20 18:53:34 steve * Revision 1.47 2004/02/20 18:53:34 steve
* Addtrbute keys are perm_strings. * Addtrbute keys are perm_strings.
* *

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.24 2004/10/13 22:01:34 steve Exp $" #ident "$Id: Makefile.in,v 1.24.2.1 2005/02/23 18:40:23 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -54,6 +54,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile rm -f Makefile
rm -rf autom4te.cache
O = main.o substit.o cflexor.o cfparse.o O = main.o substit.o cflexor.o cfparse.o

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_net.cc,v 1.138 2004/10/04 03:09:38 steve Exp $" #ident "$Id: elab_net.cc,v 1.138.2.3 2005/09/11 02:56:37 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1312,21 +1312,25 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
unsigned repeat = 1; unsigned repeat = 1;
if (repeat_) { if (repeat_) {
verinum*rep = repeat_->eval_const(des, scope); NetExpr*etmp = elab_and_eval(des, scope, repeat_);
if (rep == 0) { assert(etmp);
NetEConst*erep = dynamic_cast<NetEConst*>(etmp);
if (erep == 0) {
cerr << get_line() << ": internal error: Unable to " cerr << get_line() << ": internal error: Unable to "
<< "evaluate constant repeat expression." << endl; << "evaluate constant repeat expression." << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
repeat = rep->as_ulong(); repeat = erep->value().as_ulong();
delete etmp;
if (repeat == 0) { if (repeat == 0) {
cerr << get_line() << ": error: Invalid repeat value." cerr << get_line() << ": error: Concatenation repeat "
"may not be 0."
<< endl; << endl;
des->errors += 1; des->errors += 1;
delete rep;
return 0; return 0;
} }
} }
@ -1435,6 +1439,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
NetMux*mux = new NetMux(scope, scope->local_symbol(), 1, NetMux*mux = new NetMux(scope, scope->local_symbol(), 1,
sig_width, sel->pin_count()); sig_width, sel->pin_count());
mux->set_line(*this);
/* Connect the signal bits to the mux. Account for the /* Connect the signal bits to the mux. Account for the
direction of the numbering (lsb to msb vs. msb to lsb) by direction of the numbering (lsb to msb vs. msb to lsb) by
@ -2268,6 +2273,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
(true) connected to tru_sig. */ (true) connected to tru_sig. */
NetMux*mux = new NetMux(scope, scope->local_symbol(), dwidth, 2, 1); NetMux*mux = new NetMux(scope, scope->local_symbol(), dwidth, 2, 1);
mux->set_line(*this);
connect(mux->pin_Sel(0), expr_sig->pin(0)); connect(mux->pin_Sel(0), expr_sig->pin(0));
/* Connect the data inputs. */ /* Connect the data inputs. */
@ -2513,6 +2519,15 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/* /*
* $Log: elab_net.cc,v $ * $Log: elab_net.cc,v $
* Revision 1.138.2.3 2005/09/11 02:56:37 steve
* Attach line numbers to NetMux devices.
*
* Revision 1.138.2.2 2005/02/19 16:39:30 steve
* Spellig fixes.
*
* Revision 1.138.2.1 2005/01/29 00:18:23 steve
* Fix evaluate of constants in netlist concatenation repeats.
*
* Revision 1.138 2004/10/04 03:09:38 steve * Revision 1.138 2004/10/04 03:09:38 steve
* Fix excessive error message. * Fix excessive error message.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: eval_tree.cc,v 1.62 2004/10/04 01:10:53 steve Exp $" #ident "$Id: eval_tree.cc,v 1.62.2.3 2005/09/09 02:17:08 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -215,6 +215,11 @@ NetEConst* NetEBComp::eval_eqeq_()
NetEConst* NetEBComp::eval_less_() NetEConst* NetEBComp::eval_less_()
{ {
if (right_->expr_type() == ET_REAL)
return eval_leeq_real_(false, false);
if (left_->expr_type() == ET_REAL)
return eval_leeq_real_(false, false);
NetEConst*r = dynamic_cast<NetEConst*>(right_); NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0; if (r == 0) return 0;
@ -224,6 +229,16 @@ NetEConst* NetEBComp::eval_less_()
return new NetEConst(result); return new NetEConst(result);
} }
if (left_->expr_width() == 0) {
cerr << get_line() << ": internal error: "
<< "Having trouble evaluating left expression of < op."
<< endl;
cerr << get_line() << ": : "
<< "Expression is: "
<< *this << endl;
return 0;
}
/* Detect the case where the right side is greater that or /* Detect the case where the right side is greater that or
equal to the largest value the left side can possibly equal to the largest value the left side can possibly
have. */ have. */
@ -259,7 +274,7 @@ NetEConst* NetEBComp::eval_less_()
return new NetEConst(result); return new NetEConst(result);
} }
NetEConst* NetEBComp::eval_leeq_real_() NetEConst* NetEBComp::eval_leeq_real_(bool gt_flag, bool include_eq_flag)
{ {
NetEConst*vtmp; NetEConst*vtmp;
NetECReal*rtmp; NetECReal*rtmp;
@ -308,7 +323,16 @@ NetEConst* NetEBComp::eval_leeq_real_()
assert(0); assert(0);
} }
verinum result((lv <= rv)? verinum::V1 : verinum::V0, 1); /* This function supports < and <=. If the eq_flag is true,
then include <=. Otherwise, include only <. */
bool flag;
if (gt_flag)
flag = include_eq_flag? (lv >= rv) : (lv > rv);
else
flag = include_eq_flag? (lv <= rv) : (lv < rv);
verinum result(flag? verinum::V1 : verinum::V0, 1);
vtmp = new NetEConst(result); vtmp = new NetEConst(result);
vtmp->set_line(*this); vtmp->set_line(*this);
@ -318,9 +342,9 @@ NetEConst* NetEBComp::eval_leeq_real_()
NetEConst* NetEBComp::eval_leeq_() NetEConst* NetEBComp::eval_leeq_()
{ {
if (right_->expr_type() == ET_REAL) if (right_->expr_type() == ET_REAL)
return eval_leeq_real_(); return eval_leeq_real_(false, true);
if (left_->expr_type() == ET_REAL) if (left_->expr_type() == ET_REAL)
return eval_leeq_real_(); return eval_leeq_real_(false, true);
NetEConst*r = dynamic_cast<NetEConst*>(right_); NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0; if (r == 0) return 0;
@ -374,23 +398,10 @@ NetEConst* NetEBComp::eval_leeq_()
NetEConst* NetEBComp::eval_gt_() NetEConst* NetEBComp::eval_gt_()
{ {
if ((left_->expr_type() == NetExpr::ET_REAL) if (right_->expr_type() == ET_REAL)
&& (right_->expr_type() == NetExpr::ET_REAL)) { return eval_leeq_real_(true, false);
if (left_->expr_type() == ET_REAL)
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_); return eval_leeq_real_(true, false);
if (tmpl == 0)
return 0;
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
if (tmpr == 0)
return 0;
double ll = tmpl->value().as_double();
double rr = tmpr->value().as_double();
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
NetEConst*l = dynamic_cast<NetEConst*>(left_); NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0; if (l == 0) return 0;
@ -450,23 +461,10 @@ NetEConst* NetEBComp::eval_gt_()
NetEConst* NetEBComp::eval_gteq_() NetEConst* NetEBComp::eval_gteq_()
{ {
if ((left_->expr_type() == NetExpr::ET_REAL) if (right_->expr_type() == ET_REAL)
&& (right_->expr_type() == NetExpr::ET_REAL)) { return eval_leeq_real_(true, true);
if (left_->expr_type() == ET_REAL)
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_); return eval_leeq_real_(true, true);
if (tmpl == 0)
return 0;
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
if (tmpr == 0)
return 0;
double ll = tmpl->value().as_double();
double rr = tmpr->value().as_double();
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
NetEConst*l = dynamic_cast<NetEConst*>(left_); NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0; if (l == 0) return 0;
@ -1551,6 +1549,15 @@ NetEConst* NetEUReduce::eval_tree()
/* /*
* $Log: eval_tree.cc,v $ * $Log: eval_tree.cc,v $
* Revision 1.62.2.3 2005/09/09 02:17:08 steve
* Evaluate magnitude compare with real operands.
*
* Revision 1.62.2.2 2005/09/04 15:41:54 steve
* More explicit internal error message.
*
* Revision 1.62.2.1 2005/09/04 15:39:19 steve
* More explicit internal error message.
*
* Revision 1.62 2004/10/04 01:10:53 steve * Revision 1.62 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -16,13 +16,13 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* *
* $Id: sqrt-virtex.v,v 1.4 2003/11/25 18:35:31 steve Exp $" * $Id: sqrt-virtex.v,v 1.4.2.2 2005/02/23 18:37:52 steve Exp $"
*/ */
/* /*
* This module is a synthesizeable square-root function. It is also a * This module is a synthesizeable square-root function. It is also a
* detailed example of how to target Xilinx Virtex parts using * detailed example of how to target Xilinx Virtex parts using
* Icarus Verilog. In fact, for no particular reason other then to * Icarus Verilog. In fact, for no particular reason other than to
* be excessively specific, I will step through the process of * be excessively specific, I will step through the process of
* generating a design for a Spartan-II XC2S15-VQ100, and also how to * generating a design for a Spartan-II XC2S15-VQ100, and also how to
* generate a generic library part for larger Virtex designs. * generate a generic library part for larger Virtex designs.
@ -129,8 +129,8 @@
* This command creates from the chip.ngd the file "chip_root.v" that * This command creates from the chip.ngd the file "chip_root.v" that
* contains Verilog code that simulates the mapped design. This output * contains Verilog code that simulates the mapped design. This output
* Verilog has the single root module "chip_root", which came from the * Verilog has the single root module "chip_root", which came from the
* name of the root module when we were making hte EDIF file in the * name of the root module when we were making the EDIF file in the
* first place. The module has ports named just line the ports of the * first place. The module has ports named just like the ports of the
* chip_root module below. * chip_root module below.
* *
* The generated Verilog uses the library in the directory * The generated Verilog uses the library in the directory

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $" #ident "$Id: expr_synth.cc,v 1.59.2.2 2005/09/11 02:56:37 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -408,7 +408,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
default: { default: {
cerr << get_line() << ": internal error: " cerr << get_line() << ": internal error: "
<< "NetEBDiv has unexpeced op() code: " << "NetEBDiv has unexpected op() code: "
<< op() << endl; << op() << endl;
des->errors += 1; des->errors += 1;
@ -811,6 +811,7 @@ NetNet* NetETernary::synthesize(Design *des)
perm_string oname = csig->scope()->local_symbol(); perm_string oname = csig->scope()->local_symbol();
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1); NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1);
mux->set_line(*this);
for (unsigned idx = 0 ; idx < width; idx += 1) { for (unsigned idx = 0 ; idx < width; idx += 1) {
connect(tsig->pin(idx), mux->pin_Data(idx, 1)); connect(tsig->pin(idx), mux->pin_Data(idx, 1));
connect(fsig->pin(idx), mux->pin_Data(idx, 0)); connect(fsig->pin(idx), mux->pin_Data(idx, 0));
@ -875,6 +876,12 @@ NetNet* NetESignal::synthesize(Design*des)
/* /*
* $Log: expr_synth.cc,v $ * $Log: expr_synth.cc,v $
* Revision 1.59.2.2 2005/09/11 02:56:37 steve
* Attach line numbers to NetMux devices.
*
* Revision 1.59.2.1 2005/02/19 16:39:31 steve
* Spellig fixes.
*
* Revision 1.59 2004/06/30 02:16:26 steve * Revision 1.59 2004/06/30 02:16:26 steve
* Implement signed divide and signed right shift in nets. * Implement signed divide and signed right shift in nets.
* *

View File

@ -37,7 +37,7 @@ valid options include:
Predefine the symbol ``name'' to have the specified Predefine the symbol ``name'' to have the specified
value. If the value is not specified, then ``1'' is value. If the value is not specified, then ``1'' is
used. This is mostly of use for controlling conditional used. This is mostly of use for controlling conditional
compilaiton. compilation.
This option does *not* override existing `define This option does *not* override existing `define
directives in the source file. directives in the source file.

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: lexor.lex,v 1.86 2004/06/13 04:56:54 steve Exp $" #ident "$Id: lexor.lex,v 1.86.2.2 2005/09/09 02:13:15 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -179,6 +179,8 @@ W [ \t\b\f\r]+
<UDPTABLE>\(01\) { return 'r'; } <UDPTABLE>\(01\) { return 'r'; }
<UDPTABLE>\(0[xX]\) { return 'Q'; } <UDPTABLE>\(0[xX]\) { return 'Q'; }
<UDPTABLE>\(b[xX]\) { return 'q'; } <UDPTABLE>\(b[xX]\) { return 'q'; }
<UDPTABLE>\(b0\) { return 'f'; /* b0 is 10|00, but only 10 is meaningful */}
<UDPTABLE>\(b1\) { return 'r'; /* b1 is 11|01, but only 01 is meaningful */}
<UDPTABLE>\(0\?\) { return 'P'; } <UDPTABLE>\(0\?\) { return 'P'; }
<UDPTABLE>\(10\) { return 'f'; } <UDPTABLE>\(10\) { return 'f'; }
<UDPTABLE>\(1[xX]\) { return 'M'; } <UDPTABLE>\(1[xX]\) { return 'M'; }

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.34 2004/10/04 01:10:07 steve Exp $" #ident "$Id: Makefile.in,v 1.34.2.1 2005/02/23 18:40:24 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -93,6 +93,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32) install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: load_module.cc,v 1.12 2003/06/05 04:31:09 steve Exp $" #ident "$Id: load_module.cc,v 1.12.2.1 2005/03/22 15:53:12 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -88,7 +88,7 @@ bool load_module(const char*type)
cerr << "Executing: " << cmdline << endl; cerr << "Executing: " << cmdline << endl;
pform_parse(path, file); pform_parse(path, file);
fclose(file); pclose(file);
free(cmdline); free(cmdline);
} else { } else {
@ -193,6 +193,9 @@ int build_library_index(const char*path, bool key_case_sensitive)
/* /*
* $Log: load_module.cc,v $ * $Log: load_module.cc,v $
* Revision 1.12.2.1 2005/03/22 15:53:12 steve
* popen must be matched by pclose.
*
* Revision 1.12 2003/06/05 04:31:09 steve * Revision 1.12 2003/06/05 04:31:09 steve
* INclude missing assert.h in load_module. * INclude missing assert.h in load_module.
* *

View File

@ -18,7 +18,7 @@ bison, flex, gperf, etc. Therefore, you still need Cygwin to compile
Icarus Verilog, even if you don't need the Cygwin compilers. There are Icarus Verilog, even if you don't need the Cygwin compilers. There are
also a few precompiled library prerequisites that you need. also a few precompiled library prerequisites that you need.
* Some Preliminary Comments * Some Preliminary Comments -- PLEASE READ ME --
The Windows port of Icarus Verilog is the most difficult of all the The Windows port of Icarus Verilog is the most difficult of all the
ports. The Windows system off the shelf is completely stripped, devoid ports. The Windows system off the shelf is completely stripped, devoid
@ -26,7 +26,8 @@ of any support for software development. Everything needed to compile
Icarus Verilog must be collected from various sources and stitched Icarus Verilog must be collected from various sources and stitched
together by hand. Normal human beings with a basic understanding of together by hand. Normal human beings with a basic understanding of
software development can do this, but some patience (and access to the software development can do this, but some patience (and access to the
Internet) is required. You may choose to print these instructions. Internet) is required. You may choose to print these instructions. FOR
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
I have no plans to intentionally support MSVC++ compilation. Don't ask. I have no plans to intentionally support MSVC++ compilation. Don't ask.
@ -37,7 +38,7 @@ where each can be found. In most cases, the specific version is not
critical, but these are the versions I use. critical, but these are the versions I use.
Cygwin <http://cygwin.com> Cygwin <http://cygwin.com>
Mingw32-2.0.0 <http://www.mingw.org> Mingw32-3.1.0 <http://www.mingw.org>
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net> readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
bzip2-1.0.2-bin.zip <http://gnuwin32.sourceforge.net> bzip2-1.0.2-bin.zip <http://gnuwin32.sourceforge.net>
zlib-1.1.4-bin.zip <http://gnuwin32.sourceforge.net> zlib-1.1.4-bin.zip <http://gnuwin32.sourceforge.net>
@ -101,13 +102,13 @@ that is the usual bash prompt.
* Install Mingw32 * Install Mingw32
The obvious step 2, then, is install the mingw compilers. These can be The obvious step 2, then, is install the mingw compilers. These can be
found at the web page <http://www.mingw.org>. The Mingw-2.x.x version found at the web page <http://www.mingw.org>. The Mingw-3.x.x version
comes prepackaged in a convenient, Windows style, installer. I comes prepackaged in a convenient, Windows style, installer. I
recommend you download this package instead of picking and choosing recommend you download this package instead of picking and choosing
bits. bits.
When I install Mingw32 (using the installer) I typically set a When I install Mingw32 (using the installer) I typically set a
destination directory of d:\mingw-2.0.0 or the like. You will be using destination directory of d:\mingw-3.1.0 or the like. You will be using
that path later. that path later.
NOTES: NOTES:
@ -115,6 +116,10 @@ that path later.
need Mingw32, even if you are using a precompiled binary. VPI need Mingw32, even if you are using a precompiled binary. VPI
modules only require Mingw32, and none of the other libraries. modules only require Mingw32, and none of the other libraries.
Finally, as part of installing the mingw32 compilers, remember to add
the mingw/bin directory to your path. You will need that to be able to
find the compilers later.
* Install Mingw32 Packages * Install Mingw32 Packages
There is a collection of precompiled libraries and add-on packages There is a collection of precompiled libraries and add-on packages
@ -185,25 +190,6 @@ where we will work from now on.
The exact name of the file will vary according to the The exact name of the file will vary according to the
snapshot. The 20030303 name is only an example. snapshot. The 20030303 name is only an example.
* Select the mingw compilers
In your cygwin window, if you type "which c++" you might get the
response path "/usr/bin/c++" which is the cygwin compiler. This is not
the one we want to use, however. Tell the shell where the mingw
compilers are by setting the search path like so:
$ PATH=/cygdrive/d/mingw-2.0.0/bin:$PATH
This assumes that you installed mingw in D:\mingw-2.0.0. The actual
programs are in the bin directory under the root. After this command,
check that you are now getting the right compilers with this "which"
command:
$ which c++
/cygdrive/d/mingw-2.0.0/bin/c++
Good!
* Configure Icarus Verilog * Configure Icarus Verilog
Now we are all set to configure and compile Icarus Verilog. Choose a Now we are all set to configure and compile Icarus Verilog. Choose a
@ -215,10 +201,12 @@ without white space.
Now, configure the source to make the makefiles and configuration Now, configure the source to make the makefiles and configuration
details. Run these commands: details. Run these commands:
$ CC=mingw32-gcc
$ CXX=mingw32-g++
$ CPPFLAGS="-Id:/gnuwin32/include -Id:/mingw-packages/include" $ CPPFLAGS="-Id:/gnuwin32/include -Id:/mingw-packages/include"
$ LDFLAGS="-Ld:/gnuwin32/lib -Ld:/mingw-packages/include" $ LDFLAGS="-Ld:/gnuwin32/lib -Ld:/mingw-packages/include"
$ export CPPFLAGS LDFLAGS $ export CPPFLAGS LDFLAGS CC CXX
$ ./configure --prefix=d:/iverilog $ ./configure --prefix=d:/iverilog --host=mingw32
NOTES: NOTES:
The CPPFLAGS and LDFLAGS variables tell configure where The CPPFLAGS and LDFLAGS variables tell configure where
@ -229,6 +217,11 @@ details. Run these commands:
Your PATH variable was set in the previous step. Your PATH variable was set in the previous step.
The CC and CXX variables explicitly select the mingw32
compilers. This is important. Without this step, you may wind up
compiling with the cygwin compiler, and that is definitely *not*
what you want.
Use forward slashes as directory characters. All the various Use forward slashes as directory characters. All the various
tools prefer the forward slash. tools prefer the forward slash.

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.14 2004/02/18 17:11:56 steve Exp $" #ident "$Id: net_link.cc,v 1.14.2.1 2005/09/25 23:30:31 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -407,13 +407,14 @@ void NexusSet::add(Nexus*that)
} }
unsigned ptr = bsearch_(that); unsigned ptr = bsearch_(that);
if ((ptr < nitems_) && (items_[ptr] == that)) if (ptr < nitems_) {
assert(items_[ptr] == that);
return; return;
}
assert(ptr == nitems_);
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*)); items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*));
for (unsigned idx = nitems_ ; idx > ptr ; idx -= 1)
items_[idx] = items_[idx-1];
items_[ptr] = that; items_[ptr] = that;
nitems_ += 1; nitems_ += 1;
} }
@ -430,7 +431,7 @@ void NexusSet::rem(Nexus*that)
return; return;
unsigned ptr = bsearch_(that); unsigned ptr = bsearch_(that);
if ((ptr >= nitems_) || (items_[ptr] != that)) if (ptr >= nitems_)
return; return;
if (nitems_ == 1) { if (nitems_ == 1) {
@ -462,10 +463,8 @@ Nexus* NexusSet::operator[] (unsigned idx) const
unsigned NexusSet::bsearch_(Nexus*that) const unsigned NexusSet::bsearch_(Nexus*that) const
{ {
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
if (items_[idx] < that) if (items_[idx] == that)
continue; return idx;
return idx;
} }
return nitems_; return nitems_;
@ -499,6 +498,9 @@ bool NexusSet::intersect(const NexusSet&that) const
/* /*
* $Log: net_link.cc,v $ * $Log: net_link.cc,v $
* Revision 1.14.2.1 2005/09/25 23:30:31 steve
* More predictable ordering of items in NexusSet.
*
* Revision 1.14 2004/02/18 17:11:56 steve * Revision 1.14 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *
@ -523,35 +525,5 @@ bool NexusSet::intersect(const NexusSet&that) const
* Revision 1.7 2002/06/24 01:49:39 steve * Revision 1.7 2002/06/24 01:49:39 steve
* Make link_drive_constant cache its results in * Make link_drive_constant cache its results in
* the Nexus, to improve cprop performance. * the Nexus, to improve cprop performance.
*
* Revision 1.6 2002/04/21 04:59:08 steve
* Add support for conbinational events by finding
* the inputs to expressions and some statements.
* Get case and assignment statements working.
*
* Revision 1.5 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.4 2000/10/06 23:46:50 steve
* ivl_target updates, including more complete
* handling of ivl_nexus_t objects. Much reduced
* dependencies on pointers to netlist objects.
*
* Revision 1.3 2000/08/26 00:54:03 steve
* Get at gate information for ivl_target interface.
*
* Revision 1.2 2000/07/14 06:12:57 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.1 2000/06/25 19:59:42 steve
* Redesign Links to include the Nexus class that
* carries properties of the connected set of links.
*
*/ */

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: net_scope.cc,v 1.33 2004/10/04 01:10:54 steve Exp $" #ident "$Id: net_scope.cc,v 1.33.2.1 2005/02/19 16:39:31 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -194,7 +194,7 @@ const NetFuncDef* NetScope::func_def() const
void NetScope::set_module_name(perm_string n) void NetScope::set_module_name(perm_string n)
{ {
assert(type_ == MODULE); assert(type_ == MODULE);
module_name_ = n; /* NOTE: n mus have been permallocated. */ module_name_ = n; /* NOTE: n must have been permallocated. */
} }
perm_string NetScope::module_name() const perm_string NetScope::module_name() const
@ -467,6 +467,9 @@ string NetScope::local_hsymbol()
/* /*
* $Log: net_scope.cc,v $ * $Log: net_scope.cc,v $
* Revision 1.33.2.1 2005/02/19 16:39:31 steve
* Spellig fixes.
*
* Revision 1.33 2004/10/04 01:10:54 steve * Revision 1.33 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.321 2004/10/04 01:10:54 steve Exp $" #ident "$Id: netlist.h,v 1.321.2.4 2005/09/09 02:17:08 steve Exp $"
#endif #endif
/* /*
@ -60,6 +60,9 @@ class NetESignal;
class NetEVariable; class NetEVariable;
class NetFuncDef; class NetFuncDef;
class NetRamDq;
class NetEvTrig;
class NetEvWait;
struct target; struct target;
struct functor_t; struct functor_t;
@ -753,7 +756,7 @@ class NetMemory {
long idxl_; long idxl_;
friend class NetRamDq; friend class NetRamDq;
NetRamDq* ram_list_; class NetRamDq* ram_list_;
friend class NetScope; friend class NetScope;
NetMemory*snext_, *sprev_; NetMemory*snext_, *sprev_;
@ -1349,6 +1352,9 @@ class NetProc : public virtual LineInfo {
// synthesize as asynchronous logic, and return true. // synthesize as asynchronous logic, and return true.
virtual bool synth_async(Design*des, NetScope*scope, virtual bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetNet*nex_map, NetNet*nex_out);
virtual bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out,
NetNet*accum_in);
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff, virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetNet*nex_map, NetNet*nex_out,
@ -1606,6 +1612,8 @@ class NetCase : public NetProc {
bool synth_async(Design*des, NetScope*scope, bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetNet*nex_map, NetNet*nex_out);
bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out, NetNet*accum_in);
virtual bool emit_proc(struct target_t*) const; virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const; virtual void dump(ostream&, unsigned ind) const;
@ -1688,6 +1696,8 @@ class NetCondit : public NetProc {
bool is_asynchronous(); bool is_asynchronous();
bool synth_async(Design*des, NetScope*scope, bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out); const NetNet*nex_map, NetNet*nex_out);
bool synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out, NetNet*accum);
bool synth_sync(Design*des, NetScope*scope, NetFF*ff, bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetNet*nex_map, NetNet*nex_out,
@ -1845,12 +1855,12 @@ class NetEvent : public LineInfo {
NetEvProbe*probes_; NetEvProbe*probes_;
// Use these methods to list the triggers attached to me. // Use these methods to list the triggers attached to me.
NetEvTrig* trig_; class NetEvTrig* trig_;
// Use This member to count references by NetEvWait objects. // Use This member to count references by NetEvWait objects.
unsigned waitref_; unsigned waitref_;
struct wcell_ { struct wcell_ {
NetEvWait*obj; class NetEvWait*obj;
struct wcell_*next; struct wcell_*next;
}; };
struct wcell_ *wlist_; struct wcell_ *wlist_;
@ -2523,7 +2533,7 @@ class NetEBComp : public NetEBinary {
NetEConst*eval_eqeq_(); NetEConst*eval_eqeq_();
NetEConst*eval_less_(); NetEConst*eval_less_();
NetEConst*eval_leeq_(); NetEConst*eval_leeq_();
NetEConst*eval_leeq_real_(); NetEConst*eval_leeq_real_(bool gt_flag, bool include_eq_flag);
NetEConst*eval_gt_(); NetEConst*eval_gt_();
NetEConst*eval_gteq_(); NetEConst*eval_gteq_();
NetEConst*eval_neeq_(); NetEConst*eval_neeq_();
@ -3357,6 +3367,18 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.321.2.4 2005/09/09 02:17:08 steve
* Evaluate magnitude compare with real operands.
*
* Revision 1.321.2.3 2005/08/22 01:00:41 steve
* Add support for implicit defaults in case and conditions.
*
* Revision 1.321.2.2 2005/08/13 00:45:54 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.321.2.1 2005/07/06 22:41:34 steve
* Fix compile errors with g++-4.
*
* Revision 1.321 2004/10/04 01:10:54 steve * Revision 1.321 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

11
parse.y
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: parse.y,v 1.201 2004/10/04 01:10:54 steve Exp $" #ident "$Id: parse.y,v 1.201.2.2 2005/07/27 14:48:34 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -990,7 +990,6 @@ expr_primary
yyerror(@2, "error: Repeat expression " yyerror(@2, "error: Repeat expression "
"must be constant."); "must be constant.");
delete rep; delete rep;
delete $2;
rep = 0; rep = 0;
} }
PEConcat*tmp = new PEConcat(*$4, rep); PEConcat*tmp = new PEConcat(*$4, rep);
@ -2266,7 +2265,7 @@ specify_item
{ {
} }
| K_Shold '(' spec_reference_event ',' spec_reference_event | K_Shold '(' spec_reference_event ',' spec_reference_event
',' expression spec_notifier_opt ')' ';' ',' delay_value spec_notifier_opt ')' ';'
{ delete $7; { delete $7;
} }
| K_Speriod '(' spec_reference_event ',' delay_value | K_Speriod '(' spec_reference_event ',' delay_value
@ -2274,11 +2273,11 @@ specify_item
{ delete $5; { delete $5;
} }
| K_Srecovery '(' spec_reference_event ',' spec_reference_event | K_Srecovery '(' spec_reference_event ',' spec_reference_event
',' expression spec_notifier_opt ')' ';' ',' delay_value spec_notifier_opt ')' ';'
{ delete $7; { delete $7;
} }
| K_Ssetup '(' spec_reference_event ',' spec_reference_event | K_Ssetup '(' spec_reference_event ',' spec_reference_event
',' expression spec_notifier_opt ')' ';' ',' delay_value spec_notifier_opt ')' ';'
{ delete $7; { delete $7;
} }
| K_Ssetuphold '(' spec_reference_event ',' spec_reference_event | K_Ssetuphold '(' spec_reference_event ',' spec_reference_event
@ -2296,7 +2295,7 @@ specify_item
{ delete $5; { delete $5;
delete $7; delete $7;
} }
| K_Swidth '(' spec_reference_event ',' expression ')' ';' | K_Swidth '(' spec_reference_event ',' delay_value ')' ';'
{ delete $5; { delete $5;
} }
; ;

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: parse_api.h,v 1.3 2004/02/18 17:11:57 steve Exp $" #ident "$Id: parse_api.h,v 1.3.2.1 2005/08/13 00:45:54 steve Exp $"
#endif #endif
# include <stdio.h> # include <stdio.h>
@ -35,8 +35,8 @@ class PUdp;
* Verilog source into pform for elaboration. The parser adds modules * Verilog source into pform for elaboration. The parser adds modules
* to these maps as it compiles modules in the verilog source. * to these maps as it compiles modules in the verilog source.
*/ */
extern map<perm_string,Module*> pform_modules; extern std::map<perm_string,Module*> pform_modules;
extern map<perm_string,PUdp*> pform_primitives; extern std::map<perm_string,PUdp*> pform_primitives;
/* /*
* This code actually invokes the parser to make modules. The first * This code actually invokes the parser to make modules. The first
@ -47,10 +47,13 @@ extern map<perm_string,PUdp*> pform_primitives;
*/ */
extern int pform_parse(const char*path, FILE*file =0); extern int pform_parse(const char*path, FILE*file =0);
extern string vl_file; extern std::string vl_file;
/* /*
* $Log: parse_api.h,v $ * $Log: parse_api.h,v $
* Revision 1.3.2.1 2005/08/13 00:45:54 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.3 2004/02/18 17:11:57 steve * Revision 1.3 2004/02/18 17:11:57 steve
* Use perm_strings for named langiage items. * Use perm_strings for named langiage items.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: set_width.cc,v 1.34 2003/08/28 04:11:19 steve Exp $" #ident "$Id: set_width.cc,v 1.34.2.1 2005/03/05 01:36:16 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -167,12 +167,13 @@ bool NetEBDiv::set_width(unsigned w)
return w == expr_width(); return w == expr_width();
} }
/*
* The logical binary operators do not care what the widths of their
* operands are, the output is always 1 bit. The operands are
* self-determined, so a set_width is stopped here.
*/
bool NetEBLogic::set_width(unsigned w) bool NetEBLogic::set_width(unsigned w)
{ {
bool flag;
flag = left_->set_width(right_->expr_width());
if (!flag)
flag = right_->set_width(left_->expr_width());
return (w == 1); return (w == 1);
} }
@ -411,6 +412,9 @@ bool NetEUReduce::set_width(unsigned w)
/* /*
* $Log: set_width.cc,v $ * $Log: set_width.cc,v $
* Revision 1.34.2.1 2005/03/05 01:36:16 steve
* Fix set_width to allow binary logical operands to be self determined.
*
* Revision 1.34 2003/08/28 04:11:19 steve * Revision 1.34 2003/08/28 04:11:19 steve
* Spelling patch. * Spelling patch.
* *

View File

@ -1,7 +1,7 @@
PKG="IVLver" PKG="IVLver"
NAME="verilog" NAME="verilog"
ARCH="sparc" ARCH="sparc"
VERSION="0.7" VERSION="0.8"
CATEGORY="application" CATEGORY="application"
VENDOR="Icarus.com" VENDOR="Icarus.com"
EMAIL="steve@icarus.com" EMAIL="steve@icarus.com"

View File

@ -4,6 +4,7 @@ f none bin/iverilog 0755 bin bin
f none bin/iverilog-vpi 0755 bin bin f none bin/iverilog-vpi 0755 bin bin
f none bin/vvp 0755 bin bin f none bin/vvp 0755 bin bin
d none include 0755 bin bin d none include 0755 bin bin
f none include/_pli_types.h 0644 bin bin
f none include/acc_user.h 0644 bin bin f none include/acc_user.h 0644 bin bin
f none include/ivl_target.h 0644 bin bin f none include/ivl_target.h 0644 bin bin
f none include/veriuser.h 0644 bin bin f none include/veriuser.h 0644 bin bin
@ -11,12 +12,21 @@ f none include/vpi_user.h 0644 bin bin
d none lib 0755 bin bin d none lib 0755 bin bin
d none lib/ivl 0755 bin bin d none lib/ivl 0755 bin bin
f none lib/ivl/fpga.tgt 0644 bin bin f none lib/ivl/fpga.tgt 0644 bin bin
f none lib/ivl/fpga.conf 0644 bin bin
f none lib/ivl/fpga-s.conf 0644 bin bin
f none lib/ivl/iverilog.conf 0644 bin bin f none lib/ivl/iverilog.conf 0644 bin bin
f none lib/ivl/ivl 0755 bin bin f none lib/ivl/ivl 0755 bin bin
f none lib/ivl/ivlpp 0755 bin bin f none lib/ivl/ivlpp 0755 bin bin
f none lib/ivl/null.tgt 0644 bin bin f none lib/ivl/null.tgt 0644 bin bin
f none lib/ivl/null.conf 0644 bin bin
f none lib/ivl/null-s.conf 0644 bin bin
f none lib/ivl/system.vpi 0644 bin bin f none lib/ivl/system.vpi 0644 bin bin
f none lib/ivl/system.sft 0644 bin bin
f none lib/ivl/vvp.tgt 0644 bin bin f none lib/ivl/vvp.tgt 0644 bin bin
f none lib/ivl/vvp.conf 0644 bin bin
f none lib/ivl/vvp-s.conf 0644 bin bin
f none lib/ivl/xnf.conf 0644 bin bin
f none lib/ivl/xnf-s.conf 0644 bin bin
f none lib/libveriuser.a 0644 bin bin f none lib/libveriuser.a 0644 bin bin
f none lib/libvpi.a 0644 bin bin f none lib/libvpi.a 0644 bin bin
d none man 0755 bin bin d none man 0755 bin bin

View File

@ -21,7 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: svector.h,v 1.9 2003/07/23 02:35:44 steve Exp $" #ident "$Id: svector.h,v 1.9.2.1 2005/06/14 15:33:54 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -101,14 +101,17 @@ template <class TYPE> class svector {
* Override the implementation of the above template for the string * Override the implementation of the above template for the string
* type parameter. The initialization to nil works different here. * type parameter. The initialization to nil works different here.
*/ */
inline svector<string>::svector<string>(unsigned size) template <> inline svector<std::string>::svector(unsigned size)
: nitems_(size), items_(new string[size]) : nitems_(size), items_(new std::string[size])
{ {
} }
/* /*
* $Log: svector.h,v $ * $Log: svector.h,v $
* Revision 1.9.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.9 2003/07/23 02:35:44 steve * Revision 1.9 2003/07/23 02:35:44 steve
* Inline the svector<string> constructor. * Inline the svector<string> constructor.
* *

191
synth2.cc
View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: synth2.cc,v 1.39 2004/10/04 01:10:55 steve Exp $" #ident "$Id: synth2.cc,v 1.39.2.3 2005/09/11 02:56:38 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -47,6 +47,13 @@ bool NetProc::synth_async(Design*des, NetScope*scope,
return false; return false;
} }
bool NetProc::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out,
NetNet*accum_in)
{
return synth_async(des, scope, nex_map, nex_out);
}
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff, bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
const NetNet*nex_map, NetNet*nex_out, const NetNet*nex_map, NetNet*nex_out,
const svector<NetEvProbe*>&events) const svector<NetEvProbe*>&events)
@ -143,10 +150,17 @@ bool NetBlock::synth_async(Design*des, NetScope*scope,
const perm_string tmp1 = perm_string::literal("tmp1"); const perm_string tmp1 = perm_string::literal("tmp1");
const perm_string tmp2 = perm_string::literal("tmp2"); const perm_string tmp2 = perm_string::literal("tmp2");
const perm_string tmp3 = perm_string::literal("tmp3");
NetNet*accum_out = new NetNet(scope, tmp3, NetNet::WIRE,
nex_out->pin_count());
accum_out->local_flag(true);
bool flag = true; bool flag = true;
NetProc*cur = last_; NetProc*cur = last_;
do { do {
NetNet*new_accum;
cur = cur->next_; cur = cur->next_;
/* Create a temporary nex_map for the substatement. */ /* Create a temporary nex_map for the substatement. */
@ -162,30 +176,82 @@ bool NetBlock::synth_async(Design*des, NetScope*scope,
NetNet*tmp_out = new NetNet(scope, tmp2, NetNet::WIRE, NetNet*tmp_out = new NetNet(scope, tmp2, NetNet::WIRE,
tmp_set.count()); tmp_set.count());
bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out); /* Make a temporary set of currently accumulated outputs
that we can pass to the synth_async of the
sub-statement. Some sub-statements will use this to
handle default cases specially. We will delete this
temporary map as soon as the synth_async is done. */
new_accum = new NetNet(scope, tmp3, NetNet::WIRE, tmp_set.count());
for (unsigned idx = 0 ; idx < tmp_set.count() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
if (accum_out->pin(ptr).is_linked())
connect(new_accum->pin(idx), accum_out->pin(ptr));
}
bool ok_flag = cur->synth_async(des, scope,
tmp_map, tmp_out, new_accum);
flag = flag && ok_flag; flag = flag && ok_flag;
delete new_accum;
if (ok_flag == false) if (ok_flag == false)
continue; continue;
/* Now start building a new set of accumulated outputs
that we will pass to the next statement of the block,
or that will be the output of the block. */
new_accum = new NetNet(scope, tmp3, NetNet::WIRE,
nex_out->pin_count());
/* Use the nex_map to link up the output from the /* Use the nex_map to link up the output from the
substatement to the output of the block as a whole. */ substatement to the output of the block as a whole. */
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) { for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]); unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
connect(nex_out->pin(ptr), tmp_out->pin(idx)); connect(new_accum->pin(ptr), tmp_out->pin(idx));
} }
delete tmp_map; delete tmp_map;
delete tmp_out; delete tmp_out;
/* Anything that is not redriven by the current
statement inherits the value that was driven from any
previous statements. */
for (unsigned idx = 0; idx < new_accum->pin_count(); idx += 1) {
if (new_accum->pin(idx).is_linked())
continue;
connect(new_accum->pin(idx), accum_out->pin(idx));
}
delete accum_out;
accum_out = new_accum;
} while (cur != last_); } while (cur != last_);
/* Now bind the accumulated output valies to the nex_out
passed in. Note that each previous step has already did the
pin mapping, so just connect. */
for (unsigned idx = 0 ; idx < accum_out->pin_count() ; idx += 1) {
connect(nex_out->pin(idx), accum_out->pin(idx));
}
delete accum_out;
DEBUG_SYNTH2_EXIT("NetBlock",flag) DEBUG_SYNTH2_EXIT("NetBlock",flag)
return flag; return flag;
} }
bool NetCase::synth_async(Design*des, NetScope*scope, bool NetCase::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out) const NetNet*nex_map, NetNet*nex_out)
{
const perm_string tmp = perm_string::literal("tmp");
NetNet*stub = new NetNet(scope, tmp, NetNet::WIRE, nex_out->pin_count());
bool flag = synth_async(des, scope, nex_map, nex_out, stub);
delete stub;
return flag;
}
bool NetCase::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out, NetNet*accum)
{ {
DEBUG_SYNTH2_ENTRY("NetCase") DEBUG_SYNTH2_ENTRY("NetCase")
unsigned cur; unsigned cur;
@ -227,6 +293,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
NetMux*mux = new NetMux(scope, scope->local_symbol(), NetMux*mux = new NetMux(scope, scope->local_symbol(),
nex_out->pin_count(), nex_out->pin_count(),
1U << sel_pins, sel_pins); 1U << sel_pins, sel_pins);
mux->set_line(*this);
/* Connect the non-constant select bits to the select input of /* Connect the non-constant select bits to the select input of
the mux device. */ the mux device. */
@ -271,10 +338,23 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
statement_map[sel_idx] = items_[item].statement; statement_map[sel_idx] = items_[item].statement;
} }
/* Set up a default default_sig that uses the accumulated
input pins. This binding is suppressed by an actual default
statement if one exists. */
NetNet*default_sig = 0;
if (default_statement == 0) {
default_sig = accum;
for (unsigned idx = 0 ; idx < accum->pin_count() ; idx += 1) {
if (! accum->pin(idx).is_linked()) {
default_sig = 0;
break;
}
}
}
/* Now that statements match with mux inputs, synthesize the /* Now that statements match with mux inputs, synthesize the
sub-statements. If I get to an input that has no statement, sub-statements. If I get to an input that has no statement,
then use the default statement there. */ then use the default statement there. */
NetNet*default_sig = 0;
for (unsigned item = 0 ; item < (1U<<sel_pins) ; item += 1) { for (unsigned item = 0 ; item < (1U<<sel_pins) ; item += 1) {
/* Detect the case that this is a default input, and I /* Detect the case that this is a default input, and I
@ -298,6 +378,9 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
if (statement_map[item] == 0) { if (statement_map[item] == 0) {
/* Missing case and no default; this could still be /* Missing case and no default; this could still be
* synthesizable with synchronous logic, but not here. */ * synthesizable with synchronous logic, but not here. */
cerr << get_line()
<< ": error: Incomplete case statement"
<< " is missing a default case." << endl;
DEBUG_SYNTH2_EXIT("NetCase", false) DEBUG_SYNTH2_EXIT("NetCase", false)
return false; return false;
} }
@ -314,53 +397,95 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
return true; return true;
} }
/*
* If the synth_async method is called without an accumulated input
* (in other words not from within a block) then stub the input signal
* with an unconnected net.
*/
bool NetCondit::synth_async(Design*des, NetScope*scope, bool NetCondit::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out) const NetNet*nex_map, NetNet*nex_out)
{
const perm_string tmp = perm_string::literal("tmp");
NetNet*stub = new NetNet(scope, tmp, NetNet::WIRE, nex_out->pin_count());
bool flag = synth_async(des, scope, nex_map, nex_out, stub);
delete stub;
return flag;
}
bool NetCondit::synth_async(Design*des, NetScope*scope,
const NetNet*nex_map, NetNet*nex_out,
NetNet*accum)
{ {
DEBUG_SYNTH2_ENTRY("NetCondit") DEBUG_SYNTH2_ENTRY("NetCondit")
NetNet*ssig = expr_->synthesize(des); NetNet*ssig = expr_->synthesize(des);
assert(ssig); assert(ssig);
if (if_ == 0) { /* Use the accumulated input net as a default input for
DEBUG_SYNTH2_EXIT("NetCondit",false) covering a missing clause, except that if I find portions
return false; are unconnected, then give up on that idea. */
} NetNet*default_sig = accum;
if (else_ == 0) { for (unsigned idx = 0 ; idx < default_sig->pin_count() ; idx += 1) {
cerr << get_line() << ": error: Asynchronous if statement" if (! default_sig->pin(idx).is_linked()) {
<< " is missing the else clause." << endl; default_sig = 0;
DEBUG_SYNTH2_EXIT("NetCondit",false) break;
return false; }
} }
assert(if_ != 0); if (default_sig == 0) {
assert(else_ != 0); if (if_ == 0) {
cerr << get_line() << ": error: Asynchronous if statement"
<< " is missing the if clause." << endl;
return false;
}
if (else_ == 0) {
cerr << get_line() << ": error: Asynchronous if statement"
<< " is missing the else clause." << endl;
return false;
}
}
assert(if_ != 0 || else_ != 0);
NetNet*asig = new NetNet(scope, scope->local_symbol(), NetNet*asig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, nex_map->pin_count()); NetNet::WIRE, nex_map->pin_count());
asig->local_flag(true); asig->local_flag(true);
bool flag; if (if_ == 0) {
flag = if_->synth_async(des, scope, nex_map, asig); for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1)
if (!flag) { connect(asig->pin(idx), default_sig->pin(idx));
delete asig;
DEBUG_SYNTH2_EXIT("NetCondit",false) } else {
return false; bool flag = if_->synth_async(des, scope, nex_map, asig);
if (!flag) {
delete asig;
cerr << get_line() << ": error: Asynchronous if statement"
<< " true clause failed to synthesize." << endl;
return false;
}
} }
NetNet*bsig = new NetNet(scope, scope->local_symbol(), NetNet*bsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, nex_map->pin_count()); NetNet::WIRE, nex_map->pin_count());
bsig->local_flag(true); bsig->local_flag(true);
flag = else_->synth_async(des, scope, nex_map, bsig); if (else_ == 0) {
if (!flag) { for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1)
delete asig; connect(bsig->pin(idx), default_sig->pin(idx));
delete bsig;
DEBUG_SYNTH2_EXIT("NetCondit",false) } else {
return false; bool flag = else_->synth_async(des, scope, nex_map, bsig);
if (!flag) {
delete asig;
delete bsig;
cerr << get_line() << ": error: Asynchronous if statement"
<< " else clause failed to synthesize." << endl;
return false;
}
} }
NetMux*mux = new NetMux(scope, scope->local_symbol(), NetMux*mux = new NetMux(scope, scope->local_symbol(),
nex_out->pin_count(), 2, 1); nex_out->pin_count(), 2, 1);
mux->set_line(*this);
connect(mux->pin_Sel(0), ssig->pin(0)); connect(mux->pin_Sel(0), ssig->pin(0));
@ -375,7 +500,6 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
des->add_node(mux); des->add_node(mux);
DEBUG_SYNTH2_EXIT("NetCondit",true)
return true; return true;
} }
@ -985,6 +1109,15 @@ void synth2(Design*des)
/* /*
* $Log: synth2.cc,v $ * $Log: synth2.cc,v $
* Revision 1.39.2.3 2005/09/11 02:56:38 steve
* Attach line numbers to NetMux devices.
*
* Revision 1.39.2.2 2005/08/22 01:00:42 steve
* Add support for implicit defaults in case and conditions.
*
* Revision 1.39.2.1 2005/08/21 22:49:54 steve
* Handle statements in blocks overriding previous statement outputs.
*
* Revision 1.39 2004/10/04 01:10:55 steve * Revision 1.39 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.cc,v 1.131 2004/10/04 01:10:55 steve Exp $" #ident "$Id: t-dll.cc,v 1.131.2.1 2005/02/19 16:39:31 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1104,7 +1104,7 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
obj->type = IVL_LPM_SUB; obj->type = IVL_LPM_SUB;
else else
obj->type = IVL_LPM_ADD; obj->type = IVL_LPM_ADD;
obj->name = net->name(); // NetAddSub names are permallocated. obj->name = net->name(); // NetAddSub names are permallocated
assert(net->scope()); assert(net->scope());
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
assert(obj->scope); assert(obj->scope);
@ -1803,7 +1803,7 @@ void dll_target::lpm_mux(const NetMux*net)
{ {
ivl_lpm_t obj = new struct ivl_lpm_s; ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_MUX; obj->type = IVL_LPM_MUX;
obj->name = net->name(); // The NetMux perallocates its name. obj->name = net->name(); // NetMux names are permallocated
obj->scope = find_scope(des_, net->scope()); obj->scope = find_scope(des_, net->scope());
assert(obj->scope); assert(obj->scope);
@ -2180,6 +2180,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/* /*
* $Log: t-dll.cc,v $ * $Log: t-dll.cc,v $
* Revision 1.131.2.1 2005/02/19 16:39:31 steve
* Spellig fixes.
*
* Revision 1.131 2004/10/04 01:10:55 steve * Revision 1.131 2004/10/04 01:10:55 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

6
tgt-edif/.cvsignore Normal file
View File

@ -0,0 +1,6 @@
configure
Makefile
edif.tgt
dep
config.status
config.log

46
tgt-edif/LICENSE.txt Normal file
View File

@ -0,0 +1,46 @@
The tgt-edif files are licensed differently from the rest of Icarus
Verilog. These files are:
--
Copyright (c) 2005 Stephen Williams
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
The purpose of the different license here is to allow licensees to use
these files to make EDIF based code generators that use these common
functions without statically linking to GPL files from elsewhere
within Icarus Verilog.
As a reminder, while this more relaxed license is here to allow
entities to make closed source (binary) code generators, this is not
intended to effect the GPL standing of the rest of Icarus Verilog
source. THIS RELAXED LICENSE APPLIES ONLY TO FILES SPECIFICALLY MARKED
WITH THIS NEW LICENSE. Furthermore, all rights remain reserved. Note
specifically the requirement for you to reproduce notices in your
documentation.

139
tgt-edif/Makefile.in Normal file
View File

@ -0,0 +1,139 @@
#
# Copyright (c) 2005 Stephen Williams
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#ident "$Id: Makefile.in,v 1.1.2.2 2005/09/25 16:35:36 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.0
prefix = @prefix@
exec_prefix = @exec_prefix@
srcdir = @srcdir@
mandir = @mandir@
VPATH = $(srcdir)
bindir = @bindir@
libdir = @libdir@
includedir = $(prefix)/include
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
RANLIB = @RANLIB@
CPPFLAGS = @ident_support@ -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
all: dep edif.tgt
dep:
mkdir dep
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
D = d-lpm.o d-virtex.o xilinx.o
O = edif.o device.o target.o gates.o generic.o $D
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
TGTDEPLIBS=../libivl.a
else
TGTLDFLAGS=
TGTDEPLIBS=
endif
edif.tgt: tables.o libedif_tgt.a $(TGTDEPLIBS)
$(CC) @shared@ -o $@ tables.o libedif_tgt.a $(TGTLDFLAGS)
libedif_tgt.a: $O
rm -f libedif_tgt.a
ar cqv libedif_tgt.a $O
$(RANLIB) libedif_tgt.a
iverilog-edif.ps: $(srcdir)/iverilog-edif.man
man -t $(srcdir)/iverilog-edif.man > iverilog-edif.ps
iverilog-edif.pdf: iverilog-edif.ps
ps2pdf iverilog-edif.ps iverilog-edif.pdf
Makefile: Makefile.in config.status
./config.status
clean:
rm -rf *.o dep edif.tgt
distclean: clean
rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
check: all
ifeq (@WIN32@,yes)
#INSTALL_DOC = $(prefix)/iverilog-edif.pdf $(mandir)/man1/iverilog-edif.1
#INSTALL_DOCDIR = $(mandir)/man1
all: iverilog-edif.pdf
else
#INSTALL_DOC = $(mandir)/man1/iverilog-edif.1
#INSTALL_DOCDIR = $(mandir)/man1
endif
install: all installdirs $(libdir)/ivl/edif.tgt $(INSTALL_DOC) $(libdir)/ivl/edif.conf $(libdir)/ivl/edif-s.conf
$(libdir)/ivl/edif.tgt: ./edif.tgt
$(INSTALL_PROGRAM) ./edif.tgt $(libdir)/ivl/edif.tgt
$(libdir)/ivl/edif.conf: $(srcdir)/edif.conf
$(INSTALL_DATA) $(srcdir)/edif.conf $(libdir)/ivl/edif.conf
$(libdir)/ivl/edif-s.conf: $(srcdir)/edif-s.conf
$(INSTALL_DATA) $(srcdir)/edif-s.conf $(libdir)/ivl/edif-s.conf
$(mandir)/man1/iverilog-edif.1: $(srcdir)/iverilog-edif.man
$(INSTALL_DATA) $(srcdir)/iverilog-edif.man $(mandir)/man1/iverilog-edif.1
$(prefix)/iverilog-edif.pdf: iverilog-edif.pdf
$(INSTALL_DATA) iverilog-edif.pdf $(prefix)/iverilog-edif.pdf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(libdir)/ivl
uninstall:
rm -f $(libdir)/ivl/edif.tgt
rm -f $(INSTALL_DOC)
rm -f $(libdir)/ivl/edif-s.conf
rm -f $(libdir)/ivl/edif.conf
-include $(patsubst %.o, dep/%.d, $O)

28
tgt-edif/configure.in Normal file
View File

@ -0,0 +1,28 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(edif.conf)
dnl Checks for programs.
AC_PROG_CC
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_CANONICAL_HOST
# $host
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
AC_CHECK_HEADERS(malloc.h)
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# Compiler option for position independent code, needed whan making shared objects.
AX_C_PICFLAG
# linker options when building a shared library
AX_LD_SHAREDLIB_OPTS
AX_CPP_IDENT
AC_OUTPUT(Makefile)

979
tgt-edif/d-lpm.c Normal file
View File

@ -0,0 +1,979 @@
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: d-lpm.c,v 1.1.2.2 2005/08/21 14:39:33 steve Exp $"
#endif
/*
* This is the driver for a purely generic LPM module writer. This
* uses LPM version 2 1 0 devices, without particularly considering
* the target technology.
*
* The LPM standard is EIA-IS/103-A October 1996
* The output is EDIF 2 0 0 format.
*/
# include "device.h"
# include "edif_priv.h"
# include "edif.h"
# include "generic.h"
# include <string.h>
# include <assert.h>
static edif_cell_t lpm_cell_buf(void)
{
static edif_cell_t tmp = 0;
if (tmp != 0)
return tmp;
tmp = edif_xcell_create(xlib, "BUF", 2);
edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT);
edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
/* A buffer is an inverted inverter. */
edif_cell_port_pstring(tmp, 0, "LPM_Polarity", "INVERT");
edif_cell_pstring(tmp, "LPM_TYPE", "LPM_INV");
edif_cell_pinteger(tmp, "LPM_Width", 1);
edif_cell_pinteger(tmp, "LPM_Size", 1);
return tmp;
}
static edif_cell_t lpm_cell_inv(void)
{
static edif_cell_t tmp = 0;
if (tmp != 0)
return tmp;
tmp = edif_xcell_create(xlib, "INV", 2);
edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT);
edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
edif_cell_pstring(tmp, "LPM_TYPE", "LPM_INV");
edif_cell_pinteger(tmp, "LPM_Width", 1);
edif_cell_pinteger(tmp, "LPM_Size", 1);
return tmp;
}
static edif_cell_t lpm_cell_bufif0(void)
{
static edif_cell_t tmp = 0;
if (tmp != 0)
return tmp;
tmp = edif_xcell_create(xlib, "BUFIF1", 3);
edif_cell_portconfig(tmp, 0, "TriData", IVL_SIP_OUTPUT);
edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT);
edif_cell_port_pstring(tmp, 2, "LPM_Polarity", "INVERT");
edif_cell_pstring(tmp, "LPM_TYPE", "LPM_BUSTRI");
edif_cell_pinteger(tmp, "LPM_Width", 1);
return tmp;
}
static edif_cell_t lpm_cell_bufif1(void)
{
static edif_cell_t tmp = 0;
if (tmp != 0)
return tmp;
tmp = edif_xcell_create(xlib, "BUFIF1", 3);
edif_cell_portconfig(tmp, 0, "TriData", IVL_SIP_OUTPUT);
edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT);
edif_cell_pstring(tmp, "LPM_TYPE", "LPM_BUSTRI");
edif_cell_pinteger(tmp, "LPM_Width", 1);
return tmp;
}
static edif_cell_t lpm_cell_or(unsigned siz)
{
unsigned idx;
edif_cell_t cell;
char name[32];
sprintf(name, "or%u", siz);
cell = edif_xlibrary_findcell(xlib, name);
if (cell != 0)
return cell;
cell = edif_xcell_create(xlib, strdup(name), siz+1);
edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
for (idx = 0 ; idx < siz ; idx += 1) {
sprintf(name, "Data%ux0", idx);
edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
}
edif_cell_pstring(cell, "LPM_TYPE", "LPM_OR");
edif_cell_pinteger(cell, "LPM_Width", 1);
edif_cell_pinteger(cell, "LPM_Size", siz);
return cell;
}
static edif_cell_t lpm_cell_and(unsigned siz)
{
unsigned idx;
edif_cell_t cell;
char name[32];
sprintf(name, "and%u", siz);
cell = edif_xlibrary_findcell(xlib, name);
if (cell != 0)
return cell;
cell = edif_xcell_create(xlib, strdup(name), siz+1);
edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
for (idx = 0 ; idx < siz ; idx += 1) {
sprintf(name, "Data%ux0", idx);
edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
}
edif_cell_pstring(cell, "LPM_TYPE", "LPM_AND");
edif_cell_pinteger(cell, "LPM_Width", 1);
edif_cell_pinteger(cell, "LPM_Size", siz);
return cell;
}
static edif_cell_t lpm_cell_xor(unsigned siz)
{
unsigned idx;
edif_cell_t cell;
char name[32];
sprintf(name, "xor%u", siz);
cell = edif_xlibrary_findcell(xlib, name);
if (cell != 0)
return cell;
cell = edif_xcell_create(xlib, strdup(name), siz+1);
edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
for (idx = 0 ; idx < siz ; idx += 1) {
sprintf(name, "Data%ux0", idx);
edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
}
edif_cell_pstring(cell, "LPM_TYPE", "LPM_XOR");
edif_cell_pinteger(cell, "LPM_Width", 1);
edif_cell_pinteger(cell, "LPM_Size", siz);
return cell;
}
static edif_cell_t lpm_cell_nor(unsigned siz)
{
unsigned idx;
edif_cell_t cell;
char name[32];
sprintf(name, "nor%u", siz);
cell = edif_xlibrary_findcell(xlib, name);
if (cell != 0)
return cell;
cell = edif_xcell_create(xlib, strdup(name), siz+1);
edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
edif_cell_port_pstring(cell, 0, "LPM_Polarity", "INVERT");
for (idx = 0 ; idx < siz ; idx += 1) {
sprintf(name, "Data%ux0", idx);
edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
}
edif_cell_pstring(cell, "LPM_TYPE", "LPM_OR");
edif_cell_pinteger(cell, "LPM_Width", 1);
edif_cell_pinteger(cell, "LPM_Size", siz);
return cell;
}
static void lpm_show_header(ivl_design_t des)
{
unsigned idx;
ivl_scope_t root = ivl_design_root(des);
unsigned sig_cnt = ivl_scope_sigs(root);
unsigned nports = 0, pidx;
/* Count the ports I'm going to use. */
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
ivl_signal_t sig = ivl_scope_sig(root, idx);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
continue;
if (ivl_signal_attr(sig, "PAD") != 0)
continue;
nports += ivl_signal_pins(sig);
}
/* Create the base edf object. */
edf = edif_create(ivl_scope_basename(root), nports);
pidx = 0;
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
edif_joint_t jnt;
ivl_signal_t sig = ivl_scope_sig(root, idx);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
continue;
if (ivl_signal_attr(sig, "PAD") != 0)
continue;
if (ivl_signal_pins(sig) == 1) {
edif_portconfig(edf, pidx, ivl_signal_basename(sig),
ivl_signal_port(sig));
assert(ivl_signal_pins(sig) == 1);
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
edif_port_to_joint(jnt, edf, pidx);
} else {
const char*name = ivl_signal_basename(sig);
ivl_signal_port_t dir = ivl_signal_port(sig);
char buf[128];
unsigned bit;
for (bit = 0 ; bit < ivl_signal_pins(sig) ; bit += 1) {
const char*tmp;
sprintf(buf, "%s[%u]", name, bit);
tmp = strdup(buf);
edif_portconfig(edf, pidx+bit, tmp, dir);
jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit));
edif_port_to_joint(jnt, edf, pidx+bit);
}
}
pidx += ivl_signal_pins(sig);
}
assert(pidx == nports);
xlib = edif_xlibrary_create(edf, "LPM_LIBRARY");
}
static void lpm_show_footer(ivl_design_t des)
{
edif_print(xnf, edf);
}
static void hookup_logic_gate(ivl_net_logic_t net, edif_cell_t cell)
{
unsigned pin, idx;
edif_joint_t jnt;
edif_cellref_t ref = edif_cellref_create(edf, cell);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
pin = edif_cell_port_byname(cell, "Result0");
edif_add_to_joint(jnt, ref, pin);
for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) {
char name[32];
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx));
sprintf(name, "Data%ux0", idx-1);
pin = edif_cell_port_byname(cell, name);
edif_add_to_joint(jnt, ref, pin);
}
}
static void lpm_logic(ivl_net_logic_t net)
{
edif_cell_t cell;
edif_cellref_t ref;
edif_joint_t jnt;
switch (ivl_logic_type(net)) {
case IVL_LO_BUFZ:
case IVL_LO_BUF:
assert(ivl_logic_pins(net) == 2);
cell = lpm_cell_buf();
ref = edif_cellref_create(edf, cell);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, ref, 0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, ref, 1);
break;
case IVL_LO_BUFIF0:
assert(ivl_logic_pins(net) == 3);
cell = lpm_cell_bufif0();
ref = edif_cellref_create(edf, cell);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, ref, 0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, ref, 1);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, ref, 2);
break;
case IVL_LO_BUFIF1:
assert(ivl_logic_pins(net) == 3);
cell = lpm_cell_bufif1();
ref = edif_cellref_create(edf, cell);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, ref, 0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, ref, 1);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, ref, 2);
break;
case IVL_LO_NOT:
assert(ivl_logic_pins(net) == 2);
cell = lpm_cell_inv();
ref = edif_cellref_create(edf, cell);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, ref, 0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, ref, 1);
break;
case IVL_LO_OR:
cell = lpm_cell_or(ivl_logic_pins(net)-1);
hookup_logic_gate(net, cell);
break;
case IVL_LO_NOR:
cell = lpm_cell_nor(ivl_logic_pins(net)-1);
hookup_logic_gate(net, cell);
break;
case IVL_LO_AND:
cell = lpm_cell_and(ivl_logic_pins(net)-1);
hookup_logic_gate( net, cell);
break;
case IVL_LO_XOR:
cell = lpm_cell_xor(ivl_logic_pins(net)-1);
hookup_logic_gate( net, cell);
break;
default:
fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n",
ivl_logic_type(net));
break;
}
}
static void lpm_show_dff(ivl_lpm_t net)
{
char name[64];
edif_cell_t cell;
edif_cellref_t ref;
edif_joint_t jnt;
unsigned idx;
unsigned pin, wid = ivl_lpm_width(net);
sprintf(name, "fd%s%s%s%s%s%u",
ivl_lpm_enable(net)? "ce" : "",
ivl_lpm_async_clr(net)? "cl" : "",
ivl_lpm_sync_clr(net)? "sc" : "",
ivl_lpm_async_set(net)? "se" : "",
ivl_lpm_sync_set(net)? "ss" : "",
wid);
cell = edif_xlibrary_findcell(xlib, name);
if (cell == 0) {
unsigned nports = 2 * wid + 1;
pin = 0;
if (ivl_lpm_enable(net))
nports += 1;
if (ivl_lpm_async_clr(net))
nports += 1;
if (ivl_lpm_sync_clr(net))
nports += 1;
if (ivl_lpm_async_set(net))
nports += 1;
if (ivl_lpm_sync_set(net))
nports += 1;
cell = edif_xcell_create(xlib, strdup(name), nports);
edif_cell_pstring(cell, "LPM_Type", "LPM_FF");
edif_cell_pinteger(cell, "LPM_Width", wid);
for (idx = 0 ; idx < wid ; idx += 1) {
sprintf(name, "Q%u", idx);
edif_cell_portconfig(cell, idx*2+0, strdup(name),
IVL_SIP_OUTPUT);
sprintf(name, "Data%u", idx);
edif_cell_portconfig(cell, idx*2+1, strdup(name),
IVL_SIP_INPUT);
}
pin = wid*2;
if (ivl_lpm_enable(net)) {
edif_cell_portconfig(cell, pin, "Enable", IVL_SIP_INPUT);
pin += 1;
}
if (ivl_lpm_async_clr(net)) {
edif_cell_portconfig(cell, pin, "Aclr", IVL_SIP_INPUT);
pin += 1;
}
if (ivl_lpm_sync_clr(net)) {
edif_cell_portconfig(cell, pin, "Sclr", IVL_SIP_INPUT);
pin += 1;
}
if (ivl_lpm_async_set(net)) {
edif_cell_portconfig(cell, pin, "Aset", IVL_SIP_INPUT);
pin += 1;
}
if (ivl_lpm_sync_set(net)) {
edif_cell_portconfig(cell, pin, "Sset", IVL_SIP_INPUT);
pin += 1;
}
edif_cell_portconfig(cell, pin, "Clock", IVL_SIP_INPUT);
pin += 1;
assert(pin == nports);
}
ref = edif_cellref_create(edf, cell);
pin = edif_cell_port_byname(cell, "Clock");
jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net));
edif_add_to_joint(jnt, ref, pin);
if (ivl_lpm_enable(net)) {
pin = edif_cell_port_byname(cell, "Enable");
jnt = edif_joint_of_nexus(edf, ivl_lpm_enable(net));
edif_add_to_joint(jnt, ref, pin);
}
if (ivl_lpm_async_clr(net)) {
pin = edif_cell_port_byname(cell, "Aclr");
jnt = edif_joint_of_nexus(edf, ivl_lpm_async_clr(net));
edif_add_to_joint(jnt, ref, pin);
}
if (ivl_lpm_sync_clr(net)) {
pin = edif_cell_port_byname(cell, "Sclr");
jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_clr(net));
edif_add_to_joint(jnt, ref, pin);
}
if (ivl_lpm_async_set(net)) {
pin = edif_cell_port_byname(cell, "Aset");
jnt = edif_joint_of_nexus(edf, ivl_lpm_async_set(net));
edif_add_to_joint(jnt, ref, pin);
}
if (ivl_lpm_sync_set(net)) {
ivl_expr_t svalue = ivl_lpm_sset_value(net);
pin = edif_cell_port_byname(cell, "Sset");
jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_set(net));
edif_add_to_joint(jnt, ref, pin);
edif_cellref_pinteger(ref, "LPM_Svalue", ivl_expr_uvalue(svalue));
}
for (idx = 0 ; idx < wid ; idx += 1) {
sprintf(name, "Q%u", idx);
pin = edif_cell_port_byname(cell, name);
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
edif_add_to_joint(jnt, ref, pin);
sprintf(name, "Data%u", idx);
pin = edif_cell_port_byname(cell, name);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
edif_add_to_joint(jnt, ref, pin);
}
}
static void lpm_show_cmp_eq(ivl_lpm_t net)
{
edif_cell_t cell;
edif_cellref_t ref;
edif_joint_t jnt;
unsigned idx;
char cellname[32];
unsigned width = ivl_lpm_width(net);
sprintf(cellname, "compare%u_eq", width);
cell = edif_xlibrary_findcell(xlib, cellname);
if (cell == 0) {
unsigned pins = 2*width + 1;
cell = edif_xcell_create(xlib, strdup(cellname), pins);
/* Make the output port. */
sprintf(cellname, "AEB");
edif_cell_portconfig(cell, 2*width, strdup(cellname),
IVL_SIP_OUTPUT);
for (idx = 0 ; idx < width ; idx += 1) {
sprintf(cellname, "DataA%u", idx);
edif_cell_portconfig(cell, idx+0, strdup(cellname),
IVL_SIP_INPUT);
}
for (idx = 0 ; idx < width ; idx += 1) {
sprintf(cellname, "DataB%u", idx);
edif_cell_portconfig(cell, idx+width, strdup(cellname),
IVL_SIP_INPUT);
}
edif_cell_pstring(cell, "LPM_Type", "LPM_COMPARE");
edif_cell_pinteger(cell, "LPM_Width", width);
}
ref = edif_cellref_create(edf, cell);
for (idx = 0 ; idx < width ; idx += 1) {
unsigned pin;
sprintf(cellname, "DataA%u", idx);
pin = edif_cell_port_byname(cell, cellname);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
edif_add_to_joint(jnt, ref, pin);
}
for (idx = 0 ; idx < width ; idx += 1) {
unsigned pin;
sprintf(cellname, "DataB%u", idx);
pin = edif_cell_port_byname(cell, cellname);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
edif_add_to_joint(jnt, ref, pin);
}
{
unsigned pin;
pin = edif_cell_port_byname(cell, "AEB");
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, ref, pin);
}
}
static void lpm_show_mux(ivl_lpm_t net)
{
edif_cell_t cell;
edif_cellref_t ref;
edif_joint_t jnt;
unsigned idx, rdx;
char cellname[32];
unsigned wid_r = ivl_lpm_width(net);
unsigned wid_s = ivl_lpm_selects(net);
unsigned wid_z = ivl_lpm_size(net);
sprintf(cellname, "mux%u_%u_%u", wid_r, wid_s, wid_z);
cell = edif_xlibrary_findcell(xlib, cellname);
if (cell == 0) {
unsigned pins = wid_r + wid_s + wid_r*wid_z;
cell = edif_xcell_create(xlib, strdup(cellname), pins);
/* Make the output ports. */
for (idx = 0 ; idx < wid_r ; idx += 1) {
sprintf(cellname, "Result%u", idx);
edif_cell_portconfig(cell, idx, strdup(cellname),
IVL_SIP_OUTPUT);
}
/* Make the select ports. */
for (idx = 0 ; idx < wid_s ; idx += 1) {
sprintf(cellname, "Sel%u", idx);
edif_cell_portconfig(cell, wid_r+idx, strdup(cellname),
IVL_SIP_INPUT);
}
for (idx = 0 ; idx < wid_z ; idx += 1) {
unsigned base = wid_r + wid_s + wid_r * idx;
unsigned rdx;
for (rdx = 0 ; rdx < wid_r ; rdx += 1) {
sprintf(cellname, "Data%ux%u", idx, rdx);
edif_cell_portconfig(cell, base+rdx, strdup(cellname),
IVL_SIP_INPUT);
}
}
edif_cell_pstring(cell, "LPM_Type", "LPM_MUX");
edif_cell_pinteger(cell, "LPM_Width", wid_r);
edif_cell_pinteger(cell, "LPM_WidthS", wid_s);
edif_cell_pinteger(cell, "LPM_Size", wid_z);
}
ref = edif_cellref_create(edf, cell);
/* Connect the pins of the instance to the nexa. Access the
cell pins by name. */
for (idx = 0 ; idx < wid_r ; idx += 1) {
unsigned pin;
sprintf(cellname, "Result%u", idx);
pin = edif_cell_port_byname(cell, cellname);
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
edif_add_to_joint(jnt, ref, pin);
}
for (idx = 0 ; idx < wid_s ; idx += 1) {
unsigned pin;
sprintf(cellname, "Sel%u", idx);
pin = edif_cell_port_byname(cell, cellname);
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, idx));
edif_add_to_joint(jnt, ref, pin);
}
for (idx = 0 ; idx < wid_z ; idx += 1) {
for (rdx = 0 ; rdx < wid_r ; rdx += 1) {
unsigned pin;
sprintf(cellname, "Data%ux%u", idx, rdx);
pin = edif_cell_port_byname(cell, cellname);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, idx, rdx));
edif_add_to_joint(jnt, ref, pin);
}
}
}
static void lpm_show_add(ivl_lpm_t net)
{
unsigned idx;
unsigned cell_width;
char cellname[32];
edif_cell_t cell;
edif_cellref_t ref;
edif_joint_t jnt;
const char*type = "ADD";
if (ivl_lpm_type(net) == IVL_LPM_SUB)
type = "SUB";
/* Figure out the width of the cell. Normally, it is the LPM
width known by IVL. But if the top data input bits are
unconnected, then we really have a width one less, and we
can use the cout to fill out the output width. */
cell_width = ivl_lpm_width(net);
if ( (ivl_lpm_data(net,cell_width-1) == 0)
&& (ivl_lpm_datab(net,cell_width-1) == 0) )
cell_width -= 1;
/* Find the correct ADD/SUB device in the library, search by
name. If the device is not there, then create it and put it
in the library. */
sprintf(cellname, "%s%u", type, cell_width);
cell = edif_xlibrary_findcell(xlib, cellname);
if (cell == 0) {
unsigned pins = cell_width * 3 + 1;
cell = edif_xcell_create(xlib, strdup(cellname), pins);
for (idx = 0 ; idx < cell_width ; idx += 1) {
sprintf(cellname, "Result%u", idx);
edif_cell_portconfig(cell, idx*3+0, strdup(cellname),
IVL_SIP_OUTPUT);
sprintf(cellname, "DataA%u", idx);
edif_cell_portconfig(cell, idx*3+1, strdup(cellname),
IVL_SIP_INPUT);
sprintf(cellname, "DataB%u", idx);
edif_cell_portconfig(cell, idx*3+2, strdup(cellname),
IVL_SIP_INPUT);
}
edif_cell_portconfig(cell, pins-1, "Cout", IVL_SIP_OUTPUT);
edif_cell_pstring(cell, "LPM_Type", "LPM_ADD_SUB");
edif_cell_pstring(cell, "LPM_Direction", type);
edif_cell_pinteger(cell, "LPM_Width", ivl_lpm_width(net));
}
ref = edif_cellref_create(edf, cell);
/* Connect the pins of the instance to the nexa. Access the
cell pins by name. */
for (idx = 0 ; idx < cell_width ; idx += 1) {
unsigned pin;
sprintf(cellname, "Result%u", idx);
pin = edif_cell_port_byname(cell, cellname);
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
edif_add_to_joint(jnt, ref, pin);
sprintf(cellname, "DataA%u", idx);
pin = edif_cell_port_byname(cell, cellname);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
edif_add_to_joint(jnt, ref, pin);
sprintf(cellname, "DataB%u", idx);
pin = edif_cell_port_byname(cell, cellname);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
edif_add_to_joint(jnt, ref, pin);
}
if (cell_width < ivl_lpm_width(net)) {
unsigned pin = edif_cell_port_byname(cell, "Cout");
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, cell_width));
edif_add_to_joint(jnt, ref, pin);
}
}
static void lpm_show_mult(ivl_lpm_t net)
{
char name[64];
unsigned idx;
edif_cell_t cell;
edif_cellref_t ref;
edif_joint_t jnt;
sprintf(name, "mult%u", ivl_lpm_width(net));
cell = edif_xlibrary_findcell(xlib, name);
if (cell == 0) {
cell = edif_xcell_create(xlib, strdup(name),
3 * ivl_lpm_width(net));
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
sprintf(name, "Result%u", idx);
edif_cell_portconfig(cell, idx*3+0,
strdup(name),
IVL_SIP_OUTPUT);
sprintf(name, "DataA%u", idx);
edif_cell_portconfig(cell, idx*3+1,
strdup(name),
IVL_SIP_INPUT);
sprintf(name, "DataB%u", idx);
edif_cell_portconfig(cell, idx*3+2,
strdup(name),
IVL_SIP_INPUT);
}
edif_cell_pstring(cell, "LPM_Type", "LPM_MULT");
edif_cell_pinteger(cell, "LPM_WidthP", ivl_lpm_width(net));
edif_cell_pinteger(cell, "LPM_WidthA", ivl_lpm_width(net));
edif_cell_pinteger(cell, "LPM_WidthB", ivl_lpm_width(net));
}
ref = edif_cellref_create(edf, cell);
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
unsigned pin;
ivl_nexus_t nex;
sprintf(name, "Result%u", idx);
pin = edif_cell_port_byname(cell, name);
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
edif_add_to_joint(jnt, ref, pin);
if ( (nex = ivl_lpm_data(net, idx)) ) {
sprintf(name, "DataA%u", idx);
pin = edif_cell_port_byname(cell, name);
jnt = edif_joint_of_nexus(edf, nex);
edif_add_to_joint(jnt, ref, pin);
}
if ( (nex = ivl_lpm_datab(net, idx)) ) {
sprintf(name, "DataB%u", idx);
pin = edif_cell_port_byname(cell, name);
jnt = edif_joint_of_nexus(edf, nex);
edif_add_to_joint(jnt, ref, pin);
}
}
}
static void lpm_show_constant(ivl_net_const_t net)
{
/* We only need one instance each of constant 0 and 1 bits. If
we need either of them, then create an instance reference and
save that reference here so that later needs for 0 or 1 can
find that the reference already lives and can be added to the
joint. */
static edif_cellref_t cell0_ref = 0;
static edif_cellref_t cell1_ref = 0;
static edif_joint_t cell0_jnt = 0;
static edif_joint_t cell1_jnt = 0;
edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0");
edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1");
const char*bits;
unsigned idx;
if (cell0 == 0) {
cell0 = edif_xcell_create(xlib, "cell0", 1);
edif_cell_portconfig(cell0, 0, "Result0", IVL_SIP_OUTPUT);
edif_cell_pstring(cell0, "LPM_Type", "LPM_CONSTANT");
edif_cell_pinteger(cell0, "LPM_Width", 1);
edif_cell_pinteger(cell0, "LPM_CValue", 0);
}
if (cell1 == 0) {
cell1 = edif_xcell_create(xlib, "cell1", 1);
edif_cell_portconfig(cell1, 0, "Result0", IVL_SIP_OUTPUT);
edif_cell_pstring(cell1, "LPM_Type", "LPM_CONSTANT");
edif_cell_pinteger(cell1, "LPM_Width", 1);
edif_cell_pinteger(cell1, "LPM_CValue", 1);
}
bits = ivl_const_bits(net);
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
if (bits[idx] == '1') {
if (cell1_ref == 0) {
cell1_ref = edif_cellref_create(edf, cell1);
cell1_jnt = edif_joint_create(edf);
edif_add_to_joint(cell1_jnt, cell1_ref, 0);
}
} else {
if (cell0_ref == 0) {
cell0_ref = edif_cellref_create(edf, cell0);
cell0_jnt = edif_joint_create(edf);
edif_add_to_joint(cell0_jnt, cell0_ref, 0);
}
}
}
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
if (bits[idx] == '1')
edif_nexus_to_joint(edf, cell1_jnt, ivl_const_pin(net,idx));
else
edif_nexus_to_joint(edf, cell0_jnt, ivl_const_pin(net,idx));
}
}
const struct device_s d_lpm_edif = {
lpm_show_header,
lpm_show_footer,
0,
0, /* show_pad */
lpm_logic, /* show_logic */
lpm_show_dff, /* show_dff */
lpm_show_cmp_eq, /* show_cmp_eq */
0, /* show_cmp_ne */
0, /* show_cmp_ge */
0, /* show_cmp_gt */
lpm_show_mux, /* show_mux */
lpm_show_add, /* show_add */
lpm_show_add, /* show_sub */
0, /* show_shiftl */
0, /* show_shiftr */
lpm_show_mult, /* show_mult */
lpm_show_constant /* show_constant */
};
/*
* $Log: d-lpm.c,v $
* Revision 1.1.2.2 2005/08/21 14:39:33 steve
* Generate LPM for the CMP_EQ device.
*
* Revision 1.1.2.1 2005/08/17 01:17:28 steve
* Add the tgt-edif target.
*
*/

872
tgt-edif/d-virtex.c Normal file
View File

@ -0,0 +1,872 @@
/*
* Copyright (c) 2005 Stephen Williams (steve@icarus.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: d-virtex.c,v 1.1.2.1 2005/09/25 16:35:36 steve Exp $"
#endif
/*
* This is the driver for Xilinx Virtex style FPGA devices. The device
* table structure at the bottom of this file lists all the various
* functions that are used to generate code for virtex devices. In
* some cases this table uses entries that are common to all Xilinx
* devices, and in some cases Virtex specific entries are used. The
* Virtex specific functions are given here, the xilinx_* common
* functions are in the xilinx.{hc} source files.
*/
# include "device.h"
# include "edif.h"
# include "generic.h"
# include "xilinx.h"
# include <stdlib.h>
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <assert.h>
/*
* This is a table of cell types that are accessible via the cellref
* attribute to a gate.
*/
const static struct edif_xlib_celltable virtex_celltable[] = {
{ "BUFG", xilinx_cell_bufg },
{ "MULT_AND", xilinx_cell_mult_and },
{ 0, 0}
};
/*
* The show_header function is called before any of the devices of the
* netlist are scanned.
*
* In this function, we look at the ports of the root module to decide
* if they are to be made into ports. Modules that have PAD attributes
* are *not* to be used as ports, they will be connected to special
* PAD devices instead.
*/
static void virtex_show_header(ivl_design_t des)
{
const char*part_str = 0;
xilinx_common_header(des);
xlib = edif_xlibrary_create(edf, "VIRTEX");
edif_xlibrary_set_celltable(xlib, virtex_celltable);
if ( (part_str = ivl_design_flag(des, "part")) && (part_str[0] != 0) ) {
edif_pstring(edf, "PART", part_str);
}
cell_0 = edif_xcell_create(xlib, "GND", 1);
edif_cell_portconfig(cell_0, 0, "GROUND", IVL_SIP_OUTPUT);
cell_1 = edif_xcell_create(xlib, "VCC", 1);
edif_cell_portconfig(cell_1, 0, "VCC", IVL_SIP_OUTPUT);
}
static void virtex_or_wide(ivl_net_logic_t net)
{
edif_cell_t cell_muxcy_l = xilinx_cell_muxcy_l(xlib);
edif_cell_t cell_muxcy = xilinx_cell_muxcy(xlib);
edif_cell_t cell_lut4 = xilinx_cell_lut4(xlib);
edif_cellref_t true_out, false_out;
edif_cellref_t lut, muxcy, muxcy_down=NULL;
edif_joint_t jnt;
unsigned idx, inputs, lut4_cnt;
if (ivl_logic_type(net) == IVL_LO_OR) {
true_out = edif_cellref_create(edf, cell_1);
false_out = edif_cellref_create(edf, cell_0);
} else {
true_out = edif_cellref_create(edf, cell_0);
false_out = edif_cellref_create(edf, cell_1);
}
inputs = ivl_logic_pins(net) - 1;
lut4_cnt = (inputs-1)/4;
for (idx = 0 ; idx < lut4_cnt ; idx += 1) {
muxcy = edif_cellref_create(edf, cell_muxcy_l);
lut = edif_cellref_create(edf, cell_lut4);
edif_cellref_pstring(lut, "INIT", "0001");
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, lut, LUT_O);
edif_add_to_joint(jnt, muxcy, MUXCY_S);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, true_out, 0);
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+1));
edif_add_to_joint(jnt, lut, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+2));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+3));
edif_add_to_joint(jnt, lut, LUT_I3);
if (idx > 0) {
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
edif_add_to_joint(jnt, muxcy_down, MUXCY_O);
} else {
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
edif_add_to_joint(jnt, false_out, 0);
}
muxcy_down = muxcy;
}
muxcy = edif_cellref_create(edf, cell_muxcy);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, true_out, 0);
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
edif_add_to_joint(jnt, muxcy_down, MUXCY_O);
switch (ivl_logic_pins(net) - 1 - lut4_cnt*4) {
case 1:
lut = edif_cellref_create(edf, xilinx_cell_inv(xlib));
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
edif_add_to_joint(jnt, lut, BUF_I);
break;
case 2:
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
edif_cellref_pstring(lut, "INIT", "1");
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
edif_add_to_joint(jnt, lut, LUT_I1);
break;
case 3:
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
edif_cellref_pstring(lut, "INIT", "01");
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
edif_add_to_joint(jnt, lut, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2));
edif_add_to_joint(jnt, lut, LUT_I2);
break;
case 4:
lut = edif_cellref_create(edf, cell_lut4);
edif_cellref_pstring(lut, "INIT", "0001");
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1));
edif_add_to_joint(jnt, lut, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+3));
edif_add_to_joint(jnt, lut, LUT_I3);
break;
default:
assert(0);
}
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, lut, LUT_O);
edif_add_to_joint(jnt, muxcy, MUXCY_S);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, muxcy, MUXCY_O);
}
/*
* Pick off the cases where there is a Virtex specific implementation
* that is better then the generic Xilinx implementation. Route the
* remaining to the base xilinx_logic implementation.
*/
void virtex_logic(ivl_net_logic_t net)
{
/* Nothing I can do if the user expresses a specific
opinion. The cellref attribute forces me to let the base
xilinx_logic take care of it. */
if (ivl_logic_attr(net, "cellref")) {
xilinx_logic(net);
return;
}
switch (ivl_logic_type(net)) {
case IVL_LO_OR:
case IVL_LO_NOR:
if (ivl_logic_pins(net) <= 5) {
xilinx_logic(net);
} else {
virtex_or_wide(net);
}
break;
default:
xilinx_logic(net);
break;
}
}
void virtex_generic_dff(ivl_lpm_t net)
{
unsigned idx;
ivl_nexus_t aclr = ivl_lpm_async_clr(net);
ivl_nexus_t aset = ivl_lpm_async_set(net);
ivl_nexus_t sclr = ivl_lpm_sync_clr(net);
ivl_nexus_t sset = ivl_lpm_sync_set(net);
const char*abits = 0;
if (aset) {
ivl_expr_t avalue = ivl_lpm_aset_value(net);
assert(avalue);
abits = ivl_expr_bits(avalue);
assert(abits);
}
/* XXXX Can't handle both synchronous and asynchronous clear. */
assert( ! (aclr && sclr) );
/* XXXX Can't handle synchronous set at all. */
assert( ! sset );
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
edif_cellref_t obj;
ivl_nexus_t nex;
edif_joint_t jnt;
/* If there is a preset, then select an FDCPE instead of
an FDCE device. */
if (aset && (abits[idx] == '1')) {
obj = edif_cellref_create(edf, xilinx_cell_fdcpe(xlib));
} else if (aclr) {
obj = edif_cellref_create(edf, xilinx_cell_fdce(xlib));
} else if (sclr) {
obj = edif_cellref_create(edf, xilinx_cell_fdre(xlib));
} else {
obj = edif_cellref_create(edf, xilinx_cell_fdce(xlib));
}
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
edif_add_to_joint(jnt, obj, FDCE_Q);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
edif_add_to_joint(jnt, obj, FDCE_D);
jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net));
edif_add_to_joint(jnt, obj, FDCE_C);
if ( (nex = ivl_lpm_enable(net)) ) {
jnt = edif_joint_of_nexus(edf, nex);
edif_add_to_joint(jnt, obj, FDCE_CE);
}
if (aclr) {
jnt = edif_joint_of_nexus(edf, aclr);
edif_add_to_joint(jnt, obj, FDCE_CLR);
} else if (sclr) {
jnt = edif_joint_of_nexus(edf, sclr);
edif_add_to_joint(jnt, obj, FDCE_CLR);
}
if (aset) {
if (abits[idx] == '1') {
jnt = edif_joint_of_nexus(edf, aset);
edif_add_to_joint(jnt, obj, FDCE_PRE);
} else {
assert(aclr == 0);
jnt = edif_joint_of_nexus(edf, aset);
edif_add_to_joint(jnt, obj, FDCE_CLR);
}
}
}
}
/*
* This method handles both == and != operators, the identity
* comparison operators.
*
* If the identity compare is applied to small enough input vectors,
* it is shoved into a single LUT. Otherwise, it is strung out into a
* row of LUT devices chained together by carry muxes. The output of
* the comparison is the output of the last mux.
*
* When the compare is small, a LUT is generated with the appropriate
* truth table to cause an == or != result.
*
* When the compare is too wide for a single LUT, then it is made into
* a chain connected by a string of carry mux devices. Each LUT
* implements == for up to two pairs of bits, even if the final output
* is supposed to be !=. The LUT output is connected to an associated
* MUX select input. The CO output of each muxcy is passed up to the
* next higher order bits of the compare.
*
* For identity == compare, a != output from the LUT selects the DI
* input of the muxcy, generating a 0 output that is passed up. Since
* the next higher muxcy now gets a 0 input to both DI and CI, the
* output of the next higher muxcy is guaranteed to be 0, and so on to
* the final output of the carry chain. If the output from a LUT is ==,
* then the CI input of the muxcy is selected and the truth of this
* level depends on lower order bits. The least significant muxcy is
* connected to GND and VCC so that its CO follows the least
* significant LUT.
*
* Identity != is the same as == except that the output is
* inverted. To get that effect without putting an inverter on the
* output of the top muxcy pin CO (which would cost a LUT) the DI
* inputs are all connected to VCC instead of GND, and the CI of the
* least significant muxcy is connected to GND instead of VCC. The LUT
* expressions for the chained compare are configured for ==, with the
* changed CI/DI inputs performing the inversion.
*/
void virtex_eq(ivl_lpm_t net)
{
edif_cellref_t lut, mux, mux_prev;
edif_joint_t jnt, jnt_di;
unsigned idx;
/* True if I'm implementing CMP_EQ instead of CMP_NE */
int eq = 1;
assert(ivl_lpm_width(net) >= 1);
if (ivl_lpm_type(net) == IVL_LPM_CMP_NE)
eq = 0;
switch (ivl_lpm_width(net)) {
case 1:
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
edif_cellref_pstring(lut, "INIT", eq? "9" : "6");
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I1);
return;
case 2:
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
edif_cellref_pstring(lut, "INIT", eq? "9009" : "6FF6");
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 1));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 1));
edif_add_to_joint(jnt, lut, LUT_I3);
return;
default:
{ edif_cellref_t di;
di = edif_cellref_create(edf, eq? cell_0 : cell_1);
jnt_di = edif_joint_create(edf);
edif_add_to_joint(jnt_di, di, 0);
}
mux_prev = 0;
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 2) {
int subwid = 2;
if ((idx + 1) == ivl_lpm_width(net))
subwid = 1;
mux = edif_cellref_create(edf, xilinx_cell_muxcy(xlib));
if (subwid == 2) {
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
edif_cellref_pstring(lut, "INIT", "9009");
} else {
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
edif_cellref_pstring(lut, "INIT", "9");
}
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, lut, LUT_O);
edif_add_to_joint(jnt, mux, MUXCY_S);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
edif_add_to_joint(jnt, lut, LUT_I1);
if (subwid > 1) {
jnt = edif_joint_of_nexus(edf,
ivl_lpm_data(net, idx+1));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf,
ivl_lpm_datab(net, idx+1));
edif_add_to_joint(jnt, lut, LUT_I3);
}
edif_add_to_joint(jnt_di, mux, MUXCY_DI);
if (mux_prev) {
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, mux, MUXCY_CI);
edif_add_to_joint(jnt, mux_prev, MUXCY_O);
} else {
edif_cellref_t ci;
ci = edif_cellref_create(edf, eq? cell_1 : cell_0);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, ci, 0);
edif_add_to_joint(jnt, mux, MUXCY_CI);
}
mux_prev = mux;
}
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, mux_prev, MUXCY_O);
return;
}
}
/*
* Implement hardware for the device (A >= B). We use LUT devices if
* it can handle the slices, or carry chain logic if the slices must
* span LUT devices.
*/
void virtex_ge(ivl_lpm_t net)
{
edif_cellref_t muxcy_prev;
edif_cellref_t lut;
edif_joint_t jnt;
unsigned idx;
if (ivl_lpm_width(net) == 1) {
/* If the comparator is a single bit, then use a LUT2
with this truth table:
Q A B
--+----
1 | 0 0
0 | 0 1
1 | 1 0
1 | 1 1
Connect the A value to I1 and the B value to I0. */
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
edif_cellref_pstring(lut, "INIT", "D");
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I2);
return;
}
/* Handle the case where the device is two slices
wide. In this case, we can use a LUT4 to do all
the calculation. Use this truth table:
Q AA BB
--+------
1 | 00 00
0 | 00 01
0 | 00 10
0 | 00 11
1 | 01 00
1 | 01 01
0 | 01 10
0 | 01 11
1 | 10 00
1 | 10 01
1 | 10 10
0 | 10 11
1 | 11 xx
The I3-I0 inputs are A1 A0 B1 B0 in that order. */
assert(ivl_lpm_width(net) >= 2);
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
edif_cellref_pstring(lut, "INIT", "F731");
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I2);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 1));
edif_add_to_joint(jnt, lut, LUT_I3);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 1));
edif_add_to_joint(jnt, lut, LUT_I1);
/* There are only two slices, so this is all we need. */
if (ivl_lpm_width(net) == 2) {
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
return;
}
/* The general case requires that we make the >= comparator
from slices. This is an iterative design. Each slice has
the truth table:
An Bn | A >= B
------+-------
0 0 | CI
0 1 | 0
1 0 | 1
1 1 | CI
The CI for each slice is the output of the compare of the
next less significant bits. We get this truth table by
connecting a LUT2 to the S input of a MUXCY. When the S
input is (1), it propagates its CI. This suggests that the
init value for the LUT be "9" (XNOR).
When the MUXCY S input is 0, it propagates a local
input. We connect to that input An, and we get the desired
and complete truth table for a slice.
This iterative definition needs to terminate at the least
significant bits. In fact, we have a non-iterative was to
deal with the two least significant slices. We take the
output of the LUT4 device for the least significant bits,
and use that to generate the initial CI for the chain. */
muxcy_prev = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, lut, LUT_O);
edif_add_to_joint(jnt, muxcy_prev, MUXCY_S);
{ edif_cellref_t p0 = edif_cellref_create(edf, cell_0);
edif_cellref_t p1 = edif_cellref_create(edf, cell_1);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, p0, 0);
edif_add_to_joint(jnt, muxcy_prev, MUXCY_DI);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, p1, 0);
edif_add_to_joint(jnt, muxcy_prev, MUXCY_CI);
}
for (idx = 2 ; idx < ivl_lpm_width(net) ; idx += 1) {
edif_cellref_t muxcy;
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy(xlib));
edif_cellref_pstring(lut, "INIT", "9");
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, lut, LUT_O);
edif_add_to_joint(jnt, muxcy, MUXCY_S);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
edif_add_to_joint(jnt, lut, LUT_I0);
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
edif_add_to_joint(jnt, lut, LUT_I1);
muxcy_prev = muxcy;
}
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, muxcy_prev, MUXCY_O);
}
/*
* A 4-input N-wide mux can be made on Virtex devices using MUXF5 and
* LUT devices. The MUXF5 selects a LUT device (and is connected to
* S[1]) and the LUT devices, connected to S[0], select the input.
*/
static void virtex_mux4(ivl_lpm_t net)
{
unsigned idx;
assert(ivl_lpm_selects(net) == 2);
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
edif_joint_t jnt;
edif_cellref_t lut01;
edif_cellref_t lut23;
edif_cellref_t muxf5;
lut01 = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
edif_cellref_pstring(lut01, "INIT", "CA");
lut23 = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
edif_cellref_pstring(lut23, "INIT", "CA");
muxf5 = edif_cellref_create(edf, xilinx_cell_muxf5(xlib));
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 0, idx));
edif_add_to_joint(jnt, lut01, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 1, idx));
edif_add_to_joint(jnt, lut01, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 2, idx));
edif_add_to_joint(jnt, lut23, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 3, idx));
edif_add_to_joint(jnt, lut23, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 0));
edif_add_to_joint(jnt, lut01, LUT_I2);
edif_add_to_joint(jnt, lut23, LUT_I2);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxf5, MUXF_I0);
edif_add_to_joint(jnt, lut01, LUT_O);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxf5, MUXF_I1);
edif_add_to_joint(jnt, lut23, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
edif_add_to_joint(jnt, muxf5, MUXF_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 1));
edif_add_to_joint(jnt, muxf5, MUXF_S);
}
}
void virtex_mux(ivl_lpm_t net)
{
switch (ivl_lpm_selects(net)) {
case 2:
virtex_mux4(net);
break;
default:
xilinx_mux(net);
break;
}
}
/*
* This function generates ADD/SUB devices for Virtex devices,
* based on the documented implementations of ADD8/ADD16, etc., from
* the Libraries Guide.
*
* Each slice of the ADD/SUB device is made from a LUT2 device, an
* XORCY device that mixes with the LUT2 to make a full adder, and a
* MUXCY_L to propagate the carry. The most significant slice does not
* have a carry to propagate, so has no MUXCY_L.
*
* If the device is a wide adder, then the LUT2 devices are configured
* to implement an XOR function and a zero is pumped into the least
* significant carry input.
*
* If the device is really an adder, then the input is turned into an
* XNOR, which takes a 1-s complement of the B input. Pump a 1 into
* the LSB carry input to finish converting the B input into the 2s
* complement.
*/
void virtex_add(ivl_lpm_t net)
{
const char*ha_init = 0;
edif_cellref_t lut, xorcy, muxcy, pad;
edif_joint_t jnt;
unsigned idx;
if (ivl_lpm_width(net) < 2) {
xilinx_add(net);
return;
}
switch (ivl_lpm_type(net)) {
case IVL_LPM_ADD:
ha_init = "6";
break;
case IVL_LPM_SUB:
ha_init = "9";
break;
default:
assert(0);
}
assert(ivl_lpm_width(net) > 1);
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
xorcy = edif_cellref_create(edf, xilinx_cell_xorcy(xlib));
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
edif_cellref_pstring(lut, "INIT", ha_init);
/* The bottom carry-in takes a constant that primes the add or
subtract. */
switch (ivl_lpm_type(net)) {
case IVL_LPM_ADD:
pad = edif_cellref_create(edf, cell_0);
break;
case IVL_LPM_SUB:
pad = edif_cellref_create(edf, cell_1);
break;
default:
assert(0);
}
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, pad, 0);
edif_add_to_joint(jnt, muxcy, MUXCY_CI);
edif_add_to_joint(jnt, xorcy, XORCY_CI);
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, xorcy, XORCY_O);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, xorcy, XORCY_LI);
edif_add_to_joint(jnt, muxcy, MUXCY_S);
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
edif_add_to_joint(jnt, muxcy, MUXCY_DI);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I1);
for (idx = 1 ; idx < ivl_lpm_width(net) ; idx += 1) {
edif_cellref_t muxcy0 = muxcy;
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
xorcy = edif_cellref_create(edf, xilinx_cell_xorcy(xlib));
edif_cellref_pstring(lut, "INIT", ha_init);
/* If this is the last bit, then there is no further
propagation in the carry chain, and I can skip the
carry mux MUXCY. */
if ((idx+1) < ivl_lpm_width(net))
muxcy = edif_cellref_create(edf, xilinx_cell_muxcy_l(xlib));
else
muxcy = 0;
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, muxcy0, MUXCY_O);
edif_add_to_joint(jnt, xorcy, XORCY_CI);
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_CI);
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
edif_add_to_joint(jnt, xorcy, XORCY_O);
jnt = edif_joint_create(edf);
edif_add_to_joint(jnt, xorcy, XORCY_LI);
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_S);
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
edif_add_to_joint(jnt, lut, LUT_I0);
if (muxcy) edif_add_to_joint(jnt, muxcy, MUXCY_DI);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
edif_add_to_joint(jnt, lut, LUT_I1);
}
}
const struct device_s d_virtex_edif = {
virtex_show_header,
xilinx_show_footer,
xilinx_show_scope,
xilinx_pad,
virtex_logic,
virtex_generic_dff,
virtex_eq,
virtex_eq,
virtex_ge,
0, /* show_cmp_gt */
virtex_mux,
virtex_add,
virtex_add,
xilinx_shiftl,
0, /* show_shiftr */
0, /* show_mult */
0 /* show_constant */
};
/*
* $Log: d-virtex.c,v $
* Revision 1.1.2.1 2005/09/25 16:35:36 steve
* Add Xilinx virtex as a reference EDIF device.
*
*/

55
tgt-edif/device.c Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ident "$Id: device.c,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $"
# include "device.h"
# include <string.h>
# include <assert.h>
device_t device_from_arch(const char*arch)
{
unsigned idx;
assert(arch);
for (idx = 0 ; edif_device_table[idx].name ; idx += 1) {
if (strcmp(arch, edif_device_table[idx].name) == 0)
return edif_device_table[idx].driver;
}
return 0;
}
/*
* $Log: device.c,v $
* Revision 1.1.2.1 2005/08/17 01:17:28 steve
* Add the tgt-edif target.
*
*/

101
tgt-edif/device.h Normal file
View File

@ -0,0 +1,101 @@
#ifndef __device_H
#define __device_H
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: device.h,v 1.1.2.1 2005/08/17 01:17:28 steve Exp $"
#endif
# include <ivl_target.h>
/*
* This code generator supports a variety of device types. It does
* this by keeping a device "driver" structure for each device
* type. The device structure contains pointers to functions that emit
* the proper XNF for a given type of device.
*
* If a device supports a method, the function pointer is filled in
* with a pointer to the proper function.
*
* If a device does not support the method, then the pointer is null.
*/
typedef const struct device_s* device_t;
struct device_s {
/* These methods draw leading and trailing format text. */
void (*show_header)(ivl_design_t des);
void (*show_footer)(ivl_design_t des);
/* Draw scopes marked by ivl_synthesis_cell */
void (*show_cell_scope)(ivl_scope_t net);
/* Draw pads connected to the specified signal. */
void (*show_pad)(ivl_signal_t sig, const char*str);
/* Draw basic logic devices. */
void (*show_logic)(ivl_net_logic_t net);
/* This method emits a D type Flip-Flop */
void (*show_dff)(ivl_lpm_t net);
/* These methods show various comparators */
void (*show_cmp_eq)(ivl_lpm_t net);
void (*show_cmp_ne)(ivl_lpm_t net);
void (*show_cmp_ge)(ivl_lpm_t net);
void (*show_cmp_gt)(ivl_lpm_t net);
/* This method draws MUX devices */
void (*show_mux)(ivl_lpm_t net);
/* This method draws ADD devices */
void (*show_add)(ivl_lpm_t net);
void (*show_sub)(ivl_lpm_t net);
/* These methods draw SHIFT devices */
void (*show_shiftl)(ivl_lpm_t net);
void (*show_shiftr)(ivl_lpm_t net);
/* Multipliers */
void (*show_mult)(ivl_lpm_t net);
/* Constants */
void (*show_constant)(ivl_net_const_t net);
};
/*
* Return the device_t cookie given the name of the architecture. If
* the device is not found, return 0.
*
* This function is used if the user specifies the archetecture
* explicitly, with the -parch=name flag.
*/
extern device_t device_from_arch(const char*arch);
/*
*/
extern const struct device_table_s {
const char*name;
device_t driver;
} edif_device_table[];
/*
* $Log: device.h,v $
* Revision 1.1.2.1 2005/08/17 01:17:28 steve
* Add the tgt-edif target.
*
*/
#endif

7
tgt-edif/edif-s.conf Normal file
View File

@ -0,0 +1,7 @@
functor:synth2
functor:synth
functor:syn-rules
#functor:cprop
functor:nodangle
-t:dll
flag:DLL=edif.tgt

681
tgt-edif/edif.c Normal file
View File

@ -0,0 +1,681 @@
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: edif.c,v 1.1.2.2 2005/08/21 22:25:51 steve Exp $"
#endif
# include "edif.h"
# include <stdlib.h>
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <assert.h>
typedef enum property_e {
PRP_NONE = 0,
PRP_STRING,
PRP_INTEGER
} property_t;
struct cellref_property_ {
const char*name;
property_t ptype;
union {
const char*str;
long num;
} value_;
struct cellref_property_*next;
};
/*
* This is the root of an EDIF design. From here we can get at the
* root ports of the design (which are typically the pins of a chip or
* FPGA design) a list of external cell libraries, cells properties
* and nexa (joints).
*/
struct edif_s {
const char*name;
/* List the ports of the design. */
unsigned nports;
struct __cell_port*ports;
/* All the external libraries attached to me. */
edif_xlibrary_t xlibs;
/* list the cellref instances. */
edif_cellref_t celref;
/* The root instance has cellref properties as well. */
struct cellref_property_*property;
/* Keep a list of all the nexa */
struct edif_joint_s*nexa;
};
struct edif_xlibrary_s {
/* Name of this library. */
const char*name;
/* The cells that are contained in this library. */
struct edif_cell_s*cells;
/* point to the optional celltable. */
const struct edif_xlib_celltable*celltable;
/* used to list libraries in an edif_t. */
struct edif_xlibrary_s*next;
};
struct __cell_port {
const char*name;
const char*ename;
struct cellref_property_*property;
ivl_signal_port_t dir;
};
struct edif_cell_s {
const char*name;
edif_xlibrary_t xlib;
unsigned nports;
struct __cell_port*ports;
struct cellref_property_*property;
struct edif_cell_s*next;
};
struct edif_cellref_s {
struct edif_cell_s* cell;
unsigned u;
struct cellref_property_*property;
struct edif_cellref_s* next;
};
struct joint_cell_ {
struct edif_cellref_s*cell;
unsigned port;
struct joint_cell_*next;
};
/*
* Joints link cell ports together. The edif_t object contains a list
* of these joints, and each joint lists the ports that are connected
* together. The port is represented by a joint_cell_.
*
* The links list a singly linked list of joint_cell_ objects. To add
* a new link, simply push a new joint_cell_ into the links list. See
* the edif_add_to_joint and edif_port_to_joint functions.
*
* The joints themselves are kept in a singly linked list in the
* edif_t object. To create a new joint, simply push an initialized
* edif_joint_s onto the nexa member of the edif_t object. See the
* edif_joint_create function.
*/
struct edif_joint_s {
const char*name;
struct joint_cell_*links;
struct edif_joint_s*next;
};
static int is_edif_name(const char*text)
{
static const char*edif_name_chars = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
return (strspn(text, edif_name_chars) == strlen(text));
}
edif_t edif_create(const char*design_name, unsigned nports)
{
edif_t edf = malloc(sizeof(struct edif_s));
edf->name = design_name;
edf->nports= nports;
edf->ports = nports? calloc(nports, sizeof(struct __cell_port)) : 0;
edf->celref= 0;
edf->xlibs = 0;
edf->property = 0;
edf->nexa = 0;
return edf;
}
void edif_portconfig(edif_t edf, unsigned idx,
const char*name, ivl_signal_port_t dir)
{
assert(idx < edf->nports);
edf->ports[idx].name = name;
if (is_edif_name(name)) {
edf->ports[idx].ename = 0;
} else {
char buf[16];
sprintf(buf, "PORT%u", idx);
edf->ports[idx].ename = strdup(buf);
}
edf->ports[idx].dir = dir;
}
void edif_port_to_joint(edif_joint_t jnt, edif_t edf, unsigned port)
{
struct joint_cell_* jc = malloc(sizeof(struct joint_cell_));
jc->cell = 0;
jc->port = port;
jc->next = jnt->links;
jnt->links = jc;
}
void edif_pstring(edif_t edf, const char*name, const char*value)
{
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
prp->name = name;
prp->ptype = PRP_STRING;
prp->value_.str = value;
prp->next = edf->property;
edf->property = prp;
}
edif_xlibrary_t edif_xlibrary_create(edif_t edf, const char*name)
{
edif_xlibrary_t xlib = malloc(sizeof(struct edif_xlibrary_s));
xlib->name = name;
xlib->cells = 0;
xlib->celltable = 0;
xlib->next = edf->xlibs;
edf->xlibs = xlib;
return xlib;
}
void edif_xlibrary_set_celltable(edif_xlibrary_t xlib,
const struct edif_xlib_celltable*tab)
{
assert(xlib->celltable == 0);
xlib->celltable = tab;
}
edif_cell_t edif_xlibrary_findcell(edif_xlibrary_t xlib,
const char*cell_name)
{
const struct edif_xlib_celltable*tcur;
edif_cell_t cur;
for (cur = xlib->cells ; cur ; cur = cur->next) {
if (strcmp(cell_name, cur->name) == 0)
return cur;
}
if (xlib->celltable == 0)
return 0;
for (tcur = xlib->celltable ; tcur->cell_name ; tcur += 1)
if (strcmp(cell_name, tcur->cell_name) == 0) {
return (tcur->cell_func)(xlib);
}
return 0;
}
edif_cell_t edif_xlibrary_scope_cell(edif_xlibrary_t xlib,
ivl_scope_t scope)
{
unsigned port_count, idx;
edif_cell_t cur;
/* Check to see if the cell is already somehow defined. */
cur = edif_xlibrary_findcell(xlib, ivl_scope_tname(scope));
if (cur) return cur;
/* Count the ports of the scope. */
port_count = 0;
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
ivl_signal_t sig = ivl_scope_sig(scope, idx);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
continue;
port_count += 1;
}
cur = edif_xcell_create(xlib, ivl_scope_tname(scope), port_count);
port_count = 0;
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
ivl_signal_t sig = ivl_scope_sig(scope, idx);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
continue;
edif_cell_portconfig(cur, port_count,
ivl_signal_basename(sig),
ivl_signal_port(sig));
port_count += 1;
}
return cur;
}
edif_cell_t edif_xcell_create(edif_xlibrary_t xlib, const char*name,
unsigned nports)
{
unsigned idx;
edif_cell_t cell = malloc(sizeof(struct edif_cell_s));
cell->name = name;
cell->xlib = xlib;
cell->nports = nports;
cell->ports = calloc(nports, sizeof(struct __cell_port));
cell->property = 0;
for (idx = 0 ; idx < nports ; idx += 1) {
cell->ports[idx].name = "?";
cell->ports[idx].dir = IVL_SIP_NONE;
cell->ports[idx].property = 0;
}
cell->next = xlib->cells;
xlib->cells = cell;
return cell;
}
void edif_cell_portconfig(edif_cell_t cell, unsigned idx,
const char*name, ivl_signal_port_t dir)
{
assert(idx < cell->nports);
cell->ports[idx].name = name;
cell->ports[idx].dir = dir;
}
void edif_cell_port_pstring(edif_cell_t cell, unsigned idx,
const char*name, const char*value)
{
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
prp->name = name;
prp->ptype = PRP_STRING;
prp->value_.str = value;
prp->next = cell->ports[idx].property;
cell->ports[idx].property = prp;
}
unsigned edif_cell_port_byname(edif_cell_t cell, const char*name)
{
unsigned idx = 0;
for (idx = 0 ; idx < cell->nports ; idx += 1)
if (strcmp(name, cell->ports[idx].name) == 0)
break;
return idx;
}
void edif_cell_pstring(edif_cell_t cell, const char*name,
const char*value)
{
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
prp->name = name;
prp->ptype = PRP_STRING;
prp->value_.str = value;
prp->next = cell->property;
cell->property = prp;
}
void edif_cell_pinteger(edif_cell_t cell, const char*name,
int value)
{
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
prp->name = name;
prp->ptype = PRP_INTEGER;
prp->value_.num = value;
prp->next = cell->property;
cell->property = prp;
}
edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell)
{
static unsigned u_number = 0;
edif_cellref_t ref = malloc(sizeof(struct edif_cellref_s));
u_number += 1;
assert(cell);
assert(edf);
ref->u = u_number;
ref->cell = cell;
ref->property = 0;
ref->next = edf->celref;
edf->celref = ref;
return ref;
}
void edif_cellref_pstring(edif_cellref_t ref, const char*name,
const char*value)
{
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
prp->name = name;
prp->ptype = PRP_STRING;
prp->value_.str = value;
prp->next = ref->property;
ref->property = prp;
}
void edif_cellref_pinteger(edif_cellref_t ref, const char*name, int value)
{
struct cellref_property_*prp = malloc(sizeof(struct cellref_property_));
prp->name = name;
prp->ptype = PRP_INTEGER;
prp->value_.num = value;
prp->next = ref->property;
ref->property = prp;
}
edif_joint_t edif_joint_create(edif_t edf)
{
edif_joint_t jnt = malloc(sizeof(struct edif_joint_s));
jnt->name = 0;
jnt->links = 0;
jnt->next = edf->nexa;
edf->nexa = jnt;
return jnt;
}
edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex)
{
void*tmp = ivl_nexus_get_private(nex);
edif_joint_t jnt;
if (tmp == 0) {
jnt = edif_joint_create(edf);
ivl_nexus_set_private(nex, jnt);
return jnt;
}
jnt = (edif_joint_t) tmp;
return jnt;
}
void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex)
{
void*tmp = ivl_nexus_get_private(nex);
if (tmp != 0) {
/* There is a joint already on the nexus. Move all the
joint cells to the joint I'm joining to. */
edif_joint_t njnt = (edif_joint_t)tmp;
while (njnt->links) {
struct joint_cell_*cell = njnt->links;
njnt->links = cell->next;
cell->next = jnt->links;
jnt->links = cell;
}
/* Now njnt is dead, and should be removed from edif. */
/* Or we can ignore it as harmless. */
}
ivl_nexus_set_private(nex, jnt);
}
void edif_joint_rename(edif_joint_t jnt, const char*name)
{
assert(jnt->name == 0);
jnt->name = name;
}
void edif_add_to_joint(edif_joint_t jnt, edif_cellref_t cell, unsigned port)
{
struct joint_cell_* jc = malloc(sizeof(struct joint_cell_));
jc->cell = cell;
jc->port = port;
jc->next = jnt->links;
jnt->links = jc;
}
static void fprint_property(FILE*fd, const struct cellref_property_*prp)
{
fprintf(fd, "(property %s ", prp->name);
switch (prp->ptype) {
case PRP_NONE:
break;
case PRP_STRING:
fprintf(fd, "(string \"%s\")", prp->value_.str);
break;
case PRP_INTEGER:
fprintf(fd, "(integer %ld)", prp->value_.num);
break;
}
fprintf(fd, ")");
}
/*
* This function takes all the data structures that have been
* assembled by the code generator, and writes them into an EDIF
* formatted file.
*/
void edif_print(FILE*fd, edif_t edf)
{
edif_xlibrary_t xlib;
edif_cell_t cell;
edif_cellref_t ref;
edif_joint_t jnt;
struct cellref_property_*prp;
unsigned idx;
fprintf(fd, "(edif %s\n", edf->name);
fprintf(fd, " (edifVersion 2 0 0)\n");
fprintf(fd, " (edifLevel 0)\n");
fprintf(fd, " (keywordMap (keywordLevel 0))\n");
fprintf(fd, " (status\n");
fprintf(fd, " (written\n");
fprintf(fd, " (timeStamp 0 0 0 0 0 0)\n");
fprintf(fd, " (author \"unknown\")\n");
fprintf(fd, " (program \"Icarus Verilog/edif.tgt\")))\n");
fflush(fd);
for (xlib = edf->xlibs ; xlib ; xlib = xlib->next) {
fprintf(fd, " (external %s "
"(edifLevel 0) "
"(technology (numberDefinition))\n",
xlib->name);
for (cell = xlib->cells ; cell ; cell = cell->next) {
fprintf(fd, " (cell %s (cellType GENERIC)\n",
cell->name);
fprintf(fd, " (view net\n"
" (viewType NETLIST)\n"
" (interface");
for (idx = 0 ; idx < cell->nports ; idx += 1) {
struct __cell_port*pp = cell->ports + idx;
fprintf(fd, "\n (port %s", pp->name);
switch (pp->dir) {
case IVL_SIP_INPUT:
fprintf(fd, " (direction INPUT)");
break;
case IVL_SIP_OUTPUT:
fprintf(fd, " (direction OUTPUT)");
break;
case IVL_SIP_INOUT:
fprintf(fd, " (direction INOUT)");
break;
default:
break;
}
for (prp = pp->property ; prp ; prp=prp->next) {
fprintf(fd, " ");
fprint_property(fd, prp);
}
fprintf(fd, ")");
}
for (prp = cell->property ; prp ; prp = prp->next) {
fprintf(fd, "\n ");
fprint_property(fd, prp);
}
fprintf(fd, ")))\n");
}
fprintf(fd, " )\n"); /* terminate (external ...) sexp */
}
fflush(fd);
/* Write out the library header */
fprintf(fd, " (library DESIGN\n");
fprintf(fd, " (edifLevel 0)\n");
fprintf(fd, " (technology (numberDefinition))\n");
/* The root module is a cell in the library. */
fprintf(fd, " (cell %s\n", edf->name);
fprintf(fd, " (cellType GENERIC)\n");
fprintf(fd, " (view net\n");
fprintf(fd, " (viewType NETLIST)\n");
fprintf(fd, " (interface\n");
for (idx = 0 ; idx < edf->nports ; idx += 1) {
fprintf(fd, " (port ");
if (edf->ports[idx].ename == 0)
fprintf(fd, "%s ", edf->ports[idx].name);
else
fprintf(fd, "(rename %s \"%s\") ",
edf->ports[idx].ename,
edf->ports[idx].name);
switch (edf->ports[idx].dir) {
case IVL_SIP_INPUT:
fprintf(fd, "(direction INPUT)");
break;
case IVL_SIP_OUTPUT:
fprintf(fd, "(direction OUTPUT)");
break;
case IVL_SIP_INOUT:
fprintf(fd, "(direction INOUT)");
break;
default:
break;
}
fprintf(fd, ")\n");
}
fprintf(fd, " )\n"); /* end the (interface ) sexp */
fflush(fd);
fprintf(fd, " (contents\n");
/* Display all the instances. */
for (ref = edf->celref ; ref ; ref = ref->next) {
assert(ref->cell);
fprintf(fd, "(instance U%u (viewRef net "
"(cellRef %s (libraryRef %s)))",
ref->u, ref->cell->name, ref->cell->xlib->name);
for (prp = ref->property ; prp ; prp = prp->next) {
fprintf(fd, " ");
fprint_property(fd, prp);
}
fprintf(fd, ")\n");
}
fflush(fd);
/* Display all the joints. */
idx = 0;
for (jnt = edf->nexa ; jnt ; jnt = jnt->next, idx += 1) {
struct joint_cell_*jc;
/* Skip nil joints. */
if (jnt->links == 0)
continue;
fprintf(fd, "(net ");
if (jnt->name != 0)
fprintf(fd, "(rename N%u \"%s\")", idx, jnt->name);
else
fprintf(fd, "N%u", idx);
fprintf(fd, " (joined");
for (jc = jnt->links ; jc ; jc = jc->next) {
if (jc->cell) {
fprintf(fd, " (portRef %s (instanceRef U%u))",
jc->cell->cell->ports[jc->port].name,
jc->cell->u);
} else {
/* Reference to a port of the main cell. */
if (edf->ports[jc->port].ename)
fprintf(fd, " (portRef %s)",
edf->ports[jc->port].ename);
else
fprintf(fd, " (portRef %s)",
edf->ports[jc->port].name);
}
}
fprintf(fd, "))\n");
}
fprintf(fd, " )\n"); /* end the (contents...) sexp */
fprintf(fd, " )\n"); /* end the (view ) sexp */
fprintf(fd, " )\n"); /* end the (cell ) sexp */
fprintf(fd, " )\n"); /* end the (library DESIGN) sexp */
/* Make an instance of the defined object */
fprintf(fd, " (design %s\n", edf->name);
fprintf(fd, " (cellRef %s (libraryRef DESIGN))\n", edf->name);
for (prp = edf->property ; prp ; prp = prp->next) {
fprintf(fd, " ");
fprint_property(fd, prp);
fprintf(fd, "\n");
}
fprintf(fd, " )\n");
fprintf(fd, ")\n");
fflush(fd);
}
/*
* $Log: edif.c,v $
* Revision 1.1.2.2 2005/08/21 22:25:51 steve
* Fix the comment in the EDIT header.
*
* Revision 1.1.2.1 2005/08/17 01:17:28 steve
* Add the tgt-edif target.
*
*/

7
tgt-edif/edif.conf Normal file
View File

@ -0,0 +1,7 @@
functor:synth2
functor:synth
functor:syn-rules
functor:cprop
functor:nodangle
-t:dll
flag:DLL=edif.tgt

261
tgt-edif/edif.h Normal file
View File

@ -0,0 +1,261 @@
#ifndef __edif_H
#define __edif_H
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: edif.h,v 1.1.2.2 2005/09/25 16:35:36 steve Exp $"
#endif
# include <stdio.h>
# include <ivl_target.h>
/*
* These types and functions support the task of generating and
* writing out an EDIF 2 0 0 netlist. These functions work by
* supporting the creation of an in-core netlist of the design, then
* writing the netlist out all at once. The library manages cells with
* ports, but does not otherwise interpret cells. They have no
* contents.
*
* The general structure of netlist creation is as follows:
*
* Create a netlist with edif_create(<name>);
* This creates an edif object that represents the design. The
* design is given a name, and that name becomes the name of the
* single cell that this netlist handles.
*
* Add ports to the root with edif_portconfig
* The design may, if it is a macro to be included in a larger
* design, include ports. These are discovered by looking for port
* signals in the root module.
*
* Declare external libraries with edif_xlibrary_create
* Normally, this is the single technology library that contains
* the primitive cells that the code generator intendes to
* use. The library is given a name, such as VIRTEX or whatever
* the implementation tools expect. Cells are attached to the
* library later. An edif netlist may include multiple external
* references.
*
* Declare primitives with edif_xcell_create and edif_cell_portconfig.
* These functions create CELL TYPES that are attached to an
* external library. The libraries are created by
* edif_xlibrary_create.
*
* Cells can be created at any time before their first use. It
* therefore makes the most sense to not create the cell until it
* is certain that they are needed by the design.
*
* Create instances and join them up
* The edif_cellref_t objects represent instances of cells, and
* are the devices of the generated netlist. These cellrefs are
* connected together by the use of edif_joint_t joints. The
* joints can be created from ivl_nexus_t objects, or from their
* own ether. This instantiating of cells and joining them
* together that is the most fun. It is the technology specific
* stuff that the code generator does.
*
* Finally, print the result with edif_print(fd);
* This function writes the netlist in memory to an EDIF file on
* the stdio stream specified.
*
* This library is intended to be used once, to build up a netlist and
* print it. All the names that are taken as const char* should be
* somehow made permanent by the caller. Either they are constant
* strings, or they are strduped as necessary to make them
* permanent. The library will not duplicate them.
*/
/* TYPE DECLARATIONS */
/* This represents the entire EDIF design. You only need one of these
to hold everything. */
typedef struct edif_s* edif_t;
/* Each external library of the design gets one of these. */
typedef struct edif_xlibrary_s* edif_xlibrary_t;
/* This represents a type of cell. */
typedef struct edif_cell_s* edif_cell_t;
/* A cellref is an *instance* of a cell. */
typedef struct edif_cellref_s* edif_cellref_t;
/* This represents a generic joint. Cell ports are connected by being
associated with a joint. These can be bound to an ivl_nexus_t
object, of stand along. */
typedef struct edif_joint_s* edif_joint_t;
/* This structure defines a table that can be attached to an xlibrary
to incorporate black-box cells to the library. The cell_name is the
name that may be passed to the edif_xlibrary_findcell function, and
the function pointer points to a function that creates the cell and
defines ports for it. A real celltable is terminated by an entry
with a null pointer for the cell_name. */
struct edif_xlib_celltable {
const char*cell_name;
edif_cell_t (*cell_func)(edif_xlibrary_t xlib);
};
/* FUNCTIONS */
/* Start a new EDIF design. The design_name will be used as the name
of the top-mode module of the design. */
extern edif_t edif_create(const char*design_name, unsigned nports);
/* macro ports to the design are handled by this library similar to
cells. The user creates ports with this function. This function
configures the sole "port" of the cell with the name and dir passed
in. The direction, in this case, is the *interface* direction. */
extern void edif_portconfig(edif_t edf, unsigned idx,
const char*name, ivl_signal_port_t dir);
/* This is like edif_add_to_joint, but works with the edif port. */
extern void edif_port_to_joint(edif_joint_t jnt, edif_t edf, unsigned port);
/* The design may have properties attached to it. These properties
will be attached to the instance declared in the footer of the EDIF
file. */
extern void edif_pstring(edif_t edf, const char*name, const char*value);
/* Create an external library and attach it to the edif design. This
will lead to a (external ...) declaration of cells that can be used
by the design. */
extern edif_xlibrary_t edif_xlibrary_create(edif_t edf, const char*name);
extern void edif_xlibrary_set_celltable(edif_xlibrary_t lib,
const struct edif_xlib_celltable*table);
/* External libraries can be searched for existing cells, given a
string name. This function searches for the cell by name, and
returns it. */
extern edif_cell_t edif_xlibrary_findcell(edif_xlibrary_t lib,
const char*cell_name);
/* Similar to the above, but it gets the information it needs from the
ivl_scope_t object. */
extern edif_cell_t edif_xlibrary_scope_cell(edif_xlibrary_t xlib,
ivl_scope_t scope);
/* Create a new cell, attached to the external library. Specify the
number of ports that the cell has. The edif_cell_portconfig
function is then used to assign name and direction to each of the
ports.
The cell has a number of pins that are referenced by their number
from 0 to nports-1. You need to remember the pin numbers for the
named ports for use when joining that pin to an edif_joint_t.
Cellrefs get their port characteristics from the cell that they are
created from. So the pinouts of cellrefs match the pinout of the
associated cell. */
extern edif_cell_t edif_xcell_create(edif_xlibrary_t, const char*name,
unsigned nports);
extern void edif_cell_portconfig(edif_cell_t cell, unsigned idx,
const char*name, ivl_signal_port_t dir);
/* Attach a property to a cell port. */
extern void edif_cell_port_pstring(edif_cell_t cell, unsigned idx,
const char*name, const char*value);
/* Cells may have properties attached to them. These properties are
included in the library declaration for the cell, instead of the
cell instances. */
extern void edif_cell_pstring(edif_cell_t cell, const char*name,
const char*value);
extern void edif_cell_pinteger(edif_cell_t cell, const char*name,
int value);
/* Ports of cells are normally referenced by their port number. If you
forget what that number is, this function can look it up by name. */
extern unsigned edif_cell_port_byname(edif_cell_t cell, const char*name);
/* Create and instance from a cell. The instance refers to the cell,
which is a type, and contains pips for pins. */
extern edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell);
/* Instances can have properties attached to them. The name and value
given here are turned into a (property <name> (string "val"))
sexpression attached to the instance.
Examples of string properties commonly attached to cellref devices
include such things as the INIT=<value> to initialize LUT cells in
FPGA devices. */
extern void edif_cellref_pstring(edif_cellref_t ref, const char*name,
const char*value);
extern void edif_cellref_pinteger(edif_cellref_t ref, const char*name,
int value);
/* This function gets the joint associated with a nexus. This will
create a joint if necessary. */
extern edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex);
/* For linking cells outside the ivl netlist, this function creates an
anonymous joint. */
extern edif_joint_t edif_joint_create(edif_t edf);
/* Renaming a joint causes it to take on a name when external tools
view the EDIF file. */
extern void edif_joint_rename(edif_joint_t jnt, const char*name);
/* Given a joint, this function adds the cell reference. */
extern void edif_add_to_joint(edif_joint_t jnt,
edif_cellref_t cell,
unsigned port);
extern void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex);
/*
* Print the entire design. This should only be done after the design
* is completely assembled.
*/
extern void edif_print(FILE*fd, edif_t design);
/*
* This is the fd that should be passed to the edif_print
* function. The name "xnf" is historical. This function is opened and
* closed automatically by the edif core (the target_design function)
* so generally there is no other use then the edif_print for this
* exposed fd.
*/
extern FILE*xnf;
/*
* $Log: edif.h,v $
* Revision 1.1.2.2 2005/09/25 16:35:36 steve
* Add Xilinx virtex as a reference EDIF device.
*
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
* Add the tgt-edif target.
*
*/
#endif

67
tgt-edif/edif_priv.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef __fpga_priv_H
#define __fpga_priv_H
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: edif_priv.h,v 1.1.2.2 2005/09/25 16:35:36 steve Exp $"
#endif
# include <stdio.h>
# include "device.h"
extern int show_scope_gates(ivl_scope_t net, void*x);
extern device_t device;
extern const char*part;
extern const char*arch;
/*
* Attribute lookup, should this be provided in ivl_target.h?
*/
int scope_has_attribute(ivl_scope_t s, const char *name);
/*
* These are mangle functions.
*/
extern void xnf_mangle_logic_name(ivl_net_logic_t net, char*buf, size_t nbuf);
extern void xnf_mangle_lpm_name(ivl_lpm_t net, char*buf, size_t nbuf);
extern const char*xnf_mangle_nexus_name(ivl_nexus_t net);
/*
* $Log: edif_priv.h,v $
* Revision 1.1.2.2 2005/09/25 16:35:36 steve
* Add Xilinx virtex as a reference EDIF device.
*
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
* Add the tgt-edif target.
*
*/
#endif

192
tgt-edif/gates.c Normal file
View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: gates.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
#endif
# include <ivl_target.h>
# include "edif_priv.h"
# include <assert.h>
static void show_cell_scope(ivl_scope_t scope)
{
if (device->show_cell_scope == 0) {
fprintf(stderr, "fpga.tgt: ivl_synthesis_cell(scope)"
" not supported by this target.\n");
return;
}
device->show_cell_scope(scope);
}
static void show_gate_logic(ivl_net_logic_t net)
{
if (device->show_logic == 0) {
fprintf(stderr, "fpga.tgt: IVL LOGIC not supported"
" by this target.\n");
return;
}
assert(device->show_logic);
device->show_logic(net);
}
static void show_gate_lpm(ivl_lpm_t net)
{
switch (ivl_lpm_type(net)) {
case IVL_LPM_ADD:
if (device->show_add == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_ADD not supported"
" by this target.\n");
return;
}
device->show_add(net);
break;
case IVL_LPM_SUB:
if (device->show_sub == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SUB not supported"
" by this target.\n");
return;
}
device->show_sub(net);
break;
case IVL_LPM_CMP_EQ:
if (device->show_cmp_eq == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_EQ not supported"
" by this target.\n");
return;
}
device->show_cmp_eq(net);
break;
case IVL_LPM_CMP_NE:
if (device->show_cmp_ne == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_NE not supported"
" by this target.\n");
return;
}
device->show_cmp_ne(net);
break;
case IVL_LPM_CMP_GE:
if (device->show_cmp_ge == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_GE not supported"
" by this target.\n");
return;
}
device->show_cmp_ge(net);
break;
case IVL_LPM_CMP_GT:
if (device->show_cmp_gt == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_CMP_GT not supported"
" by this target.\n");
return;
}
device->show_cmp_gt(net);
break;
case IVL_LPM_FF:
if (device->show_dff == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_FF not supported"
" by this target.\n");
return;
}
device->show_dff(net);
break;
case IVL_LPM_MUX:
if (device->show_mux == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_MUX not supported"
" by this target.\n");
return;
}
device->show_mux(net);
break;
case IVL_LPM_MULT:
if (device->show_mult == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_MULT not supported"
" by this target.\n");
return;
}
device->show_mult(net);
break;
case IVL_LPM_SHIFTL:
if (device->show_shiftl == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTL not supported"
" by this target.\n");
return;
}
device->show_shiftl(net);
break;
case IVL_LPM_SHIFTR:
if (device->show_shiftr == 0) {
fprintf(stderr, "fpga.tgt: IVL_LPM_SHIFTR not supported"
" by this target.\n");
return;
}
device->show_shiftr(net);
break;
default:
fprintf(stderr, "fpga.tgt: unknown LPM type %u\n",
ivl_lpm_type(net));
break;
}
}
int show_scope_gates(ivl_scope_t net, void*x)
{
unsigned idx;
if (scope_has_attribute(net, "ivl_synthesis_cell")) {
show_cell_scope(net);
return 0;
}
for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1)
show_gate_logic(ivl_scope_log(net, idx));
for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1)
show_gate_lpm(ivl_scope_lpm(net, idx));
return ivl_scope_children(net, show_scope_gates, 0);
}
/*
* $Log: gates.c,v $
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
* Add the tgt-edif target.
*
*/

51
tgt-edif/generic.c Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: generic.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
#endif
# include "generic.h"
edif_t edf = 0;
edif_xlibrary_t xlib = 0;
edif_cell_t cell_0 = 0;
edif_cell_t cell_1 = 0;
edif_cell_t cell_ipad = 0;
edif_cell_t cell_opad = 0;
edif_cell_t cell_iopad = 0;
/*
* $Log: generic.c,v $
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
* Add the tgt-edif target.
*
*/

60
tgt-edif/generic.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef __generic_H
#define __generic_H
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: generic.h,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
#endif
# include "edif.h"
extern edif_t edf;
extern edif_xlibrary_t xlib;
/*
* The cell_* variables below are the various kinds of devices that
* this family supports as primitives. If the cell type is used at
* least once, then the edif_cell_t is non-zero and will also be
* included in the library declaration. The constants underneath are
* pin assignments for the cell.
*/
extern edif_cell_t cell_0;
extern edif_cell_t cell_1;
extern edif_cell_t cell_ipad;
extern edif_cell_t cell_opad;
extern edif_cell_t cell_iopad;
/*
* $Log: generic.h,v $
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
* Add the tgt-edif target.
*
*/
#endif

59
tgt-edif/tables.c Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: tables.c,v 1.1.2.2 2005/09/25 16:35:37 steve Exp $"
#endif
# include "device.h"
# include <string.h>
# include <assert.h>
/*
* This is where you hook new device types into the module. Simply
* declare your struct device_s objects (as done with d_lpm_edif) and
* add an enty in to the edif_device_table so that the user may invoke
* it via the -parch=<foo> command line switch.
*/
extern const struct device_s d_lpm_edif;
extern const struct device_s d_virtex_edif;
const struct device_table_s edif_device_table[] = {
{ "lpm", &d_lpm_edif },
{ "virtex",&d_virtex_edif },
{ 0, 0 }
};
/*
* $Log: tables.c,v $
* Revision 1.1.2.2 2005/09/25 16:35:37 steve
* Add Xilinx virtex as a reference EDIF device.
*
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
* Add the tgt-edif target.
*
*/

238
tgt-edif/target.c Normal file
View File

@ -0,0 +1,238 @@
/*
* Copyright (c) 2005 Stephen Williams
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: target.c,v 1.1.2.1 2005/08/17 01:17:29 steve Exp $"
#endif
/*
* This is the EDIF target module.
*/
# include <ivl_target.h>
# include <string.h>
# include "edif_priv.h"
# include <assert.h>
/* This is the opened xnf file descriptor. It is the output that this
code generator writes to. */
FILE*xnf = 0;
const char*part = 0;
const char*arch = 0;
device_t device = 0;
int scope_has_attribute(ivl_scope_t s, const char *name)
{
int i;
const struct ivl_attribute_s *a;
for (i=0; i<ivl_scope_attr_cnt(s); i++) {
a = ivl_scope_attr_val(s, i);
if (strcmp(a->key,name) == 0)
return 1;
}
return 0;
}
static int show_process(ivl_process_t net, void*x)
{
ivl_scope_t scope = ivl_process_scope(net);
/* Ignore processes that are within scopes that are cells. The
cell_scope will generate a cell to represent the entire
scope. */
if (scope_has_attribute(scope, "ivl_synthesis_cell"))
return 0;
fprintf(stderr, "fpga target: unsynthesized behavioral code\n");
return 0;
}
static void show_pads(ivl_scope_t scope)
{
unsigned idx;
if (device->show_pad == 0)
return;
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
ivl_signal_t sig = ivl_scope_sig(scope, idx);
const char*pad;
if (ivl_signal_port(sig) == IVL_SIP_NONE)
continue;
pad = ivl_signal_attr(sig, "PAD");
if (pad == 0)
continue;
assert(device->show_pad);
device->show_pad(sig, pad);
}
}
static void show_constants(ivl_design_t des)
{
unsigned idx;
if (device->show_constant == 0)
return;
for (idx = 0 ; idx < ivl_design_consts(des) ; idx += 1) {
ivl_net_const_t con = ivl_design_const(des, idx);
device->show_constant(con);
}
}
/*
* This is the main entry point that ivl uses to invoke me, the code
* generator.
*/
int target_design(ivl_design_t des)
{
ivl_scope_t root = ivl_design_root(des);
const char*path = ivl_design_flag(des, "-o");
xnf = fopen(path, "w");
if (xnf == 0) {
perror(path);
return -1;
}
part = ivl_design_flag(des, "part");
if (part && (part[0] == 0))
part = 0;
arch = ivl_design_flag(des, "arch");
if (arch && (arch[0] == 0))
arch = 0;
if (arch == 0)
arch = "lpm";
device = device_from_arch(arch);
if (device == 0) {
fprintf(stderr, "Unknown architecture arch=%s\n", arch);
return -1;
}
/* Call the device driver to generate the netlist header. */
device->show_header(des);
/* Catch any behavioral code that is left, and write warnings
that it is not supported. */
ivl_design_process(des, show_process, 0);
/* Get the pads from the design, and draw them to connect to
the associated signals. */
show_pads(root);
/* Scan the scopes, looking for gates to draw into the output
netlist. */
show_scope_gates(root, 0);
show_constants(des);
/* Call the device driver to close out the file. */
device->show_footer(des);
fclose(xnf);
xnf = 0;
return 0;
}
/*
* This function tests whether the nexus has a constant value. It
* returns true if the value is constant, or false if there are
* non-constant or conflicting drivers.
*/
int test_nexus_constant(ivl_nexus_t nex, char*val)
{
int count_drivers = 0;
unsigned idx;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_net_const_t con;
unsigned pin;
const char*cbits;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
/* If this nexus link is an input pin to the device (or
otherwise does not drive the nexus) then skip it. */
if (ivl_nexus_ptr_drive0(ptr) == IVL_DR_HiZ
&& ivl_nexus_ptr_drive1(ptr) == IVL_DR_HiZ)
continue;
count_drivers += 1;
/* If this driver is not a constant, then the test fails
certainly. */
con = ivl_nexus_ptr_con(ptr);
if (con == 0)
return 0;
/* Get the pin number within the constant where this
nexus is connected. */
pin = ivl_nexus_ptr_pin(ptr);
/* The pin for the constant that we located is
guaranteed to really point to the nexus that we are
working with. */
assert(ivl_const_pins(con) > pin);
assert(ivl_const_pin(con,pin) == nex);
/* Get the bit value from the constant. If there are
multiple constants driving this nexus (an unlikely
situation) then allow for them only if their value
matches. But the more common case is that this is the
only driver for the nexus. Save the constant value in
the *val result that we pass back to the user. */
cbits = ivl_const_bits(con);
if (count_drivers > 1) {
if (val[0] != cbits[pin])
return 0;
} else {
val[0] = cbits[pin];
}
}
/* If in the end there are no drivers at all for the nexus,
then assume the nexus has a constant HiZ value. */
if (count_drivers == 0)
*val = 'z';
/* Return TRUE */
return 1;
}
/*
* $Log: target.c,v $
* Revision 1.1.2.1 2005/08/17 01:17:29 steve
* Add the tgt-edif target.
*
*/

980
tgt-edif/xilinx.c Normal file
View File

@ -0,0 +1,980 @@
/*
* Copyright (c) 2005 Stephen Williams (steve at icarus.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: xilinx.c,v 1.1.2.1 2005/09/25 16:35:37 steve Exp $"
#endif
/*
* This source file contains common functions used by Xilinx
* devices. The functions here do not support any specific Xilinx part
* fimily, but instead provide some core functions that are used by
* specific devices.
*
* For example, some xilinx_* functions are suitable for placing
* directly in a device_s table, but there is no "xilinx"
* device. These functions can be placed in the tables for devices
* that have no better way to handle the device_s function, or these
* functions can be called by device specific device_s functions that
* fall back on the generic handling in certain cases. For an example
* of both cases, see d-virtex.c.
*/
# include "edif.h"
# include "generic.h"
# include "xilinx.h"
# include <stdlib.h>
# include <string.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <assert.h>
edif_cell_t xilinx_cell_buf(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "BUF", 2);
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "BUFE", 3);
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
edif_cell_portconfig(cell, BUF_T, "E", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "BUFG", 2);
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "BUFT", 3);
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
edif_cell_portconfig(cell, BUF_T, "T", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "IBUF", 2);
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_inv(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "INV", 2);
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "MUXF5", 4);
edif_cell_portconfig(cell, MUXF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, MUXF_I0, "I0", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MUXF_I1, "I1", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MUXF_S, "S", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "MUXF6", 4);
edif_cell_portconfig(cell, MUXF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, MUXF_I0, "I0", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MUXF_I1, "I1", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MUXF_S, "S", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell) return cell;
cell = edif_xcell_create(xlib, "OBUF", 2);
edif_cell_portconfig(cell, BUF_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, BUF_I, "I", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "LUT2", 3);
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "LUT3", 4);
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
edif_cell_portconfig(cell, LUT_I2, "I2", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "LUT4", 5);
edif_cell_portconfig(cell, LUT_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, LUT_I0, "I0", IVL_SIP_INPUT);
edif_cell_portconfig(cell, LUT_I1, "I1", IVL_SIP_INPUT);
edif_cell_portconfig(cell, LUT_I2, "I2", IVL_SIP_INPUT);
edif_cell_portconfig(cell, LUT_I3, "I3", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "FDCE", 5);
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_CLR,"CLR", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "FDCPE", 6);
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_CLR,"CLR", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_PRE,"PRE", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "FDRE", 5);
edif_cell_portconfig(cell, FDCE_Q, "Q", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, FDCE_D, "D", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_C, "C", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_CE, "CE", IVL_SIP_INPUT);
edif_cell_portconfig(cell, FDCE_CLR,"R", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "MULT_AND", 3);
edif_cell_portconfig(cell, MULT_AND_LO, "LO", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, MULT_AND_I0, "I0", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MULT_AND_I1, "I1", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "MUXCY", 4);
edif_cell_portconfig(cell, MUXCY_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, MUXCY_DI, "DI", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MUXCY_CI, "CI", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MUXCY_S, "S", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "MUXCY_L", 4);
edif_cell_portconfig(cell, MUXCY_O, "LO", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, MUXCY_DI, "DI", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MUXCY_CI, "CI", IVL_SIP_INPUT);
edif_cell_portconfig(cell, MUXCY_S, "S", IVL_SIP_INPUT);
return cell;
}
edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib)
{
static edif_cell_t cell = 0;
if (cell != 0) return cell;
cell = edif_xcell_create(xlib, "XORCY", 3);
edif_cell_portconfig(cell, XORCY_O, "O", IVL_SIP_OUTPUT);
edif_cell_portconfig(cell, XORCY_CI, "CI", IVL_SIP_INPUT);
edif_cell_portconfig(cell, XORCY_LI, "LI", IVL_SIP_INPUT);
return cell;
}
/*
* This function does a lot of the stuff common to the header
* functions of various Xilinx familes. This includes creating the edf
* object that holds the netlist.
*/
void xilinx_common_header(ivl_design_t des)
{
unsigned idx;
ivl_scope_t root = ivl_design_root(des);
unsigned sig_cnt = ivl_scope_sigs(root);
unsigned nports = 0, pidx;
/* Count the ports I'm going to use. */
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
ivl_signal_t sig = ivl_scope_sig(root, idx);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
continue;
if (ivl_signal_attr(sig, "PAD") != 0)
continue;
nports += ivl_signal_pins(sig);
}
edf = edif_create(ivl_scope_basename(root), nports);
pidx = 0;
for (idx = 0 ; idx < sig_cnt ; idx += 1) {
edif_joint_t jnt;
ivl_signal_t sig = ivl_scope_sig(root, idx);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
continue;
if (ivl_signal_attr(sig, "PAD") != 0)
continue;
if (ivl_signal_pins(sig) == 1) {
edif_portconfig(edf, pidx, ivl_signal_basename(sig),
ivl_signal_port(sig));
assert(ivl_signal_pins(sig) == 1);
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
edif_port_to_joint(jnt, edf, pidx);
} else {
const char*name = ivl_signal_basename(sig);
ivl_signal_port_t dir = ivl_signal_port(sig);
char buf[128];
unsigned bit;
for (bit = 0 ; bit < ivl_signal_pins(sig) ; bit += 1) {
const char*tmp;
sprintf(buf, "%s[%u]", name, bit);
tmp = strdup(buf);
edif_portconfig(edf, pidx+bit, tmp, dir);
jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit));
edif_port_to_joint(jnt, edf, pidx+bit);
}
}
pidx += ivl_signal_pins(sig);
}
assert(pidx == nports);
}
void xilinx_show_footer(ivl_design_t des)
{
unsigned idx;
for (idx = 0 ; idx < ivl_design_consts(des) ; idx += 1) {
unsigned pin;
ivl_net_const_t net = ivl_design_const(des, idx);
const char*val = ivl_const_bits(net);
for (pin = 0 ; pin < ivl_const_pins(net) ; pin += 1) {
edif_joint_t jnt;
edif_cellref_t pad;
jnt = edif_joint_of_nexus(edf, ivl_const_pin(net, pin));
switch (val[pin]) {
case '0':
pad = edif_cellref_create(edf, cell_0);
break;
case '1':
pad = edif_cellref_create(edf, cell_1);
break;
default:
assert(0);
break;
}
edif_add_to_joint(jnt, pad, 0);
}
}
edif_print(xnf, edf);
}
/*
* Make (or retrieve) a cell in the external library that reflects the
* scope with its ports.
*/
void xilinx_show_scope(ivl_scope_t scope)
{
edif_cell_t cell;
edif_cellref_t ref;
unsigned port, idx;
cell = edif_xlibrary_scope_cell(xlib, scope);
ref = edif_cellref_create(edf, cell);
for (idx = 0 ; idx < ivl_scope_sigs(scope) ; idx += 1) {
edif_joint_t jnt;
ivl_signal_t sig = ivl_scope_sig(scope, idx);
if (ivl_signal_port(sig) == IVL_SIP_NONE)
continue;
port = edif_cell_port_byname(cell, ivl_signal_basename(sig));
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
edif_add_to_joint(jnt, ref, port);
}
}
void xilinx_pad(ivl_signal_t sig, const char*str)
{
unsigned idx;
char**pins;
if (cell_ipad == 0) {
cell_ipad = edif_xcell_create(xlib, "IPAD", 1);
edif_cell_portconfig(cell_ipad, 0, "IPAD", IVL_SIP_OUTPUT);
}
if (cell_opad == 0) {
cell_opad = edif_xcell_create(xlib, "OPAD", 1);
edif_cell_portconfig(cell_opad, 0, "OPAD", IVL_SIP_INPUT);
}
if (cell_iopad == 0) {
cell_iopad = edif_xcell_create(xlib, "IOPAD", 1);
edif_cell_portconfig(cell_iopad, 0, "IOPAD", IVL_SIP_INOUT);
}
/* Collect an array of pin assignments from the attribute
string passed in as str. The format is a comma separated
list of location names. */
pins = calloc(ivl_signal_pins(sig), sizeof(char*));
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
const char*tmp = strchr(str, ',');
if (tmp == 0) tmp = str+strlen(str);
pins[idx] = malloc(tmp-str+1);
strncpy(pins[idx], str, tmp-str);
pins[idx][tmp-str] = 0;
if (*tmp != 0)
tmp += 1;
str = tmp;
}
/* Now go through the pins of the signal, creating pads and
bufs and joining them to the signal nexus. */
for (idx = 0 ; idx < ivl_signal_pins(sig) ; idx += 1) {
edif_joint_t jnt;
edif_cellref_t pad, buf;
const char*name_str = ivl_signal_basename(sig);
if (ivl_signal_pins(sig) > 1) {
char name_buf[128];
sprintf(name_buf, "%s[%u]", name_str, idx);
name_str = strdup(name_buf);
}
switch (ivl_signal_port(sig)) {
case IVL_SIP_INPUT:
pad = edif_cellref_create(edf, cell_ipad);
buf = edif_cellref_create(edf, xilinx_cell_ibuf(xlib));
jnt = edif_joint_create(edf);
edif_joint_rename(jnt, name_str);
edif_add_to_joint(jnt, pad, 0);
edif_add_to_joint(jnt, buf, BUF_I);
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
edif_add_to_joint(jnt, buf, BUF_O);
break;
case IVL_SIP_OUTPUT:
pad = edif_cellref_create(edf, cell_opad);
buf = edif_cellref_create(edf, xilinx_cell_obuf(xlib));
jnt = edif_joint_create(edf);
edif_joint_rename(jnt, name_str);
edif_add_to_joint(jnt, pad, 0);
edif_add_to_joint(jnt, buf, BUF_O);
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
edif_add_to_joint(jnt, buf, BUF_I);
break;
case IVL_SIP_INOUT:
pad = edif_cellref_create(edf, cell_iopad);
jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, idx));
edif_add_to_joint(jnt, pad, 0);
break;
default:
assert(0);
}
if (pins[idx])
edif_cellref_pstring(pad, "LOC", pins[idx]);
}
/* Don't free the allocated pad name strings. The
edif_cellref_pstring function attached the string to the
LOC attribute, so the reference is permanent. */
free(pins);
}
/*
* This function handles the case where the user specifies the cell to
* use by attribute.
*/
static void edif_cellref_logic(ivl_net_logic_t net, const char*def)
{
char*str = strdup(def);
char*pins;
edif_cell_t cell;
edif_cellref_t ref;
edif_joint_t jnt;
unsigned idx, port;
pins = strchr(str, ':');
assert(pins);
*pins++ = 0;
/* Locate the cell in the library, lookup by name. */
cell = edif_xlibrary_findcell(xlib, str);
assert(cell);
ref = edif_cellref_create(edf, cell);
for (idx = 0 ; idx < ivl_logic_pins(net) ; idx += 1) {
char*tmp;
assert(pins);
tmp = strchr(pins,',');
if (tmp != 0)
*tmp++ = 0;
else
tmp = 0;
port = edif_cell_port_byname(cell, pins);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx));
edif_add_to_joint(jnt, ref, port);
pins = tmp;
}
free(str);
}
static void lut_logic(ivl_net_logic_t net, const char*init3,
const char*init4, const char*init5)
{
edif_cellref_t lut = NULL; /* initialization shuts up gcc -Wall */
edif_joint_t jnt;
const char* init = NULL; /* ditto */
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
switch (ivl_logic_pins(net)) {
case 3:
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
init = init3;
break;
case 4:
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
init = init4;
break;
case 5:
lut = edif_cellref_create(edf, xilinx_cell_lut4(xlib));
init = init5;
break;
}
edif_cellref_pstring(lut, "INIT", init);
switch (ivl_logic_pins(net)) {
case 5:
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 4));
edif_add_to_joint(jnt, lut, LUT_I3);
case 4:
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 3));
edif_add_to_joint(jnt, lut, LUT_I2);
case 3:
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, lut, LUT_I1);
}
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
}
void xilinx_logic(ivl_net_logic_t net)
{
edif_cellref_t obj;
edif_joint_t jnt;
{ const char*cellref_attribute = ivl_logic_attr(net, "cellref");
if (cellref_attribute != 0) {
edif_cellref_logic(net, cellref_attribute);
return;
}
}
switch (ivl_logic_type(net)) {
case IVL_LO_BUF:
case IVL_LO_BUFZ:
assert(ivl_logic_pins(net) == 2);
obj = edif_cellref_create(edf, xilinx_cell_buf(xlib));
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, obj, BUF_O);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, obj, BUF_I);
break;
case IVL_LO_BUFIF0:
/* The Xilinx BUFT devices is a BUF that adds a T
input. The output is tri-stated if the T input is
1. In other words, it acts just like bufif0. */
assert(ivl_logic_pins(net) == 3);
obj = edif_cellref_create(edf, xilinx_cell_buft(xlib));
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, obj, BUF_O);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, obj, BUF_I);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, obj, BUF_T);
break;
case IVL_LO_BUFIF1:
/* The Xilinx BUFE devices is a BUF that adds an enable
input. The output is tri-stated if the E input is 0.
In other words, it acts just like bufif1. */
assert(ivl_logic_pins(net) == 3);
obj = edif_cellref_create(edf, xilinx_cell_bufe(xlib));
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, obj, BUF_O);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, obj, BUF_I);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
edif_add_to_joint(jnt, obj, BUF_T);
break;
case IVL_LO_NOT:
assert(ivl_logic_pins(net) == 2);
obj = edif_cellref_create(edf, xilinx_cell_inv(xlib));
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
edif_add_to_joint(jnt, obj, BUF_O);
jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
edif_add_to_joint(jnt, obj, BUF_I);
break;
case IVL_LO_AND:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "8", "80", "8000");
break;
case IVL_LO_NOR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "1", "01", "0001");
break;
case IVL_LO_OR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "E", "FE", "FFFE");
break;
case IVL_LO_XNOR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "9", "69", "9669");
break;
case IVL_LO_XOR:
assert(ivl_logic_pins(net) <= 5);
assert(ivl_logic_pins(net) >= 3);
lut_logic(net, "6", "96", "6996");
break;
default:
fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n",
ivl_logic_type(net));
break;
}
}
/*
* A fully generic Xilinx MUX is implemented entirely from LUT
* devices.
*/
void xilinx_mux(ivl_lpm_t net)
{
unsigned idx;
edif_cellref_t lut;
edif_joint_t jnt;
assert(ivl_lpm_selects(net) == 1);
/* A/B Mux devices are made from LUT3 devices. I0 is connected
to A, I1 to B, and I2 to the Select input. Create as many
as are needed to implement the requested width.
S B A | Q
------+--
0 0 0 | 0
0 0 1 | 1
0 1 0 | 0
0 1 1 | 1
1 0 0 | 0
1 0 1 | 0
1 1 0 | 1
1 1 1 | 1
INIT = "CA" */
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib));
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 0, idx));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, 1, idx));
edif_add_to_joint(jnt, lut, LUT_I1);
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, 0));
edif_add_to_joint(jnt, lut, LUT_I2);
edif_cellref_pstring(lut, "INIT", "CA");
}
}
/*
* Any Xilinx device works with this adder.
* Generic Xilinx add only works for single bit slices.
*/
void xilinx_add(ivl_lpm_t net)
{
const char*ha_init = 0;
edif_cellref_t lut;
edif_joint_t jnt;
switch (ivl_lpm_type(net)) {
case IVL_LPM_ADD:
ha_init = "6";
break;
case IVL_LPM_SUB:
ha_init = "9";
break;
default:
assert(0);
}
/* If this is a single bit wide, then generate only a
half-adder. Normally this is an XOR, but if this is a SUB
then it is an XNOR. */
if (ivl_lpm_width(net) == 1) {
lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib));
jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, 0));
edif_add_to_joint(jnt, lut, LUT_O);
jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, 0));
edif_add_to_joint(jnt, lut, LUT_I0);
jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, 0));
edif_add_to_joint(jnt, lut, LUT_I1);
edif_cellref_pstring(lut, "INIT", ha_init);
return;
}
assert(0);
}
/*
* The left shift is implemented as a matrix of MUX2_1 devices. The
* matrix has as many rows as the device width, and a column for each
* select.
*/
void xilinx_shiftl(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
unsigned nsel = 0, swid = 0;
unsigned sdx, qdx;
edif_cellref_t* cells;
edif_cellref_t**table;
edif_cellref_t pad0_cell;
edif_joint_t pad0;
/* First, find out how many select inputs we really need. We
can only use the selects that are enough to shift out the
entire width of the device. The excess can be used as an
enable for the last column. When disabled, the last column
emits zeros. */
while (nsel < ivl_lpm_selects(net)) {
nsel += 1;
swid = 1 << nsel;
if (swid >= width)
break;
}
assert(nsel > 0);
/* Allocate a matrix of edif_cellref_t variables. A devices
will be addressed by the expression table[sdx][qdx];
This should make the algorighm code easier to read. */
cells = calloc(nsel * width, sizeof(edif_cellref_t));
table = calloc(nsel, sizeof(edif_cellref_t*));
for (sdx = 0 ; sdx < nsel ; sdx += 1)
table[sdx] = cells + sdx*width;
/* Make a 0 valued pad bit. I wlil use this for all the shifin
values that are beyond the input. */
pad0_cell = edif_cellref_create(edf, cell_0);
pad0 = edif_joint_create(edf);
edif_add_to_joint(pad0, pad0_cell, 0);
/* The LUT matrix is <nsel> columns of <width> devices, with
the last column a LUT4 devices. The extra input of the
LUT4s in the last column are used as an enable to collect
all the excess select inputs. */
/* Allocate the LUT devices of the matrix, and connect the
select inputs to I2 of all the devices of the column. */
for (sdx = 0 ; sdx < nsel ; sdx += 1) {
const char*init_string = 0;
ivl_nexus_t nex = ivl_lpm_select(net,sdx);
edif_joint_t sdx_jnt = edif_joint_of_nexus(edf, nex);
edif_cell_t lut;
if (((sdx+1) == nsel) && (nsel < ivl_lpm_selects(net))) {
lut = xilinx_cell_lut4(xlib);
init_string = "00CA";
} else {
lut = xilinx_cell_lut3(xlib);
init_string = "CA";
}
for (qdx = 0 ; qdx < width ; qdx += 1) {
table[sdx][qdx] = edif_cellref_create(edf, lut);
edif_add_to_joint(sdx_jnt, table[sdx][qdx], LUT_I2);
edif_cellref_pstring(table[sdx][qdx], "INIT", init_string);
}
}
/* Connect the inputs of the SHIFTL device to the column 0 LUT
inputs. The slice on the low end shifts in a 0 for a select
input. */
for (qdx = 0 ; qdx < width ; qdx += 1) {
ivl_nexus_t nex0, nex1;
edif_joint_t jnt0;
edif_joint_t jnt1;
nex0 = ivl_lpm_data(net,qdx);
jnt0 = edif_joint_of_nexus(edf, nex0);
if (qdx > 0) {
nex1 = ivl_lpm_data(net,qdx-1);
jnt1 = edif_joint_of_nexus(edf, nex1);
} else {
jnt1 = pad0;
}
edif_add_to_joint(jnt0, table[0][qdx], LUT_I0);
edif_add_to_joint(jnt1, table[0][qdx], LUT_I1);
}
/* Make the inner connections between LUT devices. Each column
connects to the previous column, shifted by the power of
the column value. If the shifted input falls off the end,
then pad with zero. */
for (sdx = 1 ; sdx < nsel ; sdx += 1) {
for (qdx = 0 ; qdx < width ; qdx += 1) {
unsigned shift = 1 << sdx;
edif_joint_t jnt0 = edif_joint_create(edf);
edif_joint_t jnt1 = (qdx >= shift)
? edif_joint_create(edf)
: pad0;
edif_add_to_joint(jnt0, table[sdx][qdx], LUT_I0);
edif_add_to_joint(jnt1, table[sdx][qdx], LUT_I1);
edif_add_to_joint(jnt0, table[sdx-1][qdx], LUT_O);
if (qdx >= shift)
edif_add_to_joint(jnt1, table[sdx-1][qdx-shift], LUT_O);
}
}
/* Connect the output of the last column to the output of the
SHIFTL device. */
for (qdx = 0 ; qdx < width ; qdx += 1) {
ivl_nexus_t nex = ivl_lpm_q(net,qdx);
edif_joint_t jnt = edif_joint_of_nexus(edf, nex);
edif_add_to_joint(jnt, table[nsel-1][qdx], LUT_O);
}
/* Connect the excess select inputs to the enable inputs of
the LUT4 devices in the last column. */
if (nsel < ivl_lpm_selects(net)) {
edif_joint_t jnt;
/* XXXX Only support 1 excess bit for now. */
assert((nsel + 1) == ivl_lpm_selects(net));
jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net,nsel));
for (qdx = 0 ; qdx < width ; qdx += 1)
edif_add_to_joint(jnt, table[nsel-1][qdx], LUT_I3);
}
free(cells);
free(table);
}
/*
* $Log: xilinx.c,v $
* Revision 1.1.2.1 2005/09/25 16:35:37 steve
* Add Xilinx virtex as a reference EDIF device.
*
*/

149
tgt-edif/xilinx.h Normal file
View File

@ -0,0 +1,149 @@
#ifndef __xilinx_H
#define __xilinx_H
/*
* Copyright (c) 2005 Stephen Williams (steve at icarus.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: xilinx.h,v 1.1.2.1 2005/09/25 16:35:37 steve Exp $"
#endif
/*
* This header file includes XILINX library support functions. They
* manage the creation and reference of cells from the library. Use
* the xililx_cell_* functions to get an edif_cell_t from the
* library. The function will create the cell in the library if
* needed, or will return the existing cell if it was already called.
*
* Note that these functions are *not* part of the baseline EDIF. They
* are intended to be Xilinx specific and sometimes do things that
* would be flat-out wrong for non-xilinx devices.
*/
# include "edif.h"
/* === BUF Devices === */
/* Buffer types of devices have the BUF_O and BUF_I pin
assignments. The BUF, INV, and certain specialized devices fit in
this category. */
extern edif_cell_t xilinx_cell_buf (edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_bufe(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_bufg(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_buft(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_inv (edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_ibuf(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_obuf(edif_xlibrary_t xlib);
#define BUF_O 0
#define BUF_I 1
/* Only bufe and buft buffers have this input. */
#define BUF_T 2
/* === LUT Devices === */
/* Most Xilinx devices have LUT2/3/4 devices that take, respectively,
2, 3 or 4 inputs. All forms have a single bit output. Also, the
real behavior of the device will need to be specified by an INIT
parameter string. */
extern edif_cell_t xilinx_cell_lut2(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_lut3(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_lut4(edif_xlibrary_t xlib);
#define LUT_O 0
#define LUT_I0 1
#define LUT_I1 2
#define LUT_I2 3
#define LUT_I3 4
/* === Flip-Flop Devices === */
/*
* These are flip-flops of various sort, but similar pinouts.
*/
extern edif_cell_t xilinx_cell_fdce(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_fdcpe(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_fdre(edif_xlibrary_t xlib);
#define FDCE_Q 0
#define FDCE_C 1
#define FDCE_D 2
#define FDCE_CE 3
#define FDCE_CLR 4
#define FDCE_PRE 5
/* === Virtex/Virtex2 Carry Chain Logic === */
extern edif_cell_t xilinx_cell_mult_and(edif_xlibrary_t xlib);
#define MULT_AND_LO 0
#define MULT_AND_I0 1
#define MULT_AND_I1 2
extern edif_cell_t xilinx_cell_muxcy(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_muxcy_l(edif_xlibrary_t xlib);
#define MUXCY_O 0
#define MUXCY_DI 1
#define MUXCY_CI 2
#define MUXCY_S 3
extern edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib);
#define XORCY_O 0
#define XORCY_CI 1
#define XORCY_LI 2
/* === Virtex/Virtex2 MUX devices */
extern edif_cell_t xilinx_cell_muxf5(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_muxf6(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_muxf7(edif_xlibrary_t xlib);
extern edif_cell_t xilinx_cell_muxf8(edif_xlibrary_t xlib);
#define MUXF_O 0
#define MUXF_I0 1
#define MUXF_I1 2
#define MUXF_S 3
/* === Inheritable Methods === */
extern void virtex_logic(ivl_net_logic_t net);
extern void virtex_generic_dff(ivl_lpm_t net);
extern void virtex_eq(ivl_lpm_t net);
extern void virtex_ge(ivl_lpm_t net);
extern void virtex_mux(ivl_lpm_t net);
extern void virtex_add(ivl_lpm_t net);
extern void xilinx_common_header(ivl_design_t des);
extern void xilinx_show_footer(ivl_design_t des);
extern void xilinx_show_scope(ivl_scope_t scope);
extern void xilinx_pad(ivl_signal_t, const char*str);
extern void xilinx_logic(ivl_net_logic_t net);
extern void xilinx_mux(ivl_lpm_t net);
extern void xilinx_add(ivl_lpm_t net);
extern void xilinx_shiftl(ivl_lpm_t net);
/*
* $Log: xilinx.h,v $
* Revision 1.1.2.1 2005/09/25 16:35:37 steve
* Add Xilinx virtex as a reference EDIF device.
*
*/
#endif

View File

@ -17,7 +17,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.16 2004/02/10 19:25:01 steve Exp $" #ident "$Id: Makefile.in,v 1.16.2.1 2005/02/23 18:40:24 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -83,6 +83,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
check: all check: all

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: d-lpm.c,v 1.12 2004/10/04 01:10:56 steve Exp $" #ident "$Id: d-lpm.c,v 1.12.2.1 2005/08/25 18:52:32 steve Exp $"
#endif #endif
/* /*
@ -804,9 +804,19 @@ static void lpm_show_mult(ivl_lpm_t net)
static void lpm_show_constant(ivl_net_const_t net) static void lpm_show_constant(ivl_net_const_t net)
{ {
/* We only need one instance each of constant 0 and 1 bits. If
we need either of them, then create an instance reference and
save that reference here so that later needs for 0 or 1 can
find that the reference already lives and can be added to the
joint. */
static edif_cellref_t cell0_ref = 0;
static edif_cellref_t cell1_ref = 0;
static edif_joint_t cell0_jnt = 0;
static edif_joint_t cell1_jnt = 0;
edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0"); edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0");
edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1"); edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1");
edif_cellref_t ref0 = 0, ref1 = 0;
const char*bits; const char*bits;
unsigned idx; unsigned idx;
@ -832,23 +842,26 @@ static void lpm_show_constant(ivl_net_const_t net)
bits = ivl_const_bits(net); bits = ivl_const_bits(net);
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) { for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
if (bits[idx] == '1') { if (bits[idx] == '1') {
if (ref1 == 0) if (cell1_ref == 0) {
ref1 = edif_cellref_create(edf, cell1); cell1_ref = edif_cellref_create(edf, cell1);
cell1_jnt = edif_joint_create(edf);
edif_add_to_joint(cell1_jnt, cell1_ref, 0);
}
} else { } else {
if (ref0 == 0) if (cell0_ref == 0) {
ref0 = edif_cellref_create(edf, cell0); cell0_ref = edif_cellref_create(edf, cell0);
cell0_jnt = edif_joint_create(edf);
edif_add_to_joint(cell0_jnt, cell0_ref, 0);
}
} }
} }
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) { for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
edif_joint_t jnt;
jnt = edif_joint_of_nexus(edf, ivl_const_pin(net,idx));
if (bits[idx] == '1') if (bits[idx] == '1')
edif_add_to_joint(jnt, ref1, 0); edif_nexus_to_joint(edf, cell1_jnt, ivl_const_pin(net,idx));
else else
edif_add_to_joint(jnt, ref0, 0); edif_nexus_to_joint(edf, cell0_jnt, ivl_const_pin(net,idx));
} }
} }
@ -876,6 +889,9 @@ const struct device_s d_lpm_edif = {
/* /*
* $Log: d-lpm.c,v $ * $Log: d-lpm.c,v $
* Revision 1.12.2.1 2005/08/25 18:52:32 steve
* Join cell0 and cell1 instances in LPM target.
*
* Revision 1.12 2004/10/04 01:10:56 steve * Revision 1.12 2004/10/04 01:10:56 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: edif.c,v 1.8 2003/09/03 23:34:09 steve Exp $" #ident "$Id: edif.c,v 1.8.2.1 2005/08/27 22:29:30 steve Exp $"
#endif #endif
# include "edif.h" # include "edif.h"
@ -393,6 +393,28 @@ edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex)
return jnt; return jnt;
} }
void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex)
{
void*tmp = ivl_nexus_get_private(nex);
if (tmp != 0) {
/* There is a joint already on the nexus. Move all the
joint cells to the joint I'm joining to. */
edif_joint_t njnt = (edif_joint_t)tmp;
while (njnt->links) {
struct joint_cell_*cell = njnt->links;
njnt->links = cell->next;
cell->next = jnt->links;
jnt->links = cell;
}
/* Now njnt is dead, and should be removed from edif. */
/* Or we can ignore it as harmless. */
}
ivl_nexus_set_private(nex, jnt);
}
void edif_joint_rename(edif_joint_t jnt, const char*name) void edif_joint_rename(edif_joint_t jnt, const char*name)
{ {
assert(jnt->name == 0); assert(jnt->name == 0);
@ -617,6 +639,9 @@ void edif_print(FILE*fd, edif_t edf)
/* /*
* $Log: edif.c,v $ * $Log: edif.c,v $
* Revision 1.8.2.1 2005/08/27 22:29:30 steve
* Back-port edif_nexus_to_joint from tgt-edif.
*
* Revision 1.8 2003/09/03 23:34:09 steve * Revision 1.8 2003/09/03 23:34:09 steve
* Support synchronous set of LPM_FF devices. * Support synchronous set of LPM_FF devices.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: edif.h,v 1.7 2003/09/03 23:34:09 steve Exp $" #ident "$Id: edif.h,v 1.7.2.1 2005/08/27 22:29:31 steve Exp $"
#endif #endif
# include <stdio.h> # include <stdio.h>
@ -223,6 +223,8 @@ extern void edif_add_to_joint(edif_joint_t jnt,
edif_cellref_t cell, edif_cellref_t cell,
unsigned port); unsigned port);
extern void edif_nexus_to_joint(edif_t edf, edif_joint_t jnt, ivl_nexus_t nex);
/* /*
* Print the entire design. This should only be done after the design * Print the entire design. This should only be done after the design
* is completely assembled. * is completely assembled.
@ -231,6 +233,9 @@ extern void edif_print(FILE*fd, edif_t design);
/* /*
* $Log: edif.h,v $ * $Log: edif.h,v $
* Revision 1.7.2.1 2005/08/27 22:29:31 steve
* Back-port edif_nexus_to_joint from tgt-edif.
*
* Revision 1.7 2003/09/03 23:34:09 steve * Revision 1.7 2003/09/03 23:34:09 steve
* Support synchronous set of LPM_FF devices. * Support synchronous set of LPM_FF devices.
* *

View File

@ -2,7 +2,7 @@
FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog
Copyright 2001 Stephen Williams Copyright 2001 Stephen Williams
$Id: fpga.txt,v 1.11 2003/08/07 05:17:34 steve Exp $ $Id: fpga.txt,v 1.11.2.1 2005/02/19 16:39:32 steve Exp $
The FPGA code generator supports a variety of FPGA devices, writing The FPGA code generator supports a variety of FPGA devices, writing
XNF or EDIF depending on the target. You can select the architecture XNF or EDIF depending on the target. You can select the architecture
@ -44,7 +44,7 @@ map to target gates if desired.
If this is selected, then the output is formatted as an XNF file, If this is selected, then the output is formatted as an XNF file,
suitable for most any type of device. The devices that it emits suitable for most any type of device. The devices that it emits
are generic devices from the unified library. Some devices are macros, are generic devices from the unified library. Some devices are macros,
youmay need to further resolve the generated XNF to get working you may need to further resolve the generated XNF to get working
code for your part. code for your part.
* arch=virtex * arch=virtex
@ -188,6 +188,9 @@ Compile a single-file design with command line tools like so:
--- ---
$Log: fpga.txt,v $ $Log: fpga.txt,v $
Revision 1.11.2.1 2005/02/19 16:39:32 steve
Spellig fixes.
Revision 1.11 2003/08/07 05:17:34 steve Revision 1.11 2003/08/07 05:17:34 steve
Add arch=lpm to the documentation. Add arch=lpm to the documentation.

6
tgt-stub/stub-s.conf Normal file
View File

@ -0,0 +1,6 @@
functor:synth2
functor:synth
functor:syn-rules
functor:cprop
functor:nodangle
-t:dll

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.90 2004/10/04 01:10:57 steve Exp $" #ident "$Id: stub.c,v 1.90.2.2 2005/08/28 17:37:28 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -244,6 +244,23 @@ static void show_lpm(ivl_lpm_t net)
break; break;
} }
case IVL_LPM_CMP_GE: {
fprintf(out, " LPM_COMPARE(GE) %s: <width=%u>\n",
ivl_lpm_basename(net), width);
fprintf(out, " Q: %s\n", ivl_nexus_name(ivl_lpm_q(net, 0)));
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_data(net, idx);
fprintf(out, " Data A %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
for (idx = 0 ; idx < width ; idx += 1) {
ivl_nexus_t nex = ivl_lpm_datab(net, idx);
fprintf(out, " Data B %u: %s\n", idx,
nex? ivl_nexus_name(nex) : "");
}
break;
}
case IVL_LPM_SHIFTL: { case IVL_LPM_SHIFTL: {
fprintf(out, " LPM_SHIFTL %s: <width=%u, selects=%u %s>\n", fprintf(out, " LPM_SHIFTL %s: <width=%u, selects=%u %s>\n",
ivl_lpm_basename(net), width, ivl_lpm_selects(net), ivl_lpm_basename(net), width, ivl_lpm_selects(net),
@ -807,6 +824,10 @@ static void show_logic(ivl_net_logic_t net)
name, name,
ivl_nexus_name(ivl_logic_pin(net, 0))); ivl_nexus_name(ivl_logic_pin(net, 0)));
break; break;
case IVL_LO_NOR:
fprintf(out, " nor %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0)));
break;
case IVL_LO_OR: case IVL_LO_OR:
fprintf(out, " or %s (%s", name, fprintf(out, " or %s (%s", name,
ivl_nexus_name(ivl_logic_pin(net, 0))); ivl_nexus_name(ivl_logic_pin(net, 0)));
@ -822,7 +843,8 @@ static void show_logic(ivl_net_logic_t net)
break; break;
default: default:
fprintf(out, " unsupported gate %s (%s", name, fprintf(out, " unsupported gate(%u) %s (%s",
ivl_logic_type(net), name,
ivl_nexus_name(ivl_logic_pin(net, 0))); ivl_nexus_name(ivl_logic_pin(net, 0)));
break; break;
} }
@ -953,6 +975,12 @@ int target_design(ivl_design_t des)
/* /*
* $Log: stub.c,v $ * $Log: stub.c,v $
* Revision 1.90.2.2 2005/08/28 17:37:28 steve
* Dump CMP_GE devices.
*
* Revision 1.90.2.1 2005/08/21 22:27:57 steve
* Display NOR gates.
*
* Revision 1.90 2004/10/04 01:10:57 steve * Revision 1.90 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

3
tgt-stub/stub.conf Normal file
View File

@ -0,0 +1,3 @@
functor:cprop
functor:nodangle
-t:dll

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.22 2004/02/10 19:25:01 steve Exp $" #ident "$Id: Makefile.in,v 1.22.2.1 2005/02/23 18:40:24 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -80,6 +80,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
check: all check: all

View File

@ -3,7 +3,7 @@ THE VVP TARGET
SYMBOL NAME CONVENTIONS SYMBOL NAME CONVENTIONS
There are some naming conventions that the vp target uses for There are some naming conventions that the vvp target uses for
generating symbol names. generating symbol names.
* wires and regs * wires and regs

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_process.c,v 1.93 2004/10/04 01:10:57 steve Exp $" #ident "$Id: vvp_process.c,v 1.93.2.2 2005/01/28 18:29:29 steve Exp $"
#endif #endif
# include "vvp_priv.h" # include "vvp_priv.h"
@ -161,18 +161,39 @@ static void assign_to_memory(ivl_memory_t mem, unsigned idx,
* This function, in addition to setting the value into index 0, sets * This function, in addition to setting the value into index 0, sets
* bit 4 to 1 if the value is unknown. * bit 4 to 1 if the value is unknown.
*/ */
void draw_eval_expr_into_integer(ivl_expr_t expr, unsigned ix)
{
struct vector_info vec;
int word;
switch (ivl_expr_value(expr)) {
case IVL_VT_VECTOR:
vec = draw_eval_expr(expr, 0);
fprintf(vvp_out, " %%ix/get %u, %u, %u;\n",
ix, vec.base, vec.wid);
clr_vector(vec);
break;
case IVL_VT_REAL:
word = draw_eval_real(expr);
clr_word(word);
fprintf(vvp_out, " %%cvt/ir %u, %u;\n", ix, word);
break;
default:
assert(0);
}
}
static void calculate_into_x0(ivl_expr_t expr) static void calculate_into_x0(ivl_expr_t expr)
{ {
struct vector_info vec = draw_eval_expr(expr, 0); draw_eval_expr_into_integer(expr, 0);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", vec.base, vec.wid);
clr_vector(vec);
} }
static void calculate_into_x1(ivl_expr_t expr) static void calculate_into_x1(ivl_expr_t expr)
{ {
struct vector_info vec = draw_eval_expr(expr, 0); draw_eval_expr_into_integer(expr, 1);
fprintf(vvp_out, " %%ix/get 1, %u, %u;\n", vec.base, vec.wid);
clr_vector(vec);
} }
/* /*
@ -429,7 +450,7 @@ static int show_stmt_assign(ivl_statement_t net)
* This function handles the case of non-blocking assign to word * This function handles the case of non-blocking assign to word
* variables such as real, i.e: * variables such as real, i.e:
* *
* read foo; * real foo;
* foo <= 1.0; * foo <= 1.0;
* *
* In this case we know (by Verilog syntax) that there is only exactly * In this case we know (by Verilog syntax) that there is only exactly
@ -467,6 +488,8 @@ static int show_stmt_assign_nb_var(ivl_statement_t net)
fprintf(vvp_out, " %%assign/wr W_%s, %lu, %u;\n", fprintf(vvp_out, " %%assign/wr W_%s, %lu, %u;\n",
vvp_word_label(var), delay, word); vvp_word_label(var), delay, word);
clr_word(word);
return 0; return 0;
} }
@ -1626,6 +1649,12 @@ int draw_func_definition(ivl_scope_t scope)
/* /*
* $Log: vvp_process.c,v $ * $Log: vvp_process.c,v $
* Revision 1.93.2.2 2005/01/28 18:29:29 steve
* Add ability to compile real values into index registers.
*
* Revision 1.93.2.1 2004/12/12 04:25:10 steve
* Fix leak of word registers in code generator.
*
* Revision 1.93 2004/10/04 01:10:57 steve * Revision 1.93 2004/10/04 01:10:57 steve
* Clean up spurious trailing white space. * Clean up spurious trailing white space.
* *

7
util.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: util.h,v 1.7 2004/02/20 18:53:36 steve Exp $" #ident "$Id: util.h,v 1.7.2.1 2005/08/13 00:45:55 steve Exp $"
#endif #endif
# include <map> # include <map>
@ -44,13 +44,16 @@ struct attrib_list_t {
verinum val; verinum val;
}; };
extern attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att, extern attrib_list_t* evaluate_attributes(const std::map<perm_string,PExpr*>&att,
unsigned&natt, unsigned&natt,
const Design*des, const Design*des,
const NetScope*scope); const NetScope*scope);
/* /*
* $Log: util.h,v $ * $Log: util.h,v $
* Revision 1.7.2.1 2005/08/13 00:45:55 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.7 2004/02/20 18:53:36 steve * Revision 1.7 2004/02/20 18:53:36 steve
* Addtrbute keys are perm_strings. * Addtrbute keys are perm_strings.
* *

View File

@ -1,10 +1,10 @@
Summary: Icarus Verilog Summary: Icarus Verilog
Name: verilog Name: verilog
Version: 0.8 Version: 0.8.2
Release: 0 Release: 0
Copyright: GPL Copyright: GPL
Group: Applications/Engineering Group: Applications/Engineering
Source: ftp://icarus.com/pub/eda/verilog/v0.8/verilog-0.8.tar.gz Source: ftp://icarus.com/pub/eda/verilog/v0.8/verilog-0.8.2.tar.gz
URL: http://www.icarus.com/eda/verilog/index.html URL: http://www.icarus.com/eda/verilog/index.html
Packager: Stephen Williams <steve@icarus.com> Packager: Stephen Williams <steve@icarus.com>
@ -22,7 +22,7 @@ engineering formats, including simulation. It strives to be true
to the IEEE-1364 standard. to the IEEE-1364 standard.
%prep %prep
%setup -n verilog-0.8 %setup -n verilog-0.8.2
%build %build
%ifarch x86_64 %ifarch x86_64
@ -59,6 +59,9 @@ make prefix=$RPM_BUILD_ROOT/usr install
%attr(-,root,root) /usr/lib/ivl/fpga.tgt %attr(-,root,root) /usr/lib/ivl/fpga.tgt
%attr(-,root,root) /usr/lib/ivl/fpga.conf %attr(-,root,root) /usr/lib/ivl/fpga.conf
%attr(-,root,root) /usr/lib/ivl/fpga-s.conf %attr(-,root,root) /usr/lib/ivl/fpga-s.conf
%attr(-,root,root) /usr/lib/ivl/edif.tgt
%attr(-,root,root) /usr/lib/ivl/edif.conf
%attr(-,root,root) /usr/lib/ivl/edif-s.conf
%attr(-,root,root) /usr/lib/ivl/xnf.conf %attr(-,root,root) /usr/lib/ivl/xnf.conf
%attr(-,root,root) /usr/lib/ivl/xnf-s.conf %attr(-,root,root) /usr/lib/ivl/xnf-s.conf
%ifarch x86_64 %ifarch x86_64

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: verinum.cc,v 1.43 2004/05/18 18:43:15 steve Exp $" #ident "$Id: verinum.cc,v 1.43.2.1 2005/08/13 00:45:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -41,7 +41,7 @@ verinum::verinum(const V*bits, unsigned nbits, bool has_len)
} }
} }
verinum::verinum(const string&str) verinum::verinum(const std::string&str)
: has_len_(true), has_sign_(false), string_flag_(true) : has_len_(true), has_sign_(false), string_flag_(true)
{ {
nbits_ = str.length() * 8; nbits_ = str.length() * 8;
@ -257,7 +257,7 @@ signed long verinum::as_long() const
return val; return val;
} }
string verinum::as_string() const std::string verinum::as_string() const
{ {
assert( nbits_%8 == 0 ); assert( nbits_%8 == 0 );
if (nbits_ == 0) if (nbits_ == 0)
@ -283,7 +283,7 @@ string verinum::as_string() const
} }
tmp[nbits_/8] = 0; tmp[nbits_/8] = 0;
string result = string(tmp); std::string result = std::string(tmp);
delete[]tmp; delete[]tmp;
return result; return result;
} }
@ -370,7 +370,7 @@ verinum trim_vnum(const verinum&that)
return tmp; return tmp;
} }
ostream& operator<< (ostream&o, verinum::V v) std::ostream& operator<< (std::ostream&o, verinum::V v)
{ {
switch (v) { switch (v) {
case verinum::V0: case verinum::V0:
@ -393,7 +393,7 @@ ostream& operator<< (ostream&o, verinum::V v)
* This operator is used by various dumpers to write the verilog * This operator is used by various dumpers to write the verilog
* number in a Verilog format. * number in a Verilog format.
*/ */
ostream& operator<< (ostream&o, const verinum&v) std::ostream& operator<< (std::ostream&o, const verinum&v)
{ {
if (v.is_string()) { if (v.is_string()) {
o << "\"" << v.as_string() << "\""; o << "\"" << v.as_string() << "\"";
@ -942,6 +942,9 @@ verinum::V operator ^ (verinum::V l, verinum::V r)
/* /*
* $Log: verinum.cc,v $ * $Log: verinum.cc,v $
* Revision 1.43.2.1 2005/08/13 00:45:55 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.43 2004/05/18 18:43:15 steve * Revision 1.43 2004/05/18 18:43:15 steve
* Handle null string as a single nul character. * Handle null string as a single nul character.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: verinum.h,v 1.26 2004/02/17 06:52:55 steve Exp $" #ident "$Id: verinum.h,v 1.26.2.2 2005/08/13 00:45:55 steve Exp $"
#endif #endif
# include <string> # include <string>
@ -31,6 +31,8 @@
class ostream; class ostream;
#endif #endif
using namespace std;
/* /*
* Numbers in Verilog are multibit strings, where each bit has 4 * Numbers in Verilog are multibit strings, where each bit has 4
* possible values: 0, 1, x or z. The verinum number is store in * possible values: 0, 1, x or z. The verinum number is store in
@ -43,7 +45,7 @@ class verinum {
enum V { V0 = 0, V1, Vx, Vz }; enum V { V0 = 0, V1, Vx, Vz };
verinum(); verinum();
verinum(const string&str); verinum(const std::string&);
verinum(const V*v, unsigned nbits, bool has_len =true); verinum(const V*v, unsigned nbits, bool has_len =true);
verinum(V, unsigned nbits =1, bool has_len =true); verinum(V, unsigned nbits =1, bool has_len =true);
verinum(unsigned long val, unsigned bits); verinum(unsigned long val, unsigned bits);
@ -90,7 +92,7 @@ class verinum {
unsigned long as_ulong() const; unsigned long as_ulong() const;
signed long as_long() const; signed long as_long() const;
string as_string() const; std::string as_string() const;
private: private:
V* bits_; V* bits_;
@ -107,8 +109,8 @@ class verinum {
needed to accurately represent the contained value, signed or not. */ needed to accurately represent the contained value, signed or not. */
extern verinum trim_vnum(const verinum&); extern verinum trim_vnum(const verinum&);
extern ostream& operator<< (ostream&, const verinum&); extern std::ostream& operator<< (std::ostream&, const verinum&);
extern ostream& operator<< (ostream&, verinum::V); extern std::ostream& operator<< (std::ostream&, verinum::V);
extern verinum::V operator | (verinum::V l, verinum::V r); extern verinum::V operator | (verinum::V l, verinum::V r);
extern verinum::V operator & (verinum::V l, verinum::V r); extern verinum::V operator & (verinum::V l, verinum::V r);
@ -147,6 +149,12 @@ extern verinum v_not(const verinum&left);
/* /*
* $Log: verinum.h,v $ * $Log: verinum.h,v $
* Revision 1.26.2.2 2005/08/13 00:45:55 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.26.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.26 2004/02/17 06:52:55 steve * Revision 1.26 2004/02/17 06:52:55 steve
* Support unsigned divide of huge numbers. * Support unsigned divide of huge numbers.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: verireal.cc,v 1.15 2004/06/04 23:33:51 steve Exp $" #ident "$Id: verireal.cc,v 1.15.2.1 2005/08/13 00:45:55 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -124,7 +124,7 @@ verireal operator- (const verireal&l)
return res; return res;
} }
ostream& operator<< (ostream&out, const verireal&v) std::ostream& operator<< (std::ostream&out, const verireal&v)
{ {
out << v.value_; out << v.value_;
return out; return out;
@ -132,6 +132,9 @@ ostream& operator<< (ostream&out, const verireal&v)
/* /*
* $Log: verireal.cc,v $ * $Log: verireal.cc,v $
* Revision 1.15.2.1 2005/08/13 00:45:55 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.15 2004/06/04 23:33:51 steve * Revision 1.15 2004/06/04 23:33:51 steve
* Add unary minus as operator supported by verireal. * Add unary minus as operator supported by verireal.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: verireal.h,v 1.10 2004/06/04 23:33:51 steve Exp $" #ident "$Id: verireal.h,v 1.10.2.2 2005/08/13 00:45:55 steve Exp $"
#endif #endif
#ifdef HAVE_IOSFWD #ifdef HAVE_IOSFWD
@ -28,6 +28,8 @@
class ostream; class ostream;
#endif #endif
using namespace std;
class verinum; class verinum;
/* /*
@ -39,7 +41,7 @@ class verinum;
class verireal { class verireal {
friend ostream& operator<< (ostream&, const verireal&); friend std::ostream& operator<< (std::ostream&, const verireal&);
friend verireal operator* (const verireal&, const verireal&); friend verireal operator* (const verireal&, const verireal&);
friend verireal operator/ (const verireal&, const verireal&); friend verireal operator/ (const verireal&, const verireal&);
friend verireal operator/ (const verireal&, const verinum&); friend verireal operator/ (const verireal&, const verinum&);
@ -68,7 +70,7 @@ class verireal {
double value_; double value_;
}; };
extern ostream& operator<< (ostream&, const verireal&); extern std::ostream& operator<< (std::ostream&, const verireal&);
extern verireal operator* (const verireal&, const verireal&); extern verireal operator* (const verireal&, const verireal&);
extern verireal operator/ (const verireal&, const verireal&); extern verireal operator/ (const verireal&, const verireal&);
extern verireal operator/ (const verireal&, const verinum&); extern verireal operator/ (const verireal&, const verinum&);
@ -78,6 +80,12 @@ extern verireal operator- (const verireal&);
/* /*
* $Log: verireal.h,v $ * $Log: verireal.h,v $
* Revision 1.10.2.2 2005/08/13 00:45:55 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.10.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.10 2004/06/04 23:33:51 steve * Revision 1.10 2004/06/04 23:33:51 steve
* Add unary minus as operator supported by verireal. * Add unary minus as operator supported by verireal.
* *

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.58 2004/10/04 01:09:22 steve Exp $" #ident "$Id: Makefile.in,v 1.58.2.1 2005/02/23 18:40:24 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -112,6 +112,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile rm -f Makefile
rm -rf autom4te.cache
install: all installdirs $(vpidir)/system.vpi $(libdir)/ivl/system.sft $(INSTALL32) install: all installdirs $(vpidir)/system.vpi $(libdir)/ivl/system.sft $(INSTALL32)

View File

@ -655,8 +655,8 @@ if((lt)&&(lt->numfacs))
lt->zfacname_predec_size = lt->zpackcount; lt->zfacname_predec_size = lt->zpackcount;
gzclose(lt->zhandle); gzclose(lt->zhandle);
fseek(lt->handle, 0L, SEEK_END); fseeko(lt->handle, 0L, SEEK_END);
lt->position=ftell(lt->handle); lt->position=ftello(lt->handle);
lt->zfacname_size = lt->position - lt->zfacname_size; lt->zfacname_size = lt->position - lt->zfacname_size;
lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9"); lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");
@ -681,8 +681,8 @@ if((lt)&&(lt->numfacs))
} }
gzclose(lt->zhandle); gzclose(lt->zhandle);
fseek(lt->handle, 0L, SEEK_END); fseeko(lt->handle, 0L, SEEK_END);
lt->position=ftell(lt->handle); lt->position=ftello(lt->handle);
lt->zfacgeometry_size = lt->position - lt->facgeometry_offset; lt->zfacgeometry_size = lt->position - lt->facgeometry_offset;
if(is_interlaced_trace) if(is_interlaced_trace)
@ -696,8 +696,8 @@ if((lt)&&(lt->numfacs))
} }
gzclose(lt->zhandle); lt->zhandle = NULL; gzclose(lt->zhandle); lt->zhandle = NULL;
fseek(lt->handle, 0L, SEEK_END); fseeko(lt->handle, 0L, SEEK_END);
lt->position=ftell(lt->handle); lt->position=ftello(lt->handle);
lt->zsync_table_size = lt->position - lt->sync_table_offset; lt->zsync_table_size = lt->position - lt->sync_table_offset;
} }
} }
@ -706,7 +706,7 @@ if((lt)&&(lt->numfacs))
/* /*
* initialize the trace and get back and lt context * initialize the trace and get back an lt context
*/ */
struct lt_trace *lt_init(const char *name) struct lt_trace *lt_init(const char *name)
{ {
@ -1002,8 +1002,8 @@ for(i=0;i<lt->num_dict_entries;i++)
} }
gzclose(lt->zhandle); gzclose(lt->zhandle);
fseek(lt->handle, 0L, SEEK_END); fseeko(lt->handle, 0L, SEEK_END);
lt->position=ftell(lt->handle); lt->position=ftello(lt->handle);
lt->zdictionary_size = lt->position - lt->zdictionary_size; lt->zdictionary_size = lt->position - lt->zdictionary_size;
free(lt->sorted_dict); lt->sorted_dict = NULL; free(lt->sorted_dict); lt->sorted_dict = NULL;
@ -1057,8 +1057,8 @@ if(lt)
case LT_ZMODE_BZIP2: BZ2_bzclose(lt->zhandle); break; case LT_ZMODE_BZIP2: BZ2_bzclose(lt->zhandle); break;
} }
lt->zhandle = NULL; lt->zhandle = NULL;
fseek(lt->handle, 0L, SEEK_END); fseeko(lt->handle, 0L, SEEK_END);
lt->position=ftell(lt->handle); lt->position=ftello(lt->handle);
lt_set_zmode(lt, LT_ZMODE_NONE); lt_set_zmode(lt, LT_ZMODE_NONE);
lt->zchg_table_size = lt->position - lt->change_field_offset; lt->zchg_table_size = lt->position - lt->change_field_offset;
@ -1132,8 +1132,8 @@ if(lt)
} }
gzclose(lt->zhandle); lt->zhandle = NULL; gzclose(lt->zhandle); lt->zhandle = NULL;
fseek(lt->handle, 0L, SEEK_END); fseeko(lt->handle, 0L, SEEK_END);
lt->position=ftell(lt->handle); lt->position=ftello(lt->handle);
lt->ztime_table_size = lt->position - lt->ztime_table_size; lt->ztime_table_size = lt->position - lt->ztime_table_size;
} }
@ -1609,7 +1609,7 @@ int i;
len--; len--;
for(i=0;i<len;i++) for(i=0;i<=len;i++)
{ {
*(p++) = '0' | ((value & (1<<(len-i)))!=0); *(p++) = '0' | ((value & (1<<(len-i)))!=0);
} }
@ -1642,11 +1642,15 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
if((len>1)&&(len<=32)) if((len>1)&&(len<=32))
{ {
int ivalue = value; int ivalue = value;
int delta1, delta2;
s->clk_mask <<= 1; s->clk_mask <<= 1;
s->clk_mask |= 1; s->clk_mask |= 1;
if(((s->clk_mask&0x1f)==0x1f) && ((ivalue - s->clk_prevval1)==(s->clk_prevval1 - s->clk_prevval3)) && if( ((s->clk_mask&0x1f)==0x1f) &&
((s->clk_prevval - s->clk_prevval2)==(s->clk_prevval2 - s->clk_prevval4))) ( (delta1=(ivalue - s->clk_prevval1) & lt_optimask[s->len]) == ((s->clk_prevval1 - s->clk_prevval3) & lt_optimask[s->len]) ) &&
( (delta2=(s->clk_prevval - s->clk_prevval2) & lt_optimask[s->len]) == ((s->clk_prevval2 - s->clk_prevval4) & lt_optimask[s->len]) ) &&
( (delta1==delta2) || ((!delta1)&&(!delta2)) )
)
{ {
if(s->clk_prevtrans==ULLDescriptor(~0)) if(s->clk_prevtrans==ULLDescriptor(~0))
{ {
@ -2247,6 +2251,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
int ivalue = 0; int ivalue = 0;
int i; int i;
char *pnt = value; char *pnt = value;
int delta1, delta2;
for(i=0;i<len;i++) for(i=0;i<len;i++)
{ {
@ -2271,8 +2276,11 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
s->clk_mask <<= 1; s->clk_mask <<= 1;
s->clk_mask |= legal; s->clk_mask |= legal;
if(((s->clk_mask&0x1f)==0x1f) && ((ivalue - s->clk_prevval1)==(s->clk_prevval1 - s->clk_prevval3)) && if( ((s->clk_mask&0x1f)==0x1f) &&
((s->clk_prevval - s->clk_prevval2)==(s->clk_prevval2 - s->clk_prevval4))) ( (delta1=(ivalue - s->clk_prevval1) & lt_optimask[s->len]) == ((s->clk_prevval1 - s->clk_prevval3) & lt_optimask[s->len]) ) &&
( (delta2=(s->clk_prevval - s->clk_prevval2) & lt_optimask[s->len]) == ((s->clk_prevval2 - s->clk_prevval4) & lt_optimask[s->len]) ) &&
( (delta1==delta2) || ((!delta1)&&(!delta2)) )
)
{ {
if(s->clk_prevtrans==ULLDescriptor(~0)) if(s->clk_prevtrans==ULLDescriptor(~0))
{ {

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: sys_fileio.c,v 1.5 2004/08/24 16:16:23 steve Exp $" #ident "$Id: sys_fileio.c,v 1.5.2.1 2005/01/01 20:07:41 steve Exp $"
#endif #endif
# include "vpi_user.h" # include "vpi_user.h"
@ -52,28 +52,16 @@ static int sys_fopen_calltf(char *name)
argv = 0; argv = 0;
} }
if (! is_constant(item)) {
vpi_printf("ERROR: %s parameter must be a constant\n", name);
vpi_free_object(argv);
return 0;
}
if (vpi_get(vpiConstType, item) != vpiStringConst) {
vpi_printf("ERROR: %s parameter must be a string.\n", name);
vpi_free_object(argv);
return 0;
}
if (mode) { if (mode) {
if (! is_constant(mode)) { if (! is_constant(mode)) {
vpi_printf("ERROR: %s parameter must be a constant\n", name); vpi_printf("ERROR: %s parameter must be a constant\n", name);
vpi_free_object(argv); if (argv) vpi_free_object(argv);
return 0; return 0;
} }
if (vpi_get(vpiConstType, mode) != vpiStringConst) { if (vpi_get(vpiConstType, mode) != vpiStringConst) {
vpi_printf("ERROR: %s parameter must be a string.\n", name); vpi_printf("ERROR: %s parameter must be a string.\n", name);
vpi_free_object(argv); if (argv) vpi_free_object(argv);
return 0; return 0;
} }
value.format = vpiStringVal; value.format = vpiStringVal;
@ -81,9 +69,20 @@ static int sys_fopen_calltf(char *name)
mode_string = strdup(value.value.str); mode_string = strdup(value.value.str);
} }
/* Get the string form of the file name from the file name
argument. */
value.format = vpiStringVal; value.format = vpiStringVal;
vpi_get_value(item, &value); vpi_get_value(item, &value);
if ((value.format != vpiStringVal) || !value.value.str) {
vpi_printf("ERROR: %s: File name argument (type=%d)"
" does not have a string value\n",
name, vpi_get(vpiType, item));
if (mode) free(mode_string);
if (argv) vpi_free_object(argv);
return 0;
}
value.format = vpiIntVal; value.format = vpiIntVal;
if (mode) { if (mode) {
value.value.integer = vpi_fopen(value.value.str, mode_string); value.value.integer = vpi_fopen(value.value.str, mode_string);
@ -480,6 +479,9 @@ void sys_fileio_register()
/* /*
* $Log: sys_fileio.c,v $ * $Log: sys_fileio.c,v $
* Revision 1.5.2.1 2005/01/01 20:07:41 steve
* More robust handling of file name argument to $fopen.
*
* Revision 1.5 2004/08/24 16:16:23 steve * Revision 1.5 2004/08/24 16:16:23 steve
* Fix read count passed to fgets. * Fix read count passed to fgets.
* *

View File

@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.8 2004/02/10 19:25:01 steve Exp $" #ident "$Id: Makefile.in,v 1.8.2.1 2005/02/23 18:40:24 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -80,6 +80,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
install:: all installdirs \ install:: all installdirs \
$(libdir)/libvpip.a \ $(libdir)/libvpip.a \

View File

@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330 # 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA # Boston, MA 02111-1307, USA
# #
#ident "$Id: Makefile.in,v 1.61 2004/10/04 01:09:52 steve Exp $" #ident "$Id: Makefile.in,v 1.61.2.1 2005/02/23 18:40:24 steve Exp $"
# #
# #
SHELL = /bin/sh SHELL = /bin/sh
@ -72,6 +72,7 @@ clean:
distclean: clean distclean: clean
rm -f Makefile config.status config.log config.cache config.h rm -f Makefile config.status config.log config.cache config.h
rm -rf autom4te.cache
check: all check: all
./vvp -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.' ./vvp -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.'

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2001 Stephen Williams (steve@icarus.com) * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
* *
* $Id: README.txt,v 1.47 2004/10/04 01:10:58 steve Exp $ * $Id: README.txt,v 1.47.2.2 2005/02/23 18:37:52 steve Exp $
*/ */
VVP SIMULATION ENGINE VVP SIMULATION ENGINE
@ -55,7 +55,7 @@ compiler scales time values ahead of time.
The value is the size of a simulation tick in seconds, and is The value is the size of a simulation tick in seconds, and is
expressed as a power of 10. For example, +0 is 1 second, and -9 is 1 expressed as a power of 10. For example, +0 is 1 second, and -9 is 1
nano-second. If the record is left out, then the precision is taken to nanosecond. If the record is left out, then the precision is taken to
be +0. be +0.
LABELS AND SYMBOLS LABELS AND SYMBOLS
@ -283,7 +283,7 @@ statement, it creates no functors. The symbol list is a list of
functors that feed into each bit of the vector, and the vpiHandle functors that feed into each bit of the vector, and the vpiHandle
holds references to those functors that are fed it. holds references to those functors that are fed it.
The <label> is required and is used to locate the net object that is The <label> is required and is used to locate the net object that it
represents. This label does not map to a functor, so only references represents. This label does not map to a functor, so only references
that know they want to access .nets are able to locate the symbol. In that know they want to access .nets are able to locate the symbol. In
particular, this includes behavioral %load and %wait instructions. The particular, this includes behavioral %load and %wait instructions. The
@ -312,7 +312,7 @@ second word.
Structural read access is implemented in terms of address and data Structural read access is implemented in terms of address and data
ports. The addresses applied to the address port are expected to be ports. The addresses applied to the address port are expected to be
withing the ranges specified, not based at zero. within the ranges specified, not based at zero.
A read port is a vector of functors that is wide enough to accept all A read port is a vector of functors that is wide enough to accept all
provided address bits and at least as wide as the requested subset of provided address bits and at least as wide as the requested subset of
@ -381,12 +381,11 @@ EVENT STATEMENTS
Threads need to interact with the functors of a netlist synchronously, Threads need to interact with the functors of a netlist synchronously,
as well as asynchronously. There are cases where the web of functors as well as asynchronously. There are cases where the web of functors
needs to wake up a waiting thread. The web of functors signals threads needs to wake up a waiting thread. The web of functors signals threads
through .event objects, that are declare like so: through .event objects, that are declared like so:
<label> .event <type>, <symbols_list>; <label> .event <type>, <symbols_list>;
<label> .event "name"; <label> .event "name";
This event statement declares an object that a %wait instruction This event statement declares an object that a %wait instruction
can take as an operand. When a thread executes a %wait, it puts can take as an operand. When a thread executes a %wait, it puts
itself in the notification list of the event and suspends. The itself in the notification list of the event and suspends. The
@ -509,9 +508,9 @@ similar:
Whereas the arithmetic statements create an array of functor outputs, Whereas the arithmetic statements create an array of functor outputs,
there is only one useful functor output for the comparators. That there is only one useful functor output for the comparators. That
functor output is 1 1f the comparison is true, 0 if false, and x functor output is 1 if the comparison is true, 0 if false, and x
otherwise. The plain versions do unsigned comparison, but the ".s" otherwise. The plain versions do unsigned comparison, but the ".s"
versions to signed comparisons. (Eqlality doesn't need to care about versions do signed comparison. (Equality doesn't need to care about
sign.) sign.)
@ -742,7 +741,7 @@ compile.cc. This function in turn calls all the *_init() functions in
other parts of the source that need initialization for compile. All other parts of the source that need initialization for compile. All
the various sub-init functions are called <foo>_init(). the various sub-init functions are called <foo>_init().
Compilation is controlled by the parser, it parse.y. As the parser Compilation is controlled by the parser, in parse.y. As the parser
reads and parses input, the compilation proceeds in the rules by reads and parses input, the compilation proceeds in the rules by
calling various compile_* functions. All these functions live in the calling various compile_* functions. All these functions live in the
compile.cc file. Compilation calls other sections of the code as compile.cc file. Compilation calls other sections of the code as

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
* *
* $Id: opcodes.txt,v 1.55 2004/06/19 15:52:53 steve Exp $ * $Id: opcodes.txt,v 1.55.2.1 2005/02/19 16:39:32 steve Exp $
*/ */
@ -193,7 +193,7 @@ Only bit 4 is set by these instructions.
* %cvt/vr <bit-l>, <bit-r>, <wid> * %cvt/vr <bit-l>, <bit-r>, <wid>
Copy a word from r to l, converting it from real to integer (ir) or Copy a word from r to l, converting it from real to integer (ir) or
integer to real (ri) in the process. The source and destinaition may integer to real (ri) in the process. The source and destination may
be the same word address, leading to a convert in place. be the same word address, leading to a convert in place.
The %cvt/vr opcode converts a real word <bit-r> to a thread vector The %cvt/vr opcode converts a real word <bit-r> to a thread vector