Compare commits
42 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
05e6d51004 | |
|
|
ae583204e3 | |
|
|
018476f7cd | |
|
|
bfabeab6b9 | |
|
|
4a3f1a3641 | |
|
|
d97560caa7 | |
|
|
393102d43a | |
|
|
8e97a0e4d4 | |
|
|
4ea789a2d7 | |
|
|
354f7ad920 | |
|
|
f4a6206790 | |
|
|
fd29ba3398 | |
|
|
44fbf60885 | |
|
|
a0d69113c3 | |
|
|
86942ac592 | |
|
|
075f9cbc4b | |
|
|
9dab368880 | |
|
|
5f6027fb66 | |
|
|
53156793fe | |
|
|
4644c220e8 | |
|
|
c30cd9afea | |
|
|
a8f45a18f0 | |
|
|
6828e3e2ea | |
|
|
75eb372adf | |
|
|
3b753fe52b | |
|
|
8c73fa7840 | |
|
|
d310e656c7 | |
|
|
0510367b70 | |
|
|
3e11207a56 | |
|
|
665f31271f | |
|
|
9a2b56675c | |
|
|
c9f38f5ffa | |
|
|
5ea4152162 | |
|
|
327c897d7e | |
|
|
29ebe486b7 | |
|
|
4af0acb3be | |
|
|
8435774c26 | |
|
|
6172748c65 | |
|
|
ca0ae9040a | |
|
|
d9cdbde3f6 | |
|
|
307a97116f | |
|
|
83d2c6dfd1 |
11
LineInfo.cc
11
LineInfo.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# 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_;
|
||||
|
||||
string res = buf.str();
|
||||
std::string res = buf.str();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +61,9 @@ void LineInfo::set_lineno(unsigned n)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
|
|
|
|||
12
LineInfo.h
12
LineInfo.h
|
|
@ -19,11 +19,13 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* This class holds line information for an internal object.
|
||||
*
|
||||
|
|
@ -38,7 +40,7 @@ class LineInfo {
|
|||
LineInfo();
|
||||
~LineInfo();
|
||||
|
||||
string get_line() const;
|
||||
std::string get_line() const;
|
||||
|
||||
void set_line(const LineInfo&that);
|
||||
|
||||
|
|
@ -52,6 +54,12 @@ class LineInfo {
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -25,7 +25,7 @@ SHELL = /bin/sh
|
|||
# by the compiler. It reflects the assigned version number for the
|
||||
# product as a whole. Most components also print the CVS Name: token
|
||||
# in order to get a more automatic version stamp as well.
|
||||
VERSION = 0.8
|
||||
VERSION = 0.8.2
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
@ -103,6 +103,7 @@ distclean: clean
|
|||
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
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
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
|
||||
|
|
|
|||
9
PTask.h
9
PTask.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "LineInfo.h"
|
||||
|
|
@ -70,7 +70,7 @@ class PTask : public LineInfo {
|
|||
// Elaborate the statement to finish off the task definition.
|
||||
void elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
svector<PWire*>*ports_;
|
||||
|
|
@ -106,7 +106,7 @@ class PFunction : public LineInfo {
|
|||
/* Elaborate the behavioral statement. */
|
||||
void elaborate(Design *des, NetScope*) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
|
@ -117,6 +117,9 @@ class PFunction : public LineInfo {
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
13
PUdp.h
13
PUdp.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <map>
|
||||
|
|
@ -55,20 +55,20 @@ class PUdp {
|
|||
public:
|
||||
explicit PUdp(perm_string n, unsigned nports);
|
||||
|
||||
svector<string>ports;
|
||||
svector<std::string>ports;
|
||||
unsigned find_port(const char*name);
|
||||
|
||||
bool sequential;
|
||||
|
||||
svector<string>tinput;
|
||||
svector<std::string>tinput;
|
||||
svector<char> tcurrent;
|
||||
svector<char> toutput;
|
||||
|
||||
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_;
|
||||
private:
|
||||
|
|
@ -80,6 +80,9 @@ class PUdp {
|
|||
|
||||
/*
|
||||
* $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
|
||||
* primitive ports can bind bi name.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
most out of your install, first make sure you have both 64bit and
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "StringHeap.h"
|
||||
|
|
@ -131,7 +131,7 @@ perm_string StringHeapLex::make(const char*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()));
|
||||
}
|
||||
|
|
@ -181,6 +181,9 @@ bool operator < (perm_string a, perm_string b)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
12
StringHeap.h
12
StringHeap.h
|
|
@ -19,12 +19,14 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
# include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class perm_string {
|
||||
|
||||
public:
|
||||
|
|
@ -101,7 +103,7 @@ class StringHeapLex : private StringHeap {
|
|||
|
||||
const char*add(const char*);
|
||||
perm_string make(const char*);
|
||||
perm_string make(const string&);
|
||||
perm_string make(const std::string&);
|
||||
|
||||
unsigned add_count() const;
|
||||
unsigned add_hit_count() const;
|
||||
|
|
@ -120,6 +122,12 @@ class StringHeapLex : private StringHeap {
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
AC_DEFUN([AX_CPP_IDENT],
|
||||
[AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident,
|
||||
[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) {}],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
|
||||
|
|
@ -91,13 +91,9 @@ AC_MSG_RESULT($WIN32)
|
|||
AC_DEFUN([AX_LD_EXTRALIBS],
|
||||
[AC_MSG_CHECKING([for extra libs needed])
|
||||
EXTRALIBS=
|
||||
case "${host}" in
|
||||
*-*-cygwin* )
|
||||
if test "$MINGW32" = "yes"; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test "$MINGW32" = "yes"; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
AC_SUBST(EXTRALIBS)
|
||||
AC_MSG_RESULT($EXTRALIBS)
|
||||
])# AX_LD_EXTRALIBS
|
||||
|
|
@ -109,7 +105,7 @@ AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
|
|||
[AC_MSG_CHECKING([for shared library link flag])
|
||||
shared=-shared
|
||||
case "${host}" in
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
shared="-shared -Wl,--enable-auto-image-base"
|
||||
;;
|
||||
|
||||
|
|
@ -138,7 +134,7 @@ AC_DEFUN([AX_C_PICFLAG],
|
|||
PICFLAG=-fPIC
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
PICFLAG=
|
||||
;;
|
||||
|
||||
|
|
@ -173,7 +169,7 @@ case "${host}" in
|
|||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
echo "Autoconf in root..."
|
||||
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
|
||||
echo "Autoconf in $dir..."
|
||||
( cd ./$dir ; autoconf --include=.. )
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -86,6 +86,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,6 @@ AC_SUBST(vpidir1)
|
|||
AC_SUBST(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)
|
||||
|
|
|
|||
317
cprop.cc
317
cprop.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -47,6 +47,7 @@ struct cprop_functor : public functor_t {
|
|||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*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)
|
||||
|
|
@ -847,77 +848,298 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
*/
|
||||
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
{
|
||||
if (obj->size() > 2) {
|
||||
lpm_mux_large(des, obj);
|
||||
return;
|
||||
}
|
||||
if (obj->size() != 2)
|
||||
return;
|
||||
if (obj->sel_width() != 1)
|
||||
return;
|
||||
|
||||
/* If the first input is all constant Vz, then replace the
|
||||
NetMux with an array of BUFIF1 devices, with the enable
|
||||
connected to the select input. */
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! obj->pin_Data(idx, 0).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
bool cflag_a = obj->pin_Data(idx, 0).nexus()->drivers_constant();
|
||||
bool cflag_b = obj->pin_Data(idx, 1).nexus()->drivers_constant();
|
||||
|
||||
if (obj->pin_Data(idx, 0).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
/* If both data inputs are constant, we'll be able to do
|
||||
a substitution. */
|
||||
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) {
|
||||
NetScope*scope = obj->scope();
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
if (! flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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(),
|
||||
3, NetLogic::BUFIF1);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
count += 1;
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
/* If the Sel==1 input is constant Z, make a bufif0. */
|
||||
if (obj->pin_Data(idx, 1).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->driven_value()==verinum::Vz) {
|
||||
|
||||
/* If instead the second input is all constant Vz, replace the
|
||||
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(),
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF0);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
count += 1;
|
||||
delete obj;
|
||||
/* At this point, the only cases that are left are where
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 $
|
||||
* 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
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -54,6 +54,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
rm -rf autom4te.cache
|
||||
|
||||
O = main.o substit.o cflexor.o cfparse.o
|
||||
|
||||
|
|
|
|||
27
elab_net.cc
27
elab_net.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1312,21 +1312,25 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
|||
unsigned repeat = 1;
|
||||
|
||||
if (repeat_) {
|
||||
verinum*rep = repeat_->eval_const(des, scope);
|
||||
if (rep == 0) {
|
||||
NetExpr*etmp = elab_and_eval(des, scope, repeat_);
|
||||
assert(etmp);
|
||||
NetEConst*erep = dynamic_cast<NetEConst*>(etmp);
|
||||
|
||||
if (erep == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to "
|
||||
<< "evaluate constant repeat expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = rep->as_ulong();
|
||||
repeat = erep->value().as_ulong();
|
||||
delete etmp;
|
||||
|
||||
if (repeat == 0) {
|
||||
cerr << get_line() << ": error: Invalid repeat value."
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
"may not be 0."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete rep;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1435,6 +1439,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
|||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(), 1,
|
||||
sig_width, sel->pin_count());
|
||||
mux->set_line(*this);
|
||||
|
||||
/* Connect the signal bits to the mux. Account for the
|
||||
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. */
|
||||
|
||||
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 the data inputs. */
|
||||
|
|
@ -2513,6 +2519,15 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Fix excessive error message.
|
||||
*
|
||||
|
|
|
|||
85
eval_tree.cc
85
eval_tree.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -215,6 +215,11 @@ NetEConst* NetEBComp::eval_eqeq_()
|
|||
|
||||
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_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
|
|
@ -224,6 +229,16 @@ NetEConst* NetEBComp::eval_less_()
|
|||
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
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
|
|
@ -259,7 +274,7 @@ NetEConst* NetEBComp::eval_less_()
|
|||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_real_()
|
||||
NetEConst* NetEBComp::eval_leeq_real_(bool gt_flag, bool include_eq_flag)
|
||||
{
|
||||
NetEConst*vtmp;
|
||||
NetECReal*rtmp;
|
||||
|
|
@ -308,7 +323,16 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
|||
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->set_line(*this);
|
||||
|
||||
|
|
@ -318,9 +342,9 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
|||
NetEConst* NetEBComp::eval_leeq_()
|
||||
{
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_();
|
||||
return eval_leeq_real_(false, true);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_();
|
||||
return eval_leeq_real_(false, true);
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
|
@ -374,23 +398,10 @@ NetEConst* NetEBComp::eval_leeq_()
|
|||
|
||||
NetEConst* NetEBComp::eval_gt_()
|
||||
{
|
||||
if ((left_->expr_type() == NetExpr::ET_REAL)
|
||||
&& (right_->expr_type() == NetExpr::ET_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
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);
|
||||
}
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, false);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, false);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
|
@ -450,23 +461,10 @@ NetEConst* NetEBComp::eval_gt_()
|
|||
|
||||
NetEConst* NetEBComp::eval_gteq_()
|
||||
{
|
||||
if ((left_->expr_type() == NetExpr::ET_REAL)
|
||||
&& (right_->expr_type() == NetExpr::ET_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
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);
|
||||
}
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, true);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, true);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
|
@ -1551,6 +1549,15 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* 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
|
||||
* 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
|
||||
* generating a design for a Spartan-II XC2S15-VQ100, and also how to
|
||||
* 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
|
||||
* contains Verilog code that simulates the mapped design. This output
|
||||
* 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
|
||||
* first place. The module has ports named just line the ports of the
|
||||
* name of the root module when we were making the EDIF file in the
|
||||
* first place. The module has ports named just like the ports of the
|
||||
* chip_root module below.
|
||||
*
|
||||
* The generated Verilog uses the library in the directory
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -408,7 +408,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
|||
|
||||
default: {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "NetEBDiv has unexpeced op() code: "
|
||||
<< "NetEBDiv has unexpected op() code: "
|
||||
<< op() << endl;
|
||||
des->errors += 1;
|
||||
|
||||
|
|
@ -811,6 +811,7 @@ NetNet* NetETernary::synthesize(Design *des)
|
|||
|
||||
perm_string oname = csig->scope()->local_symbol();
|
||||
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1);
|
||||
mux->set_line(*this);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
connect(tsig->pin(idx), mux->pin_Data(idx, 1));
|
||||
connect(fsig->pin(idx), mux->pin_Data(idx, 0));
|
||||
|
|
@ -875,6 +876,12 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Implement signed divide and signed right shift in nets.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ valid options include:
|
|||
Predefine the symbol ``name'' to have the specified
|
||||
value. If the value is not specified, then ``1'' is
|
||||
used. This is mostly of use for controlling conditional
|
||||
compilaiton.
|
||||
compilation.
|
||||
|
||||
This option does *not* override existing `define
|
||||
directives in the source file.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -179,6 +179,8 @@ W [ \t\b\f\r]+
|
|||
<UDPTABLE>\(01\) { return 'r'; }
|
||||
<UDPTABLE>\(0[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>\(10\) { return 'f'; }
|
||||
<UDPTABLE>\(1[xX]\) { return 'M'; }
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -93,6 +93,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -88,7 +88,7 @@ bool load_module(const char*type)
|
|||
cerr << "Executing: " << cmdline << endl;
|
||||
|
||||
pform_parse(path, file);
|
||||
fclose(file);
|
||||
pclose(file);
|
||||
free(cmdline);
|
||||
|
||||
} else {
|
||||
|
|
@ -193,6 +193,9 @@ int build_library_index(const char*path, bool key_case_sensitive)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* INclude missing assert.h in load_module.
|
||||
*
|
||||
|
|
|
|||
45
mingw.txt
45
mingw.txt
|
|
@ -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
|
||||
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
|
||||
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
|
||||
together by hand. Normal human beings with a basic understanding of
|
||||
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.
|
||||
|
||||
|
|
@ -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.
|
||||
|
||||
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>
|
||||
bzip2-1.0.2-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
|
||||
|
||||
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
|
||||
recommend you download this package instead of picking and choosing
|
||||
bits.
|
||||
|
||||
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.
|
||||
|
||||
NOTES:
|
||||
|
|
@ -115,6 +116,10 @@ that path later.
|
|||
need Mingw32, even if you are using a precompiled binary. VPI
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
details. Run these commands:
|
||||
|
||||
$ CC=mingw32-gcc
|
||||
$ CXX=mingw32-g++
|
||||
$ CPPFLAGS="-Id:/gnuwin32/include -Id:/mingw-packages/include"
|
||||
$ LDFLAGS="-Ld:/gnuwin32/lib -Ld:/mingw-packages/include"
|
||||
$ export CPPFLAGS LDFLAGS
|
||||
$ ./configure --prefix=d:/iverilog
|
||||
$ export CPPFLAGS LDFLAGS CC CXX
|
||||
$ ./configure --prefix=d:/iverilog --host=mingw32
|
||||
|
||||
NOTES:
|
||||
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.
|
||||
|
||||
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
|
||||
tools prefer the forward slash.
|
||||
|
||||
|
|
|
|||
52
net_link.cc
52
net_link.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -407,13 +407,14 @@ void NexusSet::add(Nexus*that)
|
|||
}
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if ((ptr < nitems_) && (items_[ptr] == that))
|
||||
if (ptr < nitems_) {
|
||||
assert(items_[ptr] == that);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(ptr == nitems_);
|
||||
|
||||
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*));
|
||||
for (unsigned idx = nitems_ ; idx > ptr ; idx -= 1)
|
||||
items_[idx] = items_[idx-1];
|
||||
|
||||
items_[ptr] = that;
|
||||
nitems_ += 1;
|
||||
}
|
||||
|
|
@ -430,7 +431,7 @@ void NexusSet::rem(Nexus*that)
|
|||
return;
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if ((ptr >= nitems_) || (items_[ptr] != that))
|
||||
if (ptr >= nitems_)
|
||||
return;
|
||||
|
||||
if (nitems_ == 1) {
|
||||
|
|
@ -462,10 +463,8 @@ Nexus* NexusSet::operator[] (unsigned idx) const
|
|||
unsigned NexusSet::bsearch_(Nexus*that) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
if (items_[idx] < that)
|
||||
continue;
|
||||
|
||||
return idx;
|
||||
if (items_[idx] == that)
|
||||
return idx;
|
||||
}
|
||||
|
||||
return nitems_;
|
||||
|
|
@ -499,6 +498,9 @@ bool NexusSet::intersect(const NexusSet&that) const
|
|||
|
||||
/*
|
||||
* $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
|
||||
* 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
|
||||
* Make link_drive_constant cache its results in
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -194,7 +194,7 @@ const NetFuncDef* NetScope::func_def() const
|
|||
void NetScope::set_module_name(perm_string n)
|
||||
{
|
||||
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
|
||||
|
|
@ -467,6 +467,9 @@ string NetScope::local_hsymbol()
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
32
netlist.h
32
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
|
|
@ -60,6 +60,9 @@ class NetESignal;
|
|||
class NetEVariable;
|
||||
class NetFuncDef;
|
||||
|
||||
class NetRamDq;
|
||||
class NetEvTrig;
|
||||
class NetEvWait;
|
||||
|
||||
struct target;
|
||||
struct functor_t;
|
||||
|
|
@ -753,7 +756,7 @@ class NetMemory {
|
|||
long idxl_;
|
||||
|
||||
friend class NetRamDq;
|
||||
NetRamDq* ram_list_;
|
||||
class NetRamDq* ram_list_;
|
||||
|
||||
friend class NetScope;
|
||||
NetMemory*snext_, *sprev_;
|
||||
|
|
@ -1349,6 +1352,9 @@ class NetProc : public virtual LineInfo {
|
|||
// synthesize as asynchronous logic, and return true.
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
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,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
|
|
@ -1606,6 +1612,8 @@ class NetCase : public NetProc {
|
|||
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
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 void dump(ostream&, unsigned ind) const;
|
||||
|
|
@ -1688,6 +1696,8 @@ class NetCondit : public NetProc {
|
|||
bool is_asynchronous();
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
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,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
|
|
@ -1845,12 +1855,12 @@ class NetEvent : public LineInfo {
|
|||
NetEvProbe*probes_;
|
||||
|
||||
// Use these methods to list the triggers attached to me.
|
||||
NetEvTrig* trig_;
|
||||
class NetEvTrig* trig_;
|
||||
|
||||
// Use This member to count references by NetEvWait objects.
|
||||
unsigned waitref_;
|
||||
struct wcell_ {
|
||||
NetEvWait*obj;
|
||||
class NetEvWait*obj;
|
||||
struct wcell_*next;
|
||||
};
|
||||
struct wcell_ *wlist_;
|
||||
|
|
@ -2523,7 +2533,7 @@ class NetEBComp : public NetEBinary {
|
|||
NetEConst*eval_eqeq_();
|
||||
NetEConst*eval_less_();
|
||||
NetEConst*eval_leeq_();
|
||||
NetEConst*eval_leeq_real_();
|
||||
NetEConst*eval_leeq_real_(bool gt_flag, bool include_eq_flag);
|
||||
NetEConst*eval_gt_();
|
||||
NetEConst*eval_gteq_();
|
||||
NetEConst*eval_neeq_();
|
||||
|
|
@ -3357,6 +3367,18 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
11
parse.y
11
parse.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -990,7 +990,6 @@ expr_primary
|
|||
yyerror(@2, "error: Repeat expression "
|
||||
"must be constant.");
|
||||
delete rep;
|
||||
delete $2;
|
||||
rep = 0;
|
||||
}
|
||||
PEConcat*tmp = new PEConcat(*$4, rep);
|
||||
|
|
@ -2266,7 +2265,7 @@ specify_item
|
|||
{
|
||||
}
|
||||
| K_Shold '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Speriod '(' spec_reference_event ',' delay_value
|
||||
|
|
@ -2274,11 +2273,11 @@ specify_item
|
|||
{ delete $5;
|
||||
}
|
||||
| K_Srecovery '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Ssetup '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Ssetuphold '(' spec_reference_event ',' spec_reference_event
|
||||
|
|
@ -2296,7 +2295,7 @@ specify_item
|
|||
{ delete $5;
|
||||
delete $7;
|
||||
}
|
||||
| K_Swidth '(' spec_reference_event ',' expression ')' ';'
|
||||
| K_Swidth '(' spec_reference_event ',' delay_value ')' ';'
|
||||
{ delete $5;
|
||||
}
|
||||
;
|
||||
|
|
|
|||
11
parse_api.h
11
parse_api.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -35,8 +35,8 @@ class PUdp;
|
|||
* Verilog source into pform for elaboration. The parser adds modules
|
||||
* to these maps as it compiles modules in the verilog source.
|
||||
*/
|
||||
extern map<perm_string,Module*> pform_modules;
|
||||
extern map<perm_string,PUdp*> pform_primitives;
|
||||
extern std::map<perm_string,Module*> pform_modules;
|
||||
extern std::map<perm_string,PUdp*> pform_primitives;
|
||||
|
||||
/*
|
||||
* 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 string vl_file;
|
||||
extern std::string vl_file;
|
||||
|
||||
/*
|
||||
* $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
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
14
set_width.cc
14
set_width.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -167,12 +167,13 @@ bool NetEBDiv::set_width(unsigned w)
|
|||
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 flag;
|
||||
flag = left_->set_width(right_->expr_width());
|
||||
if (!flag)
|
||||
flag = right_->set_width(left_->expr_width());
|
||||
return (w == 1);
|
||||
}
|
||||
|
||||
|
|
@ -411,6 +412,9 @@ bool NetEUReduce::set_width(unsigned w)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Spelling patch.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
PKG="IVLver"
|
||||
NAME="verilog"
|
||||
ARCH="sparc"
|
||||
VERSION="0.7"
|
||||
VERSION="0.8"
|
||||
CATEGORY="application"
|
||||
VENDOR="Icarus.com"
|
||||
EMAIL="steve@icarus.com"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ f none bin/iverilog 0755 bin bin
|
|||
f none bin/iverilog-vpi 0755 bin bin
|
||||
f none bin/vvp 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/ivl_target.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/ivl 0755 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/ivl 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.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.sft 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/libvpi.a 0644 bin bin
|
||||
d none man 0755 bin bin
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -101,14 +101,17 @@ template <class TYPE> class svector {
|
|||
* Override the implementation of the above template for the string
|
||||
* type parameter. The initialization to nil works different here.
|
||||
*/
|
||||
inline svector<string>::svector<string>(unsigned size)
|
||||
: nitems_(size), items_(new string[size])
|
||||
template <> inline svector<std::string>::svector(unsigned size)
|
||||
: nitems_(size), items_(new std::string[size])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $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
|
||||
* Inline the svector<string> constructor.
|
||||
*
|
||||
|
|
|
|||
191
synth2.cc
191
synth2.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -47,6 +47,13 @@ bool NetProc::synth_async(Design*des, NetScope*scope,
|
|||
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,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
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 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;
|
||||
NetProc*cur = last_;
|
||||
do {
|
||||
NetNet*new_accum;
|
||||
|
||||
cur = cur->next_;
|
||||
|
||||
/* 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,
|
||||
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;
|
||||
|
||||
delete new_accum;
|
||||
|
||||
if (ok_flag == false)
|
||||
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
|
||||
substatement to the output of the block as a whole. */
|
||||
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
|
||||
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_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_);
|
||||
|
||||
/* 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)
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
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")
|
||||
unsigned cur;
|
||||
|
|
@ -227,6 +293,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
nex_out->pin_count(),
|
||||
1U << sel_pins, sel_pins);
|
||||
mux->set_line(*this);
|
||||
|
||||
/* Connect the non-constant select bits to the select input of
|
||||
the mux device. */
|
||||
|
|
@ -271,10 +338,23 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
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
|
||||
sub-statements. If I get to an input that has no statement,
|
||||
then use the default statement there. */
|
||||
NetNet*default_sig = 0;
|
||||
for (unsigned item = 0 ; item < (1U<<sel_pins) ; item += 1) {
|
||||
|
||||
/* 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) {
|
||||
/* Missing case and no default; this could still be
|
||||
* 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)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -314,53 +397,95 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
|||
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,
|
||||
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")
|
||||
NetNet*ssig = expr_->synthesize(des);
|
||||
assert(ssig);
|
||||
|
||||
if (if_ == 0) {
|
||||
DEBUG_SYNTH2_EXIT("NetCondit",false)
|
||||
return false;
|
||||
}
|
||||
if (else_ == 0) {
|
||||
cerr << get_line() << ": error: Asynchronous if statement"
|
||||
<< " is missing the else clause." << endl;
|
||||
DEBUG_SYNTH2_EXIT("NetCondit",false)
|
||||
return false;
|
||||
/* Use the accumulated input net as a default input for
|
||||
covering a missing clause, except that if I find portions
|
||||
are unconnected, then give up on that idea. */
|
||||
NetNet*default_sig = accum;
|
||||
for (unsigned idx = 0 ; idx < default_sig->pin_count() ; idx += 1) {
|
||||
if (! default_sig->pin(idx).is_linked()) {
|
||||
default_sig = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(if_ != 0);
|
||||
assert(else_ != 0);
|
||||
if (default_sig == 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::WIRE, nex_map->pin_count());
|
||||
asig->local_flag(true);
|
||||
|
||||
bool flag;
|
||||
flag = if_->synth_async(des, scope, nex_map, asig);
|
||||
if (!flag) {
|
||||
delete asig;
|
||||
DEBUG_SYNTH2_EXIT("NetCondit",false)
|
||||
return false;
|
||||
if (if_ == 0) {
|
||||
for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1)
|
||||
connect(asig->pin(idx), default_sig->pin(idx));
|
||||
|
||||
} else {
|
||||
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::WIRE, nex_map->pin_count());
|
||||
bsig->local_flag(true);
|
||||
|
||||
flag = else_->synth_async(des, scope, nex_map, bsig);
|
||||
if (!flag) {
|
||||
delete asig;
|
||||
delete bsig;
|
||||
DEBUG_SYNTH2_EXIT("NetCondit",false)
|
||||
return false;
|
||||
if (else_ == 0) {
|
||||
for (unsigned idx = 0 ; idx < asig->pin_count() ; idx += 1)
|
||||
connect(bsig->pin(idx), default_sig->pin(idx));
|
||||
|
||||
} else {
|
||||
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(),
|
||||
nex_out->pin_count(), 2, 1);
|
||||
mux->set_line(*this);
|
||||
|
||||
connect(mux->pin_Sel(0), ssig->pin(0));
|
||||
|
||||
|
|
@ -375,7 +500,6 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
|||
|
||||
des->add_node(mux);
|
||||
|
||||
DEBUG_SYNTH2_EXIT("NetCondit",true)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -985,6 +1109,15 @@ void synth2(Design*des)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
9
t-dll.cc
9
t-dll.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1104,7 +1104,7 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
|||
obj->type = IVL_LPM_SUB;
|
||||
else
|
||||
obj->type = IVL_LPM_ADD;
|
||||
obj->name = net->name(); // NetAddSub names are permallocated.
|
||||
obj->name = net->name(); // NetAddSub names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->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;
|
||||
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());
|
||||
assert(obj->scope);
|
||||
|
||||
|
|
@ -2180,6 +2180,9 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
configure
|
||||
Makefile
|
||||
edif.tgt
|
||||
dep
|
||||
config.status
|
||||
config.log
|
||||
|
|
@ -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.
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
#functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=edif.tgt
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=edif.tgt
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -83,6 +83,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
check: all
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
|
|
@ -804,9 +804,19 @@ static void lpm_show_mult(ivl_lpm_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 cell1 = edif_xlibrary_findcell(xlib, "cell1");
|
||||
edif_cellref_t ref0 = 0, ref1 = 0;
|
||||
|
||||
const char*bits;
|
||||
unsigned idx;
|
||||
|
|
@ -832,23 +842,26 @@ static void lpm_show_constant(ivl_net_const_t net)
|
|||
bits = ivl_const_bits(net);
|
||||
for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
|
||||
if (bits[idx] == '1') {
|
||||
if (ref1 == 0)
|
||||
ref1 = edif_cellref_create(edf, cell1);
|
||||
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 (ref0 == 0)
|
||||
ref0 = edif_cellref_create(edf, cell0);
|
||||
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) {
|
||||
edif_joint_t jnt;
|
||||
|
||||
jnt = edif_joint_of_nexus(edf, ivl_const_pin(net,idx));
|
||||
if (bits[idx] == '1')
|
||||
edif_add_to_joint(jnt, ref1, 0);
|
||||
edif_nexus_to_joint(edf, cell1_jnt, ivl_const_pin(net,idx));
|
||||
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 $
|
||||
* 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
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "edif.h"
|
||||
|
|
@ -393,6 +393,28 @@ edif_joint_t edif_joint_of_nexus(edif_t edf, ivl_nexus_t nex)
|
|||
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);
|
||||
|
|
@ -617,6 +639,9 @@ void edif_print(FILE*fd, edif_t edf)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Support synchronous set of LPM_FF devices.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -223,6 +223,8 @@ 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.
|
||||
|
|
@ -231,6 +233,9 @@ extern void edif_print(FILE*fd, edif_t design);
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Support synchronous set of LPM_FF devices.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
FPGA LOADABLE CODE GENERATOR FOR Icarus Verilog
|
||||
|
||||
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
|
||||
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,
|
||||
suitable for most any type of device. The devices that it emits
|
||||
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.
|
||||
|
||||
* arch=virtex
|
||||
|
|
@ -188,6 +188,9 @@ Compile a single-file design with command line tools like so:
|
|||
|
||||
---
|
||||
$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
|
||||
Add arch=lpm to the documentation.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
functor:synth2
|
||||
functor:synth
|
||||
functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -244,6 +244,23 @@ static void show_lpm(ivl_lpm_t net)
|
|||
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: {
|
||||
fprintf(out, " LPM_SHIFTL %s: <width=%u, selects=%u %s>\n",
|
||||
ivl_lpm_basename(net), width, ivl_lpm_selects(net),
|
||||
|
|
@ -807,6 +824,10 @@ static void show_logic(ivl_net_logic_t net)
|
|||
name,
|
||||
ivl_nexus_name(ivl_logic_pin(net, 0)));
|
||||
break;
|
||||
case IVL_LO_NOR:
|
||||
fprintf(out, " nor %s (%s", name,
|
||||
ivl_nexus_name(ivl_logic_pin(net, 0)));
|
||||
break;
|
||||
case IVL_LO_OR:
|
||||
fprintf(out, " or %s (%s", name,
|
||||
ivl_nexus_name(ivl_logic_pin(net, 0)));
|
||||
|
|
@ -822,7 +843,8 @@ static void show_logic(ivl_net_logic_t net)
|
|||
break;
|
||||
|
||||
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)));
|
||||
break;
|
||||
}
|
||||
|
|
@ -953,6 +975,12 @@ int target_design(ivl_design_t des)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -80,6 +80,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
check: all
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ THE VVP TARGET
|
|||
|
||||
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.
|
||||
|
||||
* wires and regs
|
||||
|
|
@ -30,4 +30,4 @@ the drivers are first fed into a resolver (or a tree of resolvers) to
|
|||
form a single output that is the nexus.
|
||||
|
||||
The nexus, then, feeds its output to the inputs of other gates, or to
|
||||
the .net objects in the design.
|
||||
the .net objects in the design.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# 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
|
||||
* 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)
|
||||
{
|
||||
struct vector_info vec = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", vec.base, vec.wid);
|
||||
clr_vector(vec);
|
||||
draw_eval_expr_into_integer(expr, 0);
|
||||
}
|
||||
|
||||
static void calculate_into_x1(ivl_expr_t expr)
|
||||
{
|
||||
struct vector_info vec = draw_eval_expr(expr, 0);
|
||||
fprintf(vvp_out, " %%ix/get 1, %u, %u;\n", vec.base, vec.wid);
|
||||
clr_vector(vec);
|
||||
draw_eval_expr_into_integer(expr, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -429,7 +450,7 @@ static int show_stmt_assign(ivl_statement_t net)
|
|||
* This function handles the case of non-blocking assign to word
|
||||
* variables such as real, i.e:
|
||||
*
|
||||
* read foo;
|
||||
* real foo;
|
||||
* foo <= 1.0;
|
||||
*
|
||||
* 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",
|
||||
vvp_word_label(var), delay, word);
|
||||
|
||||
clr_word(word);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1626,6 +1649,12 @@ int draw_func_definition(ivl_scope_t scope)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
7
util.h
7
util.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <map>
|
||||
|
|
@ -44,13 +44,16 @@ struct attrib_list_t {
|
|||
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,
|
||||
const Design*des,
|
||||
const NetScope*scope);
|
||||
|
||||
/*
|
||||
* $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
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
Summary: Icarus Verilog
|
||||
Name: verilog
|
||||
Version: 0.8
|
||||
Version: 0.8.2
|
||||
Release: 0
|
||||
Copyright: GPL
|
||||
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
|
||||
Packager: Stephen Williams <steve@icarus.com>
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ engineering formats, including simulation. It strives to be true
|
|||
to the IEEE-1364 standard.
|
||||
|
||||
%prep
|
||||
%setup -n verilog-0.8
|
||||
%setup -n verilog-0.8.2
|
||||
|
||||
%build
|
||||
%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.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-s.conf
|
||||
%ifarch x86_64
|
||||
|
|
|
|||
15
verinum.cc
15
verinum.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# 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)
|
||||
{
|
||||
nbits_ = str.length() * 8;
|
||||
|
|
@ -257,7 +257,7 @@ signed long verinum::as_long() const
|
|||
return val;
|
||||
}
|
||||
|
||||
string verinum::as_string() const
|
||||
std::string verinum::as_string() const
|
||||
{
|
||||
assert( nbits_%8 == 0 );
|
||||
if (nbits_ == 0)
|
||||
|
|
@ -283,7 +283,7 @@ string verinum::as_string() const
|
|||
}
|
||||
|
||||
tmp[nbits_/8] = 0;
|
||||
string result = string(tmp);
|
||||
std::string result = std::string(tmp);
|
||||
delete[]tmp;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -370,7 +370,7 @@ verinum trim_vnum(const verinum&that)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&o, verinum::V v)
|
||||
std::ostream& operator<< (std::ostream&o, verinum::V v)
|
||||
{
|
||||
switch (v) {
|
||||
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
|
||||
* 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()) {
|
||||
o << "\"" << v.as_string() << "\"";
|
||||
|
|
@ -942,6 +942,9 @@ verinum::V operator ^ (verinum::V l, verinum::V r)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Handle null string as a single nul character.
|
||||
*
|
||||
|
|
|
|||
18
verinum.h
18
verinum.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <string>
|
||||
|
|
@ -31,6 +31,8 @@
|
|||
class ostream;
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Numbers in Verilog are multibit strings, where each bit has 4
|
||||
* 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 };
|
||||
|
||||
verinum();
|
||||
verinum(const string&str);
|
||||
verinum(const std::string&);
|
||||
verinum(const V*v, unsigned nbits, bool has_len =true);
|
||||
verinum(V, unsigned nbits =1, bool has_len =true);
|
||||
verinum(unsigned long val, unsigned bits);
|
||||
|
|
@ -90,7 +92,7 @@ class verinum {
|
|||
|
||||
unsigned long as_ulong() const;
|
||||
signed long as_long() const;
|
||||
string as_string() const;
|
||||
std::string as_string() const;
|
||||
|
||||
private:
|
||||
V* bits_;
|
||||
|
|
@ -107,8 +109,8 @@ class verinum {
|
|||
needed to accurately represent the contained value, signed or not. */
|
||||
extern verinum trim_vnum(const verinum&);
|
||||
|
||||
extern ostream& operator<< (ostream&, const verinum&);
|
||||
extern ostream& operator<< (ostream&, verinum::V);
|
||||
extern std::ostream& operator<< (std::ostream&, const verinum&);
|
||||
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);
|
||||
|
|
@ -147,6 +149,12 @@ extern verinum v_not(const verinum&left);
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Support unsigned divide of huge numbers.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -124,7 +124,7 @@ verireal operator- (const verireal&l)
|
|||
return res;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&out, const verireal&v)
|
||||
std::ostream& operator<< (std::ostream&out, const verireal&v)
|
||||
{
|
||||
out << v.value_;
|
||||
return out;
|
||||
|
|
@ -132,6 +132,9 @@ ostream& operator<< (ostream&out, const verireal&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
|
||||
* Add unary minus as operator supported by verireal.
|
||||
*
|
||||
|
|
|
|||
14
verireal.h
14
verireal.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
class ostream;
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
class verinum;
|
||||
|
||||
/*
|
||||
|
|
@ -39,7 +41,7 @@ class verinum;
|
|||
|
||||
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 verinum&);
|
||||
|
|
@ -68,7 +70,7 @@ class verireal {
|
|||
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 verinum&);
|
||||
|
|
@ -78,6 +80,12 @@ extern verireal operator- (const verireal&);
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Add unary minus as operator supported by verireal.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -112,6 +112,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install: all installdirs $(vpidir)/system.vpi $(libdir)/ivl/system.sft $(INSTALL32)
|
||||
|
||||
|
|
|
|||
|
|
@ -655,8 +655,8 @@ if((lt)&&(lt->numfacs))
|
|||
lt->zfacname_predec_size = lt->zpackcount;
|
||||
|
||||
gzclose(lt->zhandle);
|
||||
fseek(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftell(lt->handle);
|
||||
fseeko(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftello(lt->handle);
|
||||
lt->zfacname_size = lt->position - lt->zfacname_size;
|
||||
|
||||
lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");
|
||||
|
|
@ -681,8 +681,8 @@ if((lt)&&(lt->numfacs))
|
|||
}
|
||||
|
||||
gzclose(lt->zhandle);
|
||||
fseek(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftell(lt->handle);
|
||||
fseeko(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftello(lt->handle);
|
||||
lt->zfacgeometry_size = lt->position - lt->facgeometry_offset;
|
||||
|
||||
if(is_interlaced_trace)
|
||||
|
|
@ -696,8 +696,8 @@ if((lt)&&(lt->numfacs))
|
|||
}
|
||||
|
||||
gzclose(lt->zhandle); lt->zhandle = NULL;
|
||||
fseek(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftell(lt->handle);
|
||||
fseeko(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftello(lt->handle);
|
||||
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)
|
||||
{
|
||||
|
|
@ -1002,8 +1002,8 @@ for(i=0;i<lt->num_dict_entries;i++)
|
|||
}
|
||||
|
||||
gzclose(lt->zhandle);
|
||||
fseek(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftell(lt->handle);
|
||||
fseeko(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftello(lt->handle);
|
||||
lt->zdictionary_size = lt->position - lt->zdictionary_size;
|
||||
|
||||
free(lt->sorted_dict); lt->sorted_dict = NULL;
|
||||
|
|
@ -1057,8 +1057,8 @@ if(lt)
|
|||
case LT_ZMODE_BZIP2: BZ2_bzclose(lt->zhandle); break;
|
||||
}
|
||||
lt->zhandle = NULL;
|
||||
fseek(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftell(lt->handle);
|
||||
fseeko(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftello(lt->handle);
|
||||
|
||||
lt_set_zmode(lt, LT_ZMODE_NONE);
|
||||
lt->zchg_table_size = lt->position - lt->change_field_offset;
|
||||
|
|
@ -1132,8 +1132,8 @@ if(lt)
|
|||
}
|
||||
|
||||
gzclose(lt->zhandle); lt->zhandle = NULL;
|
||||
fseek(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftell(lt->handle);
|
||||
fseeko(lt->handle, 0L, SEEK_END);
|
||||
lt->position=ftello(lt->handle);
|
||||
lt->ztime_table_size = lt->position - lt->ztime_table_size;
|
||||
}
|
||||
|
||||
|
|
@ -1609,7 +1609,7 @@ int i;
|
|||
|
||||
len--;
|
||||
|
||||
for(i=0;i<len;i++)
|
||||
for(i=0;i<=len;i++)
|
||||
{
|
||||
*(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))
|
||||
{
|
||||
int ivalue = value;
|
||||
int delta1, delta2;
|
||||
s->clk_mask <<= 1;
|
||||
s->clk_mask |= 1;
|
||||
|
||||
if(((s->clk_mask&0x1f)==0x1f) && ((ivalue - s->clk_prevval1)==(s->clk_prevval1 - s->clk_prevval3)) &&
|
||||
((s->clk_prevval - s->clk_prevval2)==(s->clk_prevval2 - s->clk_prevval4)))
|
||||
if( ((s->clk_mask&0x1f)==0x1f) &&
|
||||
( (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))
|
||||
{
|
||||
|
|
@ -2247,6 +2251,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
|
|||
int ivalue = 0;
|
||||
int i;
|
||||
char *pnt = value;
|
||||
int delta1, delta2;
|
||||
|
||||
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 |= legal;
|
||||
|
||||
if(((s->clk_mask&0x1f)==0x1f) && ((ivalue - s->clk_prevval1)==(s->clk_prevval1 - s->clk_prevval3)) &&
|
||||
((s->clk_prevval - s->clk_prevval2)==(s->clk_prevval2 - s->clk_prevval4)))
|
||||
if( ((s->clk_mask&0x1f)==0x1f) &&
|
||||
( (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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "vpi_user.h"
|
||||
|
|
@ -52,28 +52,16 @@ static int sys_fopen_calltf(char *name)
|
|||
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 (! is_constant(mode)) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
vpi_free_object(argv);
|
||||
if (argv) vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiConstType, mode) != vpiStringConst) {
|
||||
vpi_printf("ERROR: %s parameter must be a string.\n", name);
|
||||
vpi_free_object(argv);
|
||||
if (argv) vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
value.format = vpiStringVal;
|
||||
|
|
@ -81,9 +69,20 @@ static int sys_fopen_calltf(char *name)
|
|||
mode_string = strdup(value.value.str);
|
||||
}
|
||||
|
||||
/* Get the string form of the file name from the file name
|
||||
argument. */
|
||||
value.format = vpiStringVal;
|
||||
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;
|
||||
if (mode) {
|
||||
value.value.integer = vpi_fopen(value.value.str, mode_string);
|
||||
|
|
@ -480,6 +479,9 @@ void sys_fileio_register()
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Fix read count passed to fgets.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -80,6 +80,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install:: all installdirs \
|
||||
$(libdir)/libvpip.a \
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# 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
|
||||
|
|
@ -72,6 +72,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
rm -rf autom4te.cache
|
||||
|
||||
check: all
|
||||
./vvp -M../vpi $(srcdir)/examples/hello.vvp | grep 'Hello, World.'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -55,7 +55,7 @@ compiler scales time values ahead of time.
|
|||
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
that know they want to access .nets are able to locate the symbol. In
|
||||
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
|
||||
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
|
||||
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,
|
||||
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
|
||||
through .event objects, that are declare like so:
|
||||
through .event objects, that are declared like so:
|
||||
|
||||
<label> .event <type>, <symbols_list>;
|
||||
<label> .event "name";
|
||||
|
||||
|
||||
This event statement declares an object that a %wait instruction
|
||||
can take as an operand. When a thread executes a %wait, it puts
|
||||
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,
|
||||
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"
|
||||
versions to signed comparisons. (Eqlality doesn't need to care about
|
||||
versions do signed comparison. (Equality doesn't need to care about
|
||||
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
|
||||
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
|
||||
calling various compile_* functions. All these functions live in the
|
||||
compile.cc file. Compilation calls other sections of the code as
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
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.
|
||||
|
||||
The %cvt/vr opcode converts a real word <bit-r> to a thread vector
|
||||
|
|
|
|||
Loading…
Reference in New Issue