mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-27 08:16:13 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e279b61dd | ||
|
|
8ab909a765 | ||
|
|
cca07fa42d | ||
|
|
5b81798205 | ||
|
|
a8a82df47d | ||
|
|
e62e1d89b6 | ||
|
|
c032186133 | ||
|
|
b89e138404 | ||
|
|
9f80ed32b6 | ||
|
|
c16a4a3950 | ||
|
|
90fa90a508 | ||
|
|
aaa734690f | ||
|
|
88da7804c4 | ||
|
|
8604f922a5 | ||
|
|
807a758f7c | ||
|
|
ef55086543 | ||
|
|
2001903c89 | ||
|
|
751e4e4c79 | ||
|
|
9d91b5db4c | ||
|
|
9a3c9507ed | ||
|
|
d71d52bfe9 | ||
|
|
8e30bc9f9e | ||
|
|
412518d1ca | ||
|
|
03afbf157b | ||
|
|
00b2d467e4 | ||
|
|
856829d299 | ||
|
|
2fafe6866f | ||
|
|
b9188ad0ca | ||
|
|
0ccb9139c9 | ||
|
|
18e402ddc8 | ||
|
|
b82d3165da | ||
|
|
91580d1fcc | ||
|
|
35d7384903 | ||
|
|
4539632f34 | ||
|
|
0651f246b2 | ||
|
|
6d0dee9341 | ||
|
|
c692f1708c | ||
|
|
d91733d32c | ||
|
|
cd7378ff3f | ||
|
|
c98ce4a029 | ||
|
|
d035a7e92c | ||
|
|
6db6359363 | ||
|
|
5c07a29e46 | ||
|
|
42d9094e9b | ||
|
|
1742231eba | ||
|
|
3178f886b7 | ||
|
|
cbc4a0ab52 | ||
|
|
cfd8cbf850 | ||
|
|
013b18b3dc | ||
|
|
db9f20b21a | ||
|
|
f611260089 | ||
|
|
e34e3a4875 | ||
|
|
aa8869a3c7 | ||
|
|
588931fcf2 | ||
|
|
07e49e215e | ||
|
|
1b84893ccb | ||
|
|
6445bb6915 | ||
|
|
db899bd1b5 | ||
|
|
c6dcc38fe0 | ||
|
|
b0a7909162 | ||
|
|
d7ae85a13a | ||
|
|
46ee38b466 | ||
|
|
bc6a958a50 | ||
|
|
0e751ad975 | ||
|
|
de94d09706 | ||
|
|
2f88a631df | ||
|
|
4e5dd49a37 | ||
|
|
8463dcc878 | ||
|
|
18bc2f65b3 | ||
|
|
b4e8ea5a0c | ||
|
|
06a8087cb5 | ||
|
|
a9dfef0f55 | ||
|
|
e4540c3d0d | ||
|
|
0cc8396244 | ||
|
|
946693ad4d | ||
|
|
f014d4c533 | ||
|
|
6a1e3f7e27 | ||
|
|
7ad66b0725 | ||
|
|
0341c0c727 | ||
|
|
20c8550139 | ||
|
|
39aa90ce59 | ||
|
|
6c67a64fc3 | ||
|
|
86032c0aa5 | ||
|
|
f243f694b4 | ||
|
|
276ae3e228 | ||
|
|
fe6756eb07 | ||
|
|
539e494bc0 | ||
|
|
1298656c22 | ||
|
|
c66d319d9c | ||
|
|
ae27165ffe | ||
|
|
32f1ca6f8b | ||
|
|
9ce2806710 | ||
|
|
3d4593d4d5 | ||
|
|
df5ae54ec7 | ||
|
|
fbee1b424d | ||
|
|
555017b525 | ||
|
|
1e170ee005 | ||
|
|
43501809b1 | ||
|
|
c0c67a101a | ||
|
|
1eb714e097 | ||
|
|
54a8e12856 | ||
|
|
6203f05ef9 | ||
|
|
703ad04067 | ||
|
|
778e96330d | ||
|
|
e3eb89fb12 | ||
|
|
166621bcb3 | ||
|
|
879a5a4cbe | ||
|
|
9faabfe995 | ||
|
|
6f23fa61ac | ||
|
|
30b6cf7821 | ||
|
|
6258011210 | ||
|
|
7557a46382 | ||
|
|
a0a91f358c | ||
|
|
0128286966 | ||
|
|
acd5e86e04 | ||
|
|
ab94b0a636 | ||
|
|
de6d696667 | ||
|
|
63946c4cfb | ||
|
|
475b603d15 | ||
|
|
096956cda9 | ||
|
|
3d3116d48b | ||
|
|
616360d751 | ||
|
|
7a5c30d297 | ||
|
|
9c5ab36a8b | ||
|
|
466656b167 | ||
|
|
5d6567cb02 | ||
|
|
c44c123ef5 | ||
|
|
4ecbf56e2b | ||
|
|
ed9a2c4b3f | ||
|
|
90751b9250 | ||
|
|
7d8011669d | ||
|
|
eb81062d85 | ||
|
|
8fbacc966e | ||
|
|
75801a12e3 | ||
|
|
9f1ce170e6 | ||
|
|
327c8826f4 | ||
|
|
fb0383d2bd | ||
|
|
28725d0d74 | ||
|
|
dac99b9374 | ||
|
|
1573477caf | ||
|
|
70a7513781 | ||
|
|
0277035496 | ||
|
|
33f462fdf6 |
@@ -2,10 +2,14 @@ lexor_keyword.cc
|
||||
parse.h
|
||||
parse.cc
|
||||
parse.cc.output
|
||||
parse.output
|
||||
syn-rules.cc
|
||||
syn-rules.cc.output
|
||||
syn-rules.output
|
||||
lexor.cc
|
||||
iverilog-vpi
|
||||
iverilog-vpi.pdf
|
||||
iverilog-vpi.ps
|
||||
ivl
|
||||
ivl.exp
|
||||
dep
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.cc,v 1.4 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: HName.cc,v 1.5 2002/11/02 03:27:52 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -75,6 +75,11 @@ hname_t::~hname_t()
|
||||
}
|
||||
}
|
||||
|
||||
unsigned hname_t::component_count() const
|
||||
{
|
||||
return count_;
|
||||
}
|
||||
|
||||
void hname_t::append(const char*text)
|
||||
{
|
||||
char**tmp;
|
||||
@@ -253,6 +258,10 @@ ostream& operator<< (ostream&out, const hname_t&that)
|
||||
|
||||
/*
|
||||
* $Log: HName.cc,v $
|
||||
* Revision 1.5 2002/11/02 03:27:52 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.4 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.h,v 1.3 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: HName.h,v 1.4 2002/11/02 03:27:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
@@ -61,6 +61,10 @@ class hname_t {
|
||||
const char*peek_name(unsigned idx) const;
|
||||
const char*peek_tail_name() const;
|
||||
|
||||
// Return the number of components in the hierarchical
|
||||
// name. If this is a simple name, this will return 1.
|
||||
unsigned component_count() const;
|
||||
|
||||
friend ostream& operator<< (ostream&, const hname_t&);
|
||||
|
||||
private:
|
||||
@@ -79,6 +83,10 @@ extern bool operator == (const hname_t&, const hname_t&);
|
||||
|
||||
/*
|
||||
* $Log: HName.h,v $
|
||||
* Revision 1.4 2002/11/02 03:27:51 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+17
-6
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.133 2002/08/12 00:27:10 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.140 2002/12/10 05:45: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.6
|
||||
VERSION = 0.7
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -83,6 +83,10 @@ all: dosify.exe
|
||||
dosify.exe: dosify.c
|
||||
$(CC) -o dosify.exe dosify.c
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
SUBDIRS += driver-vpi
|
||||
endif
|
||||
|
||||
else
|
||||
all: iverilog-vpi
|
||||
endif
|
||||
@@ -126,7 +130,7 @@ net_design.o net_event.o net_expr.o net_force.o net_func.o \
|
||||
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
||||
net_proc.o net_scope.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
set_width.o \
|
||||
set_width.o sync.o \
|
||||
verinum.o verireal.o target.o targets.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o \
|
||||
@@ -216,7 +220,7 @@ INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/QUICK_START.txt
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt
|
||||
else
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi
|
||||
endif
|
||||
@@ -229,7 +233,7 @@ install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
|
||||
|
||||
$(bindir)/iverilog-vpi: ./iverilog-vpi
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi $(bindir)/iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
|
||||
|
||||
$(libdir)/libvpi.a : ./libvpi.a
|
||||
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
|
||||
@@ -238,7 +242,10 @@ $(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(STRIP) $(strip_dynamic) $(libdir)/ivl/ivl@EXEEXT@
|
||||
|
||||
$(libdir)/ivl/iverilog.conf: $(srcdir)/iverilog.conf
|
||||
# Install iverilog.conf whenever ivl.exe is installed. This
|
||||
# forces iverilog.conf to be treated similarly, in spite of
|
||||
# dates in the source bundle.
|
||||
$(libdir)/ivl/iverilog.conf: $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.conf $(libdir)/ivl/iverilog.conf
|
||||
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
@@ -270,6 +277,10 @@ $(prefix)/sqrt.vl: $(srcdir)/examples/sqrt.vl
|
||||
./dosify.exe $(srcdir)/examples/sqrt.vl tmp.vl
|
||||
mv tmp.vl $(prefix)/sqrt.vl
|
||||
|
||||
$(prefix)/sqrt-virtex.v: $(srcdir)/examples/sqrt-virtex.v
|
||||
./dosify.exe $(srcdir)/examples/sqrt-virtex.v tmp.vl
|
||||
mv tmp.vl $(prefix)/sqrt-virtex.v
|
||||
|
||||
$(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
|
||||
./dosify.exe $(srcdir)/QUICK_START.txt tmp.txt
|
||||
mv tmp.txt $(prefix)/QUICK_START.txt
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.cc,v 1.31 2002/08/19 02:39:16 steve Exp $"
|
||||
#ident "$Id: PExpr.cc,v 1.32 2002/11/09 19:20:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -46,7 +46,7 @@ bool PExpr::is_constant(Module*) const
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
|
||||
{
|
||||
cerr << get_line() << ": error: expression not valid in assign l-value: "
|
||||
<< *this << endl;
|
||||
@@ -256,6 +256,9 @@ bool PEUnary::is_constant(Module*m) const
|
||||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.32 2002/11/09 19:20:48 steve
|
||||
* Port expressions for output ports are lnets, not nets.
|
||||
*
|
||||
* Revision 1.31 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.62 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.63 2002/11/09 19:20:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -80,7 +80,8 @@ class PExpr : public LineInfo {
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
|
||||
// Expressions that can be in the l-value of procedural
|
||||
// assignments can be elaborated with this method.
|
||||
@@ -126,7 +127,8 @@ class PEConcat : public PExpr {
|
||||
// continuous assignments.
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
@@ -216,7 +218,8 @@ class PEIdent : public PExpr {
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
// Identifiers are allowed (with restrictions) is assign l-values.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
|
||||
// Identifiers are also allowed as procedural assignment l-values.
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
@@ -501,6 +504,9 @@ class PECallFunction : public PExpr {
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.63 2002/11/09 19:20:48 steve
|
||||
* Port expressions for output ports are lnets, not nets.
|
||||
*
|
||||
* Revision 1.62 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+11
@@ -396,6 +396,17 @@ language that are defined.
|
||||
Icarus Verilog will override the $timeformat minimum width and
|
||||
use the explicit minimum width.
|
||||
|
||||
vpiScope iterator on vpiScope objects.
|
||||
|
||||
In the VPI, the normal way to iterate over vpiScope objects
|
||||
contained within a vpiScope object, is the vpiInternalScope
|
||||
iterator. Icarus Verilog adds support for the vpiScope
|
||||
iterator of a vpiScope object, that iterates over *everything*
|
||||
the is contained in the current scope. This is useful in cases
|
||||
where one wants to iterate over all the objects in a scope
|
||||
without iterating over all the contained types explicitly.
|
||||
|
||||
|
||||
6.0 CREDITS
|
||||
|
||||
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ autoconf
|
||||
for dir in vpip vvp tgt-vvp tgt-fpga libveriuser
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd $dir ; autoconf )
|
||||
( cd ./$dir ; autoconf )
|
||||
done
|
||||
|
||||
echo "Precompiling lexor_keyword.gperf"
|
||||
|
||||
+62
-62
@@ -46,7 +46,8 @@ do_times=no
|
||||
AC_MSG_RESULT($do_times)
|
||||
|
||||
AC_CHECK_HEADER(ipal.h, HAVE_IPAL=yes, HAVE_IPAL=)
|
||||
AC_ARG_WITH(ipal,enable PAL target,
|
||||
AC_ARG_WITH(ipal,
|
||||
[ --with-ipal enable PAL target],
|
||||
if test "$with_ipal" = no; then
|
||||
echo Disabling ipal support
|
||||
HAVE_IPAL=
|
||||
@@ -74,66 +75,6 @@ AC_LANG_C
|
||||
AC_CANONICAL_HOST
|
||||
# $host
|
||||
|
||||
|
||||
#######################
|
||||
## test for underscores. The vpi module loader needs to know this
|
||||
## in order to know the name of the start symbol for the .vpi module.
|
||||
#######################
|
||||
|
||||
AC_CYGWIN
|
||||
AC_EXEEXT
|
||||
AC_MINGW32
|
||||
|
||||
|
||||
WIN32=no
|
||||
AC_MSG_CHECKING("Checking for windows")
|
||||
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
|
||||
then
|
||||
WIN32=yes
|
||||
fi
|
||||
AC_SUBST(WIN32)
|
||||
AC_MSG_RESULT($WIN32)
|
||||
AC_SUBST(EXEEXT)
|
||||
|
||||
|
||||
AC_MSG_CHECKING("for leading and/or trailing underscores")
|
||||
cat << EOF > underscore.c
|
||||
void underscore(void){}
|
||||
EOF
|
||||
$CC -shared -c underscore.c > /dev/null 2>&1
|
||||
|
||||
CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output" -a -z "$CYGWIN" -a -z "$MINGW32"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
|
||||
|
||||
|
||||
output=`nm underscore.o|grep underscore_ 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_TRAILING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_TU)
|
||||
fi
|
||||
|
||||
if test "$CC_LEADING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WLU)
|
||||
fi
|
||||
if test "$CC_TRAILING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WTU)
|
||||
fi
|
||||
|
||||
rm underscore.c underscore.o
|
||||
|
||||
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
|
||||
|
||||
#######################
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
# The -fPIC flag is used to tell the compiler to make position
|
||||
# independent code. It is needed when making shared objects.
|
||||
|
||||
@@ -233,6 +174,65 @@ esac
|
||||
AC_SUBST(shared)
|
||||
AC_MSG_RESULT($shared)
|
||||
|
||||
#######################
|
||||
## test for underscores. The vpi module loader needs to know this
|
||||
## in order to know the name of the start symbol for the .vpi module.
|
||||
#######################
|
||||
|
||||
AC_CYGWIN
|
||||
AC_EXEEXT
|
||||
AC_MINGW32
|
||||
|
||||
|
||||
WIN32=no
|
||||
AC_MSG_CHECKING("Checking for windows")
|
||||
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
|
||||
then
|
||||
WIN32=yes
|
||||
fi
|
||||
|
||||
AC_SUBST(MINGW32)
|
||||
AC_SUBST(WIN32)
|
||||
AC_MSG_RESULT($WIN32)
|
||||
AC_SUBST(EXEEXT)
|
||||
|
||||
|
||||
AC_MSG_CHECKING("for leading and/or trailing underscores")
|
||||
cat << EOF > underscore.c
|
||||
void underscore(void){}
|
||||
EOF
|
||||
|
||||
$CC $shared -c underscore.c > /dev/null 2>&1
|
||||
|
||||
CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output" -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
|
||||
output=`nm underscore.o|grep underscore_ 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_TRAILING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_TU)
|
||||
fi
|
||||
|
||||
if test "$CC_LEADING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WLU)
|
||||
fi
|
||||
if test "$CC_TRAILING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WTU)
|
||||
fi
|
||||
|
||||
rm underscore.c underscore.o
|
||||
|
||||
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
|
||||
|
||||
#######################
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
AC_MSG_CHECKING("for ident support in C compiler")
|
||||
ident_support='-DHAVE_CVS_IDENT=1'
|
||||
@@ -257,4 +257,4 @@ AC_MSG_RESULT($ident_support)
|
||||
|
||||
AC_CONFIG_SUBDIRS(vvp tgt-vvp tgt-fpga libveriuser)
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
+28
-7
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.133 2002/08/19 00:06:11 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.135 2002/10/23 01:47:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -271,7 +271,8 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
void NetFF::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "") << endl;
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -699,17 +700,26 @@ void NetScope::dump(ostream&o) const
|
||||
|
||||
/* Dump the parameters for this scope. */
|
||||
{
|
||||
map<string,NetExpr*>::const_iterator pp;
|
||||
map<string,param_expr_t>::const_iterator pp;
|
||||
for (pp = parameters_.begin()
|
||||
; pp != parameters_.end() ; pp ++) {
|
||||
o << " parameter " << (*pp).first << " = " <<
|
||||
*(*pp).second << ";" << endl;
|
||||
o << " parameter ";
|
||||
|
||||
if ((*pp).second.signed_flag)
|
||||
o << "signed ";
|
||||
|
||||
if ((*pp).second.msb)
|
||||
o << "[" << *(*pp).second.msb
|
||||
<< ":" << *(*pp).second.lsb << "] ";
|
||||
|
||||
o << (*pp).first << " = " <<
|
||||
*(*pp).second.expr << ";" << endl;
|
||||
}
|
||||
|
||||
for (pp = localparams_.begin()
|
||||
; pp != localparams_.end() ; pp ++) {
|
||||
o << " localparam " << (*pp).first << " = " <<
|
||||
*(*pp).second << ";" << endl;
|
||||
*(*pp).second.expr << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -925,7 +935,10 @@ void NetEMemory::dump(ostream&o) const
|
||||
|
||||
void NetEParam::dump(ostream&o) const
|
||||
{
|
||||
o << "<" << scope_->name() << "." << name_ << ">";
|
||||
if (scope_ != 0)
|
||||
o << "<" << scope_->name() << "." << name_ << ">";
|
||||
else
|
||||
o << "<" << name_ << ">";
|
||||
}
|
||||
|
||||
void NetETernary::dump(ostream&o) const
|
||||
@@ -991,6 +1004,14 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.135 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.134 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.133 2002/08/19 00:06:11 steve
|
||||
* Allow release to handle removal of target net.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
iverilog-vpi.exe
|
||||
@@ -0,0 +1,82 @@
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.5 2002/12/08 03:06:30 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.7
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
mandir = @mandir@
|
||||
|
||||
dllib=@DLLIB@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @CFLAGS@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"'
|
||||
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)/..
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: iverilog-vpi@EXEEXT@
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f iverilog-vpi@EXEEXT@
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
||||
O = main.o res.o
|
||||
|
||||
iverilog-vpi@EXEEXT@: $O
|
||||
$(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@
|
||||
|
||||
|
||||
main.o: main.c
|
||||
$(CC) $(CFLAGS) -c $(srcdir)/main.c
|
||||
|
||||
# Windows specific...
|
||||
res.o: res.rc
|
||||
windres -i res.rc -o res.o
|
||||
#
|
||||
|
||||
install: all installdirs $(bindir)/iverilog-vpi@EXEEXT@
|
||||
|
||||
$(bindir)/iverilog-vpi@EXEEXT@: ./iverilog-vpi@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi@EXEEXT@
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir)
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog-vpi@EXEEXT@
|
||||
@@ -0,0 +1,565 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Gus Baldauf ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* iverilog-vpi.c
|
||||
*
|
||||
* this program provides the functionality of iverilog-vpi.sh under Win32
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* Macros used for compiling and linking */
|
||||
|
||||
#define IVERILOG_VPI_CC "gcc" /* no .exe extension */
|
||||
#define IVERILOG_VPI_CXX "gcc" /* no .exe extension */
|
||||
#define IVERILOG_VPI_CFLAGS "-O" /* -I appended later */
|
||||
#define IVERILOG_VPI_LD "gcc" /* no .exe extension */
|
||||
#define IVERILOG_VPI_LDFLAGS "-shared -Wl,--enable-auto-image-base"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser -lvpi" /* -L prepended later */
|
||||
|
||||
/* pointers to global strings */
|
||||
|
||||
static struct global_strings {
|
||||
char *pCCSRC; /* list of C source files */
|
||||
char *pCXSRC; /* list of C++ source files */
|
||||
char *pOBJ; /* list of object files */
|
||||
char *pLIB; /* list of library files */
|
||||
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
|
||||
char *pMINGW; /* path to MinGW directory */
|
||||
char *pIVL; /* path to IVL directory */
|
||||
char *pCFLAGS; /* CFLAGS option */
|
||||
char *pLDLIBS; /* LDLIBS option */
|
||||
char *pNewPath; /* new PATH environment variable setting */
|
||||
} gstr;
|
||||
|
||||
|
||||
static void deInitDynString(char *str)
|
||||
{
|
||||
free(str);
|
||||
}
|
||||
|
||||
/* when finished, free allocated memory and return error code */
|
||||
|
||||
static void myExit(int exitVal)
|
||||
{
|
||||
deInitDynString(gstr.pCCSRC);
|
||||
deInitDynString(gstr.pCXSRC);
|
||||
deInitDynString(gstr.pOBJ);
|
||||
deInitDynString(gstr.pLIB);
|
||||
deInitDynString(gstr.pOUT);
|
||||
deInitDynString(gstr.pMINGW);
|
||||
deInitDynString(gstr.pIVL);
|
||||
deInitDynString(gstr.pCFLAGS);
|
||||
deInitDynString(gstr.pLDLIBS);
|
||||
deInitDynString(gstr.pNewPath);
|
||||
|
||||
exit(exitVal);
|
||||
}
|
||||
|
||||
/* display usage summary and exit */
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr,"usage: iverilog-vpi [--name=name] [-llibrary] [-mingw=dir] [-ivl=dir] sourcefile...\n");
|
||||
fprintf(stderr," or iverilog-vpi -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi -ivl=dir\n");
|
||||
myExit(1);
|
||||
}
|
||||
|
||||
static void initDynString(char **str)
|
||||
{
|
||||
*str = (char *) malloc(1);
|
||||
|
||||
if (!*str) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
|
||||
*str[0] = 0;
|
||||
}
|
||||
|
||||
/* initialize dynamic memory buffers */
|
||||
|
||||
static void init()
|
||||
{
|
||||
initDynString(&gstr.pCCSRC);
|
||||
initDynString(&gstr.pCXSRC);
|
||||
initDynString(&gstr.pOBJ);
|
||||
initDynString(&gstr.pLIB);
|
||||
initDynString(&gstr.pOUT);
|
||||
initDynString(&gstr.pMINGW);
|
||||
initDynString(&gstr.pIVL);
|
||||
initDynString(&gstr.pCFLAGS);
|
||||
initDynString(&gstr.pLDLIBS);
|
||||
initDynString(&gstr.pNewPath);
|
||||
}
|
||||
|
||||
/* return true if "str" is terminated with with "end", case insensitive */
|
||||
|
||||
static int endsIn (char *end, char *str)
|
||||
{
|
||||
char *ext;
|
||||
|
||||
if (strlen(end) >= strlen(str))
|
||||
return 0;
|
||||
|
||||
ext = str + (strlen(str) - strlen(end));
|
||||
|
||||
return stricmp(end,ext) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* return true if "str" begins with "prefix", case insensitive */
|
||||
|
||||
static int startsWith (char *prefix, char *str)
|
||||
{
|
||||
if (strlen(prefix) >= strlen(str))
|
||||
return 0;
|
||||
|
||||
return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* append "app" to "ptr", allocating memory as needed */
|
||||
/* if count is zero, then copy all characters of "app" */
|
||||
|
||||
static void appendn (char **ptr, char *app, int count)
|
||||
{
|
||||
*ptr = (char *) realloc(*ptr,strlen(*ptr)+(count?count:strlen(app))+1);
|
||||
|
||||
if (*ptr == NULL) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
|
||||
if (count)
|
||||
strncat(*ptr,app,count);
|
||||
else
|
||||
strcat(*ptr,app);
|
||||
}
|
||||
|
||||
/* append "app" to "ptr", allocating memory as needed */
|
||||
|
||||
static void append (char **ptr, char *app)
|
||||
{
|
||||
appendn(ptr,app,0);
|
||||
}
|
||||
|
||||
/* if the string does not end with a backslash, add one */
|
||||
|
||||
static void appendBackSlash(char **str)
|
||||
{
|
||||
if ((*str)[strlen(*str)-1] != '\\')
|
||||
append(str,"\\");
|
||||
}
|
||||
|
||||
/* copy count characters of "str" to "ptr", allocating memory as needed */
|
||||
/* if count is zero, then copy all characters of "str" */
|
||||
|
||||
static void assignn (char **ptr, char *str, int count)
|
||||
{
|
||||
*ptr = (char *) realloc(*ptr,(count?count:strlen(str))+1);
|
||||
|
||||
if (*ptr == NULL) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
|
||||
if (count) {
|
||||
strncpy(*ptr,str,count);
|
||||
(*ptr)[count] = 0;
|
||||
}
|
||||
else
|
||||
strcpy(*ptr,str);
|
||||
}
|
||||
|
||||
/* copy count characters of "str" to "ptr", allocating memory as needed */
|
||||
|
||||
static void assign (char **ptr, char *str)
|
||||
{
|
||||
assignn(ptr,str,0);
|
||||
}
|
||||
|
||||
/* get a copy of a Icarus Verilog registry string key */
|
||||
|
||||
static int GetRegistryKey(char *key, char **value)
|
||||
{
|
||||
long lrv;
|
||||
HKEY hkKey;
|
||||
char *regKeyBuffer;
|
||||
DWORD regKeyType, regKeySize;
|
||||
|
||||
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey);
|
||||
if (lrv != ERROR_SUCCESS)
|
||||
return 0;
|
||||
|
||||
lrv = RegQueryValueEx(hkKey,key,NULL,®KeyType,NULL,®KeySize);
|
||||
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
regKeyBuffer = (char *) malloc(regKeySize+1);
|
||||
if (!regKeyBuffer) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */
|
||||
|
||||
lrv = RegQueryValueEx(hkKey,key,NULL,®KeyType,regKeyBuffer,®KeySize);
|
||||
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
free(regKeyBuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
RegCloseKey(hkKey);
|
||||
|
||||
assign(value,regKeyBuffer);
|
||||
free(regKeyBuffer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* store a copy of a Icarus Verilog registry string key */
|
||||
|
||||
static void SetRegistryKey(char *key, char *value)
|
||||
{
|
||||
HKEY hkKey;
|
||||
DWORD res;
|
||||
|
||||
if (RegCreateKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
"Software\\Icarus Verilog",
|
||||
0,
|
||||
"",
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS,NULL,
|
||||
&hkKey,
|
||||
&res) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
RegSetValueEx(hkKey,key,0,REG_SZ,value,strlen(value)+1);
|
||||
RegCloseKey(hkKey);
|
||||
|
||||
printf("info: storing %s in Windows' registry entry\n",value);
|
||||
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key);
|
||||
}
|
||||
|
||||
/* parse the command line, assign results to global variable strings */
|
||||
|
||||
static int parse(int argc, char *argv[])
|
||||
{
|
||||
int idx, srcFileCnt=0;
|
||||
|
||||
char dot_c_ext[] = ".c";
|
||||
char dot_cc_ext[] = ".cc";
|
||||
char dot_o_ext[] = ".o";
|
||||
char name_option[] = "--name=";
|
||||
char lib_option[] = "-l";
|
||||
char mingw_option[] = "-mingw=";
|
||||
char ivl_option[] = "-ivl=";
|
||||
|
||||
if (argc == 1)
|
||||
return 0;
|
||||
|
||||
for (idx=1; idx<argc; ++idx) {
|
||||
if (endsIn(dot_c_ext,argv[idx])) { /* check for C source files */
|
||||
++srcFileCnt;
|
||||
append(&gstr.pCCSRC,argv[idx]);
|
||||
append(&gstr.pCCSRC," ");
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_c_ext));
|
||||
}
|
||||
else if (endsIn(dot_cc_ext,argv[idx])) { /* check for C++ source files */
|
||||
++srcFileCnt;
|
||||
append(&gstr.pCXSRC,argv[idx]);
|
||||
append(&gstr.pCXSRC," ");
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext));
|
||||
}
|
||||
else if (endsIn(dot_o_ext,argv[idx])) { /* check for compiled object files */
|
||||
++srcFileCnt;
|
||||
append(&gstr.pOBJ,argv[idx]);
|
||||
append(&gstr.pOBJ," ");
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_o_ext));
|
||||
}
|
||||
else if (startsWith(name_option,argv[idx])) { /* check for --name option */
|
||||
assignn(&gstr.pOUT,argv[idx]+sizeof(name_option)-1,strlen(argv[idx])-(sizeof(name_option)-1));
|
||||
}
|
||||
else if (startsWith(lib_option,argv[idx])) { /* check for -l option */
|
||||
append(&gstr.pLIB,argv[idx]);
|
||||
append(&gstr.pLIB," ");
|
||||
}
|
||||
else if (startsWith(mingw_option,argv[idx])) /* check for -mingw option */
|
||||
assignn(&gstr.pMINGW,argv[idx]+sizeof(mingw_option)-1,strlen(argv[idx])-(sizeof(mingw_option)-1));
|
||||
else if (startsWith(ivl_option,argv[idx])) /* check for -ivl option */
|
||||
assignn(&gstr.pIVL,argv[idx]+sizeof(ivl_option)-1,strlen(argv[idx])-(sizeof(ivl_option)-1));
|
||||
else
|
||||
return 0; /* different from iverilog-vpi.sh, we don't ignore accept arguments */
|
||||
}
|
||||
|
||||
if (0 == srcFileCnt)
|
||||
assign(&gstr.pOUT,""); /* in case they used --name with no source files */
|
||||
|
||||
if (!*gstr.pOUT) { /* normally it's an error if there are no *.c,*.cc,*.o files */
|
||||
if (!*gstr.pMINGW && !*gstr.pIVL) /* unless they are just setting the IVL or MinGW registry entries */
|
||||
usage();
|
||||
}
|
||||
else {
|
||||
append(&gstr.pOUT,".vpi"); /* the result file should have a .vpi extension */
|
||||
append(&gstr.pOUT," ");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* do minimal check that the MinGW root directory looks valid */
|
||||
|
||||
static void checkMingwDir(char *root)
|
||||
{
|
||||
int irv;
|
||||
struct _stat stat_buf;
|
||||
|
||||
char *path;
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\" IVERILOG_VPI_CC ".exe");
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root);
|
||||
fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr," point to the MinGW root directory. For a Windows command\n");
|
||||
fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr," -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
}
|
||||
|
||||
/* do minimal check that the Icarus Verilog root directory looks valid */
|
||||
|
||||
static void checkIvlDir(char *root)
|
||||
{
|
||||
int irv;
|
||||
struct _stat stat_buf;
|
||||
|
||||
char *path;
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pIVL);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\vvp.exe");
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
|
||||
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
|
||||
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\\\iverilog\n");
|
||||
myExit(6);
|
||||
}
|
||||
}
|
||||
|
||||
/* see if we can find mingw root */
|
||||
|
||||
#define IVL_REGKEY_MINGW "MingwDir"
|
||||
|
||||
static void setup_mingw_environment()
|
||||
{
|
||||
char *pOldPATH = getenv("PATH"); /* get current path */
|
||||
|
||||
if (*gstr.pMINGW) {
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
|
||||
}
|
||||
else
|
||||
if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) {
|
||||
fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n");
|
||||
fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n");
|
||||
fprintf(stderr," a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n");
|
||||
fprintf(stderr," something like -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
|
||||
assign(&gstr.pNewPath,"PATH="); /* create new path */
|
||||
append(&gstr.pNewPath,gstr.pMINGW);
|
||||
appendBackSlash(&gstr.pNewPath);
|
||||
append(&gstr.pNewPath,"bin;");
|
||||
append(&gstr.pNewPath,pOldPATH);
|
||||
|
||||
_putenv(gstr.pNewPath); /* place new path in environment variable */
|
||||
}
|
||||
|
||||
/* see if we can find iverilog root */
|
||||
|
||||
#define IVL_REGKEY_IVL "InstallDir"
|
||||
|
||||
static void setup_ivl_environment()
|
||||
{
|
||||
if (*gstr.pIVL) {
|
||||
checkIvlDir(gstr.pIVL);
|
||||
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
|
||||
}
|
||||
else
|
||||
if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
|
||||
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
|
||||
fprintf(stderr," of iverilog-vpi.exe to point to the Icarus Verilog root directory.\n");
|
||||
fprintf(stderr," For a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
|
||||
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
|
||||
myExit(6);
|
||||
}
|
||||
|
||||
/* build up the CFLAGS option string */
|
||||
|
||||
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS);
|
||||
append(&gstr.pCFLAGS," -I");
|
||||
append(&gstr.pCFLAGS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCFLAGS);
|
||||
append(&gstr.pCFLAGS,"include");
|
||||
|
||||
/* build up the LDFLAGS option string */
|
||||
|
||||
assign(&gstr.pLDLIBS,"-L");
|
||||
append(&gstr.pLDLIBS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pLDLIBS);
|
||||
append(&gstr.pLDLIBS,"lib ");
|
||||
append(&gstr.pLDLIBS,IVERILOG_VPI_LDLIBS);
|
||||
}
|
||||
|
||||
/* compile source modules */
|
||||
|
||||
static void compile(char *pSource, char **pObject, char *ext, int *compile_errors, char *compiler)
|
||||
{
|
||||
char *ptr1 = pSource;
|
||||
char *ptr2 = strchr(pSource,' ');
|
||||
char *buf=0,*src=0,*obj=0;
|
||||
|
||||
while (ptr2) {
|
||||
int len = ptr2 - ptr1;
|
||||
assignn(&src,ptr1,len);
|
||||
|
||||
assignn(&obj,ptr1,len-strlen(ext)); /* strip off the extension */
|
||||
append (&obj,".o");
|
||||
|
||||
assign (&buf,compiler);
|
||||
append (&buf," -c -o ");
|
||||
append (&buf,obj);
|
||||
append (&buf," ");
|
||||
append (&buf,gstr.pCFLAGS);
|
||||
append (&buf," ");
|
||||
append (&buf,src);
|
||||
|
||||
append (pObject,obj);
|
||||
append (pObject," ");
|
||||
|
||||
printf("%s\n",buf);
|
||||
|
||||
if (system(buf))
|
||||
++*compile_errors;
|
||||
|
||||
ptr1 = ptr2 + 1; /* advance to next token */
|
||||
ptr2 = strchr(ptr1,' ');
|
||||
}
|
||||
|
||||
free(buf);
|
||||
free(src);
|
||||
free(obj);
|
||||
}
|
||||
|
||||
/* using the global strings, compile and link */
|
||||
|
||||
static void compile_and_link()
|
||||
{
|
||||
char *buf=0;
|
||||
int iRet, compile_errors = 0;
|
||||
|
||||
/* print out the mingw and ivl directories to help the user debug problems */
|
||||
|
||||
printf("info: %s will be used as the MinGW root directory.\n",gstr.pMINGW);
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
|
||||
printf("info: %s will be used as the Icarus Verilog root directory.\n",gstr.pIVL);
|
||||
checkIvlDir(gstr.pIVL);
|
||||
|
||||
/* compile */
|
||||
|
||||
compile(gstr.pCCSRC,&gstr.pOBJ,".c" ,&compile_errors,IVERILOG_VPI_CC ); /* compile the C source files */
|
||||
compile(gstr.pCXSRC,&gstr.pOBJ,".cc",&compile_errors,IVERILOG_VPI_CXX); /* compile the C++ source files */
|
||||
|
||||
if (compile_errors) {
|
||||
fprintf(stderr,"iverilog-vpi: Some %d files failed to compile.\n",compile_errors);
|
||||
myExit(2);
|
||||
}
|
||||
|
||||
/* link */
|
||||
|
||||
assign(&buf,IVERILOG_VPI_LD);
|
||||
append(&buf," -o ");
|
||||
append(&buf,gstr.pOUT); /* has a trailing space */
|
||||
append(&buf,IVERILOG_VPI_LDFLAGS);
|
||||
append(&buf," ");
|
||||
append(&buf,gstr.pOBJ) /* has a trailing space */;
|
||||
append(&buf,gstr.pLIB); /* has a trailing space */
|
||||
append(&buf,gstr.pLDLIBS);
|
||||
|
||||
printf("%s\n",buf);
|
||||
|
||||
iRet = system(buf);
|
||||
|
||||
free(buf);
|
||||
|
||||
if (iRet)
|
||||
myExit(3);
|
||||
}
|
||||
|
||||
/* program execution starts here */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
init();
|
||||
|
||||
if (!parse(argc,argv))
|
||||
usage();
|
||||
|
||||
setup_mingw_environment();
|
||||
setup_ivl_environment();
|
||||
|
||||
if (*gstr.pOUT) /* are there any *.c,*.cc,*.o files specified */
|
||||
compile_and_link();
|
||||
|
||||
myExit(0);
|
||||
}
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
|
||||
// LANGUAGE ENGLISH
|
||||
LANGUAGE 9, 4
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 2002,11,13,0
|
||||
PRODUCTVERSION 0,7,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEFLAGS 0x2L
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Icarus Verilog\0"
|
||||
VALUE "FileDescription", "Icarus Veriog VPI Tool\0"
|
||||
VALUE "FileVersion", "2002, 11, 13, 0\0"
|
||||
VALUE "InternalName", "iverilog-vpi\0"
|
||||
VALUE "LegalCopyright", "Copyright 2002 Gus Baldauf\0"
|
||||
VALUE "OriginalFilename", "iverilog-vpi.exe\0"
|
||||
VALUE "ProductName", "Icarus Verilog\0"
|
||||
VALUE "ProductVersion", "0, 7, 0, 0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
+3
-5
@@ -3,9 +3,7 @@
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version. In order to redistribute the software in
|
||||
# binary form, you will need a Picture Elements Binary Software
|
||||
# License.
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@@ -18,12 +16,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.15 2002/08/10 22:36:59 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.16 2002/12/08 03:06:30 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.6
|
||||
VERSION = 0.7
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
+37
-2
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: main.c,v 1.47 2002/08/12 01:27:48 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.49 2002/12/04 03:26:59 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -119,6 +119,35 @@ char tmp[MAXSIZE];
|
||||
|
||||
static char ivl_root[MAXSIZE];
|
||||
|
||||
#ifdef __MINGW32__
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
static FILE*fopen_safe(const char*path)
|
||||
{
|
||||
FILE*file = 0;
|
||||
int fd;
|
||||
|
||||
fd = _open(path, _O_WRONLY|_O_CREAT|_O_EXCL, 0700);
|
||||
if (fd != -1)
|
||||
file = _fdopen(fd, "w");
|
||||
|
||||
return file;
|
||||
}
|
||||
#else
|
||||
# include <fcntl.h>
|
||||
static FILE*fopen_safe(const char*path)
|
||||
{
|
||||
FILE*file = 0;
|
||||
int fd;
|
||||
|
||||
fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0700);
|
||||
if (fd != -1)
|
||||
file = fdopen(fd, "w");
|
||||
|
||||
return file;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char*my_tempfile(const char*str, FILE**fout)
|
||||
{
|
||||
FILE*file;
|
||||
@@ -148,7 +177,7 @@ static const char*my_tempfile(const char*str, FILE**fout)
|
||||
while ((retry > 0) && (file == NULL)) {
|
||||
unsigned code = rand();
|
||||
sprintf(pathbuf, "%s%c%s%04x", tmpdir, sep, str, code);
|
||||
file = fopen(pathbuf, "w");
|
||||
file = fopen_safe(pathbuf);
|
||||
retry -= 1;
|
||||
}
|
||||
|
||||
@@ -657,6 +686,12 @@ int main(int argc, char **argv)
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.49 2002/12/04 03:26:59 steve
|
||||
* Mingw32 compatible temp file management.
|
||||
*
|
||||
* Revision 1.48 2002/12/04 02:29:36 steve
|
||||
* Use O_EXCL when opening temp files.
|
||||
*
|
||||
* Revision 1.47 2002/08/12 01:27:48 steve
|
||||
* Escape the backslash in the windows file name.
|
||||
*
|
||||
|
||||
+20
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: dup_expr.cc,v 1.8 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: dup_expr.cc,v 1.9 2002/11/09 00:25:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -65,6 +65,21 @@ NetETernary* NetETernary::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUFunc* NetEUFunc::dup_expr() const
|
||||
{
|
||||
NetEUFunc*tmp;
|
||||
svector<NetExpr*> tmp_parms (parms_.count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < tmp_parms.count() ; idx += 1) {
|
||||
assert(parms_[idx]);
|
||||
tmp_parms[idx] = parms_[idx]->dup_expr();
|
||||
}
|
||||
|
||||
tmp = new NetEUFunc(func_, result_->dup_expr(), tmp_parms);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEUnary* NetEUnary::dup_expr() const
|
||||
{
|
||||
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
|
||||
@@ -74,6 +89,9 @@ NetEUnary* NetEUnary::dup_expr() const
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.9 2002/11/09 00:25:27 steve
|
||||
* Add dup_expr for user defined function calls.
|
||||
*
|
||||
* Revision 1.8 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
@@ -97,12 +115,5 @@ NetEUnary* NetEUnary::dup_expr() const
|
||||
* Revision 1.3 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+26
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_expr.cc,v 1.63 2002/08/19 02:39:16 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.66 2002/09/21 21:28:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -120,7 +120,8 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
case '^':
|
||||
case '&':
|
||||
case '|':
|
||||
case 'O':
|
||||
case 'O': // NOR (~|)
|
||||
case 'A': // NAND (~&)
|
||||
case 'X':
|
||||
tmp = new NetEBBits(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
@@ -632,11 +633,21 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned idx = net->sb_to_idx(msv);
|
||||
|
||||
if (idx >= net->pin_count()) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "bit " << msv << " out of range of net "
|
||||
/* The bit select is out of range of the
|
||||
vector. This is legal, but returns a
|
||||
constant 1'bx value. */
|
||||
verinum x (verinum::Vx);
|
||||
NetEConst*tmp = new NetEConst(x);
|
||||
tmp->set_line(*this);
|
||||
|
||||
cerr << get_line() << ": warning: Bit select ["
|
||||
<< msv << "] out of range of vector "
|
||||
<< net->name() << "[" << net->msb()
|
||||
<< ":" << net->lsb() << "]." << endl;
|
||||
return 0;
|
||||
cerr << get_line() << ": : Replacing "
|
||||
<< "expression with a constant 1'bx." << endl;
|
||||
delete msn;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net, idx, idx);
|
||||
@@ -697,7 +708,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
assert(idx_ == 0);
|
||||
NetExpr*i = msb_->elaborate_expr(des, scope);
|
||||
if (msb_ && i == 0) {
|
||||
cerr << get_line() << ": error: Unable to exaborate "
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
"index expression `" << *msb_ << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
@@ -874,6 +885,15 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.66 2002/09/21 21:28:18 steve
|
||||
* Allow constant bit selects out of range.
|
||||
*
|
||||
* Revision 1.65 2002/09/18 04:08:45 steve
|
||||
* Spelling errors.
|
||||
*
|
||||
* Revision 1.64 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.63 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
|
||||
+45
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.20 2002/08/12 01:34:58 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.23 2002/11/21 23:27:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -170,16 +170,20 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
verinum*vl = lsb_->eval_const(des, scope);
|
||||
if (vl == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant: "
|
||||
<< *lsb_;
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << lsb_->get_line() << ": : This lsb expression "
|
||||
"violates the rule: " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
verinum*vm = msb_->eval_const(des, scope);
|
||||
if (vl == 0) {
|
||||
if (vm == 0) {
|
||||
cerr << msb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant: "
|
||||
<< *msb_;
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << msb_->get_line() << ": : This msb expression "
|
||||
"violates the rule: " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -277,12 +281,38 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
if (msb_ == 0) {
|
||||
cerr << get_line() << ": error: Assign to memory \""
|
||||
<< mem->name() << "\" requires a word select index."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": error: Cannot use part select on "
|
||||
<< "memory \"" << mem->name() << ".\"" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ && !lsb_);
|
||||
|
||||
NetExpr*ix = msb_->elaborate_expr(des, scope);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
/* Evaluate the memory index expression down as must as
|
||||
possible. Ideally, we can get it down to a constant. */
|
||||
if (! dynamic_cast<NetEConst*>(ix)) {
|
||||
NetExpr*tmp = ix->eval_tree();
|
||||
if (tmp) {
|
||||
tmp->set_line(*ix);
|
||||
delete ix;
|
||||
ix = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
lv->set_part(0, mem->width());
|
||||
@@ -299,6 +329,15 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.23 2002/11/21 23:27:51 steve
|
||||
* Precalculate indices to l-value arrays.
|
||||
*
|
||||
* Revision 1.22 2002/11/21 18:15:40 steve
|
||||
* Fix const test of msb in assignment l-values.
|
||||
*
|
||||
* Revision 1.21 2002/11/02 01:10:49 steve
|
||||
* Detect memories without work index in l-value.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+127
-14
@@ -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.99 2002/09/08 01:37:13 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.103 2002/12/06 03:08:19 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -67,6 +67,8 @@ NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
|
||||
case '|': // Bitwise OR
|
||||
case '&':
|
||||
case '^':
|
||||
case 'A': // Bitwise NAND (~&)
|
||||
case 'O': // Bitwise NOR (~|)
|
||||
case 'X': // Exclusing NOR
|
||||
return elaborate_net_bit_(des, scope, width, rise, fall, decay);
|
||||
case 'E': // === (case equals)
|
||||
@@ -340,6 +342,20 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A': // NAND (~&)
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
|
||||
3, NetLogic::NAND);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
break;
|
||||
|
||||
case '|': // Bitwise OR
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
|
||||
@@ -354,6 +370,20 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
|
||||
}
|
||||
break;
|
||||
|
||||
case 'O': // Bitwise NOR
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
|
||||
3, NetLogic::NOR);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -1407,11 +1437,70 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* The concatenation is also OK an an l-value. This method elaborates
|
||||
* it as a structural l-value.
|
||||
*/
|
||||
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
svector<NetNet*>nets (parms_.count());
|
||||
unsigned pins = 0;
|
||||
unsigned errors = 0;
|
||||
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": sorry: I do not know how to"
|
||||
" elaborate repeat concatenation nets." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Elaborate the operands of the concatenation. */
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
|
||||
implicit_net_ok);
|
||||
if (nets[idx] == 0)
|
||||
errors += 1;
|
||||
else
|
||||
pins += nets[idx]->pin_count();
|
||||
}
|
||||
|
||||
/* If any of the sub expressions failed to elaborate, then
|
||||
delete all those that did and abort myself. */
|
||||
if (errors) {
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
if (nets[idx]) delete nets[idx];
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make the temporary signal that connects to all the
|
||||
operands, and connect it up. Scan the operands of the
|
||||
concat operator from least significant to most significant,
|
||||
which is opposite from how they are given in the list. */
|
||||
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
|
||||
NetNet::IMPLICIT, pins);
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
}
|
||||
}
|
||||
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identifiers in continuous assignment l-values are limited to wires
|
||||
* and that ilk. Detect registers and memories here and report errors.
|
||||
*/
|
||||
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok) const
|
||||
{
|
||||
string path = scope->name();
|
||||
|
||||
@@ -1425,29 +1514,41 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
cerr << get_line() << ": error: Net " << path_
|
||||
<< " is not defined in this context." << endl;
|
||||
cerr << get_line() << ": : Do you mean this? wire "
|
||||
<< path_ << " = <expr>;" << endl;
|
||||
return 0;
|
||||
if (implicit_net_ok && !error_implicit) {
|
||||
|
||||
sig = new NetNet(scope, scope->name()+"."+path_.peek_name(0),
|
||||
NetNet::IMPLICIT, 1);
|
||||
|
||||
if (warn_implicit) {
|
||||
cerr << get_line() << ": warning: implicit "
|
||||
"definition of wire " << scope->name()
|
||||
<< "." << path_.peek_name(0) << "." << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": error: Net " << path_
|
||||
<< " is not defined in this context." << endl;
|
||||
cerr << get_line() << ": : Do you mean this? wire "
|
||||
<< path_ << " = <expr>;" << endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
|
||||
/* Don't allow registers as assign l-values. */
|
||||
if (sig->type() == NetNet::REG) {
|
||||
cerr << get_line() << ": error: registers (" << sig->name()
|
||||
<< ") cannot be l-values in continuous"
|
||||
cerr << get_line() << ": error: reg " << sig->name()
|
||||
<< "; cannot be an L-value in continuous"
|
||||
<< " assignments." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sig->port_type() == NetNet::PINPUT) {
|
||||
cerr << get_line() << ": warning: assign l-value ``"
|
||||
<< sig->name() << "'' is also an input to "
|
||||
<< sig->scope()->name() << "." << endl;
|
||||
cerr << sig->get_line() << ": warning: input ``"
|
||||
<< sig->name() << "'' is coerced to inout." << endl;
|
||||
cerr << get_line() << ": warning: L-value ``"
|
||||
<< sig->name() << "'' is also an input port." << endl;
|
||||
cerr << sig->get_line() << ": warning: input "
|
||||
<< sig->name() << "; is coerced to inout." << endl;
|
||||
sig->port_type(NetNet::PINOUT);
|
||||
}
|
||||
|
||||
@@ -2177,6 +2278,18 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.103 2002/12/06 03:08:19 steve
|
||||
* Reword some error messages for clarity.
|
||||
*
|
||||
* Revision 1.102 2002/11/09 19:20:48 steve
|
||||
* Port expressions for output ports are lnets, not nets.
|
||||
*
|
||||
* Revision 1.101 2002/09/18 04:29:55 steve
|
||||
* Add support for binary NOR operator.
|
||||
*
|
||||
* Revision 1.100 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.99 2002/09/08 01:37:13 steve
|
||||
* Fix padding of operand of unary minus.
|
||||
*
|
||||
|
||||
+24
-12
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_pexpr.cc,v 1.16 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: elab_pexpr.cc,v 1.18 2002/12/05 02:14:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -108,11 +108,6 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
<< *ex << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (ex->expr_width() == 0) {
|
||||
cerr << ex->get_line() << ": internal error: "
|
||||
<< "Operand of concatenation has no width: "
|
||||
<< *ex << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
tmp->set(idx, ex);
|
||||
@@ -150,15 +145,26 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msb_ || lsb_ || idx_) {
|
||||
cerr << get_line() << ": error: Cannot bit/part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetExpr*res = new NetEParam(des, pscope, hname_t(name));
|
||||
assert(res);
|
||||
delete name;
|
||||
|
||||
assert(idx_ == 0);
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": sorry: Cannot part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (msb_) {
|
||||
|
||||
/* We have here a bit select. Insert a NetESelect node
|
||||
to handle it. */
|
||||
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
|
||||
if (tmp != 0) {
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -222,6 +228,12 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.18 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.17 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
* Revision 1.16 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+23
-35
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_scope.cc,v 1.16 2002/09/01 03:01:48 steve Exp $"
|
||||
#ident "$Id: elab_scope.cc,v 1.17 2002/10/19 22:59:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -68,7 +68,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp);
|
||||
scope->set_parameter((*cur).first, tmp, 0, 0, false);
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
@@ -78,7 +78,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp);
|
||||
scope->set_parameter((*cur).first, tmp, 0, 0, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,9 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = false;
|
||||
|
||||
/* If the parameter declaration includes msb and lsb,
|
||||
then use them to calculate a width for the
|
||||
@@ -101,37 +104,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
parameter value is coerced to have the correct
|
||||
and defined width. */
|
||||
if ((*cur).second.msb) {
|
||||
verinum*msb = (*cur).second.msb ->eval_const(des, scope);
|
||||
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
|
||||
assert(msb);
|
||||
verinum*lsb = (*cur).second.lsb ->eval_const(des, scope);
|
||||
assert(lsb);
|
||||
|
||||
long msl = msb->as_long();
|
||||
long lsl = lsb->as_long();
|
||||
delete msb;
|
||||
delete lsb;
|
||||
|
||||
unsigned width;
|
||||
if (msl >= lsl)
|
||||
width = msl - lsl + 1;
|
||||
else
|
||||
width = lsl - msl + 1;
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(val)) {
|
||||
verinum tval (tmp->value(), width);
|
||||
tval.has_sign((*cur).second.signed_flag);
|
||||
val = new NetEConst(tval);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
/* If the parameter has a range, then the
|
||||
signedness is taken from the parameter
|
||||
declaration, and the signedness of the
|
||||
expression is ignored. */
|
||||
val->cast_signed( (*cur).second.signed_flag );
|
||||
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
|
||||
signed_flag = (*cur).second.signed_flag;
|
||||
}
|
||||
|
||||
val = scope->set_parameter((*cur).first, val);
|
||||
val->cast_signed(signed_flag);
|
||||
val = scope->set_parameter((*cur).first, val,
|
||||
msb, lsb, signed_flag);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
@@ -143,7 +124,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
val = scope->set_parameter((*cur).first, val);
|
||||
val = scope->set_parameter((*cur).first, val, 0, 0, false);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
@@ -351,9 +332,12 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
|
||||
PExpr*tmp = (*cur).second;
|
||||
NetExpr*val = tmp->elaborate_pexpr(des, sc);
|
||||
val = my_scope->set_parameter((*cur).first, val);
|
||||
assert(val);
|
||||
delete val;
|
||||
bool flag = my_scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< sc->name() << "." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,6 +496,10 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_scope.cc,v $
|
||||
* Revision 1.17 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.16 2002/09/01 03:01:48 steve
|
||||
* Properly cast signedness of parameters with ranges.
|
||||
*
|
||||
|
||||
+54
-78
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.263 2002/08/28 18:54:36 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.266 2002/12/05 04:15:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -612,33 +612,38 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
// port. sig is the thing outside the module that
|
||||
// connects to the port.
|
||||
|
||||
NetNet*sig = (*pins)[idx]->elaborate_net(des, scope,
|
||||
prts_pin_count,
|
||||
0, 0, 0);
|
||||
if (sig == 0) {
|
||||
cerr << "internal error: Expression too complicated "
|
||||
"for elaboration." << endl;
|
||||
continue;
|
||||
NetNet*sig;
|
||||
if ((prts.count() >= 1)
|
||||
&& (prts[0]->port_type() != NetNet::PINPUT)) {
|
||||
|
||||
sig = (*pins)[idx]->elaborate_lnet(des, scope, true);
|
||||
if (sig == 0) {
|
||||
cerr << (*pins)[idx]->get_line() << ": error: "
|
||||
<< "Output port expression must support "
|
||||
<< "continuous assignment." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
sig = (*pins)[idx]->elaborate_net(des, scope,
|
||||
prts_pin_count,
|
||||
0, 0, 0);
|
||||
if (sig == 0) {
|
||||
cerr << "internal error: Expression too complicated "
|
||||
"for elaboration." << endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
|
||||
// Check that a reg is not passed as an output or inout
|
||||
// port of the module. sig is the elaborated signal in
|
||||
// the outside that is to be passed, and prts is a
|
||||
// concatenation of signals on the input that receive a
|
||||
// reg value.
|
||||
if ((sig->type() == NetNet::REG)
|
||||
&& (prts.count() >= 1)
|
||||
#ifndef NDEBUG
|
||||
if ((prts.count() >= 1)
|
||||
&& (prts[0]->port_type() != NetNet::PINPUT)) {
|
||||
cerr << get_line() << ": error: reg/variable "
|
||||
<< sig->name() << " cannot connect to "
|
||||
<< "output port " << (idx+1) << " of "
|
||||
<< my_scope->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
assert(sig->type() != NetNet::REG);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Check that the parts have matching pin counts. If
|
||||
// not, they are different widths. Note that idx is 0
|
||||
@@ -838,61 +843,6 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The concatenation is also OK an an l-value. This method elaborates
|
||||
* it as a structural l-value.
|
||||
*/
|
||||
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
svector<NetNet*>nets (parms_.count());
|
||||
unsigned pins = 0;
|
||||
unsigned errors = 0;
|
||||
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": sorry: I do not know how to"
|
||||
" elaborate repeat concatenation nets." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Elaborate the operands of the concatenation. */
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
|
||||
if (nets[idx] == 0)
|
||||
errors += 1;
|
||||
else
|
||||
pins += nets[idx]->pin_count();
|
||||
}
|
||||
|
||||
/* If any of the sub expressions failed to elaborate, then
|
||||
delete all those that did and abort myself. */
|
||||
if (errors) {
|
||||
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
|
||||
if (nets[idx]) delete nets[idx];
|
||||
}
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make the temporary signal that connects to all the
|
||||
operands, and connect it up. Scan the operands of the
|
||||
concat operator from least significant to most significant,
|
||||
which is opposite from how they are given in the list. */
|
||||
NetNet*osig = new NetNet(scope, des->local_symbol(scope->name()),
|
||||
NetNet::IMPLICIT, pins);
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
for (unsigned pin = 0 ; pin < cur->pin_count() ; pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
}
|
||||
}
|
||||
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetProc* Statement::elaborate(Design*des, NetScope*) const
|
||||
{
|
||||
@@ -1025,7 +975,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
|
||||
if (! rv->set_width(wid)) {
|
||||
if (wid != rv->expr_width()) {
|
||||
cerr << get_line() << ": error: Unable to match "
|
||||
"expression width of " << rv->expr_width() <<
|
||||
" to l-value width of " << wid << "." << endl;
|
||||
@@ -1126,6 +1076,12 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
assert(rv);
|
||||
|
||||
/* Try to evaluate the expression, at least as far as possible. */
|
||||
if (NetExpr*tmp = rv->eval_tree()) {
|
||||
delete rv;
|
||||
rv = tmp;
|
||||
}
|
||||
|
||||
{ unsigned wid = count_lval_width(lv);
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
@@ -1401,6 +1357,17 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
PExpr*ex = parm(idx);
|
||||
eparms[idx] = ex? ex->elaborate_expr(des, scope, true) : 0;
|
||||
|
||||
/* Attempt to pre-evaluate the parameters. It may be
|
||||
possible to at least partially reduce the
|
||||
expression. */
|
||||
if (eparms[idx] && !dynamic_cast<NetEConst*>(eparms[idx])) {
|
||||
NetExpr*tmp = eparms[idx]->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete eparms[idx];
|
||||
eparms[idx] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
|
||||
@@ -2522,6 +2489,15 @@ Design* elaborate(list<const char*>roots)
|
||||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.266 2002/12/05 04:15:14 steve
|
||||
* precalculate r-values of nb assignments and task arguments.
|
||||
*
|
||||
* Revision 1.265 2002/11/26 03:35:13 steve
|
||||
* Do not set width if width is already OK.
|
||||
*
|
||||
* Revision 1.264 2002/11/09 19:20:48 steve
|
||||
* Port expressions for output ports are lnets, not nets.
|
||||
*
|
||||
* Revision 1.263 2002/08/28 18:54:36 steve
|
||||
* Evaluate nonblocking assign r-values.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.69 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.70 2002/11/03 20:36:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -470,11 +470,18 @@ bool emit(const Design*des, const char*type)
|
||||
return des->emit(tgt->meth);
|
||||
|
||||
}
|
||||
|
||||
cerr << "error: Code generator type " << type
|
||||
<< " not found." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.70 2002/11/03 20:36:10 steve
|
||||
* Error message for mising code generator type.
|
||||
*
|
||||
* Revision 1.69 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval.cc,v 1.30 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.32 2002/10/19 22:59:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -143,6 +143,13 @@ verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
|
||||
return 0;
|
||||
|
||||
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
|
||||
if (eval == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to evaluate "
|
||||
<< "constant expression (parameter=" << path_
|
||||
<< "): " << *expr << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(eval);
|
||||
|
||||
if (msb_ || lsb_)
|
||||
@@ -219,6 +226,13 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.32 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.31 2002/10/13 05:01:07 steve
|
||||
* More verbose eval_const assert message.
|
||||
*
|
||||
* Revision 1.30 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+65
-2
@@ -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.41 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.44 2002/12/05 02:14:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -752,7 +752,13 @@ NetEConst* NetEConcat::eval_tree()
|
||||
<< "operand has indefinite width: "
|
||||
<< *parms_[idx] << endl;
|
||||
local_errors += 1;
|
||||
} else if (expr->expr_width() == 0) {
|
||||
cerr << expr->get_line() << ": internal error: "
|
||||
<< "Operand of concatenation has no width: "
|
||||
<< *expr << endl;
|
||||
local_errors += 1;
|
||||
}
|
||||
|
||||
gap += expr->expr_width();
|
||||
}
|
||||
|
||||
@@ -884,10 +890,57 @@ NetExpr* NetEParam::eval_tree()
|
||||
|
||||
// The result can be saved as the value of the parameter for
|
||||
// future reference, and return a copy to the caller.
|
||||
scope_->set_parameter(name_.peek_name(0), res);
|
||||
scope_->replace_parameter(name_.peek_name(0), res);
|
||||
return res->dup_expr();
|
||||
}
|
||||
|
||||
NetEConst* NetESelect::eval_tree()
|
||||
{
|
||||
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
|
||||
if (expr == 0) {
|
||||
NetExpr*tmp = expr_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete expr_;
|
||||
expr_ = tmp;
|
||||
}
|
||||
|
||||
expr = dynamic_cast<NetEConst*>(expr_);
|
||||
}
|
||||
|
||||
NetEConst*base = dynamic_cast<NetEConst*>(base_);
|
||||
if (base == 0) {
|
||||
NetExpr*tmp = base_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete base_;
|
||||
base_ = tmp;
|
||||
}
|
||||
|
||||
base = dynamic_cast<NetEConst*>(base_);
|
||||
}
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
if (base == 0)
|
||||
return 0;
|
||||
|
||||
verinum eval = expr->value();
|
||||
verinum oval (verinum::V0, expr_width(), true);
|
||||
long bval = base->value().as_long();
|
||||
|
||||
for (long idx = 0 ; idx < expr_width() ; idx += 1) {
|
||||
if ((bval >= eval.len()) || (bval < 0))
|
||||
oval.set(idx, verinum::Vx);
|
||||
else
|
||||
oval.set(idx, eval.get(bval));
|
||||
|
||||
bval += 1;
|
||||
}
|
||||
|
||||
NetEConst*res = new NetEConst(oval);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A ternary expression evaluation is controlled by the condition
|
||||
* expression. If the condition evaluates to true or false, then
|
||||
@@ -1134,6 +1187,16 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.44 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.43 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
* Revision 1.42 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.41 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
* file "hello" which is compiled, linked and ready to run. Run this
|
||||
* program like so:
|
||||
*
|
||||
* ./hello
|
||||
* vvp hello
|
||||
*
|
||||
* and the program will print the message to its output. Easy! For
|
||||
* more on how to make the iverilog command work, see the iverilog
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* $Id: sqrt-virtex.v,v 1.2 2002/11/13 01:49:43 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
|
||||
* 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.
|
||||
*
|
||||
* In addition to Icarus Verilog, you will need implementation
|
||||
* software from Xilinx. As of this writing, this example was tested
|
||||
* with Foundation 4.2i, but it should work the same with ISE and
|
||||
* Webpack software.
|
||||
*
|
||||
* This example source contains all the Verilog needed to do
|
||||
* everything described below. We use conditional compilation to
|
||||
* select the bits of Verilog that are needed to perform each specific
|
||||
* task.
|
||||
*
|
||||
* SIMULATE THE DESIGN
|
||||
*
|
||||
* This source file includes a simulation test bench. To compile the
|
||||
* program to include this test bench, use the command line:
|
||||
*
|
||||
* iverilog -DSIMULATE=1 -oa.out sqrt-virtex.v
|
||||
*
|
||||
* This generates the file "a.out" that can then be executed with the
|
||||
* command:
|
||||
*
|
||||
* vvp a.out
|
||||
*
|
||||
* This causes the simulation to run a long set of example sqrt
|
||||
* calculations. Each result is checked by the test bench to assure
|
||||
* that the result is valid. When it is done, the program prints
|
||||
* "PASSED" and finishes the simulation.
|
||||
*
|
||||
* When you take a close look at the "main" module below, you will see
|
||||
* that it uses Verilog constructs that are not synthesizeable. This
|
||||
* is fine, as we will never try to synthesize it.
|
||||
*
|
||||
* LIBRARY PARTS
|
||||
*
|
||||
* One can use the sqrt32 module to generate an EDIF file suitable for
|
||||
* use as a library part. This part can be imported to the Xilinx
|
||||
* schematic editor, then placed like any other pre-existing
|
||||
* macro. One can also pass the generated EDIF as a precompiled macro
|
||||
* that other designers may use as they see fit.
|
||||
*
|
||||
* To make an EDIF file from the sqrt32 module, execute the command:
|
||||
*
|
||||
* iverilog -osqrt32.edf -tfpga -parch=virtex sqrt-virtex.v
|
||||
*
|
||||
* The -parch=virtex tells the code generator to generate code for the
|
||||
* virtex architecture family (we don't yet care what specific part)
|
||||
* and the -osqrt32.edf places the output into the file
|
||||
* sqrt32.edf.
|
||||
*
|
||||
* Without any preprocessor directives, the only module is the sqrt32
|
||||
* module, so sqrt32 is compiled as the root. The ports of the module
|
||||
* are automatically made into ports of the sqrt32.edf netlist, and
|
||||
* the contents of the sqrt32 module are connected approprately.
|
||||
*
|
||||
* COMPLETE CHIP DESIGNS
|
||||
*
|
||||
* To make a complete chip design, there are other bits that need to
|
||||
* be accounted for. Signals must be assigned to pins, and some
|
||||
* special devices may need to be created. We also want to write into
|
||||
* the EDIF file complete part information so that the implementation
|
||||
* tools know how to route the complete design. The command to compile
|
||||
* for our target part is:
|
||||
*
|
||||
* iverilog -ochip.edf -tfpga \
|
||||
* -parch=virtex -ppart=XC2S15-VQ100 \
|
||||
* -DMAKE_CHIP=1 sqrt-virtex.v
|
||||
*
|
||||
* This command uses the "chip" module as the root. This module in
|
||||
* turn has ports that are destined to be the pins of the completed
|
||||
* part. The -ppart= option gives complete part information, that is
|
||||
* in turn written into the EDIF file. This saves us the drudgery of
|
||||
* repeating that part number for later commands.
|
||||
*
|
||||
* The next steps involve Xilinx software, and to talk to Xilinx
|
||||
* software, the netlist must be in the form of an "ngd" file, a
|
||||
* binary netlist format. The command:
|
||||
*
|
||||
* ngdbuild chip.edf chip.ngd
|
||||
*
|
||||
* does the trick. The input to ngdbuild is the chip.edf file created
|
||||
* by Icarus Verilog, and the output is the chip.ngd file that the
|
||||
* implementation tools may read. From this point, it is best to refer
|
||||
* to Xilinx documentation for the software you are using, but the
|
||||
* quick summary is:
|
||||
*
|
||||
* map -o map.ncd chip.ngd
|
||||
* par -w map.ncd chip.ncd
|
||||
*
|
||||
* The result of this sequence of commands is the chip.ncd file that
|
||||
* is ready to be viewed by FPGA Edit, or converted to a bit stream,
|
||||
* or whatever.
|
||||
*
|
||||
* POST MAP SIMULATION
|
||||
*
|
||||
* Warm fuzzies are good, and retesting your design after the part
|
||||
* is mapped by the Xilinx backend tools is a cheap source of fuzzies.
|
||||
* The command to make a Verilog file out of the mapped design is:
|
||||
*
|
||||
* ngd2ver chip.ngd chip_root.v
|
||||
*
|
||||
* 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
|
||||
* chip_root module below.
|
||||
*
|
||||
* The generated Verilog uses the library in the directory
|
||||
* $(XILINX)/verilog/src/simprims. This directory comes with the ISE
|
||||
* WebPACK installation that you are using. Icarus Verilog is able to
|
||||
* simulate using that library.
|
||||
*
|
||||
* To compile a post-map simulation of the chip_root.v, use the
|
||||
* command:
|
||||
*
|
||||
* iverilog -DSIMULATE -DPOST_MAP -ob.out \
|
||||
* -y $(XILINX)/verilog/src/simprims \
|
||||
* sqrt-virtex.v chip_root.v \
|
||||
* $(XILINX)/verilog/src/glbl.v
|
||||
*
|
||||
* This command line generates b.out from the source files
|
||||
* sqrt-virtex.v and chip_root.v (the latter from ngd2ver)
|
||||
* and the "-y <path>" flag specifies the library directory that will
|
||||
* be needed. The glbl.v source file is also included to provide the
|
||||
* GSR and related signals.
|
||||
*
|
||||
* The POST_MAP compiler directive causes the GSR manipulations
|
||||
* included in the test bench to be compiled in, to simulate the chip
|
||||
* startup. Other then that, the test bench runs the post-map design
|
||||
* the same way the pre-synthesis design works.
|
||||
*
|
||||
* Run this design with the command:
|
||||
*
|
||||
* vvp b.out
|
||||
*
|
||||
* And there you go.
|
||||
*/
|
||||
|
||||
`ifndef POST_MAP
|
||||
/*
|
||||
* This module approximates the square root of an unsigned 32bit
|
||||
* number. The algorithm works by doing a bit-wise binary search.
|
||||
* Starting from the most significant bit, the accumulated value
|
||||
* tries to put a 1 in the bit position. If that makes the square
|
||||
* too big for the input, the bit is left zero, otherwise it is set
|
||||
* in the result. This continues for each bit, decreasing in
|
||||
* significance, until all the bits are calculated or all the
|
||||
* remaining bits are zero.
|
||||
*
|
||||
* Since the result is an integer, this function really calculates
|
||||
* value of the expression:
|
||||
*
|
||||
* x = floor(sqrt(y))
|
||||
*
|
||||
* where sqrt(y) is the exact square root of y and floor(N) is the
|
||||
* largest integer <= N.
|
||||
*
|
||||
* For 32bit numbers, this will never run more then 16 iterations,
|
||||
* which amounts to 16 clocks.
|
||||
*/
|
||||
|
||||
module sqrt32(clk, rdy, reset, x, .y(acc));
|
||||
input clk;
|
||||
output rdy;
|
||||
input reset;
|
||||
|
||||
input [31:0] x;
|
||||
output [15:0] acc;
|
||||
|
||||
|
||||
// acc holds the accumulated result, and acc2 is the accumulated
|
||||
// square of the accumulated result.
|
||||
reg [15:0] acc;
|
||||
reg [31:0] acc2;
|
||||
|
||||
// Keep track of which bit I'm working on.
|
||||
reg [4:0] bitl;
|
||||
wire [15:0] bit = 1 << bitl;
|
||||
wire [31:0] bit2 = 1 << (bitl << 1);
|
||||
|
||||
// The output is ready when the bitl counter underflows.
|
||||
wire rdy = bitl[4];
|
||||
|
||||
// guess holds the potential next values for acc, and guess2 holds
|
||||
// the square of that guess. The guess2 calculation is a little bit
|
||||
// subtle. The idea is that:
|
||||
//
|
||||
// guess2 = (acc + bit) * (acc + bit)
|
||||
// = (acc * acc) + 2*acc*bit + bit*bit
|
||||
// = acc2 + 2*acc*bit + bit2
|
||||
// = acc2 + 2 * (acc<<bitl) + bit
|
||||
//
|
||||
// This works out using shifts because bit and bit2 are known to
|
||||
// have only a single bit in them.
|
||||
wire [15:0] guess = acc | bit;
|
||||
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
|
||||
|
||||
(* ivl_synthesis_on *)
|
||||
always @(posedge clk or posedge reset)
|
||||
if (reset) begin
|
||||
acc = 0;
|
||||
acc2 = 0;
|
||||
bitl = 15;
|
||||
end else begin
|
||||
if (guess2 <= x) begin
|
||||
acc <= guess;
|
||||
acc2 <= guess2;
|
||||
end
|
||||
bitl <= bitl - 5'd1;
|
||||
end
|
||||
|
||||
endmodule // sqrt32
|
||||
|
||||
`endif // `ifndef POST_MAP
|
||||
|
||||
`ifdef SIMULATE
|
||||
/*
|
||||
* This module is a test bench for the sqrt32 module. It runs some
|
||||
* test input values through the sqrt32 module, and checks that the
|
||||
* output is valid. If an invalid output is generated, print and
|
||||
* error message and stop immediately. If all the tested values pass,
|
||||
* then print PASSED after the test is complete.
|
||||
*/
|
||||
module main;
|
||||
|
||||
reg [31:0] x;
|
||||
reg clk, reset;
|
||||
|
||||
wire [15:0] y;
|
||||
wire rdy;
|
||||
|
||||
`ifdef POST_MAP
|
||||
chip_root dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
|
||||
`else
|
||||
sqrt32 dut(.clk(clk), .reset(reset), .rdy(rdy), .x(x), .y(y));
|
||||
`endif
|
||||
|
||||
(* ivl_synthesis_off *)
|
||||
always #5 clk = !clk;
|
||||
|
||||
task reset_dut;
|
||||
begin
|
||||
reset = 1;
|
||||
#1 reset = 0;
|
||||
@(negedge clk) ;
|
||||
end
|
||||
endtask // reset_dut
|
||||
|
||||
task crank_dut;
|
||||
begin
|
||||
while (rdy == 0) begin
|
||||
@(posedge clk) /* wait */;
|
||||
end
|
||||
end
|
||||
endtask // crank_dut
|
||||
|
||||
`ifdef POST_MAP
|
||||
reg GSR;
|
||||
assign glbl.GSR = GSR;
|
||||
`endif
|
||||
|
||||
integer idx;
|
||||
|
||||
(* ivl_synthesis_off *)
|
||||
initial begin
|
||||
reset = 0;
|
||||
clk = 0;
|
||||
|
||||
/* If doing a post-map simulation, when we need to wiggle
|
||||
The GSR bit to simulate chip power-up. */
|
||||
`ifdef POST_MAP
|
||||
GSR = 1;
|
||||
#100 GSR = 0;
|
||||
`endif
|
||||
#100 x = 1;
|
||||
reset_dut;
|
||||
crank_dut;
|
||||
$display("x=%d, y=%d", x, y);
|
||||
|
||||
x = 3;
|
||||
reset_dut;
|
||||
crank_dut;
|
||||
$display("x=%d, y=%d", x, y);
|
||||
|
||||
x = 4;
|
||||
reset_dut;
|
||||
crank_dut;
|
||||
$display("x=%d, y=%d", x, y);
|
||||
|
||||
for (idx = 0 ; idx < 200 ; idx = idx + 1) begin
|
||||
x = $random;
|
||||
reset_dut;
|
||||
crank_dut;
|
||||
$display("x=%d, y=%d", x, y);
|
||||
|
||||
if (x < (y * y)) begin
|
||||
$display("ERROR: y is too big");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (x > ((y + 1)*(y + 1))) begin
|
||||
$display("ERROR: y is too small");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
`endif
|
||||
|
||||
`ifdef MAKE_CHIP
|
||||
/*
|
||||
* This module represents the chip packaging that we intend to
|
||||
* generate. We bind pins here, and route the clock to the global
|
||||
* clock buffer.
|
||||
*/
|
||||
module chip_root(clk, rdy, reset, x, y);
|
||||
input clk;
|
||||
output rdy;
|
||||
input reset;
|
||||
|
||||
input [31:0] x;
|
||||
output [15:0] y;
|
||||
|
||||
wire clk_int;
|
||||
|
||||
(* cellref="BUFG:O,I" *)
|
||||
buf gbuf (clk_int, clk);
|
||||
|
||||
sqrt32 dut(.clk(clk_int), .reset(reset), .rdy(rdy), .x(x), .y(y));
|
||||
|
||||
/* Assign the clk to GCLK0, which is on pin P39. */
|
||||
$attribute(clk, "PAD", "39");
|
||||
|
||||
// We don't care where the remaining pins go, so set the pin number
|
||||
// to 0. This tells the implementation tools that we want a PAD,
|
||||
// but we don't care which. Also note the use of a comma (,)
|
||||
// separated list to assign pins to the bits of a vector.
|
||||
$attribute(rdy, "PAD", "0");
|
||||
$attribute(reset, "PAD", "0");
|
||||
$attribute(x, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
|
||||
$attribute(y, "PAD", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0");
|
||||
|
||||
endmodule // chip_root
|
||||
|
||||
`endif
|
||||
+31
-1
@@ -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.36 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.37 2002/11/17 23:37:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -192,6 +192,33 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
/* sig > 0 is true if any bit in sig is set. This
|
||||
is very much like sig != 0. (0 > sig) shouldn't
|
||||
happen. */
|
||||
if (rcon) {
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
/* 0 < sig is handled like sig > 0. */
|
||||
if (! rcon) {
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::OR);
|
||||
} else {
|
||||
assert(0);
|
||||
gate = new NetLogic(scope, des->local_symbol(path),
|
||||
lsig->pin_count()+1, NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -608,6 +635,9 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.37 2002/11/17 23:37:55 steve
|
||||
* Magnitude compare to 0.
|
||||
*
|
||||
* Revision 1.36 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+26
-2
@@ -1,4 +1,4 @@
|
||||
.TH iverilog-vpi 1 "$Date: 2002/07/05 17:17:20 $" Version "$Date: 2002/07/05 17:17:20 $"
|
||||
.TH iverilog-vpi 1 "$Date: 2002/11/23 00:51:53 $" Version "$Date: 2002/11/23 00:51:53 $"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
@@ -32,13 +32,37 @@ VPI modules to further reference external libraries.
|
||||
Normally, the output VPI module will be named after the first source
|
||||
file passed to the command. This flag sets the name (without the .vpi
|
||||
suffix) of the output vpi module.
|
||||
|
||||
.SH "PC-ONLY OPTIONS"
|
||||
|
||||
The PC port of \fIiverilog-vpi\fP includes two special flags needed to
|
||||
support the more intractable development environment. These flags help
|
||||
the program locate parts that it needs.
|
||||
|
||||
.TP 8
|
||||
.B -mingw=\fIpath\fP
|
||||
Tell the program the root of the Mingw compiler tool suite. The
|
||||
\fBvvp\fP runtime is compiled with this compiler, and this is the
|
||||
compiler that \fIiverilog-vpi\fP expects to use to compile your source
|
||||
code. This is notmally not needed, and if you do use it, it is only
|
||||
needed once. The compiler will save the \fIpath\fP in the registry for
|
||||
use later.
|
||||
|
||||
.TP 8
|
||||
.B -ivl=\fIpath\fP
|
||||
Set for the use during compilation the root if the Icarus Verilog
|
||||
install. This is the place where you installed Icarus Verilog when you
|
||||
ran the installer. This flag is also only needed once, and the path is
|
||||
stored in the registry for future use.
|
||||
|
||||
.SH "AUTHOR"
|
||||
.nf
|
||||
Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
iverilog(1), vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
.BR "<http://www.icarus.com/eda/verilog/>",
|
||||
.BR "<http://www.mingw.org>",
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
|
||||
+6
-8
@@ -17,7 +17,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.6 2002/07/05 17:17:20 steve Exp $"
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.9 2002/10/19 23:18:52 steve Exp $"
|
||||
|
||||
# These are the variables used for compiling files
|
||||
CC=gcc
|
||||
@@ -44,13 +44,13 @@ do
|
||||
case $parm
|
||||
in
|
||||
|
||||
*.c) CCSRC="$SRC $parm"
|
||||
*.c) CCSRC="$CCSRC $parm"
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .c`
|
||||
fi
|
||||
;;
|
||||
|
||||
*.cc) CXSRC="$SRC $parm"
|
||||
*.cc) CXSRC="$CXSRC $parm"
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .cc`
|
||||
fi
|
||||
@@ -84,8 +84,7 @@ OUT=$OUT".vpi"
|
||||
compile_errors=0
|
||||
|
||||
# Compile all the source files into object files
|
||||
for src
|
||||
in $CCSRC
|
||||
for src in $CCSRC
|
||||
do
|
||||
base=`basename $src .c`
|
||||
obj=$base".o"
|
||||
@@ -95,8 +94,7 @@ do
|
||||
OBJ="$OBJ $obj"
|
||||
done
|
||||
|
||||
for src
|
||||
in $CXSRC
|
||||
for src in $CXSRC
|
||||
do
|
||||
base=`basename $src .cc`
|
||||
obj=$base".o"
|
||||
@@ -113,4 +111,4 @@ then
|
||||
fi
|
||||
|
||||
echo "Making $OUT from $OBJ..."
|
||||
exec $LD -o $OUT $LDFLAGS $OBJ $LDLIBS
|
||||
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@
|
||||
# This is the XNF code generator.
|
||||
|
||||
[-txnf]
|
||||
<ivl>%B/ivl -C%C %[v-v] %g %s %[M-M%M] %[N-N%N] %[T-T%T] -txnf -Fsynth2 -Fsynth -Fsyn-rules -Fxnfio -Fcprop -Fnodangle -o%o -- -
|
||||
<ivl>%B/ivl -C%C %[v-v] %g %s %[M-M%M] %[N-N%N] %[T-T%T] -txnf -Fsynth -Fsyn-rules -Fxnfio -Fcprop -Fnodangle -o%o -- -
|
||||
|
||||
# And this is another XNF code generator, under development.
|
||||
[-tfpga]
|
||||
|
||||
@@ -54,6 +54,9 @@ ivl_logic_pin
|
||||
ivl_logic_pins
|
||||
ivl_logic_udp
|
||||
|
||||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
ivl_lpm_basename
|
||||
ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
|
||||
+24
-2
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.105 2002/08/24 05:03:40 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.108 2002/10/23 01:47:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -418,7 +418,15 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
|
||||
*
|
||||
* ivl_expr_width
|
||||
* This method returns the bit width of the expression at this
|
||||
* node. It can be applied to any expression node.
|
||||
* node. It can be applied to any expression node, and returns the
|
||||
* *output* width of the expression node.
|
||||
*
|
||||
* ivl_expr_opcode
|
||||
* IVL_EX_BINARY and IVL_EX_UNARY expression nodes include an
|
||||
* upcode from this table:
|
||||
* & -- AND
|
||||
* A -- NAND (~&)
|
||||
* X -- XNOR (~^)
|
||||
*/
|
||||
|
||||
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
|
||||
@@ -604,6 +612,10 @@ extern ivl_scope_t ivl_lpm_scope(ivl_lpm_t net);
|
||||
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
|
||||
extern unsigned ivl_lpm_width(ivl_lpm_t net);
|
||||
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net);
|
||||
extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
@@ -1079,6 +1091,16 @@ _END_DECL
|
||||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.108 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.107 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.106 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.105 2002/08/24 05:03:40 steve
|
||||
* Missing declaration of ivl_memory_scope.
|
||||
*
|
||||
|
||||
+13
-12
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.32 2002/04/04 05:26:13 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.36 2002/11/08 00:04:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -170,7 +170,7 @@ W [ \t\b\f]+
|
||||
directive and the name, go into PPDEFINE mode and prepare to
|
||||
collect the defined value. */
|
||||
|
||||
`define{W}[a-zA-Z_][a-zA-Z0-9_]*{W}? { yy_push_state(PPDEFINE); def_start(); }
|
||||
`define{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}? { yy_push_state(PPDEFINE); def_start(); }
|
||||
|
||||
<PPDEFINE>.* {
|
||||
do_define();
|
||||
@@ -194,7 +194,7 @@ W [ \t\b\f]+
|
||||
yy_pop_state();
|
||||
}
|
||||
|
||||
`undef{W}[a-zA-Z_][a-zA-Z0-9_]*{W}?.* { def_undefine(); }
|
||||
`undef{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}?.* { def_undefine(); }
|
||||
|
||||
|
||||
/* Detect conditional compilation directives, and parse them. If I
|
||||
@@ -206,7 +206,7 @@ W [ \t\b\f]+
|
||||
condition that stacks on top of the IFDEF_FALSE so that output is
|
||||
not accidentally turned on within nested ifdefs. */
|
||||
|
||||
^{W}?`ifdef{W}[a-zA-Z_][a-zA-Z0-9_]* {
|
||||
`ifdef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char*name = strchr(yytext, '`');
|
||||
assert(name);
|
||||
name += 6;
|
||||
@@ -219,7 +219,7 @@ W [ \t\b\f]+
|
||||
}
|
||||
}
|
||||
|
||||
^{W}?`ifndef{W}[a-zA-Z_][a-zA-Z0-9_]* {
|
||||
`ifndef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char*name = strchr(yytext, '`');
|
||||
assert(name);
|
||||
name += 7;
|
||||
@@ -232,22 +232,23 @@ W [ \t\b\f]+
|
||||
}
|
||||
}
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>^{W}?`ifdef{W}.* { yy_push_state(IFDEF_SUPR); }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>^{W}?`ifndef{W}.* { yy_push_state(IFDEF_SUPR); }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>`ifdef{W} { yy_push_state(IFDEF_SUPR); }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>`ifndef{W} { yy_push_state(IFDEF_SUPR); }
|
||||
|
||||
<IFDEF_TRUE>{W}?`else { BEGIN(IFDEF_FALSE); }
|
||||
<IFDEF_FALSE>{W}?`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>{W}?`else { }
|
||||
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
|
||||
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>`else { }
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>"//".* { }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>. { }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>\n { istack->lineno += 1; fputc('\n', yyout); }
|
||||
|
||||
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>^{W}?`endif {
|
||||
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif {
|
||||
yy_pop_state();
|
||||
}
|
||||
|
||||
/* This pattern notices macros and arranges for them to be replaced. */
|
||||
`[a-zA-Z][a-zA-Z0-9_]* { def_match(); }
|
||||
`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
|
||||
|
||||
/* Any text that is not a directive just gets passed through to the
|
||||
output. Very easy. */
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.73 2002/06/06 18:57:18 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.74 2002/12/04 02:07:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -375,7 +375,7 @@ W [ \t\b\f\r]+
|
||||
if (isgraph(yytext[0]))
|
||||
cerr << yytext[0];
|
||||
else
|
||||
cerr << (unsigned)yytext[0];
|
||||
cerr << "hex " << hex << (0xffU & ((unsigned) (yytext[0])));
|
||||
|
||||
cerr << ")" << endl; }
|
||||
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ rpmos, K_rpmos
|
||||
rtran, K_rtran
|
||||
rtranif0, K_rtranif0
|
||||
rtranif1, K_rtranif1
|
||||
scalered, K_scalered
|
||||
scalared, K_scalared
|
||||
signed, K_signed
|
||||
small, K_small
|
||||
specify, K_specify
|
||||
|
||||
+20
-2
@@ -33,7 +33,16 @@ install software from source form.
|
||||
then just make sure the distributed lexor_keyword.cc is newer then
|
||||
lexor_keyword.gperf, and use that.
|
||||
|
||||
3) Configure, build and install the Icarus Verilog sources as normal.
|
||||
3) If working with a CVS snapshot, you must run autoconf in several
|
||||
directories. This is aided by the 'autoconf.sh' script at the
|
||||
top of the source tree:
|
||||
|
||||
sh ./autoconf.sh
|
||||
|
||||
This will also run the gperf command, so make sure you'd completed
|
||||
step #2 first.
|
||||
|
||||
4) Configure, build and install the Icarus Verilog sources as normal.
|
||||
|
||||
The only change you need to make here is to use a configure command like:
|
||||
|
||||
@@ -47,8 +56,17 @@ install software from source form.
|
||||
|
||||
You can, of course, add other configure options.
|
||||
|
||||
6) NOTE: 'make check' will not work until after 'make install' has been run
|
||||
since dynamically loaded code is searched for in the install location
|
||||
rather than the build location. The dlopen emulation library doesn't
|
||||
support a search path option.
|
||||
|
||||
4) Done!
|
||||
If you are worried about overwriting a working installation with a new,
|
||||
potentially broken one, you can always configure using --prefix="/some/path",
|
||||
and install there to make sure everything is working and then re-configure
|
||||
with the real path you want to install at, make clean, and make install.
|
||||
|
||||
5) Done!
|
||||
|
||||
|
||||
GPERF FOR MACOSX
|
||||
|
||||
@@ -76,13 +76,18 @@ without white space.
|
||||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run this command:
|
||||
|
||||
$ ./configure --prefix=/cygdrive/d/iverilog
|
||||
$ ./configure --prefix=d:/iverilog
|
||||
|
||||
Substitute your chosen directory for the prefix. This will cause the
|
||||
makefiles to build and the source code to configure. The configure
|
||||
program will detect that this is a mingw environment and set things up
|
||||
to build properly.
|
||||
|
||||
(For a prefix, use the drive letter notation, the mingw compiled parts
|
||||
require it, and the Cygwin tools should be able to handle it. You may
|
||||
need to check or upgrade your Cygwin installation if this causes
|
||||
problems for you.)
|
||||
|
||||
|
||||
* Compile Icarus Verilog
|
||||
|
||||
@@ -108,7 +113,7 @@ window.
|
||||
|
||||
When you are ready, install like this:
|
||||
|
||||
$ /usr/bin/make STRIP=/usr/bin/strip.exe install
|
||||
$ /usr/bin/make install
|
||||
|
||||
This is part of what the configure program did for you. The Makefiles
|
||||
now know to put the files under the D:\iverilog (or whatever directory
|
||||
|
||||
+141
-111
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_design.cc,v 1.27 2002/08/16 05:18:27 steve Exp $"
|
||||
#ident "$Id: net_design.cc,v 1.30 2002/12/07 02:49:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -242,13 +242,11 @@ void NetScope::run_defparams(Design*des)
|
||||
continue;
|
||||
}
|
||||
|
||||
NetExpr*tmp = targ_scope->set_parameter(name, val);
|
||||
if (tmp == 0) {
|
||||
bool flag = targ_scope->replace_parameter(name, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< name << " not found in " << targ_scope->name()
|
||||
<< "." << endl;
|
||||
} else {
|
||||
delete tmp;
|
||||
<< name << " not found in "
|
||||
<< targ_scope->name() << "." << endl;
|
||||
}
|
||||
|
||||
delete[]name;
|
||||
@@ -276,34 +274,129 @@ void NetScope::evaluate_parameters(Design*des)
|
||||
// scanning code. Now the parameter expression can be fully
|
||||
// evaluated, or it cannot be evaluated at all.
|
||||
|
||||
typedef map<string,NetExpr*>::iterator mparm_it_t;
|
||||
typedef map<string,param_expr_t>::iterator mparm_it_t;
|
||||
|
||||
for (mparm_it_t cur = parameters_.begin()
|
||||
; cur != parameters_.end() ; cur ++) {
|
||||
|
||||
// Get the NetExpr for the parameter.
|
||||
NetExpr*expr = (*cur).second;
|
||||
assert(expr);
|
||||
long msb = 0;
|
||||
long lsb = 0;
|
||||
bool range_flag = false;
|
||||
NetExpr*expr;
|
||||
|
||||
// If it's already a NetEConst, then this parameter is done.
|
||||
if (dynamic_cast<const NetEConst*>(expr))
|
||||
continue;
|
||||
/* Evaluate the msb expression, if it is present. */
|
||||
expr = (*cur).second.msb;
|
||||
|
||||
// Try to evaluate the expression.
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second->get_line() << ": internal error: "
|
||||
"unable to evaluate parm expression: " <<
|
||||
*expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
if (expr) {
|
||||
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
|
||||
|
||||
if (! tmp) {
|
||||
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_line()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate msb expression "
|
||||
<< "for parameter " << (*cur).first << ": "
|
||||
<< *expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.msb = nexpr;
|
||||
|
||||
tmp = dynamic_cast<NetEConst*>(nexpr);
|
||||
}
|
||||
|
||||
assert(tmp);
|
||||
msb = tmp->value().as_long();
|
||||
range_flag = true;
|
||||
}
|
||||
|
||||
// The evaluate worked, replace the old expression with
|
||||
// this constant value.
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second = nexpr;
|
||||
/* Evaluate the lsb expression, if it is present. */
|
||||
expr = (*cur).second.lsb;
|
||||
if (expr) {
|
||||
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
|
||||
|
||||
if (! tmp) {
|
||||
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_line()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate lsb expression "
|
||||
<< "for parameter " << (*cur).first << ": "
|
||||
<< *expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.lsb = nexpr;
|
||||
|
||||
tmp = dynamic_cast<NetEConst*>(nexpr);
|
||||
}
|
||||
|
||||
assert(tmp);
|
||||
lsb = tmp->value().as_long();
|
||||
|
||||
assert(range_flag);
|
||||
}
|
||||
|
||||
|
||||
/* Evaluate the parameter expression, if necessary. */
|
||||
expr = (*cur).second.expr;
|
||||
assert(expr);
|
||||
if (! dynamic_cast<const NetEConst*>(expr)) {
|
||||
|
||||
// Try to evaluate the expression.
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_line()
|
||||
<< ": internal error: "
|
||||
"unable to evaluate parameter value: " <<
|
||||
*expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The evaluate worked, replace the old expression with
|
||||
// this constant value.
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.expr = nexpr;
|
||||
|
||||
// Set the signedness flag.
|
||||
(*cur).second.expr->cast_signed( (*cur).second.signed_flag );
|
||||
}
|
||||
|
||||
/* If the parameter has range information, then make
|
||||
sure the value is set right. */
|
||||
if (range_flag) {
|
||||
long wid = (msb >= lsb)? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
|
||||
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
|
||||
assert(val);
|
||||
|
||||
verinum value = val->value();
|
||||
|
||||
if (! (value.has_len()
|
||||
&& (value.len() == wid)
|
||||
&& (value.has_sign() == (*cur).second.signed_flag))) {
|
||||
|
||||
verinum tmp (value, wid);
|
||||
tmp.has_sign ( (*cur).second.signed_flag );
|
||||
delete val;
|
||||
val = new NetEConst(tmp);
|
||||
(*cur).second.expr = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -408,12 +501,18 @@ NetScope* Design::find_task(const hname_t&key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEvent* Design::find_event(NetScope*scope, hname_t path)
|
||||
NetEvent* Design::find_event(NetScope*scope, const hname_t&p)
|
||||
{
|
||||
hname_t path = p;
|
||||
assert(scope);
|
||||
|
||||
char*key = path.remove_tail_name();
|
||||
if (path.peek_name(0))
|
||||
scope = find_scope(scope, path);
|
||||
|
||||
while (scope) {
|
||||
if (NetEvent*ev = scope->find_event(path)) {
|
||||
if (NetEvent*ev = scope->find_event(key)) {
|
||||
delete key;
|
||||
return ev;
|
||||
}
|
||||
|
||||
@@ -422,6 +521,7 @@ NetEvent* Design::find_event(NetScope*scope, hname_t path)
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
delete key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -500,6 +600,17 @@ void Design::delete_process(NetProcTop*top)
|
||||
|
||||
/*
|
||||
* $Log: net_design.cc,v $
|
||||
* Revision 1.30 2002/12/07 02:49:24 steve
|
||||
* Named event triggers can take hierarchical names.
|
||||
*
|
||||
* Revision 1.29 2002/11/02 03:27:52 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.28 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.27 2002/08/16 05:18:27 steve
|
||||
* Fix intermix of node functors and node delete.
|
||||
*
|
||||
@@ -518,86 +629,5 @@ void Design::delete_process(NetProcTop*top)
|
||||
*
|
||||
* Revision 1.22 2001/10/20 05:21:51 steve
|
||||
* Scope/module names are char* instead of string.
|
||||
*
|
||||
* Revision 1.21 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
* Revision 1.20 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.19 2001/04/02 02:28:12 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.18 2001/01/14 23:04:56 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.17 2000/12/16 01:45:48 steve
|
||||
* Detect recursive instantiations (PR#2)
|
||||
*
|
||||
* Revision 1.16 2000/09/24 17:41:13 steve
|
||||
* fix null pointer when elaborating undefined task.
|
||||
*
|
||||
* Revision 1.15 2000/08/26 00:54:03 steve
|
||||
* Get at gate information for ivl_target interface.
|
||||
*
|
||||
* Revision 1.14 2000/08/12 17:59:48 steve
|
||||
* Limit signal scope search at module boundaries.
|
||||
*
|
||||
* Revision 1.13 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.12 2000/07/23 02:41:32 steve
|
||||
* Excessive assert.
|
||||
*
|
||||
* Revision 1.11 2000/07/22 22:09:03 steve
|
||||
* Parse and elaborate timescale to scopes.
|
||||
*
|
||||
* Revision 1.10 2000/07/16 04:56:08 steve
|
||||
* Handle some edge cases during node scans.
|
||||
*
|
||||
* Revision 1.9 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.8 2000/05/02 16:27:38 steve
|
||||
* Move signal elaboration to a seperate pass.
|
||||
*
|
||||
* Revision 1.7 2000/05/02 03:13:31 steve
|
||||
* Move memories to the NetScope object.
|
||||
*
|
||||
* Revision 1.6 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.5 2000/04/28 16:50:53 steve
|
||||
* Catch memory word parameters to tasks.
|
||||
*
|
||||
* Revision 1.4 2000/04/10 05:26:06 steve
|
||||
* All events now use the NetEvent class.
|
||||
*
|
||||
* Revision 1.3 2000/03/11 03:25:52 steve
|
||||
* Locate scopes in statements.
|
||||
*
|
||||
* Revision 1.2 2000/03/10 06:20:48 steve
|
||||
* Handle defparam to partial hierarchical names.
|
||||
*
|
||||
* Revision 1.1 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+85
-2
@@ -17,13 +17,79 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_expr.cc,v 1.7 2002/09/01 03:01:48 steve Exp $"
|
||||
#ident "$Id: net_expr.cc,v 1.10 2002/11/09 01:40:19 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "netlist.h"
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* Create an add/sub node from the two operands. Make a best guess of
|
||||
* the
|
||||
*/
|
||||
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
NetEConst* tmp;
|
||||
|
||||
/* Catch the special case that one of the operands is an
|
||||
unsized constant number. If so, then we should set the
|
||||
width of that number to the size of the other operand, plus
|
||||
one. This expands the expression to account for the largest
|
||||
possible result.
|
||||
|
||||
The set_width applied to a constant value will only
|
||||
truncate the constant so far as it can still hold its
|
||||
logical value, so this is safe to do. */
|
||||
if ( (tmp = dynamic_cast<NetEConst*>(r))
|
||||
&& (! tmp->has_width())
|
||||
&& (tmp->expr_width() > l->expr_width()) ) {
|
||||
|
||||
unsigned target_width = l->expr_width() + 1;
|
||||
r->set_width(target_width);
|
||||
|
||||
/* Note: This constant value will not gain a defined
|
||||
with from this. Make sure. */
|
||||
assert(! r->has_width() );
|
||||
|
||||
} else if ( (tmp = dynamic_cast<NetEConst*>(l))
|
||||
&& (! tmp->has_width())
|
||||
&& (tmp->expr_width() > r->expr_width()) ) {
|
||||
|
||||
unsigned target_width = r->expr_width() + 1;
|
||||
l->set_width(target_width);
|
||||
|
||||
/* Note: This constant value will not gain a defined
|
||||
with from this. Make sure. */
|
||||
assert(! l->has_width() );
|
||||
|
||||
}
|
||||
|
||||
/* Now that we have the operand sizes the way we like, or as
|
||||
good as we are going to get them, set the size of myself. */
|
||||
if (r->expr_width() > l->expr_width()) {
|
||||
|
||||
expr_width(r->expr_width());
|
||||
|
||||
} else {
|
||||
expr_width(l->expr_width());
|
||||
}
|
||||
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBAdd::~NetEBAdd()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBAdd* NetEBAdd::dup_expr() const
|
||||
{
|
||||
NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
NetEConcat::NetEConcat(unsigned cnt, NetExpr* r)
|
||||
: parms_(cnt), repeat_(r)
|
||||
{
|
||||
@@ -43,6 +109,11 @@ NetEConcat::~NetEConcat()
|
||||
delete parms_[idx];
|
||||
}
|
||||
|
||||
bool NetEConcat::has_width() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetEConcat::set(unsigned idx, NetExpr*e)
|
||||
{
|
||||
assert(idx < parms_.count());
|
||||
@@ -111,7 +182,7 @@ unsigned NetEConcat::repeat() const
|
||||
}
|
||||
|
||||
NetEParam::NetEParam()
|
||||
: des_(0)
|
||||
: des_(0), scope_(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -171,6 +242,18 @@ bool NetESelect::set_width(unsigned w)
|
||||
|
||||
/*
|
||||
* $Log: net_expr.cc,v $
|
||||
* Revision 1.10 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
* Revision 1.9 2002/11/06 02:25:13 steve
|
||||
* No need to keep excess width from an
|
||||
* unsigned constant value, if it can
|
||||
* be trimmed safely.
|
||||
*
|
||||
* Revision 1.8 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.7 2002/09/01 03:01:48 steve
|
||||
* Properly cast signedness of parameters with ranges.
|
||||
*
|
||||
|
||||
+17
-1
@@ -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.11 2002/08/18 22:07:16 steve Exp $"
|
||||
#ident "$Id: net_link.cc,v 1.12 2002/10/21 01:42:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -484,8 +484,24 @@ bool NexusSet::contains(const NexusSet&that) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NexusSet::intersect(const NexusSet&that) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < that.nitems_ ; idx += 1) {
|
||||
unsigned where = bsearch_(that[idx]);
|
||||
if (where == nitems_)
|
||||
continue;
|
||||
if (items_[where] == that[idx])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.12 2002/10/21 01:42:08 steve
|
||||
* Synthesizer support for synchronous begin-end blocks.
|
||||
*
|
||||
* Revision 1.11 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
|
||||
+13
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_nex_input.cc,v 1.6 2002/08/18 22:07:16 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.7 2002/11/16 05:45:41 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -250,11 +250,15 @@ NexusSet* NetCase::nex_input()
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
assert(items_[idx].guard);
|
||||
tmp = items_[idx].guard->nex_input();
|
||||
assert(tmp);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
/* Usually, this is the guard expression. The default
|
||||
case is special and is identified by a null
|
||||
guard. The default guard obviously has no input. */
|
||||
if (items_[idx].guard) {
|
||||
tmp = items_[idx].guard->nex_input();
|
||||
assert(tmp);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -358,6 +362,9 @@ NexusSet* NetWhile::nex_input()
|
||||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.7 2002/11/16 05:45:41 steve
|
||||
* Handle default: case in net_inputs for NetCase.
|
||||
*
|
||||
* Revision 1.6 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
|
||||
+8
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_nex_output.cc,v 1.5 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: net_nex_output.cc,v 1.6 2002/09/17 04:39:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -42,8 +42,10 @@ void NetAssignBase::nex_output(NexusSet&out)
|
||||
assert(lsig);
|
||||
assert(lval_->more == 0);
|
||||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
|
||||
out.add(lsig->pin(idx).nexus());
|
||||
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) {
|
||||
unsigned off = lval_->get_loff() + idx;
|
||||
out.add(lsig->pin(off).nexus());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,6 +87,9 @@ void NetEvWait::nex_output(NexusSet&out)
|
||||
|
||||
/*
|
||||
* $Log: net_nex_output.cc,v $
|
||||
* Revision 1.6 2002/09/17 04:39:20 steve
|
||||
* Account for part select in l-value.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+50
-13
@@ -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.19 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: net_scope.cc,v 1.21 2002/12/07 02:49:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -78,33 +78,63 @@ NetScope::~NetScope()
|
||||
free(module_name_);
|
||||
}
|
||||
|
||||
NetExpr* NetScope::set_parameter(const string&key, NetExpr*expr)
|
||||
NetExpr* NetScope::set_parameter(const string&key, NetExpr*expr,
|
||||
NetExpr*msb, NetExpr*lsb, bool signed_flag)
|
||||
{
|
||||
NetExpr*&ref = parameters_[key];
|
||||
NetExpr* res = ref;
|
||||
ref = expr;
|
||||
param_expr_t&ref = parameters_[key];
|
||||
NetExpr* res = ref.expr;
|
||||
ref.expr = expr;
|
||||
ref.msb = msb;
|
||||
ref.lsb = lsb;
|
||||
ref.signed_flag = signed_flag;
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return false if this creates a new parameter.
|
||||
*/
|
||||
bool NetScope::replace_parameter(const string&key, NetExpr*expr)
|
||||
{
|
||||
bool flag = true;
|
||||
param_expr_t&ref = parameters_[key];
|
||||
|
||||
NetExpr* res = ref.expr;
|
||||
|
||||
if (res) {
|
||||
delete res;
|
||||
} else {
|
||||
flag = false;
|
||||
ref.msb = 0;
|
||||
ref.lsb = 0;
|
||||
ref.signed_flag = false;
|
||||
}
|
||||
|
||||
ref.expr = expr;
|
||||
return flag;
|
||||
}
|
||||
|
||||
NetExpr* NetScope::set_localparam(const string&key, NetExpr*expr)
|
||||
{
|
||||
NetExpr*&ref = localparams_[key];
|
||||
NetExpr* res = ref;
|
||||
ref = expr;
|
||||
param_expr_t&ref = localparams_[key];
|
||||
NetExpr* res = ref.expr;
|
||||
ref.expr = expr;
|
||||
ref.msb = 0;
|
||||
ref.lsb = 0;
|
||||
ref.signed_flag = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
const NetExpr* NetScope::get_parameter(const string&key) const
|
||||
{
|
||||
map<string,NetExpr*>::const_iterator idx;
|
||||
map<string,param_expr_t>::const_iterator idx;
|
||||
|
||||
idx = parameters_.find(key);
|
||||
if (idx != parameters_.end())
|
||||
return (*idx).second;
|
||||
return (*idx).second.expr;
|
||||
|
||||
idx = localparams_.find(key);
|
||||
if (idx != localparams_.end())
|
||||
return (*idx).second;
|
||||
return (*idx).second.expr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -225,10 +255,10 @@ void NetScope::rem_event(NetEvent*ev)
|
||||
}
|
||||
|
||||
|
||||
NetEvent* NetScope::find_event(const hname_t&name)
|
||||
NetEvent* NetScope::find_event(const char*name)
|
||||
{
|
||||
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
|
||||
if (strcmp(cur->name(), name.peek_tail_name()) == 0)
|
||||
if (strcmp(cur->name(), name) == 0)
|
||||
return cur;
|
||||
|
||||
return 0;
|
||||
@@ -402,6 +432,13 @@ string NetScope::local_hsymbol()
|
||||
|
||||
/*
|
||||
* $Log: net_scope.cc,v $
|
||||
* Revision 1.21 2002/12/07 02:49:24 steve
|
||||
* Named event triggers can take hierarchical names.
|
||||
*
|
||||
* Revision 1.20 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.19 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+37
-36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.cc,v 1.199 2002/09/01 03:01:48 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.203 2002/11/09 00:25:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -592,11 +592,21 @@ Link& NetFF::pin_Aset()
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
const Link& NetFF::pin_Aset() const
|
||||
{
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
Link& NetFF::pin_Aclr()
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
const Link& NetFF::pin_Aclr() const
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
Link& NetFF::pin_Sload()
|
||||
{
|
||||
return pin(5);
|
||||
@@ -640,6 +650,16 @@ const Link& NetFF::pin_Q(unsigned w) const
|
||||
return pin(pn);
|
||||
}
|
||||
|
||||
void NetFF::aset_value(const verinum&val)
|
||||
{
|
||||
aset_value_ = val;
|
||||
}
|
||||
|
||||
const verinum& NetFF::aset_value() const
|
||||
{
|
||||
return aset_value_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
|
||||
@@ -1687,12 +1707,6 @@ const NetScope* NetEUFunc::func() const
|
||||
return func_;
|
||||
}
|
||||
|
||||
NetEUFunc* NetEUFunc::dup_expr() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetUTask::NetUTask(NetScope*def)
|
||||
: task_(def)
|
||||
{
|
||||
@@ -1736,34 +1750,6 @@ bool NetExpr::has_width() const
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a bitwise operator node from the opcode and the left and
|
||||
* right expressions. Don't worry about the width of the expression
|
||||
* yet, we'll get that from the l-value, whatever that turns out to
|
||||
* be.
|
||||
*/
|
||||
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
if (r->expr_width() > l->expr_width())
|
||||
expr_width(r->expr_width());
|
||||
else
|
||||
expr_width(l->expr_width());
|
||||
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBAdd::~NetEBAdd()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBAdd* NetEBAdd::dup_expr() const
|
||||
{
|
||||
NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a bitwise operator node from the opcode and the left and
|
||||
* right expressions. Don't worry about the width of the expression
|
||||
@@ -2300,6 +2286,21 @@ const NetProc*NetTaskDef::proc() const
|
||||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.203 2002/11/09 00:25:27 steve
|
||||
* Add dup_expr for user defined function calls.
|
||||
*
|
||||
* Revision 1.202 2002/11/06 02:25:13 steve
|
||||
* No need to keep excess width from an
|
||||
* unsigned constant value, if it can
|
||||
* be trimmed safely.
|
||||
*
|
||||
* Revision 1.201 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.200 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.199 2002/09/01 03:01:48 steve
|
||||
* Properly cast signedness of parameters with ranges.
|
||||
*
|
||||
|
||||
@@ -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.260 2002/08/19 00:06:12 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.271 2002/12/07 02:49:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -51,6 +51,7 @@ class NetProc;
|
||||
class NetProcTop;
|
||||
class NetRelease;
|
||||
class NetScope;
|
||||
class NetEvProbe;
|
||||
class NetExpr;
|
||||
class NetESignal;
|
||||
class NetFuncDef;
|
||||
@@ -296,6 +297,9 @@ class NexusSet {
|
||||
// Return true if this set contains every nexus in that set.
|
||||
bool contains(const NexusSet&that) const;
|
||||
|
||||
// Return true if this set contains any nexus in that set.
|
||||
bool intersect(const NexusSet&that) const;
|
||||
|
||||
private:
|
||||
Nexus**items_;
|
||||
unsigned nitems_;
|
||||
@@ -662,12 +666,20 @@ class NetFF : public NetNode {
|
||||
|
||||
const Link& pin_Clock() const;
|
||||
const Link& pin_Enable() const;
|
||||
const Link& pin_Aset() const;
|
||||
const Link& pin_Aclr() const;
|
||||
const Link& pin_Data(unsigned) const;
|
||||
const Link& pin_Q(unsigned) const;
|
||||
|
||||
void aset_value(const verinum&val);
|
||||
const verinum& aset_value() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
verinum aset_value_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1214,10 +1226,18 @@ class NetProc : public LineInfo {
|
||||
// process. Most process types are not.
|
||||
virtual bool is_asynchronous();
|
||||
|
||||
// Return true if this represents the root of a synchronous
|
||||
// process. Most process types are not.
|
||||
virtual bool is_synchronous();
|
||||
|
||||
// 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_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -1400,6 +1420,10 @@ class NetBlock : public NetProc {
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
// This version of emit_recurse scans all the statements of
|
||||
// the begin-end block sequentially. It is typically of use
|
||||
// for sequential blocks.
|
||||
@@ -1530,6 +1554,10 @@ class NetCondit : public NetProc {
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual int match_proc(struct proc_match_t*);
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
@@ -1735,11 +1763,19 @@ class NetEvWait : public NetProc {
|
||||
// process. This method checks.
|
||||
virtual bool is_asynchronous();
|
||||
|
||||
// It is possible that this is the root of a synchronous
|
||||
// process? This method checks.
|
||||
virtual bool is_synchronous();
|
||||
|
||||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -2116,13 +2152,20 @@ class NetProcTop : public LineInfo, public Attrib {
|
||||
NetScope*scope();
|
||||
const NetScope*scope() const;
|
||||
|
||||
/* Return true of this process represents combinational logic. */
|
||||
/* Return true if this process represents combinational logic. */
|
||||
bool is_asynchronous();
|
||||
|
||||
/* Create asynchronous logic from this thread and return true,
|
||||
or return false if that cannot be done. */
|
||||
bool synth_async(Design*des);
|
||||
|
||||
/* Return true if this process represents synchronous logic. */
|
||||
bool is_synchronous();
|
||||
|
||||
/* Create synchronous logic from this thread and return true,
|
||||
or return false if that cannot be done. */
|
||||
bool synth_sync(Design*des);
|
||||
|
||||
void dump(ostream&, unsigned ind) const;
|
||||
bool emit(struct target_t*tgt) const;
|
||||
|
||||
@@ -2157,8 +2200,9 @@ class NetProcTop : public LineInfo, public Attrib {
|
||||
* n -- Logical inequality (!=)
|
||||
* N -- Case inequality (!==)
|
||||
* a -- Logical AND (&&)
|
||||
* A -- Bitwise NAND (~&)
|
||||
* o -- Logical OR (||)
|
||||
* O -- Bit-wise NOR
|
||||
* O -- Bit-wise NOR (~|)
|
||||
* l -- Left shift (<<)
|
||||
* r -- Right shift (>>)
|
||||
* X -- Bitwise exclusive NOR (~^)
|
||||
@@ -2384,6 +2428,7 @@ class NetEConcat : public NetExpr {
|
||||
NetExpr* parm(unsigned idx) const { return parms_[idx]; }
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual bool has_width() const;
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEConcat* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
@@ -2449,6 +2494,7 @@ class NetESelect : public NetExpr {
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual bool has_width() const;
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetESelect* dup_expr() const;
|
||||
|
||||
private:
|
||||
@@ -2733,16 +2779,23 @@ class NetScope {
|
||||
the scope. The return value from set_parameter is the
|
||||
previous expression, if there was one. */
|
||||
|
||||
NetExpr* set_parameter(const string&name, NetExpr*val);
|
||||
NetExpr* set_parameter(const string&name, NetExpr*val,
|
||||
NetExpr*msb, NetExpr*lsb, bool signed_flag);
|
||||
NetExpr* set_localparam(const string&name, NetExpr*val);
|
||||
const NetExpr*get_parameter(const string&name) const;
|
||||
|
||||
/* These are used by defparam elaboration to replace the
|
||||
expression with a new expression, without affecting the
|
||||
range or signed_flag. Return false if the name does not
|
||||
exist. */
|
||||
bool replace_parameter(const string&name, NetExpr*val);
|
||||
|
||||
/* These methods set or access events that live in this
|
||||
scope. */
|
||||
|
||||
void add_event(NetEvent*);
|
||||
void rem_event(NetEvent*);
|
||||
NetEvent*find_event(const hname_t&name);
|
||||
NetEvent*find_event(const char*name);
|
||||
|
||||
|
||||
/* These methods manage signals. The add_ and rem_signal
|
||||
@@ -2837,8 +2890,14 @@ class NetScope {
|
||||
|
||||
signed char time_unit_, time_prec_;
|
||||
|
||||
map<string,NetExpr*>parameters_;
|
||||
map<string,NetExpr*>localparams_;
|
||||
struct param_expr_t {
|
||||
NetExpr*expr;
|
||||
NetExpr*msb;
|
||||
NetExpr*lsb;
|
||||
bool signed_flag;
|
||||
};
|
||||
map<string,param_expr_t>parameters_;
|
||||
map<string,param_expr_t>localparams_;
|
||||
|
||||
NetEvent *events_;
|
||||
NetNet *signals_;
|
||||
@@ -2938,7 +2997,7 @@ class Design {
|
||||
NetScope* find_task(const hname_t&key);
|
||||
|
||||
// Events
|
||||
NetEvent* find_event(NetScope*scope, const hname_t path);
|
||||
NetEvent* find_event(NetScope*scope, const hname_t&path);
|
||||
|
||||
// NODES
|
||||
void add_node(NetNode*);
|
||||
@@ -3026,6 +3085,44 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
||||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.271 2002/12/07 02:49:24 steve
|
||||
* Named event triggers can take hierarchical names.
|
||||
*
|
||||
* Revision 1.270 2002/12/05 02:14:33 steve
|
||||
* Support bit select in constant expressions.
|
||||
*
|
||||
* Revision 1.269 2002/11/09 01:40:19 steve
|
||||
* Postpone parameter width check to evaluation.
|
||||
*
|
||||
* Revision 1.268 2002/11/02 03:27:52 steve
|
||||
* Allow named events to be referenced by
|
||||
* hierarchical names.
|
||||
*
|
||||
* Revision 1.267 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.266 2002/10/21 01:42:08 steve
|
||||
* Synthesizer support for synchronous begin-end blocks.
|
||||
*
|
||||
* Revision 1.265 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.264 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.263 2002/09/26 01:13:14 steve
|
||||
* Synthesize async set/reset is certain cases.
|
||||
*
|
||||
* Revision 1.262 2002/09/16 00:30:33 steve
|
||||
* Add to synth2 support for synthesis of
|
||||
* synchronous logic. This includes DFF enables
|
||||
* modeled by if/then/else.
|
||||
*
|
||||
* Revision 1.261 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.260 2002/08/19 00:06:12 steve
|
||||
* Allow release to handle removal of target net.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse.y,v 1.159 2002/09/01 03:01:48 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.168 2002/12/10 05:49:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -33,6 +33,13 @@ extern void lex_end_table();
|
||||
static svector<PExpr*>* active_range = 0;
|
||||
static bool active_signed = false;
|
||||
|
||||
/* Later version of bison (including 1.35) will not compile in stack
|
||||
extension if the output is compiled with C++ and either the YYSTYPE
|
||||
or YYLTYPE are provided by the source code. However, I can get the
|
||||
old behavior back by defining these symbols. */
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define YYLTYPE_IS_TRIVIAL 1
|
||||
|
||||
/*
|
||||
* These are some common strength pairs that are used as defaults when
|
||||
* the user is not otherwise specific.
|
||||
@@ -115,7 +122,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
||||
%token K_notif1 K_or K_output K_parameter K_pmos K_posedge K_primitive
|
||||
%token K_pull0 K_pull1 K_pulldown K_pullup K_rcmos K_real K_realtime
|
||||
%token K_reg K_release K_repeat
|
||||
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalered
|
||||
%token K_rnmos K_rpmos K_rtran K_rtranif0 K_rtranif1 K_scalared
|
||||
%token K_signed K_small K_specify
|
||||
%token K_specparam K_strong0 K_strong1 K_supply0 K_supply1 K_table K_task
|
||||
%token K_time K_tran K_tranif0 K_tranif1 K_tri K_tri0 K_tri1 K_triand
|
||||
@@ -551,11 +558,11 @@ dr_strength1
|
||||
;
|
||||
|
||||
event_control
|
||||
: '@' IDENTIFIER
|
||||
{ PEIdent*tmpi = new PEIdent(hname_t($2));
|
||||
: '@' identifier
|
||||
{ PEIdent*tmpi = new PEIdent(*$2);
|
||||
tmpi->set_file(@2.text);
|
||||
tmpi->set_lineno(@2.first_line);
|
||||
delete[]$2;
|
||||
delete $2;
|
||||
PEEvent*tmpe = new PEEvent(PEEvent::ANYEDGE, tmpi);
|
||||
PEventStatement*tmps = new PEventStatement(tmpe);
|
||||
tmps->set_file(@1.text);
|
||||
@@ -736,6 +743,12 @@ expression
|
||||
tmp->set_lineno(@2.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression K_NAND expression
|
||||
{ PEBinary*tmp = new PEBinary('A', $1, $3);
|
||||
tmp->set_file(@2.text);
|
||||
tmp->set_lineno(@2.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression K_NOR expression
|
||||
{ PEBinary*tmp = new PEBinary('O', $1, $3);
|
||||
tmp->set_file(@2.text);
|
||||
@@ -889,7 +902,7 @@ expr_primary
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
delete $1
|
||||
delete $1;
|
||||
}
|
||||
| identifier '[' expression ']'
|
||||
{ PEIdent*tmp = new PEIdent(*$1);
|
||||
@@ -1678,7 +1691,7 @@ localparam_assign_list
|
||||
|
||||
|
||||
/* The parameters of a module instance can be overridden by writing
|
||||
a list of expressions in a syntax much line a delay list. (The
|
||||
a list of expressions in a syntax much like a delay list. (The
|
||||
difference being the list can have any length.) The pform that
|
||||
attaches the expression list to the module checks that the
|
||||
expressions are constant.
|
||||
@@ -2078,6 +2091,7 @@ specify_item_list
|
||||
|
||||
specify_edge_path_decl
|
||||
: specify_edge_path '=' '(' specify_delay_value_list ')'
|
||||
| specify_edge_path '=' delay_value_simple
|
||||
;
|
||||
|
||||
specify_edge_path
|
||||
@@ -2133,9 +2147,9 @@ specparam
|
||||
delete $5;
|
||||
delete $7;
|
||||
}
|
||||
| PATHPULSE_IDENTIFIER '=' '(' expression ')'
|
||||
| PATHPULSE_IDENTIFIER '=' expression
|
||||
{ delete $1;
|
||||
delete $4;
|
||||
delete $3;
|
||||
}
|
||||
| PATHPULSE_IDENTIFIER '=' '(' expression ',' expression ')'
|
||||
{ delete $1;
|
||||
@@ -2309,8 +2323,8 @@ statement
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_TRIGGER IDENTIFIER ';'
|
||||
{ PTrigger*tmp = new PTrigger(hname_t($2));
|
||||
| K_TRIGGER identifier ';'
|
||||
{ PTrigger*tmp = new PTrigger(*$2);
|
||||
tmp->set_file(@2.text);
|
||||
tmp->set_lineno(@2.first_line);
|
||||
delete $2;
|
||||
|
||||
+9
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse_misc.h,v 1.5 2002/08/12 01:35:00 steve Exp $"
|
||||
#ident "$Id: parse_misc.h,v 1.6 2002/11/03 20:36:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -38,6 +38,11 @@ struct vlltype {
|
||||
const char*text;
|
||||
};
|
||||
# define YYLTYPE vlltype
|
||||
|
||||
/* This for compatibility with new and older bison versions. */
|
||||
#ifndef yylloc
|
||||
# define yylloc VLlloc
|
||||
#endif
|
||||
extern YYLTYPE yylloc;
|
||||
|
||||
/*
|
||||
@@ -53,6 +58,9 @@ extern unsigned error_count, warn_count;
|
||||
|
||||
/*
|
||||
* $Log: parse_misc.h,v $
|
||||
* Revision 1.6 2002/11/03 20:36:53 steve
|
||||
* Support old/new bison yylloc.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:35:00 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+7
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform_dump.cc,v 1.76 2002/08/19 02:39:17 steve Exp $"
|
||||
#ident "$Id: pform_dump.cc,v 1.77 2002/10/19 22:59:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -712,6 +712,8 @@ void Module::dump(ostream&out) const
|
||||
for (parm_iter_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
out << " parameter ";
|
||||
if ((*cur).second.signed_flag)
|
||||
out << "signed ";
|
||||
if ((*cur).second.msb)
|
||||
out << "[" << *(*cur).second.msb << ":"
|
||||
<< *(*cur).second.lsb << "] ";
|
||||
@@ -846,6 +848,10 @@ void PUdp::dump(ostream&out) const
|
||||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.77 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.76 2002/08/19 02:39:17 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
|
||||
+27
-6
@@ -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.23 2002/08/12 01:35:00 steve Exp $"
|
||||
#ident "$Id: set_width.cc,v 1.25 2002/11/13 03:03:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -193,9 +193,22 @@ bool NetEBShift::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
left_->set_width(w);
|
||||
if (left_->expr_width() < w)
|
||||
left_ = pad_to_width(left_, w);
|
||||
switch (op()) {
|
||||
|
||||
case 'l':
|
||||
left_->set_width(w);
|
||||
if (left_->expr_width() < w)
|
||||
left_ = pad_to_width(left_, w);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (left_->expr_width() < w)
|
||||
left_ = pad_to_width(left_, w);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
expr_width(left_->expr_width());
|
||||
flag = expr_width() == w;
|
||||
@@ -238,7 +251,7 @@ bool NetEConst::set_width(unsigned w)
|
||||
if (value_.has_sign())
|
||||
pad = value_.get(value_.len()-1);
|
||||
|
||||
verinum tmp (verinum::V0, w);
|
||||
verinum tmp (verinum::V0, w, has_width());
|
||||
for (unsigned idx = 0 ; idx < value_.len() ; idx += 1)
|
||||
tmp.set(idx, value_[idx]);
|
||||
for (unsigned idx = value_.len() ; idx < w ; idx += 1)
|
||||
@@ -259,7 +272,7 @@ bool NetEConst::set_width(unsigned w)
|
||||
if (value_[idx] != verinum::V0)
|
||||
use_w = idx+1;
|
||||
|
||||
verinum tmp (verinum::V0, use_w);
|
||||
verinum tmp (verinum::V0, use_w, has_width());
|
||||
for (unsigned idx = 0 ; idx < use_w ; idx += 1)
|
||||
tmp.set(idx, value_[idx]);
|
||||
|
||||
@@ -357,6 +370,14 @@ bool NetEUReduce::set_width(unsigned w)
|
||||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.25 2002/11/13 03:03:08 steve
|
||||
* Do not truncate high bits of right shift.
|
||||
*
|
||||
* Revision 1.24 2002/11/06 02:25:13 steve
|
||||
* No need to keep excess width from an
|
||||
* unsigned constant value, if it can
|
||||
* be trimmed safely.
|
||||
*
|
||||
* Revision 1.23 2002/08/12 01:35:00 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
PKG="IVLver"
|
||||
NAME="verilog"
|
||||
ARCH="sparc"
|
||||
VERSION="0.6"
|
||||
VERSION="0.7"
|
||||
CATEGORY="application"
|
||||
VENDOR="Icarus.com"
|
||||
EMAIL="[email protected]"
|
||||
|
||||
+5
-10
@@ -1,18 +1,13 @@
|
||||
i pkginfo=./pkginfo
|
||||
d none bin 0755 bin bin
|
||||
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/acc_user.h 0644 bin bin
|
||||
f none include/ivl_target.h 0644 bin bin
|
||||
f none include/vpi_priv.h 0644 bin bin
|
||||
f none include/veriuser.h 0644 bin bin
|
||||
f none include/vpi_user.h 0644 bin bin
|
||||
f none include/vvm.h 0644 bin bin
|
||||
f none include/vvm_calltf.h 0644 bin bin
|
||||
f none include/vvm_func.h 0644 bin bin
|
||||
f none include/vvm_gates.h 0644 bin bin
|
||||
f none include/vvm_nexus.h 0644 bin bin
|
||||
f none include/vvm_signal.h 0644 bin bin
|
||||
f none include/vvm_thread.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
|
||||
@@ -22,10 +17,10 @@ f none lib/ivl/ivlpp 0755 bin bin
|
||||
f none lib/ivl/null.tgt 0644 bin bin
|
||||
f none lib/ivl/system.vpi 0644 bin bin
|
||||
f none lib/ivl/vvp.tgt 0644 bin bin
|
||||
f none lib/libveriuser.a 0644 bin bin
|
||||
f none lib/libvpi.a 0644 bin bin
|
||||
f none lib/libvpip.a 0644 bin bin
|
||||
f none lib/libvvm.a 0644 bin bin
|
||||
d none man 0755 bin bin
|
||||
d none man/man1 0755 bin bin
|
||||
f none man/man1/iverilog.1 0644 bin bin
|
||||
f none man/man1/iverilog-vpi.1 0644 bin bin
|
||||
f none man/man1/vvp.1 0644 bin bin
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sync.cc,v 1.3 2002/09/24 00:58:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* Most process statements are not roots of synchronous logic.
|
||||
*/
|
||||
bool NetProc::is_synchronous()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetEvWait::is_synchronous()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
NetEvent*ev = events_[idx];
|
||||
|
||||
if (ev->nprobe() == 0)
|
||||
return false;
|
||||
|
||||
for (unsigned pdx = 0 ; pdx < ev->nprobe() ; pdx += 1) {
|
||||
NetEvProbe*pr = ev->probe(pdx);
|
||||
|
||||
/* No level sensitive clocks. */
|
||||
if (pr->edge() == NetEvProbe::ANYEDGE)
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* So we know that there is a clock source. Check that the
|
||||
input to the storage is asynchronous. */
|
||||
return true; //statement_->is_asynchronous();
|
||||
}
|
||||
|
||||
bool NetProcTop::is_synchronous()
|
||||
{
|
||||
if (type_ == NetProcTop::KINITIAL)
|
||||
return false;
|
||||
|
||||
return statement_->is_synchronous();
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sync.cc,v $
|
||||
* Revision 1.3 2002/09/24 00:58:35 steve
|
||||
* More detailed check of process edge events.
|
||||
*
|
||||
* Revision 1.2 2002/09/16 21:55:06 steve
|
||||
* Reject multiple probes on synchronous logic.
|
||||
*
|
||||
* Revision 1.1 2002/09/16 00:30:33 steve
|
||||
* Add to synth2 support for synthesis of
|
||||
* synchronous logic. This includes DFF enables
|
||||
* modeled by if/then/else.
|
||||
*
|
||||
*/
|
||||
@@ -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.8 2002/08/18 22:07:16 steve Exp $"
|
||||
#ident "$Id: synth2.cc,v 1.20 2002/11/09 23:29:29 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -27,6 +27,26 @@
|
||||
# include "compiler.h"
|
||||
# include <assert.h>
|
||||
|
||||
bool NetProc::synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetProc::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events)
|
||||
{
|
||||
if (events.count() > 0) {
|
||||
cerr << get_line() << ": error: Events are unaccounted"
|
||||
<< " for in process synthesis." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
return synth_async(des, scope, nex_map, nex_out);
|
||||
}
|
||||
|
||||
static unsigned find_nexus_in_set(const NetNet*nset, const Nexus*nex)
|
||||
{
|
||||
unsigned idx = 0;
|
||||
@@ -57,11 +77,12 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
assert(lsig);
|
||||
assert(lval_->more == 0);
|
||||
|
||||
assert(lsig->pin_count() == nex_map->pin_count());
|
||||
assert(lval_->lwidth() == nex_map->pin_count());
|
||||
assert(nex_map->pin_count() <= rsig->pin_count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(idx).nexus());
|
||||
for (unsigned idx = 0 ; idx < lval_->lwidth() ; idx += 1) {
|
||||
unsigned off = lval_->get_loff()+idx;
|
||||
unsigned ptr = find_nexus_in_set(nex_map, lsig->pin(off).nexus());
|
||||
connect(nex_out->pin(ptr), rsig->pin(idx));
|
||||
}
|
||||
|
||||
@@ -85,27 +106,33 @@ bool NetBlock::synth_async(Design*des, NetScope*scope,
|
||||
do {
|
||||
cur = cur->next_;
|
||||
|
||||
/* Create a temporary nex_out for the substatement. */
|
||||
/* Create a temporary nex_map for the substatement. */
|
||||
NexusSet tmp_set;
|
||||
cur->nex_output(tmp_set);
|
||||
NetNet*tmp_out = new NetNet(scope, "tmp", NetNet::WIRE,
|
||||
NetNet*tmp_map = new NetNet(scope, "tmp1", NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1)
|
||||
connect(tmp_set[idx], tmp_out->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
|
||||
connect(tmp_set[idx], tmp_map->pin(idx));
|
||||
|
||||
bool ok_flag = cur->synth_async(des, scope, tmp_out, tmp_out);
|
||||
/* Create also a temporary net_out to collect the
|
||||
output. */
|
||||
NetNet*tmp_out = new NetNet(scope, "tmp2", NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
|
||||
bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out);
|
||||
flag = flag && ok_flag;
|
||||
|
||||
if (ok_flag == false)
|
||||
continue;
|
||||
|
||||
/* Use tne nex_map to link up the output from the
|
||||
/* Use the nex_map to link up the output from the
|
||||
substatement to the output of the block as a whole. */
|
||||
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));
|
||||
}
|
||||
|
||||
delete tmp_map;
|
||||
delete tmp_out;
|
||||
|
||||
} while (cur != last_);
|
||||
@@ -201,6 +228,14 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
NetNet*ssig = expr_->synthesize(des);
|
||||
assert(ssig);
|
||||
|
||||
if (if_ == 0)
|
||||
return false;
|
||||
if (else_ == 0) {
|
||||
cerr << get_line() << ": error: Asynchronous if statement"
|
||||
<< " is missing the else clause." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(if_ != 0);
|
||||
assert(else_ != 0);
|
||||
|
||||
@@ -241,12 +276,6 @@ bool NetEvWait::synth_async(Design*des, NetScope*scope,
|
||||
return statement_->synth_async(des, scope, nex_map, nex_out);
|
||||
}
|
||||
|
||||
bool NetProc::synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetProcTop::synth_async(Design*des)
|
||||
{
|
||||
NexusSet nex_set;
|
||||
@@ -263,6 +292,379 @@ bool NetProcTop::synth_async(Design*des)
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called when a block is encountered near the surface
|
||||
* of a synchronous always statement. For example, this code will be
|
||||
* invoked for input like this:
|
||||
*
|
||||
* always @(posedge clk...) begin
|
||||
* <statement1>
|
||||
* <statement2>
|
||||
* ...
|
||||
* end
|
||||
*
|
||||
* This needs to be split into a DFF bank for each statement, because
|
||||
* the statements may each infer different reset and enable signals.
|
||||
*/
|
||||
bool NetBlock::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
{
|
||||
if (last_ == 0)
|
||||
return true;
|
||||
|
||||
bool flag = true;
|
||||
|
||||
/* Keep an accounting of which statement accounts for which
|
||||
bit slice of the FF bank. This is used for error checking. */
|
||||
NetProc**pin_accounting = new NetProc* [ff->pin_count()];
|
||||
for (unsigned idx = 0 ; idx < ff->pin_count() ; idx += 1)
|
||||
pin_accounting[idx] = 0;
|
||||
|
||||
NetProc*cur = last_;
|
||||
do {
|
||||
cur = cur->next_;
|
||||
|
||||
/* Create a temporary nex_map for the substatement. */
|
||||
NexusSet tmp_set;
|
||||
cur->nex_output(tmp_set);
|
||||
NetNet*tmp_map = new NetNet(scope, "tmp1", NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
for (unsigned idx = 0 ; idx < tmp_map->pin_count() ; idx += 1)
|
||||
connect(tmp_set[idx], tmp_map->pin(idx));
|
||||
|
||||
/* Create also a temporary net_out to collect the
|
||||
output. The tmp1 and tmp2 map and out sets together
|
||||
are used to collect the outputs from the substatement
|
||||
for the inputs of the FF bank. */
|
||||
NetNet*tmp_out = new NetNet(scope, "tmp2", NetNet::WIRE,
|
||||
tmp_set.count());
|
||||
|
||||
verinum tmp_aset = ff->aset_value();
|
||||
|
||||
/* Create a new DFF to handle this part of the begin-end
|
||||
block. Connect this NetFF to the associated pins of
|
||||
the existing wide NetFF device. While I'm at it, also
|
||||
copy the aset_value bits for the new ff device. */
|
||||
NetFF*ff2 = new NetFF(scope, scope->local_hsymbol().c_str(),
|
||||
tmp_out->pin_count());
|
||||
des->add_node(ff2);
|
||||
|
||||
verinum aset_value2 (verinum::V1, ff2->width());
|
||||
for (unsigned idx = 0 ; idx < ff2->width() ; idx += 1) {
|
||||
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
|
||||
connect(ff->pin_Data(ptr), ff2->pin_Data(idx));
|
||||
connect(ff->pin_Q(ptr), ff2->pin_Q(idx));
|
||||
|
||||
if (ptr < tmp_aset.len())
|
||||
aset_value2.set(idx, tmp_aset[ptr]);
|
||||
|
||||
if (pin_accounting[ptr] != 0) {
|
||||
cerr << cur->get_line() << ": error: "
|
||||
<< "Synchronous output conflicts with "
|
||||
<< pin_accounting[ptr]->get_line()
|
||||
<< "." << endl;
|
||||
flag = false;
|
||||
|
||||
} else {
|
||||
pin_accounting[ptr] = cur;
|
||||
}
|
||||
}
|
||||
if (ff->pin_Aclr().is_linked())
|
||||
connect(ff->pin_Aclr(), ff2->pin_Aclr());
|
||||
if (ff->pin_Aset().is_linked())
|
||||
connect(ff->pin_Aset(), ff2->pin_Aset());
|
||||
if (ff->pin_Clock().is_linked())
|
||||
connect(ff->pin_Clock(), ff2->pin_Clock());
|
||||
if (ff->pin_Enable().is_linked())
|
||||
connect(ff->pin_Enable(),ff2->pin_Enable());
|
||||
|
||||
/* Remember to store the aset value into the new FF. If
|
||||
this leads to an Aset value of 0 (and Aclr is not
|
||||
otherwise used) then move the Aset input to Aclr. */
|
||||
if (tmp_aset.len() == ff->width()) {
|
||||
|
||||
if ((aset_value2.as_ulong() == 0)
|
||||
&& ff2->pin_Aset().is_linked()
|
||||
&& !ff2->pin_Aclr().is_linked()) {
|
||||
|
||||
connect(ff2->pin_Aclr(), ff2->pin_Aset());
|
||||
ff2->pin_Aset().unlink();
|
||||
|
||||
} else {
|
||||
ff2->aset_value(aset_value2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now go on with the synchronous synthesis for this
|
||||
subset of the statement. */
|
||||
bool ok_flag = cur->synth_sync(des, scope, ff2, tmp_map,
|
||||
tmp_out, events_in);
|
||||
flag = flag && ok_flag;
|
||||
|
||||
if (ok_flag == false)
|
||||
continue;
|
||||
|
||||
/* Use the nex_map to link up the output from the
|
||||
substatement to the output of the block as a
|
||||
whole. It is occasionally possible to have outputs
|
||||
beyond the input set, for example when the l-value of
|
||||
an assignment is smaller then the r-value. */
|
||||
for (unsigned idx = 0 ; idx < tmp_out->pin_count() ; idx += 1) {
|
||||
unsigned ptr = find_nexus_in_set(nex_map, tmp_set[idx]);
|
||||
if (ptr < nex_out->pin_count())
|
||||
connect(nex_out->pin(ptr), tmp_out->pin(idx));
|
||||
}
|
||||
|
||||
delete tmp_map;
|
||||
delete tmp_out;
|
||||
|
||||
} while (cur != last_);
|
||||
|
||||
delete[]pin_accounting;
|
||||
|
||||
/* Done. The large NetFF is no longer needed, as it has been
|
||||
taken up by the smaller NetFF devices. */
|
||||
delete ff;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method handles the case where I find a conditional near the
|
||||
* surface of a synchronous thread. This conditional can be a CE or an
|
||||
* asynchronous set/reset, depending on whether the pin of the
|
||||
* expression is connected to an event, or not.
|
||||
*/
|
||||
bool NetCondit::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
{
|
||||
|
||||
/* Synthesize the enable expression. */
|
||||
NetNet*ce = expr_->synthesize(des);
|
||||
assert(ce->pin_count() == 1);
|
||||
|
||||
/* Try first to turn the ce into an asynchronous set/reset
|
||||
input. If the ce is linked to a probe, then that probe is a
|
||||
set/reset input. */
|
||||
for (unsigned idx = 0 ; idx < events_in.count() ; idx += 1) {
|
||||
NetEvProbe*ev = events_in[idx];
|
||||
|
||||
if (connected(ce->pin(0), ev->pin(0))) {
|
||||
|
||||
bool flag = true;
|
||||
assert(ev->edge() == NetEvProbe::POSEDGE);
|
||||
|
||||
/* Synthesize the true clause to figure out what
|
||||
kind of set/reset we have. */
|
||||
NetNet*asig = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::WIRE, nex_map->pin_count());
|
||||
asig->local_flag(true);
|
||||
flag = if_->synth_async(des, scope, nex_map, asig) && flag;
|
||||
|
||||
assert(asig->pin_count() == ff->width());
|
||||
|
||||
/* Collect the set/reset value into a verinum. If
|
||||
this turns out to be entirely 0 values, then
|
||||
use the Aclr input. Otherwise, use the Aset
|
||||
input and save the set value. */
|
||||
verinum tmp (verinum::V0, ff->width());
|
||||
for (unsigned bit = 0 ; bit < ff->width() ; bit += 1) {
|
||||
|
||||
assert(asig->pin(bit).nexus()->drivers_constant());
|
||||
tmp.set(bit, asig->pin(bit).nexus()->driven_value());
|
||||
}
|
||||
|
||||
assert(tmp.is_defined());
|
||||
if (tmp.as_ulong() == 0) {
|
||||
connect(ff->pin_Aclr(), ce->pin(0));
|
||||
|
||||
} else {
|
||||
connect(ff->pin_Aset(), ce->pin(0));
|
||||
ff->aset_value(tmp);
|
||||
}
|
||||
|
||||
delete asig;
|
||||
|
||||
assert(events_in.count() == 1);
|
||||
return else_->synth_sync(des, scope, ff, nex_map,
|
||||
nex_out, svector<NetEvProbe*>(0))
|
||||
&& flag;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Failed to find an asynchronous set/reset, so any events
|
||||
input are probably in error. */
|
||||
if (events_in.count() > 0) {
|
||||
cerr << get_line() << ": error: Events are unaccounted"
|
||||
<< " for in process synthesis." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
/* If this is an if/then/else, then it is likely a
|
||||
combinational if, and I should synthesize it that way. */
|
||||
if (if_ && else_) {
|
||||
return synth_async(des, scope, nex_map, nex_out);
|
||||
}
|
||||
|
||||
assert(if_);
|
||||
assert(!else_);
|
||||
|
||||
/* What's left, is a synchronous CE statement like this:
|
||||
|
||||
if (expr_) <true statement>;
|
||||
|
||||
The expr_ expression has alreacy been synthesized to the ce
|
||||
net, so we connect it here to the FF. What's left is to
|
||||
synthesize the substatement as a combinational
|
||||
statement.
|
||||
|
||||
Watch out for the special case that there is already a CE
|
||||
connected to this FF. This can be caused by code like this:
|
||||
|
||||
if (a) if (b) <statement>;
|
||||
|
||||
In this case, we are working on the inner IF, so we AND the
|
||||
a and b expressions to make a new CE. */
|
||||
|
||||
if (ff->pin_Enable().is_linked()) {
|
||||
NetLogic*ce_and = new NetLogic(scope,
|
||||
scope->local_hsymbol(), 3,
|
||||
NetLogic::AND);
|
||||
des->add_node(ce_and);
|
||||
connect(ff->pin_Enable(), ce_and->pin(1));
|
||||
connect(ce->pin(0), ce_and->pin(2));
|
||||
|
||||
ff->pin_Enable().unlink();
|
||||
connect(ff->pin_Enable(), ce_and->pin(0));
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->local_flag(true);
|
||||
connect(ff->pin_Enable(), tmp->pin(0));
|
||||
|
||||
} else {
|
||||
|
||||
connect(ff->pin_Enable(), ce->pin(0));
|
||||
}
|
||||
|
||||
bool flag = if_->synth_sync(des, scope, ff, nex_map, nex_out, events_in);
|
||||
if (flag == false)
|
||||
return flag;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events_in)
|
||||
{
|
||||
if (events_in.count() > 0) {
|
||||
cerr << get_line() << ": error: Events are unaccounted"
|
||||
<< " for in process synthesis." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
assert(events_in.count() == 0);
|
||||
|
||||
/* This can't be other then one unless there are named events,
|
||||
which I cannot synthesize. */
|
||||
assert(nevents_ == 1);
|
||||
NetEvent*ev = events_[0];
|
||||
|
||||
assert(ev->nprobe() >= 1);
|
||||
svector<NetEvProbe*>events (ev->nprobe() - 1);
|
||||
|
||||
/* Get the input set from the substatement. This will be used
|
||||
to figure out which of the probes in the clock. */
|
||||
NexusSet*statement_input = statement_ -> nex_input();
|
||||
|
||||
/* Search for a clock input. The clock input is the edge event
|
||||
that is not also an input to the substatement. */
|
||||
NetEvProbe*pclk = 0;
|
||||
unsigned event_idx = 0;
|
||||
for (unsigned idx = 0 ; idx < ev->nprobe() ; idx += 1) {
|
||||
NetEvProbe*tmp = ev->probe(idx);
|
||||
assert(tmp->pin_count() == 1);
|
||||
|
||||
NexusSet tmp_nex;
|
||||
tmp_nex .add( tmp->pin(0).nexus() );
|
||||
|
||||
if (! statement_input ->contains(tmp_nex)) {
|
||||
if (pclk != 0) {
|
||||
cerr << get_line() << ": error: Too many "
|
||||
<< "clocks for synchronous logic." << endl;
|
||||
cerr << get_line() << ": : Perhaps an"
|
||||
<< " asynchronous set/reset is misused?" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
pclk = tmp;
|
||||
|
||||
} else {
|
||||
events[event_idx++] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (pclk == 0) {
|
||||
cerr << get_line() << ": error: None of the edges"
|
||||
<< " are valid clock inputs." << endl;
|
||||
cerr << get_line() << ": : Perhaps the clock"
|
||||
<< " is read by a statement or expression?" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
connect(ff->pin_Clock(), pclk->pin(0));
|
||||
if (pclk->edge() == NetEvProbe::NEGEDGE)
|
||||
ff->attribute("Clock:LPM_Polarity", verinum("INVERT"));
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope, ff,
|
||||
nex_map, nex_out, events);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetProcTop::synth_sync(Design*des)
|
||||
{
|
||||
NexusSet nex_set;
|
||||
statement_->nex_output(nex_set);
|
||||
|
||||
NetFF*ff = new NetFF(scope(), scope()->local_hsymbol().c_str(),
|
||||
nex_set.count());
|
||||
des->add_node(ff);
|
||||
ff->attribute("LPM_FFType", verinum("DFF"));
|
||||
|
||||
/* The D inputs to the DFF device will receive the output from
|
||||
the statments of the process. */
|
||||
NetNet*nex_d = new NetNet(scope(), scope()->local_hsymbol().c_str(),
|
||||
NetNet::WIRE, nex_set.count());
|
||||
nex_d->local_flag(true);
|
||||
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
|
||||
connect(nex_d->pin(idx), ff->pin_Data(idx));
|
||||
}
|
||||
|
||||
/* The Q outputs of the DFF will connect to the actual outputs
|
||||
of the process. Thus, the DFF will be between the outputs
|
||||
of the process and the outputs of the substatement. */
|
||||
NetNet*nex_q = new NetNet(scope(), "tmpq", NetNet::WIRE,
|
||||
nex_set.count());
|
||||
for (unsigned idx = 0 ; idx < nex_set.count() ; idx += 1) {
|
||||
connect(nex_set[idx], nex_q->pin(idx));
|
||||
connect(nex_q->pin(idx), ff->pin_Q(idx));
|
||||
}
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope(), ff,
|
||||
nex_q, nex_d,
|
||||
svector<NetEvProbe*>());
|
||||
|
||||
delete nex_q;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
class synth2_f : public functor_t {
|
||||
|
||||
public:
|
||||
@@ -281,6 +683,18 @@ void synth2_f::process(class Design*des, class NetProcTop*top)
|
||||
if (top->attribute("ivl_synthesis_off").as_ulong() != 0)
|
||||
return;
|
||||
|
||||
if (top->is_synchronous()) do {
|
||||
bool flag = top->synth_sync(des);
|
||||
if (! flag) {
|
||||
cerr << top->get_line() << ": error: "
|
||||
<< "Unable to synthesize synchronous process." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
des->delete_process(top);
|
||||
return;
|
||||
} while (0);
|
||||
|
||||
if (! top->is_asynchronous()) {
|
||||
bool synth_error_flag = false;
|
||||
if (top->attribute("ivl_combinational").as_ulong() != 0) {
|
||||
@@ -324,6 +738,45 @@ void synth2(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: synth2.cc,v $
|
||||
* Revision 1.20 2002/11/09 23:29:29 steve
|
||||
* Handle nested-if chip enables.
|
||||
*
|
||||
* Revision 1.19 2002/11/09 20:22:57 steve
|
||||
* Detect synthesis conflicts blocks statements share outputs.
|
||||
*
|
||||
* Revision 1.18 2002/11/06 03:22:28 steve
|
||||
* More forgiving about assignment rval width mismatch.
|
||||
*
|
||||
* Revision 1.17 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.16 2002/10/21 01:42:09 steve
|
||||
* Synthesizer support for synchronous begin-end blocks.
|
||||
*
|
||||
* Revision 1.15 2002/10/20 19:19:37 steve
|
||||
* Handle conditional error cases better.
|
||||
*
|
||||
* Revision 1.14 2002/09/26 03:42:10 steve
|
||||
* Remove excess debug messages.
|
||||
*
|
||||
* Revision 1.13 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.12 2002/09/26 01:13:14 steve
|
||||
* Synthesize async set/reset is certain cases.
|
||||
*
|
||||
* Revision 1.11 2002/09/24 00:58:35 steve
|
||||
* More detailed check of process edge events.
|
||||
*
|
||||
* Revision 1.10 2002/09/17 04:40:28 steve
|
||||
* Connect output of block to net_out, instead of statement outputs.
|
||||
*
|
||||
* Revision 1.9 2002/09/16 00:30:33 steve
|
||||
* Add to synth2 support for synthesis of
|
||||
* synchronous logic. This includes DFF enables
|
||||
* modeled by if/then/else.
|
||||
*
|
||||
* Revision 1.8 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
|
||||
+43
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.86 2002/08/12 01:35:00 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.88 2002/10/23 01:47:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -540,6 +540,29 @@ extern "C" const char* ivl_lpm_basename(ivl_lpm_t net)
|
||||
return basename(net->scope, net->name);
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch(net->type) {
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.aclr;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch(net->type) {
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.aset;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
||||
{
|
||||
@@ -554,6 +577,18 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.aset_value;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
extern "C" ivl_scope_t ivl_lpm_define(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1550,6 +1585,13 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.88 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.87 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.86 2002/08/12 01:35:00 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+37
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-expr.cc,v 1.28 2002/08/12 01:35:00 steve Exp $"
|
||||
#ident "$Id: t-dll-expr.cc,v 1.29 2002/10/23 01:47:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -103,6 +103,38 @@ void dll_target::mul_expr_by_const_(long val)
|
||||
expr_ = tmps;
|
||||
}
|
||||
|
||||
ivl_expr_t dll_target::expr_from_value_(const verinum&val)
|
||||
{
|
||||
ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(expr);
|
||||
|
||||
unsigned idx;
|
||||
char*bits;
|
||||
expr->type_ = IVL_EX_NUMBER;
|
||||
expr->width_= val.len();
|
||||
expr->signed_ = val.has_sign()? 1 : 0;
|
||||
expr->u_.number_.bits_ = bits = (char*)malloc(expr->width_);
|
||||
for (idx = 0 ; idx < expr->width_ ; idx += 1)
|
||||
switch (val.get(idx)) {
|
||||
case verinum::V0:
|
||||
bits[idx] = '0';
|
||||
break;
|
||||
case verinum::V1:
|
||||
bits[idx] = '1';
|
||||
break;
|
||||
case verinum::Vx:
|
||||
bits[idx] = 'x';
|
||||
break;
|
||||
case verinum::Vz:
|
||||
bits[idx] = 'z';
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
void dll_target::expr_binary(const NetEBinary*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
@@ -458,6 +490,10 @@ void dll_target::expr_unary(const NetEUnary*net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-expr.cc,v $
|
||||
* Revision 1.29 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.28 2002/08/12 01:35:00 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -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.95 2002/08/12 01:35:00 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.100 2002/11/05 02:12:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -36,32 +36,33 @@
|
||||
|
||||
inline ivl_dll_t ivl_dlopen(const char *name)
|
||||
{
|
||||
return (ivl_dll_t) LoadLibrary(name);
|
||||
ivl_dll_t res = (ivl_dll_t) LoadLibrary(name);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
inline void * ivl_dlsym(ivl_dll_t dll, const char *nm)
|
||||
{
|
||||
FARPROC sym;
|
||||
return GetProcAddress((HMODULE)dll, nm);
|
||||
FARPROC sym;
|
||||
return (void*)GetProcAddress((HMODULE)dll, nm);
|
||||
}
|
||||
|
||||
inline void ivl_dlclose(ivl_dll_t dll)
|
||||
{
|
||||
FreeLibrary((HMODULE)dll);
|
||||
FreeLibrary((HMODULE)dll);
|
||||
}
|
||||
|
||||
const char *dlerror(void)
|
||||
{
|
||||
static char msg[255];
|
||||
|
||||
static char msg[256];
|
||||
unsigned long err = GetLastError();
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &msg,
|
||||
0,
|
||||
sizeof(msg) - 1,
|
||||
NULL
|
||||
);
|
||||
return msg;
|
||||
@@ -448,6 +449,7 @@ bool dll_target::start_design(const Design*des)
|
||||
dll_path_ = des->get_flag("DLL");
|
||||
dll_ = ivl_dlopen(dll_path_.c_str());
|
||||
if (dll_ == 0) {
|
||||
cerr << "error: " << dll_path_ << " failed to load." << endl;
|
||||
cerr << dll_path_ << ": " << dlerror() << endl;
|
||||
return false;
|
||||
}
|
||||
@@ -1361,6 +1363,31 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
obj->u_.ff.we = 0;
|
||||
}
|
||||
|
||||
if (net->pin_Aclr().is_linked()) {
|
||||
nex = net->pin_Aclr().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.aclr = (ivl_nexus_t) nex->t_cookie();
|
||||
assert(obj->u_.ff.aclr);
|
||||
nexus_lpm_add(obj->u_.ff.aclr, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
} else {
|
||||
obj->u_.ff.aclr = 0;
|
||||
}
|
||||
|
||||
if (net->pin_Aset().is_linked()) {
|
||||
nex = net->pin_Aset().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.aset = (ivl_nexus_t) nex->t_cookie();
|
||||
assert(obj->u_.ff.aset);
|
||||
nexus_lpm_add(obj->u_.ff.aset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
verinum tmp = net->aset_value();
|
||||
obj->u_.ff.aset_value = expr_from_value_(tmp);
|
||||
|
||||
} else {
|
||||
obj->u_.ff.aset = 0;
|
||||
obj->u_.ff.aset_value = 0;
|
||||
}
|
||||
|
||||
if (obj->u_.ff.width == 1) {
|
||||
nex = net->pin_Q(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
@@ -1954,6 +1981,22 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.100 2002/11/05 02:12:35 steve
|
||||
* Fix the call to FormatMessage under Windows.
|
||||
*
|
||||
* Revision 1.99 2002/11/03 22:44:19 steve
|
||||
* Cast for gcc convenience.
|
||||
*
|
||||
* Revision 1.98 2002/11/03 20:47:23 steve
|
||||
* Slightly more verbose load fail message.
|
||||
*
|
||||
* Revision 1.97 2002/10/23 01:47:18 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.96 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.95 2002/08/12 01:35:00 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.h,v 1.93 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.95 2002/10/23 01:47:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -154,6 +154,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
|
||||
void sub_off_from_expr_(long);
|
||||
void mul_expr_by_const_(long);
|
||||
|
||||
static ivl_expr_t expr_from_value_(const verinum&that);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -267,6 +269,8 @@ struct ivl_lpm_s {
|
||||
unsigned short swid; // ram only
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
ivl_nexus_t aclr;
|
||||
ivl_nexus_t aset;
|
||||
union {
|
||||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
@@ -280,6 +284,7 @@ struct ivl_lpm_s {
|
||||
ivl_nexus_t pin;
|
||||
} s;
|
||||
ivl_memory_t mem; // ram only
|
||||
ivl_expr_t aset_value;
|
||||
} ff;
|
||||
|
||||
struct ivl_lpm_mux_s {
|
||||
@@ -617,6 +622,13 @@ struct ivl_statement_s {
|
||||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.95 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.94 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.93 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.5 2002/08/12 00:27:10 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.6 2002/11/05 02:14:41 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -79,7 +79,7 @@ check: all
|
||||
install: all installdirs $(libdir)/ivl/fpga.tgt
|
||||
|
||||
$(libdir)/ivl/fpga.tgt: ./fpga.tgt
|
||||
$(INSTALL_DATA) ./fpga.tgt $(libdir)/ivl/fpga.tgt
|
||||
$(INSTALL_PROGRAM) ./fpga.tgt $(libdir)/ivl/fpga.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-generic-edif.c,v 1.9 2002/08/12 01:35:02 steve Exp $"
|
||||
#ident "$Id: d-generic-edif.c,v 1.12 2002/11/01 02:36:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "device.h"
|
||||
@@ -174,7 +174,18 @@ static const char*external_library_text =
|
||||
" (port Q (direction OUTPUT))\n"
|
||||
" (port D (direction INPUT))\n"
|
||||
" (port C (direction INPUT))\n"
|
||||
" (port CE (direction INPUT)))))\n"
|
||||
" (port CE (direction INPUT))\n"
|
||||
" (port CLR (direction INPUT)))))\n"
|
||||
" (cell FDCPE (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
" (interface\n"
|
||||
" (port Q (direction OUTPUT))\n"
|
||||
" (port D (direction INPUT))\n"
|
||||
" (port C (direction INPUT))\n"
|
||||
" (port CE (direction INPUT))\n"
|
||||
" (port PRE (direction INPUT))\n"
|
||||
" (port CLR (direction INPUT)))))\n"
|
||||
" (cell GND (cellType GENERIC)\n"
|
||||
" (view net\n"
|
||||
" (viewType NETLIST)\n"
|
||||
@@ -226,11 +237,11 @@ static void edif_show_consts(ivl_design_t des)
|
||||
switch (val[pin]) {
|
||||
case '0':
|
||||
name = "GND";
|
||||
port = "G";
|
||||
port = "GROUND";
|
||||
break;
|
||||
case '1':
|
||||
name = "VCC";
|
||||
port = "P";
|
||||
port = "VCC";
|
||||
break;
|
||||
default:
|
||||
name = "???";
|
||||
@@ -260,7 +271,8 @@ void edif_show_footer(ivl_design_t des)
|
||||
edif_show_consts(des);
|
||||
|
||||
for (cur = net_list ; cur ; cur = cur->next) {
|
||||
fprintf(xnf, "(net N%u (joined %s))\n", nref, cur->joined);
|
||||
fprintf(xnf, "(net (rename N%u \"%s\") (joined %s))\n",
|
||||
nref, ivl_nexus_name(cur->nex), cur->joined);
|
||||
nref += 1;
|
||||
}
|
||||
|
||||
@@ -355,6 +367,19 @@ void edif_show_generic_dff(ivl_lpm_t net)
|
||||
ivl_nexus_t nex;
|
||||
char jbuf[1024];
|
||||
unsigned idx;
|
||||
ivl_nexus_t aclr = ivl_lpm_async_clr(net);
|
||||
ivl_nexus_t aset = ivl_lpm_async_set(net);
|
||||
ivl_expr_t avalue = 0;
|
||||
const char*abits = 0;
|
||||
const char*fdcell = "FDCE";
|
||||
|
||||
if (aset != 0) {
|
||||
fdcell = "FDCPE";
|
||||
avalue = ivl_lpm_aset_value(net);
|
||||
assert(avalue);
|
||||
abits = ivl_expr_bits(avalue);
|
||||
assert(abits);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
|
||||
|
||||
@@ -363,7 +388,8 @@ void edif_show_generic_dff(ivl_lpm_t net)
|
||||
fprintf(xnf, "(instance (rename U%u \"%s[%u]\")",
|
||||
edif_uref, ivl_lpm_name(net), idx);
|
||||
fprintf(xnf, " (viewRef net"
|
||||
" (cellRef FDCE (libraryRef VIRTEX))))\n");
|
||||
" (cellRef %s (libraryRef VIRTEX))))\n",
|
||||
fdcell);
|
||||
|
||||
nex = ivl_lpm_q(net, idx);
|
||||
sprintf(jbuf, "(portRef Q (instanceRef U%u))", edif_uref);
|
||||
@@ -381,6 +407,25 @@ void edif_show_generic_dff(ivl_lpm_t net)
|
||||
sprintf(jbuf, "(portRef CE (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(nex, jbuf);
|
||||
}
|
||||
|
||||
if (aclr) {
|
||||
sprintf(jbuf, "(portRef CLR (instanceRef U%u))", edif_uref);
|
||||
edif_set_nexus_joint(aclr, jbuf);
|
||||
}
|
||||
|
||||
|
||||
if (aset) {
|
||||
if (abits[idx] == '1') {
|
||||
sprintf(jbuf, "(portRef PRE (instanceRef U%u))",
|
||||
edif_uref);
|
||||
edif_set_nexus_joint(aset, jbuf);
|
||||
} else {
|
||||
assert(aclr == 0);
|
||||
sprintf(jbuf, "(portRef CLR (instanceRef U%u))",
|
||||
edif_uref);
|
||||
edif_set_nexus_joint(aset, jbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,12 +439,28 @@ const struct device_s d_generic_edif = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
0,
|
||||
0, /* show_add */
|
||||
0, /* show_sub */
|
||||
0, /* show_shiftl */
|
||||
0 /* show_shiftr */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: d-generic-edif.c,v $
|
||||
* Revision 1.12 2002/11/01 02:36:22 steve
|
||||
* Give nets better names, if available.
|
||||
*
|
||||
* Revision 1.11 2002/10/30 03:58:45 steve
|
||||
* Fix up left shift to pass compile,
|
||||
* fix up ADD/SUB to generate missing pieces,
|
||||
* Add the asynch set/reset to DFF devices.
|
||||
*
|
||||
* Revision 1.10 2002/10/28 02:05:56 steve
|
||||
* Add Virtex code generators for left shift,
|
||||
* subtraction, and GE comparators.
|
||||
*
|
||||
* Revision 1.9 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+10
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: d-generic.c,v 1.11 2002/08/12 01:35:02 steve Exp $"
|
||||
#ident "$Id: d-generic.c,v 1.12 2002/10/28 02:05:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "device.h"
|
||||
@@ -503,13 +503,21 @@ const struct device_s d_generic = {
|
||||
generic_show_dff,
|
||||
generic_show_cmp_eq,
|
||||
generic_show_cmp_eq,
|
||||
0, /* ge not implemented */
|
||||
generic_show_mux,
|
||||
generic_show_add
|
||||
generic_show_add,
|
||||
0, /* subtract not implemented */
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: d-generic.c,v $
|
||||
* Revision 1.12 2002/10/28 02:05:56 steve
|
||||
* Add Virtex code generators for left shift,
|
||||
* subtraction, and GE comparators.
|
||||
*
|
||||
* Revision 1.11 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+914
-75
File diff suppressed because it is too large
Load Diff
+10
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: device.h,v 1.9 2002/08/12 01:35:02 steve Exp $"
|
||||
#ident "$Id: device.h,v 1.10 2002/10/28 02:05:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
@@ -50,10 +50,15 @@ struct device_s {
|
||||
/* 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);
|
||||
/* 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);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -68,6 +73,10 @@ extern device_t device_from_arch(const char*arch);
|
||||
|
||||
/*
|
||||
* $Log: device.h,v $
|
||||
* Revision 1.10 2002/10/28 02:05:56 steve
|
||||
* Add Virtex code generators for left shift,
|
||||
* subtraction, and GE comparators.
|
||||
*
|
||||
* Revision 1.9 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+41
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: gates.c,v 1.9 2002/08/12 01:35:03 steve Exp $"
|
||||
#ident "$Id: gates.c,v 1.10 2002/10/28 02:05:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
@@ -42,6 +42,15 @@ static void show_gate_lpm(ivl_lpm_t net)
|
||||
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"
|
||||
@@ -60,6 +69,15 @@ static void show_gate_lpm(ivl_lpm_t net)
|
||||
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_FF:
|
||||
if (device->show_dff == 0) {
|
||||
fprintf(stderr, "fpga.tgt: IVL_LPM_FF not supported"
|
||||
@@ -78,6 +96,24 @@ static void show_gate_lpm(ivl_lpm_t net)
|
||||
device->show_mux(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));
|
||||
@@ -100,6 +136,10 @@ int show_scope_gates(ivl_scope_t net, void*x)
|
||||
|
||||
/*
|
||||
* $Log: gates.c,v $
|
||||
* Revision 1.10 2002/10/28 02:05:56 steve
|
||||
* Add Virtex code generators for left shift,
|
||||
* subtraction, and GE comparators.
|
||||
*
|
||||
* Revision 1.9 2002/08/12 01:35:03 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.6 2001/11/17 17:57:58 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.7 2002/11/05 02:14:41 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -74,7 +74,7 @@ distclean: clean
|
||||
install: all installdirs $(libdir)/ivl/null.tgt
|
||||
|
||||
$(libdir)/ivl/null.tgt: ./null.tgt
|
||||
$(INSTALL_DATA) ./null.tgt $(libdir)/ivl/null.tgt
|
||||
$(INSTALL_PROGRAM) ./null.tgt $(libdir)/ivl/null.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.8 2001/11/17 17:57:58 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.9 2002/11/05 02:14:41 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -71,7 +71,7 @@ clean:
|
||||
install: all installdirs $(libdir)/ivl/pal.tgt
|
||||
|
||||
$(libdir)/ivl/pal.tgt: ./pal.tgt
|
||||
$(INSTALL_DATA) ./pal.tgt $(libdir)/ivl/pal.tgt
|
||||
$(INSTALL_PROGRAM) ./pal.tgt $(libdir)/ivl/pal.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.9 2001/11/17 17:57:58 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.10 2002/11/05 02:14:41 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -72,7 +72,7 @@ install: all installdirs $(libdir)/ivl/stub.tgt \
|
||||
$(includedir)/vpi_user.h
|
||||
|
||||
$(libdir)/ivl/stub.tgt: ./stub.tgt
|
||||
$(INSTALL_DATA) ./stub.tgt $(libdir)/ivl/stub.tgt
|
||||
$(INSTALL_PROGRAM) ./stub.tgt $(libdir)/ivl/stub.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
|
||||
+38
-3
@@ -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.66 2002/08/12 01:35:03 steve Exp $"
|
||||
#ident "$Id: stub.c,v 1.70 2002/10/23 01:45:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -182,8 +182,25 @@ static void show_lpm(ivl_lpm_t net)
|
||||
|
||||
fprintf(out, " LPM_FF %s: <width=%u>\n",
|
||||
ivl_lpm_name(net), width);
|
||||
fprintf(out, " clk: %s\n",
|
||||
ivl_nexus_name(ivl_lpm_clk(net)));
|
||||
|
||||
if (ivl_lpm_enable(net))
|
||||
fprintf(out, " clk: %s CE: %s\n",
|
||||
ivl_nexus_name(ivl_lpm_clk(net)),
|
||||
ivl_nexus_name(ivl_lpm_enable(net)));
|
||||
else
|
||||
fprintf(out, " clk: %s\n",
|
||||
ivl_nexus_name(ivl_lpm_clk(net)));
|
||||
|
||||
if (ivl_lpm_async_clr(net))
|
||||
fprintf(out, " Aclr: %s\n",
|
||||
ivl_nexus_name(ivl_lpm_async_clr(net)));
|
||||
|
||||
if (ivl_lpm_async_set(net)) {
|
||||
fprintf(out, " Aset: %s\n",
|
||||
ivl_nexus_name(ivl_lpm_async_set(net)));
|
||||
if (ivl_lpm_aset_value(net))
|
||||
show_expression(ivl_lpm_aset_value(net), 10);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1)
|
||||
fprintf(out, " Data %u: %s\n", idx,
|
||||
@@ -476,6 +493,8 @@ static void show_signal(ivl_signal_t net)
|
||||
case IVL_SIT_SUPPLY1:
|
||||
type = "supply1";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ivl_signal_port(net)) {
|
||||
@@ -491,6 +510,9 @@ static void show_signal(ivl_signal_t net)
|
||||
case IVL_SIP_INOUT:
|
||||
port = "inout ";
|
||||
break;
|
||||
|
||||
case IVL_SIP_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(out, " %s %s %s[%u] %s\n", type, sign, port,
|
||||
@@ -706,6 +728,19 @@ int target_design(ivl_design_t des)
|
||||
|
||||
/*
|
||||
* $Log: stub.c,v $
|
||||
* Revision 1.70 2002/10/23 01:45:24 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.69 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.68 2002/09/18 03:33:10 steve
|
||||
* Fix switch case warnings.
|
||||
*
|
||||
* Revision 1.67 2002/09/16 00:28:25 steve
|
||||
* Display FF enables.
|
||||
*
|
||||
* Revision 1.66 2002/08/12 01:35:03 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.8 2001/11/17 17:57:58 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.9 2002/11/05 02:14:41 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -71,7 +71,7 @@ install: all installdirs $(libdir)/ivl/verilog.tgt \
|
||||
$(includedir)/vpi_user.h
|
||||
|
||||
$(libdir)/ivl/verilog.tgt: ./verilog.tgt
|
||||
$(INSTALL_DATA) ./verilog.tgt $(libdir)/ivl/verilog.tgt
|
||||
$(INSTALL_PROGRAM) ./verilog.tgt $(libdir)/ivl/verilog.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.10 2002/08/12 00:27:10 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.12 2002/11/05 02:14:41 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -50,7 +50,7 @@ all: vvp.tgt
|
||||
$(CC) -Wall @ident_support@ -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = vvp.o draw_mux.o eval_expr.o vvp_process.o vvp_scope.o
|
||||
O = vvp.o draw_mux.o eval_expr.o vector.o vvp_process.o vvp_scope.o
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
@@ -78,7 +78,7 @@ check: all
|
||||
install: all installdirs $(libdir)/ivl/vvp.tgt
|
||||
|
||||
$(libdir)/ivl/vvp.tgt: ./vvp.tgt
|
||||
$(INSTALL_DATA) ./vvp.tgt $(libdir)/ivl/vvp.tgt
|
||||
$(INSTALL_PROGRAM) ./vvp.tgt $(libdir)/ivl/vvp.tgt
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
|
||||
+346
-229
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_expr.c,v 1.74 2002/09/01 01:42:34 steve Exp $"
|
||||
#ident "$Id: eval_expr.c,v 1.86 2002/11/22 00:01:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -28,71 +28,8 @@
|
||||
# include <stdlib.h>
|
||||
# include <assert.h>
|
||||
|
||||
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid);
|
||||
|
||||
static unsigned char allocation_map[0x10000/8];
|
||||
|
||||
static inline int peek_bit(unsigned addr)
|
||||
{
|
||||
unsigned bit = addr % 8;
|
||||
addr /= 8;
|
||||
return 1 & (allocation_map[addr] >> bit);
|
||||
}
|
||||
|
||||
static inline void set_bit(unsigned addr)
|
||||
{
|
||||
unsigned bit = addr % 8;
|
||||
addr /= 8;
|
||||
allocation_map[addr] |= (1 << bit);
|
||||
}
|
||||
|
||||
static inline void clr_bit(unsigned addr)
|
||||
{
|
||||
unsigned bit = addr % 8;
|
||||
addr /= 8;
|
||||
allocation_map[addr] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
/*
|
||||
* This clears a vector that was previously allocated by
|
||||
* allocate_vector. That is, it unmarks all the bits of the map that
|
||||
* represent this vector.
|
||||
*
|
||||
* If the vector is based in one of 4 constant bit values, then there
|
||||
* are no bits to clear. If the vector is based in the 4-8 result
|
||||
* area, then someone is broken.
|
||||
*/
|
||||
void clr_vector(struct vector_info vec)
|
||||
{
|
||||
unsigned idx;
|
||||
if (vec.base < 4)
|
||||
return;
|
||||
assert(vec.base >= 8);
|
||||
for (idx = 0 ; idx < vec.wid ; idx += 1)
|
||||
clr_bit(vec.base + idx);
|
||||
}
|
||||
|
||||
unsigned short allocate_vector(unsigned short wid)
|
||||
{
|
||||
unsigned short base = 8;
|
||||
|
||||
unsigned short idx = 0;
|
||||
while (idx < wid) {
|
||||
assert((base + idx) < 0x10000);
|
||||
if (peek_bit(base+idx)) {
|
||||
base = base + idx + 1;
|
||||
idx = 0;
|
||||
|
||||
} else {
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1)
|
||||
set_bit(base+idx);
|
||||
|
||||
return base;
|
||||
}
|
||||
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
|
||||
int ok_flags);
|
||||
|
||||
int number_is_unknown(ivl_expr_t ex)
|
||||
{
|
||||
@@ -162,30 +99,44 @@ unsigned long get_number_immediate(ivl_expr_t ex)
|
||||
return imm;
|
||||
}
|
||||
|
||||
/*
|
||||
* The STUFF_OK_XZ bit is true if the output is going to be further
|
||||
* processed so that x and z values are equivilent. This may allow for
|
||||
* new optimizations.
|
||||
*/
|
||||
static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
|
||||
ivl_expr_t le,
|
||||
ivl_expr_t re)
|
||||
ivl_expr_t re,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
unsigned wid;
|
||||
struct vector_info lv;
|
||||
unsigned long imm = get_number_immediate(re);
|
||||
|
||||
wid = ivl_expr_width(le);
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case 'E': /* === */
|
||||
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
|
||||
lv.base, imm, wid);
|
||||
clr_vector(lv);
|
||||
if (lv.base >= 8)
|
||||
clr_vector(lv);
|
||||
lv.base = 6;
|
||||
lv.wid = 1;
|
||||
break;
|
||||
|
||||
case 'e': /* == */
|
||||
/* If this is a single bit being compared to 1, and the
|
||||
output doesn't care about x vs z, then just return
|
||||
the value itself. */
|
||||
if ((stuff_ok_flag&STUFF_OK_XZ) && (lv.wid == 1) && (imm == 1))
|
||||
break;
|
||||
|
||||
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
|
||||
lv.base, imm, wid);
|
||||
clr_vector(lv);
|
||||
if (lv.base >= 8)
|
||||
clr_vector(lv);
|
||||
lv.base = 4;
|
||||
lv.wid = 1;
|
||||
break;
|
||||
@@ -193,16 +144,24 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
|
||||
case 'N': /* !== */
|
||||
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
|
||||
lv.base, imm, wid);
|
||||
clr_vector(lv);
|
||||
if (lv.base >= 8)
|
||||
clr_vector(lv);
|
||||
lv.base = 6;
|
||||
lv.wid = 1;
|
||||
fprintf(vvp_out, " %%inv 6, 1;\n");
|
||||
break;
|
||||
|
||||
case 'n': /* != */
|
||||
/* If this is a single bit being compared to 0, and the
|
||||
output doesn't care about x vs z, then just return
|
||||
the value itself. */
|
||||
if ((stuff_ok_flag&STUFF_OK_XZ) && (lv.wid == 1) && (imm == 0))
|
||||
break;
|
||||
|
||||
fprintf(vvp_out, " %%cmpi/u %u, %lu, %u;\n",
|
||||
lv.base, imm, wid);
|
||||
clr_vector(lv);
|
||||
if (lv.base >= 8)
|
||||
clr_vector(lv);
|
||||
lv.base = 4;
|
||||
lv.wid = 1;
|
||||
fprintf(vvp_out, " %%inv 4, 1;\n");
|
||||
@@ -212,21 +171,39 @@ static struct vector_info draw_eq_immediate(ivl_expr_t exp, unsigned ewid,
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* In the special case that 47 bits are ok, and this really is
|
||||
a single bit value, then we are done. */
|
||||
if ((lv.wid == 1) && (ewid == 1) && (stuff_ok_flag&STUFF_OK_47))
|
||||
return lv;
|
||||
|
||||
/* Move the result out out the 4-7 bit that the compare
|
||||
uses. This is because that bit may be clobbered by other
|
||||
expressions. */
|
||||
{ unsigned short base = allocate_vector(ewid);
|
||||
fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base);
|
||||
lv.base = base;
|
||||
lv.wid = ewid;
|
||||
if (ewid > 1)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, ewid-1);
|
||||
if (lv.base < 8) {
|
||||
unsigned short base = allocate_vector(ewid);
|
||||
fprintf(vvp_out, " %%mov %u, %u, 1;\n", base, lv.base);
|
||||
lv.base = base;
|
||||
lv.wid = ewid;
|
||||
if (ewid > 1)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n", base+1, ewid-1);
|
||||
|
||||
} else if (lv.wid < ewid) {
|
||||
unsigned short base = allocate_vector(ewid);
|
||||
clr_vector(lv);
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", base,
|
||||
lv.base, lv.wid);
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
base+lv.wid, ewid-lv.wid);
|
||||
lv.base = base;
|
||||
lv.wid = ewid;
|
||||
}
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
|
||||
static struct vector_info draw_binary_expr_eq(ivl_expr_t exp,
|
||||
unsigned ewid,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(exp);
|
||||
ivl_expr_t re = ivl_expr_oper2(exp);
|
||||
@@ -238,19 +215,19 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
|
||||
|
||||
if ((ivl_expr_type(re) == IVL_EX_ULONG)
|
||||
&& (0 == (ivl_expr_uvalue(re) & ~0xffff)))
|
||||
return draw_eq_immediate(exp, ewid, le, re);
|
||||
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
|
||||
|
||||
if ((ivl_expr_type(re) == IVL_EX_NUMBER)
|
||||
&& (! number_is_unknown(re))
|
||||
&& number_is_immediate(re, 16))
|
||||
return draw_eq_immediate(exp, ewid, le, re);
|
||||
return draw_eq_immediate(exp, ewid, le, re, stuff_ok_flag);
|
||||
|
||||
wid = ivl_expr_width(le);
|
||||
if (ivl_expr_width(re) > wid)
|
||||
wid = ivl_expr_width(re);
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
rv = draw_eval_expr_wid(re, wid);
|
||||
lv = draw_eval_expr_wid(le, wid, stuff_ok_flag&STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, wid, stuff_ok_flag&STUFF_OK_XZ);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case 'E': /* === */
|
||||
@@ -316,6 +293,10 @@ static struct vector_info draw_binary_expr_eq(ivl_expr_t exp, unsigned ewid)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) {
|
||||
return lv;
|
||||
}
|
||||
|
||||
/* Move the result out out the 4-7 bit that the compare
|
||||
uses. This is because that bit may be clobbered by other
|
||||
expressions. */
|
||||
@@ -339,7 +320,7 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid)
|
||||
struct vector_info rv;
|
||||
|
||||
|
||||
lv = draw_eval_expr(le);
|
||||
lv = draw_eval_expr(le, STUFF_OK_XZ);
|
||||
|
||||
if ((lv.base >= 4) && (lv.wid > 1)) {
|
||||
struct vector_info tmp;
|
||||
@@ -351,7 +332,7 @@ static struct vector_info draw_binary_expr_land(ivl_expr_t exp, unsigned wid)
|
||||
lv = tmp;
|
||||
}
|
||||
|
||||
rv = draw_eval_expr(re);
|
||||
rv = draw_eval_expr(re, STUFF_OK_XZ);
|
||||
if ((rv.base >= 4) && (rv.wid > 1)) {
|
||||
struct vector_info tmp;
|
||||
clr_vector(rv);
|
||||
@@ -411,7 +392,7 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
|
||||
struct vector_info lv;
|
||||
struct vector_info rv;
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
|
||||
/* if the left operand has width, then evaluate the single-bit
|
||||
logical equivilent. */
|
||||
@@ -425,7 +406,7 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
|
||||
lv = tmp;
|
||||
}
|
||||
|
||||
rv = draw_eval_expr_wid(re, wid);
|
||||
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
|
||||
|
||||
/* if the right operand has width, then evaluate the single-bit
|
||||
logical equivilent. */
|
||||
@@ -481,7 +462,9 @@ static struct vector_info draw_binary_expr_lor(ivl_expr_t exp, unsigned wid)
|
||||
return lv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
|
||||
static struct vector_info draw_binary_expr_le(ivl_expr_t exp,
|
||||
unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
ivl_expr_t le = ivl_expr_oper1(exp);
|
||||
ivl_expr_t re = ivl_expr_oper2(exp);
|
||||
@@ -495,8 +478,8 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
|
||||
if (ivl_expr_width(re) > owid)
|
||||
owid = ivl_expr_width(re);
|
||||
|
||||
lv = draw_eval_expr_wid(le, owid);
|
||||
rv = draw_eval_expr_wid(re, owid);
|
||||
lv = draw_eval_expr_wid(le, owid, STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, owid, STUFF_OK_XZ);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case 'G':
|
||||
@@ -532,6 +515,12 @@ static struct vector_info draw_binary_expr_le(ivl_expr_t exp, unsigned wid)
|
||||
clr_vector(lv);
|
||||
clr_vector(rv);
|
||||
|
||||
if ((stuff_ok_flag&STUFF_OK_47) && (wid == 1)) {
|
||||
lv.base = 5;
|
||||
lv.wid = wid;
|
||||
return lv;
|
||||
}
|
||||
|
||||
/* Move the result out out the 4-7 bit that the compare
|
||||
uses. This is because that bit may be clobbered by other
|
||||
expressions. */
|
||||
@@ -555,8 +544,8 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
|
||||
struct vector_info lv;
|
||||
struct vector_info rv;
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
rv = draw_eval_expr_wid(re, wid);
|
||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
|
||||
|
||||
/* The result goes into the left operand, and that is returned
|
||||
as the result. The instructions do not allow the lv value
|
||||
@@ -595,6 +584,16 @@ static struct vector_info draw_binary_expr_logic(ivl_expr_t exp,
|
||||
lv.base, rv.base, wid);
|
||||
break;
|
||||
|
||||
case 'A': /* NAND (~&) */
|
||||
fprintf(vvp_out, " %%nand %u, %u, %u;\n",
|
||||
lv.base, rv.base, wid);
|
||||
break;
|
||||
|
||||
case 'O': /* NOR (~|) */
|
||||
fprintf(vvp_out, " %%nor %u, %u, %u;\n",
|
||||
lv.base, rv.base, wid);
|
||||
break;
|
||||
|
||||
case 'X': /* exclusive nor (~^) */
|
||||
fprintf(vvp_out, " %%xnor %u, %u, %u;\n",
|
||||
lv.base, rv.base, wid);
|
||||
@@ -654,7 +653,7 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
default: {
|
||||
struct vector_info rv;
|
||||
rv = draw_eval_expr(re);
|
||||
rv = draw_eval_expr(re, 0);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n",
|
||||
rv.base, rv.wid);
|
||||
clr_vector(rv);
|
||||
@@ -662,15 +661,51 @@ static struct vector_info draw_binary_expr_lrs(ivl_expr_t exp, unsigned wid)
|
||||
}
|
||||
}
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
|
||||
case 'l': /* << (left shift) */
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
|
||||
/* shifting 0 gets 0. */
|
||||
if (lv.base == 0)
|
||||
break;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
tmp.base = allocate_vector(lv.wid);
|
||||
tmp.wid = lv.wid;
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
tmp.base, lv.base, lv.wid);
|
||||
lv = tmp;
|
||||
}
|
||||
fprintf(vvp_out, " %%shiftl/i0 %u, %u;\n", lv.base, lv.wid);
|
||||
break;
|
||||
|
||||
case 'r': /* >> (unsigned right shift) */
|
||||
|
||||
/* with the right shift, there may be high bits that are
|
||||
shifted into the desired width of the expression, so
|
||||
we let the expression size itself, if it is bigger
|
||||
then what is requested of us. */
|
||||
if (wid > ivl_expr_width(le)) {
|
||||
lv = draw_eval_expr_wid(le, wid, 0);
|
||||
} else {
|
||||
lv = draw_eval_expr_wid(le, ivl_expr_width(le), 0);
|
||||
}
|
||||
|
||||
/* shifting 0 gets 0. */
|
||||
if (lv.base == 0)
|
||||
break;
|
||||
|
||||
if (lv.base < 4) {
|
||||
struct vector_info tmp;
|
||||
tmp.base = allocate_vector(lv.wid);
|
||||
tmp.wid = lv.wid;
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
tmp.base, lv.base, lv.wid);
|
||||
lv = tmp;
|
||||
}
|
||||
fprintf(vvp_out, " %%shiftr/i0 %u, %u;\n", lv.base, lv.wid);
|
||||
break;
|
||||
|
||||
@@ -688,7 +723,7 @@ static struct vector_info draw_add_immediate(ivl_expr_t le,
|
||||
struct vector_info lv;
|
||||
unsigned long imm;
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
assert(lv.wid == wid);
|
||||
|
||||
imm = get_number_immediate(re);
|
||||
@@ -725,7 +760,7 @@ static struct vector_info draw_sub_immediate(ivl_expr_t le,
|
||||
struct vector_info lv;
|
||||
unsigned long imm;
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
assert(lv.wid == wid);
|
||||
|
||||
imm = get_number_immediate(re);
|
||||
@@ -743,7 +778,7 @@ static struct vector_info draw_mul_immediate(ivl_expr_t le,
|
||||
struct vector_info lv;
|
||||
unsigned long imm;
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
assert(lv.wid == wid);
|
||||
|
||||
imm = get_number_immediate(re);
|
||||
@@ -789,8 +824,8 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
|
||||
&& number_is_immediate(re, 16))
|
||||
return draw_mul_immediate(le, re, wid);
|
||||
|
||||
lv = draw_eval_expr_wid(le, wid);
|
||||
rv = draw_eval_expr_wid(re, wid);
|
||||
lv = draw_eval_expr_wid(le, wid, STUFF_OK_XZ);
|
||||
rv = draw_eval_expr_wid(re, wid, STUFF_OK_XZ);
|
||||
|
||||
assert(lv.wid == wid);
|
||||
assert(rv.wid == wid);
|
||||
@@ -840,9 +875,12 @@ static struct vector_info draw_binary_expr_arith(ivl_expr_t exp, unsigned wid)
|
||||
return lv;
|
||||
}
|
||||
|
||||
static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
|
||||
static struct vector_info draw_binary_expr(ivl_expr_t exp,
|
||||
unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
struct vector_info rv;
|
||||
int stuff_ok_used_flag = 0;
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case 'a': /* && (logical and) */
|
||||
@@ -853,14 +891,16 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
|
||||
case 'e': /* == */
|
||||
case 'N': /* !== */
|
||||
case 'n': /* != */
|
||||
rv = draw_binary_expr_eq(exp, wid);
|
||||
rv = draw_binary_expr_eq(exp, wid, stuff_ok_flag);
|
||||
stuff_ok_used_flag = 1;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
case '>':
|
||||
case 'L': /* <= */
|
||||
case 'G': /* >= */
|
||||
rv = draw_binary_expr_le(exp, wid);
|
||||
rv = draw_binary_expr_le(exp, wid, stuff_ok_flag);
|
||||
stuff_ok_used_flag = 1;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
@@ -883,7 +923,9 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
|
||||
case '&':
|
||||
case '|':
|
||||
case '^':
|
||||
case 'X':
|
||||
case 'A': /* NAND (~&) */
|
||||
case 'O': /* NOR (~|) */
|
||||
case 'X': /* XNOR (~^) */
|
||||
rv = draw_binary_expr_logic(exp, wid);
|
||||
break;
|
||||
|
||||
@@ -893,6 +935,21 @@ static struct vector_info draw_binary_expr(ivl_expr_t exp, unsigned wid)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* Mark in the lookaside that this value is done. If any OK
|
||||
flags besides the STUFF_OK_47 flag are set, then the result
|
||||
may not be a pure one, so clear the lookaside for the range
|
||||
instead of setting in to the new expression result.
|
||||
|
||||
The stuff_ok_used_flag tells me if the stuff_ok_flag was
|
||||
even used by anything. If not, then I can ignore it in the
|
||||
following logic. */
|
||||
if (rv.base >= 8) {
|
||||
if (stuff_ok_used_flag && (stuff_ok_flag & ~STUFF_OK_47))
|
||||
save_expression_lookaside(rv.base, 0, wid);
|
||||
else
|
||||
save_expression_lookaside(rv.base, exp, wid);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -904,7 +961,7 @@ static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
/* Evaluate the bit select expression and save the result into
|
||||
index register 0. */
|
||||
res = draw_eval_expr(sel);
|
||||
res = draw_eval_expr(sel, 0);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u,%u;\n", res.base, res.wid);
|
||||
clr_vector(res);
|
||||
|
||||
@@ -924,6 +981,8 @@ static struct vector_info draw_bitsel_expr(ivl_expr_t exp, unsigned wid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -961,18 +1020,34 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
|
||||
ivl_expr_t arg = ivl_expr_parm(exp, idx-1);
|
||||
unsigned awid = ivl_expr_width(arg);
|
||||
|
||||
/* Evaluate this sub expression. */
|
||||
struct vector_info avec = draw_eval_expr_wid(arg, awid);
|
||||
unsigned trans;
|
||||
struct vector_info avec;
|
||||
|
||||
unsigned trans = awid;
|
||||
/* Try to locate the subexpression in the
|
||||
lookaside map. */
|
||||
avec.base = allocate_vector_exp(arg, awid);
|
||||
avec.wid = awid;
|
||||
|
||||
trans = awid;
|
||||
if ((off + awid) > wid)
|
||||
trans = wid - off;
|
||||
|
||||
assert(awid == avec.wid);
|
||||
if (avec.base != 0) {
|
||||
assert(awid == avec.wid);
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
res.base+off,
|
||||
avec.base, trans);
|
||||
clr_vector(avec);
|
||||
|
||||
} else {
|
||||
struct vector_info dest;
|
||||
|
||||
dest.base = res.base+off;
|
||||
dest.wid = trans;
|
||||
draw_eval_expr_dest(arg, dest, 0);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base+off,
|
||||
avec.base, trans);
|
||||
clr_vector(avec);
|
||||
|
||||
idx -= 1;
|
||||
off += trans;
|
||||
@@ -987,6 +1062,10 @@ static struct vector_info draw_concat_expr(ivl_expr_t exp, unsigned wid)
|
||||
res.base+off, wid-off);
|
||||
}
|
||||
|
||||
/* Save the accumulated result in the lookaside map. */
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1072,6 +1151,9 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
|
||||
if (idx < wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
|
||||
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1119,6 +1201,9 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
|
||||
if (idx < wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n", res.base+idx, wid-idx);
|
||||
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1128,28 +1213,54 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
|
||||
* offsetting the read from the lsi (least significant index) of the
|
||||
* signal.
|
||||
*/
|
||||
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
|
||||
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned lsi = ivl_expr_lsi(exp);
|
||||
unsigned swid = ivl_expr_width(exp);
|
||||
ivl_signal_t sig = ivl_expr_signal(exp);
|
||||
|
||||
if (swid > res.wid)
|
||||
swid = res.wid;
|
||||
|
||||
if (ivl_signal_type(sig) == IVL_SIT_REG) {
|
||||
/* If this is a REG (a variable) then I can do a vector
|
||||
read. */
|
||||
fprintf(vvp_out, " %%load/v %u, V_%s[%u], %u;\n",
|
||||
res.base, vvp_signal_label(sig), lsi, swid);
|
||||
|
||||
} else {
|
||||
/* Vector reads of nets do not in general work because
|
||||
they are not really functors but references to
|
||||
scattered functors. So generate an array of loads. */
|
||||
for (idx = 0 ; idx < swid ; idx += 1) {
|
||||
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
|
||||
res.base+idx, vvp_signal_label(sig), idx+lsi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < res.wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+swid, res.wid-swid);
|
||||
}
|
||||
|
||||
static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid)
|
||||
{
|
||||
struct vector_info res;
|
||||
|
||||
if (swid > wid)
|
||||
swid = wid;
|
||||
/* Already in the vector lookaside? */
|
||||
res.base = allocate_vector_exp(exp, wid);
|
||||
res.wid = wid;
|
||||
if (res.base != 0)
|
||||
return res;
|
||||
|
||||
res.base = allocate_vector(wid);
|
||||
res.wid = wid;
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
for (idx = 0 ; idx < swid ; idx += 1)
|
||||
fprintf(vvp_out, " %%load %u, V_%s[%u];\n",
|
||||
res.base+idx, vvp_signal_label(sig), idx+lsi);
|
||||
|
||||
/* Pad the signal value with zeros. */
|
||||
if (swid < wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+swid, wid-swid);
|
||||
draw_signal_dest(exp, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1191,7 +1302,7 @@ void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
struct vector_info addr = draw_eval_expr(ae);
|
||||
struct vector_info addr = draw_eval_expr(ae, 0);
|
||||
fprintf(vvp_out, " %%ix/get 3, %u, %u;\n",
|
||||
addr.base, addr.wid);
|
||||
clr_vector(addr);
|
||||
@@ -1231,6 +1342,9 @@ static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
|
||||
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
|
||||
res.base+swid, wid-swid);
|
||||
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1241,7 +1355,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
|
||||
ivl_expr_t shift = ivl_expr_oper2(exp);
|
||||
|
||||
/* Evaluate the sub-expression. */
|
||||
subv = draw_eval_expr(sube);
|
||||
subv = draw_eval_expr(sube, 0);
|
||||
|
||||
/* Any bit select of a constant zero is another constant zero,
|
||||
so short circuit and return the value we know. */
|
||||
@@ -1252,7 +1366,7 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
/* Evaluate the bit select base expression and store the
|
||||
result into index register 0. */
|
||||
shiv = draw_eval_expr(shift);
|
||||
shiv = draw_eval_expr(shift, STUFF_OK_XZ);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
|
||||
clr_vector(shiv);
|
||||
|
||||
@@ -1280,6 +1394,9 @@ static struct vector_info draw_select_expr(ivl_expr_t exp, unsigned wid)
|
||||
res = subv;
|
||||
}
|
||||
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1296,7 +1413,7 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
|
||||
lab_false = local_count++;
|
||||
lab_out = local_count++;
|
||||
|
||||
tmp = draw_eval_expr(cond);
|
||||
tmp = draw_eval_expr(cond, STUFF_OK_XZ);
|
||||
clr_vector(tmp);
|
||||
|
||||
if ((tmp.base >= 4) && (tmp.wid > 1)) {
|
||||
@@ -1316,11 +1433,11 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
|
||||
/* Ambiguous case. Evaluate both true and false expressions,
|
||||
and use %blend to merge them. */
|
||||
|
||||
tmp = draw_eval_expr_wid(true_ex, wid);
|
||||
tmp = draw_eval_expr_wid(true_ex, wid, 0);
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
|
||||
clr_vector(tmp);
|
||||
|
||||
tmp = draw_eval_expr_wid(false_ex, wid);
|
||||
tmp = draw_eval_expr_wid(false_ex, wid, 0);
|
||||
fprintf(vvp_out, " %%blend %u, %u, %u;\n", res.base, tmp.base, wid);
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
|
||||
if (tmp.base >= 8)
|
||||
@@ -1328,8 +1445,9 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
/* This is the true case. Just evaluate the true expression. */
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_true);
|
||||
clear_expression_lookaside();
|
||||
|
||||
tmp = draw_eval_expr_wid(true_ex, wid);
|
||||
tmp = draw_eval_expr_wid(true_ex, wid, 0);
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
|
||||
if (tmp.base >= 8)
|
||||
@@ -1338,14 +1456,19 @@ static struct vector_info draw_ternary_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
/* This is the false case. Just evaluate the false expression. */
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_false);
|
||||
clear_expression_lookaside();
|
||||
|
||||
tmp = draw_eval_expr_wid(false_ex, wid);
|
||||
tmp = draw_eval_expr_wid(false_ex, wid, 0);
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n", res.base, tmp.base, wid);
|
||||
if (tmp.base >= 8)
|
||||
clr_vector(tmp);
|
||||
|
||||
/* This is the out label. */
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out);
|
||||
clear_expression_lookaside();
|
||||
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1396,7 +1519,7 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
vec = (struct vector_info *)
|
||||
realloc(vec, (vecs+1)*sizeof(struct vector_info));
|
||||
vec[vecs] = draw_eval_expr(expr);
|
||||
vec[vecs] = draw_eval_expr(expr, 0);
|
||||
vecs++;
|
||||
}
|
||||
|
||||
@@ -1476,6 +1599,9 @@ static struct vector_info draw_sfunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
free(vec);
|
||||
}
|
||||
|
||||
/* New basic block starts after VPI calls. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
|
||||
|
||||
@@ -1510,7 +1636,7 @@ static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
unsigned pin, bit;
|
||||
|
||||
res = draw_eval_expr_wid(ivl_expr_parm(exp, idx),
|
||||
ivl_signal_pins(port));
|
||||
ivl_signal_pins(port), 0);
|
||||
bit = res.base;
|
||||
assert(res.wid <= ivl_signal_pins(port));
|
||||
for (pin = 0 ; pin < res.wid ; pin += 1) {
|
||||
@@ -1530,6 +1656,9 @@ static struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
|
||||
fprintf(vvp_out, ", S_%s;\n", vvp_mangle_id(ivl_scope_name(def)));
|
||||
fprintf(vvp_out, " %%join;\n");
|
||||
|
||||
/* Fresh basic block starts after the join. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
/* The return value is in a signal that has the name of the
|
||||
expression. Load that into the thread and return the
|
||||
vector result. */
|
||||
@@ -1577,7 +1706,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
||||
|
||||
switch (ivl_expr_opcode(exp)) {
|
||||
case '~':
|
||||
res = draw_eval_expr_wid(sub, wid);
|
||||
res = draw_eval_expr_wid(sub, wid, STUFF_OK_XZ);
|
||||
switch (res.base) {
|
||||
case 0:
|
||||
res.base = 1;
|
||||
@@ -1600,7 +1729,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
||||
complement of the number. That is the 1's complement
|
||||
(bitwise invert) with a 1 added in. Note that the
|
||||
%sub subtracts -1 (1111...) to get %add of +1. */
|
||||
res = draw_eval_expr_wid(sub, wid);
|
||||
res = draw_eval_expr_wid(sub, wid, STUFF_OK_XZ);
|
||||
switch (res.base) {
|
||||
case 0:
|
||||
res.base = 0;
|
||||
@@ -1620,7 +1749,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
||||
break;
|
||||
|
||||
case '!':
|
||||
res = draw_eval_expr(sub);
|
||||
res = draw_eval_expr(sub, STUFF_OK_XZ);
|
||||
if (res.wid > 1) {
|
||||
/* a ! on a vector is implemented with a reduction
|
||||
nor. Generate the result into the first bit of
|
||||
@@ -1672,7 +1801,7 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
||||
case '&':
|
||||
case '|':
|
||||
case '^':
|
||||
res = draw_eval_expr(sub);
|
||||
res = draw_eval_expr(sub, 0);
|
||||
if (res.wid > 1) {
|
||||
struct vector_info tmp;
|
||||
/* If the previous result is in the constant area
|
||||
@@ -1719,10 +1848,49 @@ static struct vector_info draw_unary_expr(ivl_expr_t exp, unsigned wid)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (res.base >= 8)
|
||||
save_expression_lookaside(res.base, exp, wid);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
|
||||
/*
|
||||
* Sometimes we know ahead of time where we want the expression value
|
||||
* to go. In that case, call this function. It will check to see if
|
||||
* the expression can be preplaced, and if so it will evaluate it in
|
||||
* place.
|
||||
*/
|
||||
static void draw_eval_expr_dest(ivl_expr_t exp, struct vector_info dest,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
struct vector_info tmp;
|
||||
|
||||
switch (ivl_expr_type(exp)) {
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
draw_signal_dest(exp, dest);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fallback, is to draw the expression by width, and mov it to
|
||||
the required dest. */
|
||||
tmp = draw_eval_expr_wid(exp, dest.wid, stuff_ok_flag);
|
||||
assert(tmp.wid == dest.wid);
|
||||
|
||||
fprintf(vvp_out, " %%mov %u, %u, %u;\n",
|
||||
dest.base, tmp.base, dest.wid);
|
||||
|
||||
if (tmp.base >= 8)
|
||||
save_expression_lookaside(tmp.base, exp, tmp.wid);
|
||||
|
||||
clr_vector(tmp);
|
||||
}
|
||||
|
||||
struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
|
||||
int stuff_ok_flag)
|
||||
{
|
||||
struct vector_info res;
|
||||
|
||||
@@ -1741,7 +1909,7 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
|
||||
break;
|
||||
|
||||
case IVL_EX_BINARY:
|
||||
res = draw_binary_expr(exp, wid);
|
||||
res = draw_binary_expr(exp, wid, stuff_ok_flag);
|
||||
break;
|
||||
|
||||
case IVL_EX_BITSEL:
|
||||
@@ -1788,13 +1956,50 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid)
|
||||
return res;
|
||||
}
|
||||
|
||||
struct vector_info draw_eval_expr(ivl_expr_t exp)
|
||||
struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
|
||||
{
|
||||
return draw_eval_expr_wid(exp, ivl_expr_width(exp));
|
||||
return draw_eval_expr_wid(exp, ivl_expr_width(exp), stuff_ok_flag);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: eval_expr.c,v $
|
||||
* Revision 1.86 2002/11/22 00:01:50 steve
|
||||
* Careful of left operands to shift that are constant.
|
||||
*
|
||||
* Revision 1.85 2002/11/21 22:42:48 steve
|
||||
* Allow right values of right shift to shift in.
|
||||
*
|
||||
* Revision 1.84 2002/11/07 03:12:17 steve
|
||||
* Vectorize load from REG variables.
|
||||
*
|
||||
* Revision 1.83 2002/11/06 05:41:37 steve
|
||||
* Concatenation can evaluate sub-expressions in place.
|
||||
*
|
||||
* Revision 1.82 2002/10/20 02:55:37 steve
|
||||
* Properly set or clear expression lookaside for binary expressions.
|
||||
*
|
||||
* Revision 1.81 2002/09/27 20:24:42 steve
|
||||
* Allow expression lookaside map to spam statements.
|
||||
*
|
||||
* Revision 1.80 2002/09/27 16:33:34 steve
|
||||
* Add thread expression lookaside map.
|
||||
*
|
||||
* Revision 1.79 2002/09/24 04:20:32 steve
|
||||
* Allow results in register bits 47 in certain cases.
|
||||
*
|
||||
* Revision 1.78 2002/09/18 04:29:55 steve
|
||||
* Add support for binary NOR operator.
|
||||
*
|
||||
* Revision 1.77 2002/09/13 04:09:51 steve
|
||||
* single bit optimization for != in expressions,
|
||||
* and expand ++ and != results if needed.
|
||||
*
|
||||
* Revision 1.76 2002/09/13 03:12:50 steve
|
||||
* Optimize ==1 when in context where x vs z doesnt matter.
|
||||
*
|
||||
* Revision 1.75 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.74 2002/09/01 01:42:34 steve
|
||||
* Fix leaking vthread bits in ?: eval.
|
||||
*
|
||||
@@ -1825,93 +2030,5 @@ struct vector_info draw_eval_expr(ivl_expr_t exp)
|
||||
* generate vvp labels. -tdll target does not
|
||||
* used hierarchical name string to look up the
|
||||
* memory objects in the design.
|
||||
*
|
||||
* Revision 1.66 2002/08/03 22:30:48 steve
|
||||
* Eliminate use of ivl_signal_name for signal labels.
|
||||
*
|
||||
* Revision 1.65 2002/07/12 18:10:45 steve
|
||||
* Use all bits of ?: condit expression.
|
||||
*
|
||||
* Revision 1.64 2002/07/01 00:52:47 steve
|
||||
* Carry can propagate to the otp in addi.
|
||||
*
|
||||
* Revision 1.63 2002/06/02 18:57:17 steve
|
||||
* Generate %cmpi/u where appropriate.
|
||||
*
|
||||
* Revision 1.62 2002/05/31 20:04:57 steve
|
||||
* Generate %muli instructions when possible.
|
||||
*
|
||||
* Revision 1.61 2002/05/30 01:57:23 steve
|
||||
* Use addi with wide immediate values.
|
||||
*
|
||||
* Revision 1.60 2002/05/29 16:29:34 steve
|
||||
* Add %addi, which is faster to simulate.
|
||||
*
|
||||
* Revision 1.59 2002/05/07 03:49:58 steve
|
||||
* Handle x case of unary ! properly.
|
||||
*
|
||||
* Revision 1.58 2002/04/22 02:41:30 steve
|
||||
* Reduce the while loop expression if needed.
|
||||
*
|
||||
* Revision 1.57 2002/04/14 18:41:34 steve
|
||||
* Support signed integer division.
|
||||
*
|
||||
* Revision 1.56 2002/02/03 05:53:00 steve
|
||||
* Fix parameter bit select check for magic constants.
|
||||
*
|
||||
* Revision 1.55 2002/01/28 00:52:42 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.54 2002/01/11 05:23:05 steve
|
||||
* Handle certain special cases of stime.
|
||||
*
|
||||
* Revision 1.53 2001/11/19 04:25:46 steve
|
||||
* Handle padding out of logical values.
|
||||
*
|
||||
* Revision 1.52 2001/10/24 05:06:54 steve
|
||||
* The ! expression returns 0 to x and z values.
|
||||
*
|
||||
* Revision 1.51 2001/10/18 16:41:49 steve
|
||||
* Evaluate string expressions (Philip Blundell)
|
||||
*
|
||||
* Revision 1.50 2001/10/16 01:27:17 steve
|
||||
* Generate %div instructions for binary /.
|
||||
*
|
||||
* Revision 1.49 2001/10/14 03:24:35 steve
|
||||
* Handle constant bits in arithmetic expressions.
|
||||
*
|
||||
* Revision 1.48 2001/10/10 04:47:43 steve
|
||||
* Support vectors as operands to logical and.
|
||||
*
|
||||
* Revision 1.47 2001/09/29 04:37:44 steve
|
||||
* Generate code for unary minus (PR#272)
|
||||
*
|
||||
* Revision 1.46 2001/09/29 01:53:22 steve
|
||||
* Fix the size of unsized constant operants to compare (PR#274)
|
||||
*
|
||||
* Revision 1.45 2001/09/20 03:46:38 steve
|
||||
* Handle short l-values to concatenation.
|
||||
*
|
||||
* Revision 1.44 2001/09/15 18:27:04 steve
|
||||
* Make configure detect malloc.h
|
||||
*
|
||||
* Revision 1.43 2001/08/31 01:37:56 steve
|
||||
* Handle update in place of repeat constants.
|
||||
*
|
||||
* Revision 1.42 2001/08/23 02:54:15 steve
|
||||
* Handle wide assignment to narrow return value.
|
||||
*
|
||||
* Revision 1.41 2001/08/03 17:06:10 steve
|
||||
* More detailed messages about unsupported things.
|
||||
*
|
||||
* Revision 1.40 2001/07/27 04:51:45 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
*
|
||||
* Revision 1.39 2001/07/27 02:41:56 steve
|
||||
* Fix binding of dangling function ports. do not elide them.
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vector.c,v 1.1 2002/09/27 16:33:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
# include <assert.h>
|
||||
|
||||
static struct allocation_score_s {
|
||||
ivl_expr_t exp;
|
||||
unsigned bit :16;
|
||||
unsigned alloc : 1;
|
||||
} allocation_map[0x10000] = { {0} };
|
||||
|
||||
/* This is the largest bit to have lookaside values. */
|
||||
static unsigned lookaside_top = 0;
|
||||
|
||||
static inline int peek_bit(unsigned addr)
|
||||
{
|
||||
return allocation_map[addr].alloc;
|
||||
}
|
||||
|
||||
static inline void set_bit(unsigned addr)
|
||||
{
|
||||
allocation_map[addr].alloc = 1;
|
||||
}
|
||||
|
||||
static inline void clr_bit(unsigned addr)
|
||||
{
|
||||
allocation_map[addr].alloc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This clears a vector that was previously allocated by
|
||||
* allocate_vector. That is, it unmarks all the bits of the map that
|
||||
* represent this vector.
|
||||
*
|
||||
* If the vector is based in one of 4 constant bit values, then there
|
||||
* are no bits to clear. If the vector is based in the 4-8 result
|
||||
* area, then someone is broken.
|
||||
*/
|
||||
void clr_vector(struct vector_info vec)
|
||||
{
|
||||
unsigned idx;
|
||||
if (vec.base < 4)
|
||||
return;
|
||||
assert(vec.base >= 8);
|
||||
for (idx = 0 ; idx < vec.wid ; idx += 1)
|
||||
clr_bit(vec.base + idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* This unconditionally allocates a stretch of bits from the register
|
||||
* set. It never returns a bit addressed <8 (0-3 are constant, 4-7 are
|
||||
* condition codes).
|
||||
*/
|
||||
unsigned short allocate_vector(unsigned short wid)
|
||||
{
|
||||
unsigned short base = 8;
|
||||
|
||||
unsigned short idx = 0;
|
||||
while (idx < wid) {
|
||||
assert((base + idx) < 0x10000);
|
||||
if (peek_bit(base+idx)) {
|
||||
base = base + idx + 1;
|
||||
idx = 0;
|
||||
|
||||
} else {
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1) {
|
||||
allocation_map[base+idx].alloc = 1;
|
||||
allocation_map[base+idx].exp = 0;
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
/*
|
||||
* This clears the expression cache of the allocation map. It is
|
||||
* called to prevent reuse of existing expressions, normally at the
|
||||
* start of a basic block.
|
||||
*/
|
||||
void clear_expression_lookaside(void)
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < lookaside_top ; idx += 1) {
|
||||
allocation_map[idx].exp = 0;
|
||||
}
|
||||
|
||||
lookaside_top = 0;
|
||||
}
|
||||
|
||||
void save_expression_lookaside(unsigned short addr, ivl_expr_t exp,
|
||||
unsigned short wid)
|
||||
{
|
||||
unsigned idx;
|
||||
assert(addr >= 8);
|
||||
assert((addr+wid) <= 0x10000);
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1) {
|
||||
allocation_map[addr+idx].exp = exp;
|
||||
allocation_map[addr+idx].bit = idx;
|
||||
}
|
||||
|
||||
if ((addr+wid) > lookaside_top)
|
||||
lookaside_top = addr+wid;
|
||||
}
|
||||
|
||||
static int compare_exp(ivl_expr_t l, ivl_expr_t r)
|
||||
{
|
||||
if (! (l && r))
|
||||
return 0;
|
||||
if (l == r)
|
||||
return 1;
|
||||
|
||||
if (ivl_expr_type(l) != ivl_expr_type(r))
|
||||
return 0;
|
||||
|
||||
switch (ivl_expr_type(l)) {
|
||||
case IVL_EX_SIGNAL:
|
||||
if (ivl_expr_signal(l) != ivl_expr_signal(r))
|
||||
return 0;
|
||||
|
||||
if (ivl_expr_lsi(l) != ivl_expr_lsi(r))
|
||||
return 0;
|
||||
|
||||
if (ivl_expr_width(l) != ivl_expr_width(r))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned short find_expression_lookaside(ivl_expr_t exp,
|
||||
unsigned short wid)
|
||||
{
|
||||
unsigned top;
|
||||
unsigned idx, match;
|
||||
|
||||
if (lookaside_top <= wid)
|
||||
return 0;
|
||||
|
||||
top = lookaside_top - wid + 1;
|
||||
|
||||
assert(exp);
|
||||
match = 0;
|
||||
for (idx = 8 ; idx < top ; idx += 1) {
|
||||
if (! compare_exp(allocation_map[idx].exp, exp)) {
|
||||
match = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (allocation_map[idx].bit != match) {
|
||||
match = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
match += 1;
|
||||
if (match == wid)
|
||||
return idx-match+1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned short allocate_vector_exp(ivl_expr_t exp, unsigned short wid)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned short la = find_expression_lookaside(exp, wid);
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1)
|
||||
if (allocation_map[la+idx].alloc)
|
||||
return 0;
|
||||
|
||||
for (idx = 0 ; idx < wid ; idx += 1)
|
||||
allocation_map[la+idx].alloc = 1;
|
||||
|
||||
return la;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: vector.c,v $
|
||||
* Revision 1.1 2002/09/27 16:33:34 steve
|
||||
* Add thread expression lookaside map.
|
||||
*
|
||||
*/
|
||||
|
||||
+63
-3
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_priv.h,v 1.19 2002/08/27 05:39:57 steve Exp $"
|
||||
#ident "$Id: vvp_priv.h,v 1.22 2002/09/27 16:33:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "ivl_target.h"
|
||||
@@ -83,14 +83,28 @@ extern void draw_input_from_net(ivl_nexus_t nex);
|
||||
* allocation. When the caller is done with the bits, it must release
|
||||
* the vector with clr_vector so that the code generator can reuse
|
||||
* those bits.
|
||||
*
|
||||
* The stuff_ok_flag is normally empty. Bits in the bitmask are set
|
||||
* true in cases where certain special situations are allows. This
|
||||
* might allow deeper expressions to make assumptions about the
|
||||
* caller.
|
||||
*
|
||||
* STUFF_OK_XZ -- This bit is set if the code processing the result
|
||||
* doesn't distinguish between x and z values.
|
||||
*
|
||||
* STUFF_OK_47 -- This bit is set if the node is allowed to leave a
|
||||
* result in any of the 4-7 vthread bits.
|
||||
*/
|
||||
struct vector_info {
|
||||
unsigned short base;
|
||||
unsigned short wid;
|
||||
};
|
||||
|
||||
extern struct vector_info draw_eval_expr(ivl_expr_t exp);
|
||||
extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w);
|
||||
extern struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag);
|
||||
extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w,
|
||||
int stuff_ok_flag);
|
||||
#define STUFF_OK_XZ 0x0001
|
||||
#define STUFF_OK_47 0x0002
|
||||
|
||||
/*
|
||||
* This function draws code to evaluate the index expression exp for
|
||||
@@ -100,9 +114,46 @@ extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w);
|
||||
*/
|
||||
extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp);
|
||||
|
||||
/*
|
||||
* These functions manage vector allocation in the thread register
|
||||
* space. They presume that we work on one thread at a time, to
|
||||
* completion.
|
||||
*
|
||||
* allocate_vector
|
||||
* Return the base of an allocated vector in the thread. The bits
|
||||
* are marked allocated in the process.
|
||||
*
|
||||
* clr_bector
|
||||
* Clear a vector previously allocated.
|
||||
*
|
||||
* The thread vector allocator also keeps a lookaside of expression
|
||||
* results that are stored in register bit. This lookaside can be used
|
||||
* by the code generator to notice that certain expression bits are
|
||||
* already calculated, and can be reused.
|
||||
*
|
||||
* clear_expression_lookaside
|
||||
* Clear the lookaside tables for the current thread.
|
||||
*
|
||||
* save_expression_lookaside
|
||||
* Mark the given expression as available in the given register
|
||||
* bits. This remains until the lookaside is cleared.
|
||||
*
|
||||
* allocate_vector_exp
|
||||
* This function attempts to locate the expression in the
|
||||
* lookaside. If it finds it, return a reallocated base for the
|
||||
* expression. Otherwise, return 0.
|
||||
*/
|
||||
extern unsigned short allocate_vector(unsigned short wid);
|
||||
extern void clr_vector(struct vector_info vec);
|
||||
|
||||
extern void clear_expression_lookaside(void);
|
||||
extern void save_expression_lookaside(unsigned short addr,
|
||||
ivl_expr_t exp,
|
||||
unsigned short wid);
|
||||
|
||||
extern unsigned short allocate_vector_exp(ivl_expr_t exp,
|
||||
unsigned short wid);
|
||||
|
||||
extern int number_is_unknown(ivl_expr_t ex);
|
||||
extern int number_is_immediate(ivl_expr_t ex, unsigned lim_wid);
|
||||
extern unsigned long get_number_immediate(ivl_expr_t ex);
|
||||
@@ -115,6 +166,15 @@ extern unsigned thread_count;
|
||||
|
||||
/*
|
||||
* $Log: vvp_priv.h,v $
|
||||
* Revision 1.22 2002/09/27 16:33:34 steve
|
||||
* Add thread expression lookaside map.
|
||||
*
|
||||
* Revision 1.21 2002/09/24 04:20:32 steve
|
||||
* Allow results in register bits 47 in certain cases.
|
||||
*
|
||||
* Revision 1.20 2002/09/13 03:12:50 steve
|
||||
* Optimize ==1 when in context where x vs z doesnt matter.
|
||||
*
|
||||
* Revision 1.19 2002/08/27 05:39:57 steve
|
||||
* Fix l-value indexing of memories and vectors so that
|
||||
* an unknown (x) index causes so cell to be addresses.
|
||||
|
||||
+238
-158
@@ -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.67 2002/09/01 00:19:35 steve Exp $"
|
||||
#ident "$Id: vvp_process.c,v 1.76 2002/11/21 22:43:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -71,17 +71,25 @@ unsigned bitchar_to_idx(char bit)
|
||||
* nexus.
|
||||
*/
|
||||
|
||||
static void set_to_lvariable(ivl_lval_t lval, unsigned idx, unsigned bit)
|
||||
static void set_to_lvariable(ivl_lval_t lval, unsigned idx,
|
||||
unsigned bit, unsigned wid)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
|
||||
if (ivl_lval_mux(lval))
|
||||
fprintf(vvp_out, " %%set/x V_%s, %u, 0;\n",
|
||||
vvp_signal_label(sig), bit);
|
||||
else
|
||||
if (ivl_lval_mux(lval)) {
|
||||
assert(wid == 1);
|
||||
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
|
||||
vvp_signal_label(sig), bit, ivl_signal_pins(sig)-1);
|
||||
} else if (wid == 1) {
|
||||
fprintf(vvp_out, " %%set V_%s[%u], %u;\n",
|
||||
vvp_signal_label(sig), idx+part_off, bit);
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, " %%set/v V_%s[%u], %u, %u;\n",
|
||||
vvp_signal_label(sig), idx+part_off, bit, wid);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void set_to_memory(ivl_memory_t mem, unsigned idx, unsigned bit)
|
||||
@@ -116,6 +124,19 @@ static void assign_to_lvariable(ivl_lval_t lval, unsigned idx,
|
||||
idx+part_off, delay, bit);
|
||||
}
|
||||
|
||||
static void assign_to_lvector(ivl_lval_t lval, unsigned idx,
|
||||
unsigned bit, unsigned delay, unsigned width)
|
||||
{
|
||||
ivl_signal_t sig = ivl_lval_sig(lval);
|
||||
unsigned part_off = ivl_lval_part_off(lval);
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
|
||||
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
|
||||
fprintf(vvp_out, " %%assign/v0 V_%s[%u], %u, %u;\n",
|
||||
vvp_signal_label(sig), part_off+idx, delay, bit);
|
||||
|
||||
}
|
||||
|
||||
static void assign_to_memory(ivl_memory_t mem, unsigned idx,
|
||||
unsigned bit, unsigned delay)
|
||||
{
|
||||
@@ -131,14 +152,14 @@ static void assign_to_memory(ivl_memory_t mem, unsigned idx,
|
||||
*/
|
||||
static void calculate_into_x0(ivl_expr_t expr)
|
||||
{
|
||||
struct vector_info vec = draw_eval_expr(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);
|
||||
}
|
||||
|
||||
static void calculate_into_x1(ivl_expr_t expr)
|
||||
{
|
||||
struct vector_info vec = draw_eval_expr(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);
|
||||
}
|
||||
@@ -170,6 +191,8 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
value and write it into index0. */
|
||||
if (ivl_lval_mux(lval)) {
|
||||
calculate_into_x0(ivl_lval_mux(lval));
|
||||
/* Generate code to skip around the set
|
||||
if the index has X values. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
@@ -177,6 +200,8 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
mem = ivl_lval_mem(lval);
|
||||
if (mem) {
|
||||
draw_memory_index_expr(mem, ivl_lval_idx(lval));
|
||||
/* Generate code to skip around the set
|
||||
if the index has X values. */
|
||||
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
|
||||
skip_set_flag = 1;
|
||||
}
|
||||
@@ -198,26 +223,38 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
|
||||
|
||||
} else {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
set_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]));
|
||||
idx = 0;
|
||||
while (idx < bit_limit) {
|
||||
unsigned cnt = 1;
|
||||
while (((idx + cnt) < bit_limit)
|
||||
&& (bits[cur_rbit] == bits[cur_rbit+cnt]))
|
||||
cnt += 1;
|
||||
|
||||
cur_rbit += 1;
|
||||
set_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
cnt);
|
||||
|
||||
cur_rbit += cnt;
|
||||
idx += cnt;
|
||||
}
|
||||
|
||||
for (idx = bit_limit
|
||||
; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
set_to_lvariable(lval, idx, 0);
|
||||
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
|
||||
set_to_lvariable(lval, bit_limit, 0, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_set_flag)
|
||||
if (skip_set_flag) {
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
{ struct vector_info res = draw_eval_expr(rval);
|
||||
{ struct vector_info res = draw_eval_expr(rval, 0);
|
||||
unsigned wid = res.wid;
|
||||
unsigned lidx;
|
||||
unsigned cur_rbit = 0;
|
||||
@@ -247,27 +284,37 @@ static int show_stmt_assign(ivl_statement_t net)
|
||||
if (bit_limit > ivl_lval_pins(lval))
|
||||
bit_limit = ivl_lval_pins(lval);
|
||||
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
if (mem) {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
: (res.base+cur_rbit);
|
||||
set_to_memory(mem, idx, bidx);
|
||||
cur_rbit += 1;
|
||||
}
|
||||
|
||||
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
|
||||
set_to_memory(mem, idx, 0);
|
||||
|
||||
} else {
|
||||
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
: (res.base+cur_rbit);
|
||||
if (mem)
|
||||
set_to_memory(mem, idx, bidx);
|
||||
else
|
||||
set_to_lvariable(lval, idx, bidx);
|
||||
set_to_lvariable(lval, 0, bidx, bit_limit);
|
||||
cur_rbit += bit_limit;
|
||||
|
||||
cur_rbit += 1;
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned cnt = ivl_lval_pins(lval) - bit_limit;
|
||||
set_to_lvariable(lval, bit_limit, 0, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
if (mem)
|
||||
set_to_memory(mem, idx, 0);
|
||||
else
|
||||
set_to_lvariable(lval, idx, 0);
|
||||
|
||||
if (skip_set_flag)
|
||||
if (skip_set_flag) {
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
}
|
||||
|
||||
if (res.base > 3)
|
||||
@@ -342,6 +389,54 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
||||
; idx += 1) {
|
||||
assign_to_memory(mem, idx, 0, delay);
|
||||
}
|
||||
|
||||
} else if ((del == 0) && (bit_limit > 2)) {
|
||||
|
||||
/* We have a vector, but no runtime
|
||||
calculated delays, to try to use vector
|
||||
assign instructions. */
|
||||
idx = 0;
|
||||
while (idx < bit_limit) {
|
||||
unsigned wid = 0;
|
||||
|
||||
do {
|
||||
wid += 1;
|
||||
if ((idx + wid) == bit_limit)
|
||||
break;
|
||||
|
||||
} while (bits[cur_rbit] == bits[cur_rbit+wid]);
|
||||
|
||||
switch (wid) {
|
||||
case 1:
|
||||
assign_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
break;
|
||||
case 2:
|
||||
assign_to_lvariable(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
assign_to_lvariable(lval, idx+1,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, 0);
|
||||
break;
|
||||
default:
|
||||
assign_to_lvector(lval, idx,
|
||||
bitchar_to_idx(bits[cur_rbit]),
|
||||
delay, wid);
|
||||
break;
|
||||
}
|
||||
|
||||
idx += wid;
|
||||
cur_rbit += wid;
|
||||
}
|
||||
|
||||
if (bit_limit < ivl_lval_pins(lval)) {
|
||||
unsigned wid = ivl_lval_pins(lval) - bit_limit;
|
||||
assign_to_lvector(lval, bit_limit,
|
||||
0, delay, wid);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
if (del != 0)
|
||||
@@ -367,14 +462,16 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
||||
}
|
||||
}
|
||||
|
||||
if (skip_set_flag)
|
||||
if (skip_set_flag) {
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
{ struct vector_info res = draw_eval_expr(rval);
|
||||
{ struct vector_info res = draw_eval_expr(rval, 0);
|
||||
unsigned wid = res.wid;
|
||||
unsigned lidx;
|
||||
unsigned cur_rbit = 0;
|
||||
@@ -407,34 +504,45 @@ static int show_stmt_assign_nb(ivl_statement_t net)
|
||||
if (bit_limit > ivl_lval_pins(lval))
|
||||
bit_limit = ivl_lval_pins(lval);
|
||||
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
if ((bit_limit > 2) && (mem == 0) && (del == 0)) {
|
||||
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
: (res.base+cur_rbit);
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, bidx, delay);
|
||||
else if (del != 0)
|
||||
assign_to_lvariable(lval, idx, bidx,
|
||||
1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, bidx,
|
||||
delay, 0);
|
||||
assign_to_lvector(lval, 0, bidx, delay, bit_limit);
|
||||
cur_rbit += bit_limit;
|
||||
|
||||
cur_rbit += 1;
|
||||
} else {
|
||||
for (idx = 0 ; idx < bit_limit ; idx += 1) {
|
||||
unsigned bidx = res.base < 4
|
||||
? res.base
|
||||
: (res.base+cur_rbit);
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, bidx, delay);
|
||||
else if (del != 0)
|
||||
assign_to_lvariable(lval, idx, bidx,
|
||||
1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, bidx,
|
||||
delay, 0);
|
||||
|
||||
cur_rbit += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (idx = bit_limit ; idx < ivl_lval_pins(lval) ; idx += 1)
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, 0, delay);
|
||||
else if (del != 0)
|
||||
assign_to_lvariable(lval, idx, 0, 1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, 0, delay, 0);
|
||||
for (idx = bit_limit; idx < ivl_lval_pins(lval); idx += 1)
|
||||
if (mem)
|
||||
assign_to_memory(mem, idx, 0, delay);
|
||||
else if (del != 0)
|
||||
assign_to_lvariable(lval, idx, 0, 1, 1);
|
||||
else
|
||||
assign_to_lvariable(lval, idx, 0, delay, 0);
|
||||
|
||||
|
||||
if (skip_set_flag)
|
||||
if (skip_set_flag) {
|
||||
fprintf(vvp_out, "t_%u ;\n", skip_set);
|
||||
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
}
|
||||
|
||||
if (res.base > 3)
|
||||
@@ -480,6 +588,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope)
|
||||
fprintf(vvp_out, " %%end;\n");
|
||||
|
||||
fprintf(vvp_out, "t_%u %%join;\n", out_id);
|
||||
clear_expression_lookaside();
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -488,7 +597,7 @@ static int show_stmt_block_named(ivl_statement_t net, ivl_scope_t scope)
|
||||
static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
|
||||
{
|
||||
ivl_expr_t exp = ivl_stmt_cond_expr(net);
|
||||
struct vector_info cond = draw_eval_expr(exp);
|
||||
struct vector_info cond = draw_eval_expr(exp, 0);
|
||||
unsigned count = ivl_stmt_case_count(net);
|
||||
|
||||
unsigned local_base = local_count;
|
||||
@@ -531,7 +640,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
|
||||
|
||||
/* Oh well, do this case the hard way. */
|
||||
|
||||
cvec = draw_eval_expr_wid(cex, cond.wid);
|
||||
cvec = draw_eval_expr_wid(cex, cond.wid, 0);
|
||||
assert(cvec.wid == cond.wid);
|
||||
|
||||
switch (ivl_statement_type(net)) {
|
||||
@@ -585,6 +694,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
|
||||
continue;
|
||||
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+idx);
|
||||
clear_expression_lookaside();
|
||||
show_statement(cst, sscope);
|
||||
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count,
|
||||
@@ -592,8 +702,10 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope)
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* The out of the case. */
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, local_base+count);
|
||||
clear_expression_lookaside();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -651,7 +763,7 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope)
|
||||
int rc = 0;
|
||||
unsigned lab_false, lab_out;
|
||||
ivl_expr_t exp = ivl_stmt_cond_expr(net);
|
||||
struct vector_info cond = draw_eval_expr(exp);
|
||||
struct vector_info cond = draw_eval_expr(exp, STUFF_OK_XZ|STUFF_OK_47);
|
||||
|
||||
assert(cond.wid == 1);
|
||||
|
||||
@@ -662,21 +774,26 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope)
|
||||
thread_count, lab_false, cond.base);
|
||||
|
||||
/* Done with the condition expression. */
|
||||
clr_vector(cond);
|
||||
if (cond.base >= 8)
|
||||
clr_vector(cond);
|
||||
|
||||
if (ivl_stmt_cond_true(net))
|
||||
rc += show_statement(ivl_stmt_cond_true(net), sscope);
|
||||
|
||||
|
||||
if (ivl_stmt_cond_false(net)) {
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, lab_out);
|
||||
fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_false);
|
||||
clear_expression_lookaside();
|
||||
|
||||
rc += show_statement(ivl_stmt_cond_false(net), sscope);
|
||||
|
||||
fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_out);
|
||||
clear_expression_lookaside();
|
||||
|
||||
} else {
|
||||
fprintf(vvp_out, "T_%d.%u ;\n", thread_count, lab_false);
|
||||
clear_expression_lookaside();
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -697,6 +814,9 @@ static int show_stmt_delay(ivl_statement_t net, ivl_scope_t sscope)
|
||||
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
|
||||
|
||||
fprintf(vvp_out, " %%delay %lu;\n", delay);
|
||||
/* Lots of things can happen during a delay. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
rc += show_statement(stmt, sscope);
|
||||
|
||||
return rc;
|
||||
@@ -714,12 +834,14 @@ static int show_stmt_delayx(ivl_statement_t net, ivl_scope_t sscope)
|
||||
ivl_expr_t exp = ivl_stmt_delay_expr(net);
|
||||
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
|
||||
|
||||
{ struct vector_info del = draw_eval_expr(exp);
|
||||
{ struct vector_info del = draw_eval_expr(exp, 0);
|
||||
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", del.base, del.wid);
|
||||
clr_vector(del);
|
||||
}
|
||||
|
||||
fprintf(vvp_out, " %%delayx 0;\n");
|
||||
/* Lots of things can happen during a delay. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
rc += show_statement(stmt, sscope);
|
||||
return rc;
|
||||
@@ -741,6 +863,7 @@ static int show_stmt_force(ivl_statement_t net)
|
||||
ivl_lval_t lval;
|
||||
ivl_signal_t lsig;
|
||||
unsigned idx;
|
||||
static unsigned force_functor_label = 0;
|
||||
|
||||
assert(ivl_stmt_lvals(net) == 1);
|
||||
lval = ivl_stmt_lval(net, 0);
|
||||
@@ -750,16 +873,17 @@ static int show_stmt_force(ivl_statement_t net)
|
||||
assert(ivl_lval_mux(lval) == 0);
|
||||
assert(ivl_lval_part_off(lval) == 0);
|
||||
|
||||
force_functor_label += 1;
|
||||
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
|
||||
fprintf(vvp_out, "f_%s.%u .force V_%s[%u], %s;\n",
|
||||
vvp_signal_label(lsig), idx,
|
||||
fprintf(vvp_out, "f_%u.%u .force V_%s[%u], %s;\n",
|
||||
force_functor_label, idx,
|
||||
vvp_signal_label(lsig), idx,
|
||||
draw_net_input(ivl_stmt_nexus(net, idx)));
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < ivl_lval_pins(lval) ; idx += 1) {
|
||||
fprintf(vvp_out, " %%force f_%s.%u, 1;\n",
|
||||
vvp_signal_label(lsig), idx);
|
||||
fprintf(vvp_out, " %%force f_%u.%u, 1;\n",
|
||||
force_functor_label, idx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -808,12 +932,14 @@ static int show_stmt_fork(ivl_statement_t net, ivl_scope_t sscope)
|
||||
|
||||
for (idx = 0 ; idx < cnt-1 ; idx += 1) {
|
||||
fprintf(vvp_out, "t_%u ;\n", id_base+idx);
|
||||
clear_expression_lookaside();
|
||||
rc += show_statement(ivl_stmt_block_stmt(net, idx), sscope);
|
||||
fprintf(vvp_out, " %%end;\n");
|
||||
}
|
||||
|
||||
/* This is the label for the out. Use this to branch around
|
||||
the implementations of all the child threads. */
|
||||
clear_expression_lookaside();
|
||||
fprintf(vvp_out, "t_%u ;\n", out);
|
||||
|
||||
return rc;
|
||||
@@ -868,11 +994,12 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope)
|
||||
int rc = 0;
|
||||
unsigned lab_top = local_count++, lab_out = local_count++;
|
||||
ivl_expr_t exp = ivl_stmt_cond_expr(net);
|
||||
struct vector_info cnt = draw_eval_expr(exp);
|
||||
struct vector_info cnt = draw_eval_expr(exp, 0);
|
||||
|
||||
/* Test that 0 < expr */
|
||||
fprintf(vvp_out, "T_%u.%u %%cmp/u 0, %u, %u;\n", thread_count,
|
||||
lab_top, cnt.base, cnt.wid);
|
||||
clear_expression_lookaside();
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, 5;\n", thread_count, lab_out);
|
||||
/* This adds -1 (all ones in 2's complement) to the count. */
|
||||
fprintf(vvp_out, " %%add %u, 1, %u;\n", cnt.base, cnt.wid);
|
||||
@@ -881,6 +1008,7 @@ static int show_stmt_repeat(ivl_statement_t net, ivl_scope_t sscope)
|
||||
|
||||
fprintf(vvp_out, " %%jmp T_%u.%u;\n", thread_count, lab_top);
|
||||
fprintf(vvp_out, "T_%u.%u ;\n", thread_count, lab_out);
|
||||
clear_expression_lookaside();
|
||||
|
||||
clr_vector(cnt);
|
||||
|
||||
@@ -905,6 +1033,7 @@ static int show_stmt_utask(ivl_statement_t net)
|
||||
fprintf(vvp_out, ", S_%s;\n",
|
||||
vvp_mangle_id(ivl_scope_name(task)));
|
||||
fprintf(vvp_out, " %%join;\n");
|
||||
clear_expression_lookaside();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -914,6 +1043,10 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope)
|
||||
fprintf(vvp_out, " %%wait E_%s;\n",
|
||||
vvp_mangle_id(ivl_event_name(ev)));
|
||||
|
||||
/* Always clear the expression lookaside after a
|
||||
%wait. Anything can happen while the thread is waiting. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
return show_statement(ivl_stmt_sub_stmt(net), sscope);
|
||||
}
|
||||
|
||||
@@ -955,18 +1088,23 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
|
||||
unsigned top_label = local_count++;
|
||||
unsigned out_label = local_count++;
|
||||
|
||||
/* Start the loop. The top of the loop starts a basic block
|
||||
because it can be entered from above or from the bottom of
|
||||
the loop. */
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, top_label);
|
||||
clear_expression_lookaside();
|
||||
|
||||
/* Draw the evaluation of the condition expression, and test
|
||||
the result. If the expression evaluates to false, then
|
||||
branch to the out label. */
|
||||
cvec = draw_eval_expr(ivl_stmt_cond_expr(net));
|
||||
cvec = draw_eval_expr(ivl_stmt_cond_expr(net), STUFF_OK_XZ|STUFF_OK_47);
|
||||
if (cvec.wid > 1)
|
||||
cvec = reduction_or(cvec);
|
||||
|
||||
fprintf(vvp_out, " %%jmp/0xz T_%d.%d, %u;\n",
|
||||
thread_count, out_label, cvec.base);
|
||||
clr_vector(cvec);
|
||||
if (cvec.base >= 8)
|
||||
clr_vector(cvec);
|
||||
|
||||
/* Draw the body of the loop. */
|
||||
rc += show_statement(ivl_stmt_sub_stmt(net), sscope);
|
||||
@@ -975,6 +1113,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
|
||||
test is repeased, and also draw the out label. */
|
||||
fprintf(vvp_out, " %%jmp T_%d.%d;\n", thread_count, top_label);
|
||||
fprintf(vvp_out, "T_%d.%d ;\n", thread_count, out_label);
|
||||
clear_expression_lookaside();
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -988,6 +1127,7 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
|
||||
if (parm_count == 0) {
|
||||
fprintf(vvp_out, " %%vpi_call \"%s\";\n", ivl_stmt_name(net));
|
||||
clear_expression_lookaside();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1023,7 +1163,7 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
|
||||
vec = (struct vector_info *)
|
||||
realloc(vec, (vecs+1)*sizeof(struct vector_info));
|
||||
vec[vecs] = draw_eval_expr(expr);
|
||||
vec[vecs] = draw_eval_expr(expr, 0);
|
||||
vecs++;
|
||||
}
|
||||
|
||||
@@ -1106,6 +1246,10 @@ static int show_system_task_call(ivl_statement_t net)
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
|
||||
/* VPI calls can manipulate anything, so clear the expression
|
||||
lookahead table after the call. */
|
||||
clear_expression_lookaside();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1240,6 +1384,7 @@ int draw_process(ivl_process_t net, void*x)
|
||||
/* Generate the entry label. Just give the thread a number so
|
||||
that we ar certain the label is unique. */
|
||||
fprintf(vvp_out, "T_%d ;\n", thread_count);
|
||||
clear_expression_lookaside();
|
||||
|
||||
/* Draw the contents of the thread. */
|
||||
rc += show_statement(stmt, scope);
|
||||
@@ -1274,6 +1419,7 @@ int draw_task_definition(ivl_scope_t scope)
|
||||
ivl_statement_t def = ivl_scope_def(scope);
|
||||
|
||||
fprintf(vvp_out, "TD_%s ;\n", vvp_mangle_id(ivl_scope_name(scope)));
|
||||
clear_expression_lookaside();
|
||||
|
||||
assert(def);
|
||||
rc += show_statement(def, scope);
|
||||
@@ -1290,6 +1436,7 @@ int draw_func_definition(ivl_scope_t scope)
|
||||
ivl_statement_t def = ivl_scope_def(scope);
|
||||
|
||||
fprintf(vvp_out, "TD_%s ;\n", vvp_mangle_id(ivl_scope_name(scope)));
|
||||
clear_expression_lookaside();
|
||||
|
||||
assert(def);
|
||||
rc += show_statement(def, scope);
|
||||
@@ -1302,6 +1449,33 @@ int draw_func_definition(ivl_scope_t scope)
|
||||
|
||||
/*
|
||||
* $Log: vvp_process.c,v $
|
||||
* Revision 1.76 2002/11/21 22:43:13 steve
|
||||
* %set/x0 instruction to support bounds checking.
|
||||
*
|
||||
* Revision 1.75 2002/11/17 18:31:09 steve
|
||||
* Generate unique labels for force functors.
|
||||
*
|
||||
* Revision 1.74 2002/11/08 05:00:31 steve
|
||||
* Use the vectorized %assign where appropriate.
|
||||
*
|
||||
* Revision 1.73 2002/11/07 05:19:55 steve
|
||||
* Use Vector %set to set constants in variables.
|
||||
*
|
||||
* Revision 1.72 2002/11/07 03:12:18 steve
|
||||
* Vectorize load from REG variables.
|
||||
*
|
||||
* Revision 1.71 2002/09/27 20:24:42 steve
|
||||
* Allow expression lookaside map to spam statements.
|
||||
*
|
||||
* Revision 1.70 2002/09/27 16:33:34 steve
|
||||
* Add thread expression lookaside map.
|
||||
*
|
||||
* Revision 1.69 2002/09/24 04:20:32 steve
|
||||
* Allow results in register bits 47 in certain cases.
|
||||
*
|
||||
* Revision 1.68 2002/09/13 03:12:50 steve
|
||||
* Optimize ==1 when in context where x vs z doesnt matter.
|
||||
*
|
||||
* Revision 1.67 2002/09/01 00:19:35 steve
|
||||
* Watch for x indices in l-value of non-blocking assignments.
|
||||
*
|
||||
@@ -1384,99 +1558,5 @@ int draw_func_definition(ivl_scope_t scope)
|
||||
*
|
||||
* Revision 1.44 2001/09/01 00:58:16 steve
|
||||
* dead comments.
|
||||
*
|
||||
* Revision 1.43 2001/08/26 23:00:13 steve
|
||||
* Generate code for l-value bit selects.
|
||||
*
|
||||
* Revision 1.42 2001/08/25 23:50:03 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.41 2001/08/16 03:45:17 steve
|
||||
* statement ends after while loop labels.
|
||||
*
|
||||
* Revision 1.40 2001/07/28 01:18:07 steve
|
||||
* Evaluate part selects when passed to system tasks.
|
||||
*
|
||||
* Revision 1.39 2001/07/19 04:55:06 steve
|
||||
* Support calculated delays in vvp.tgt.
|
||||
*
|
||||
* Revision 1.38 2001/06/29 02:41:05 steve
|
||||
* Handle null parameters to system tasks.
|
||||
*
|
||||
* Revision 1.37 2001/06/23 00:30:42 steve
|
||||
* Handle short inputs to tasks. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.36 2001/06/18 03:10:34 steve
|
||||
* 1. Logic with more than 4 inputs
|
||||
* 2. Id and name mangling
|
||||
* 3. A memory leak in draw_net_in_scope()
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.35 2001/05/24 04:31:00 steve
|
||||
* Attach noops to case labels.
|
||||
*
|
||||
* Revision 1.34 2001/05/17 04:37:02 steve
|
||||
* Behavioral ternary operators for vvp.
|
||||
*
|
||||
* Revision 1.33 2001/05/10 00:26:53 steve
|
||||
* VVP support for memories in expressions,
|
||||
* including general support for thread bit
|
||||
* vectors as system task parameters.
|
||||
* (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.32 2001/05/08 23:59:33 steve
|
||||
* Add ivl and vvp.tgt support for memories in
|
||||
* expressions and l-values. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.31 2001/05/03 04:55:28 steve
|
||||
* Generate null statements for conditional labels.
|
||||
*
|
||||
* Revision 1.30 2001/04/21 03:26:23 steve
|
||||
* Right shift by constant.
|
||||
*
|
||||
* Revision 1.29 2001/04/21 00:55:46 steve
|
||||
* Generate code for disable.
|
||||
*
|
||||
* Revision 1.28 2001/04/18 05:12:03 steve
|
||||
* Use the new %fork syntax.
|
||||
*
|
||||
* Revision 1.27 2001/04/15 02:58:11 steve
|
||||
* vvp support for <= with internal delay.
|
||||
*
|
||||
* Revision 1.26 2001/04/06 02:28:03 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Revision 1.25 2001/04/05 03:20:58 steve
|
||||
* Generate vvp code for the repeat statement.
|
||||
*
|
||||
* Revision 1.24 2001/04/04 04:50:35 steve
|
||||
* Support forever loops in the tgt-vvp target.
|
||||
*
|
||||
* Revision 1.23 2001/04/04 04:28:41 steve
|
||||
* Fix broken look scanning down bits of number.
|
||||
*
|
||||
* Revision 1.22 2001/04/04 04:14:09 steve
|
||||
* emit vpi parameters values as vectors.
|
||||
*
|
||||
* Revision 1.21 2001/04/03 04:50:37 steve
|
||||
* Support non-blocking assignments.
|
||||
*
|
||||
* Revision 1.20 2001/04/02 04:09:20 steve
|
||||
* thread bit allocation leak in assign.
|
||||
*
|
||||
* Revision 1.19 2001/04/02 02:28:13 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.18 2001/04/02 00:27:53 steve
|
||||
* Scopes and numbers as vpi_call parameters.
|
||||
*
|
||||
* Revision 1.17 2001/04/01 06:49:04 steve
|
||||
* Generate code for while statements.
|
||||
*/
|
||||
|
||||
|
||||
+133
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_scope.c,v 1.77 2002/08/12 01:35:04 steve Exp $"
|
||||
#ident "$Id: vvp_scope.c,v 1.81 2002/11/21 18:08:09 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvp_priv.h"
|
||||
@@ -330,6 +330,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
|
||||
lpm = ivl_nexus_ptr_lpm(nptr);
|
||||
if (lpm) switch (ivl_lpm_type(lpm)) {
|
||||
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_MUX:
|
||||
for (idx = 0 ; idx < ivl_lpm_width(lpm) ; idx += 1)
|
||||
if (ivl_lpm_q(lpm, idx) == nex) {
|
||||
@@ -1264,13 +1265,123 @@ static void draw_lpm_eq(ivl_lpm_t net)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* primitive FD (q, clk, ce, d);
|
||||
* output q;
|
||||
* reg q;
|
||||
* input clk, ce, d;
|
||||
* table
|
||||
* // clk ce d r s q q+
|
||||
* r 1 0 0 0 : ? : 0;
|
||||
* r 1 1 0 0 : ? : 1;
|
||||
* f 1 ? 0 0 : ? : -;
|
||||
* ? 1 ? 0 0 : ? : -;
|
||||
* * 0 ? 0 0 : ? : -;
|
||||
* ? ? ? 1 ? : ? : 0;
|
||||
* ? ? ? 0 1 : ? : 1;
|
||||
* endtable
|
||||
* endprimitive
|
||||
*/
|
||||
static void draw_lpm_ff(ivl_lpm_t net)
|
||||
{
|
||||
ivl_expr_t aset_expr = 0;
|
||||
const char*aset_bits = 0;
|
||||
|
||||
unsigned width, idx;
|
||||
|
||||
width = ivl_lpm_width(net);
|
||||
|
||||
/* Q C CE D RS --> Q+ */
|
||||
fprintf(vvp_out, "L_%s/def .udp/sequ \"DFF\", 5, 2,"
|
||||
" \"?" "r" "1" "0" "00" "0\","
|
||||
" \"?" "r" "1" "1" "00" "1\","
|
||||
" \"?" "r" "1" "x" "00" "x\","
|
||||
" \"0" "r" "x" "0" "00" "0\","
|
||||
" \"1" "r" "x" "1" "00" "1\","
|
||||
" \"?" "*" "0" "?" "00" "-\","
|
||||
" \"?" "_" "?" "?" "00" "-\","
|
||||
" \"?" "?" "?" "?" "01" "1\","
|
||||
" \"?" "?" "?" "?" "1?" "0\","
|
||||
" \"?" "?" "1" "?" "00" "-\","
|
||||
" \"?" "?" "?" "?" "00" "-\""
|
||||
";\n", vvp_mangle_id(ivl_lpm_name(net)));
|
||||
|
||||
aset_expr = ivl_lpm_aset_value(net);
|
||||
if (aset_expr) {
|
||||
assert(ivl_expr_width(aset_expr) == width);
|
||||
aset_bits = ivl_expr_bits(aset_expr);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
ivl_nexus_t tmp;
|
||||
|
||||
fprintf(vvp_out, "L_%s/%u .udp ",
|
||||
vvp_mangle_id(ivl_lpm_name(net)), idx);
|
||||
|
||||
fprintf(vvp_out, "L_%s/def, ", vvp_mangle_id(ivl_lpm_name(net)));
|
||||
|
||||
tmp = ivl_lpm_clk(net);
|
||||
draw_input_from_net(tmp);
|
||||
|
||||
tmp = ivl_lpm_enable(net);
|
||||
fprintf(vvp_out, ", ");
|
||||
if (tmp)
|
||||
draw_input_from_net(tmp);
|
||||
else
|
||||
fprintf(vvp_out, "C<1>");
|
||||
|
||||
tmp = ivl_lpm_data(net, idx);
|
||||
assert(tmp);
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(tmp);
|
||||
|
||||
/* Connect reset input. This may be the Aclr input, or
|
||||
an Aset to zero. */
|
||||
fprintf(vvp_out, ", ");
|
||||
tmp = ivl_lpm_async_clr(net);
|
||||
if (tmp) {
|
||||
draw_input_from_net(tmp);
|
||||
} else {
|
||||
tmp = ivl_lpm_async_set(net);
|
||||
if (aset_bits && (aset_bits[idx] == '0'))
|
||||
draw_input_from_net(tmp);
|
||||
else
|
||||
fprintf(vvp_out, "C<0>");
|
||||
}
|
||||
|
||||
/* Connect set input */
|
||||
fprintf(vvp_out, ", ");
|
||||
tmp = ivl_lpm_async_set(net);
|
||||
if (aset_bits && (aset_bits[idx] != '1'))
|
||||
tmp = 0;
|
||||
|
||||
if (tmp)
|
||||
draw_input_from_net(tmp);
|
||||
else
|
||||
fprintf(vvp_out, "C<0>");
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_lpm_shiftl(ivl_lpm_t net)
|
||||
{
|
||||
unsigned idx, width, selects;
|
||||
unsigned selwid;
|
||||
|
||||
width = ivl_lpm_width(net);
|
||||
selects = ivl_lpm_selects(net);
|
||||
|
||||
/* The .shift device can only take as many select inputs as
|
||||
the width of the device.
|
||||
|
||||
XXXX I should make some sort of overflow gate for this? If
|
||||
any high bits are set, then the shift is certain to be
|
||||
*way* beyond the width of the left shifted value. XXXX */
|
||||
selwid = selects;
|
||||
if (selwid > width)
|
||||
selwid = width;
|
||||
|
||||
if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
|
||||
fprintf(vvp_out, "L_%s .shift/r %u",
|
||||
vvp_mangle_id(ivl_lpm_name(net)), width);
|
||||
@@ -1283,11 +1394,15 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
|
||||
draw_input_from_net(ivl_lpm_data(net, idx));
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < selects ; idx += 1) {
|
||||
for (idx = 0 ; idx < selwid ; idx += 1) {
|
||||
fprintf(vvp_out, ", ");
|
||||
draw_input_from_net(ivl_lpm_select(net, idx));
|
||||
}
|
||||
|
||||
for (idx = selwid ; idx < width ; idx += 1) {
|
||||
fprintf(vvp_out, ", C<0>");
|
||||
}
|
||||
|
||||
fprintf(vvp_out, ";\n");
|
||||
}
|
||||
|
||||
@@ -1373,6 +1488,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
|
||||
draw_lpm_eq(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
draw_lpm_ff(net);
|
||||
return;
|
||||
|
||||
case IVL_LPM_CMP_GE:
|
||||
case IVL_LPM_CMP_GT:
|
||||
draw_lpm_cmp(net);
|
||||
@@ -1488,6 +1607,18 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
|
||||
|
||||
/*
|
||||
* $Log: vvp_scope.c,v $
|
||||
* Revision 1.81 2002/11/21 18:08:09 steve
|
||||
* Better handling of select width of shifters.
|
||||
*
|
||||
* Revision 1.80 2002/10/23 04:39:35 steve
|
||||
* draw lpm ff with aset_expr taken into account.
|
||||
*
|
||||
* Revision 1.79 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.78 2002/09/17 05:37:45 steve
|
||||
* Generate vvp code for structural flip-flops.
|
||||
*
|
||||
* Revision 1.77 2002/08/12 01:35:04 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
Summary: Icarus Verilog
|
||||
Name: verilog
|
||||
Version: 0.6.20020907
|
||||
Version: 0.7
|
||||
Release: 0
|
||||
Copyright: GPL
|
||||
Group: Applications/Engineering
|
||||
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-20020907.tar.gz
|
||||
Source: ftp://icarus.com/pub/eda/verilog/snapshots/verilog-0.7.tar.gz
|
||||
URL: http://www.icarus.com/eda/verilog/index.html
|
||||
Packager: Stephen Williams <[email protected]>
|
||||
|
||||
@@ -20,7 +20,7 @@ engineering formats, including simulation. It strives to be true
|
||||
to the IEEE-1364 standard.
|
||||
|
||||
%prep
|
||||
%setup -n verilog-20020907
|
||||
%setup -n verilog-0.7
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
|
||||
+27
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_display.c,v 1.45 2002/09/06 04:56:28 steve Exp $"
|
||||
#ident "$Id: sys_display.c,v 1.46 2002/11/09 06:01:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -609,6 +609,29 @@ static int format_str(vpiHandle scope, unsigned int mcd,
|
||||
cp += 1;
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
if (isdigit(cp[0])
|
||||
&& isdigit(cp[1])
|
||||
&& isdigit(cp[2])) {
|
||||
/* handle octal escapes (e.g. "\015" is CR)*/
|
||||
vpi_mcd_printf(mcd, "%c",
|
||||
(cp[2] - '0') +
|
||||
8 * ((cp[1] - '0') +
|
||||
8 * (cp[0] - '0')));
|
||||
cp += 3;
|
||||
} else {
|
||||
vpi_mcd_printf(mcd, "%c", *cp);
|
||||
cp += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_mcd_printf(mcd, "%c", *cp);
|
||||
cp += 1;
|
||||
@@ -1461,6 +1484,9 @@ void sys_display_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_display.c,v $
|
||||
* Revision 1.46 2002/11/09 06:01:11 steve
|
||||
* display octal escapes properly.
|
||||
*
|
||||
* Revision 1.45 2002/09/06 04:56:28 steve
|
||||
* Add support for %v is the display system task.
|
||||
* Change the encoding of H and L outputs from
|
||||
|
||||
+7
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_lxt.c,v 1.11 2002/08/15 02:12:20 steve Exp $"
|
||||
#ident "$Id: sys_lxt.c,v 1.12 2002/11/17 22:28:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -460,6 +460,9 @@ static int sys_dumpfile_calltf(char*name)
|
||||
path = strdup("dumpfile.lxt");
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
close_dumpfile();
|
||||
|
||||
assert(dump_file == 0);
|
||||
open_dumpfile(path);
|
||||
|
||||
@@ -814,6 +817,9 @@ void sys_lxt_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_lxt.c,v $
|
||||
* Revision 1.12 2002/11/17 22:28:42 steve
|
||||
* Close old file if $dumpfile is called again.
|
||||
*
|
||||
* Revision 1.11 2002/08/15 02:12:20 steve
|
||||
* add dumpvars_compiletf to check first argument.
|
||||
*
|
||||
|
||||
+13
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: sys_vcd.c,v 1.37 2002/08/15 02:12:20 steve Exp $"
|
||||
#ident "$Id: sys_vcd.c,v 1.39 2002/11/17 22:28:42 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -146,7 +146,7 @@ inline static void vcd_names_add(const char *name)
|
||||
struct vcd_names_s *nl = (struct vcd_names_s *)
|
||||
malloc(sizeof(struct vcd_names_s));
|
||||
assert(nl);
|
||||
nl->name = name;
|
||||
nl->name = strdup(name);
|
||||
nl->next = vcd_names_list;
|
||||
vcd_names_list = nl;
|
||||
listed_names ++;
|
||||
@@ -449,6 +449,11 @@ static int sys_dumpfile_calltf(char*name)
|
||||
path = strdup("dumpfile.vcd");
|
||||
}
|
||||
|
||||
if (dump_file) {
|
||||
fclose(dump_file);
|
||||
dump_file = 0;
|
||||
}
|
||||
|
||||
assert(dump_file == 0);
|
||||
open_dumpfile(path);
|
||||
|
||||
@@ -844,6 +849,12 @@ void sys_vcd_register()
|
||||
|
||||
/*
|
||||
* $Log: sys_vcd.c,v $
|
||||
* Revision 1.39 2002/11/17 22:28:42 steve
|
||||
* Close old file if $dumpfile is called again.
|
||||
*
|
||||
* Revision 1.38 2002/11/14 22:43:58 steve
|
||||
* Save vpiFullName results.
|
||||
*
|
||||
* Revision 1.37 2002/08/15 02:12:20 steve
|
||||
* add dumpvars_compiletf to check first argument.
|
||||
*
|
||||
|
||||
+10
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpithunk.c,v 1.6 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: vpithunk.c,v 1.7 2002/12/11 23:55:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -188,6 +188,11 @@ extern vpiHandle vpi_handle_by_index(vpiHandle ref, int index)
|
||||
VPIT_CALL(vpi_handle_by_index,0,(ref, index));
|
||||
}
|
||||
|
||||
extern vpiHandle vpi_handle_by_name(char *name, vpiHandle scope)
|
||||
{
|
||||
VPIT_CALL(vpi_handle_by_name,0,(name, scope));
|
||||
}
|
||||
|
||||
extern void vpi_get_time(vpiHandle obj, s_vpi_time*t)
|
||||
{
|
||||
VPITV_CALL(vpi_get_time, (obj,t));
|
||||
@@ -232,6 +237,10 @@ extern int vpi_chk_error(p_vpi_error_info info)
|
||||
|
||||
/*
|
||||
* $Log: vpithunk.c,v $
|
||||
* Revision 1.7 2002/12/11 23:55:22 steve
|
||||
* Add vpi_handle_by_name to the VPI interface,
|
||||
* and bump the vpithunk magic number.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+9
-2
@@ -20,7 +20,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpithunk.h,v 1.4 2002/08/12 01:35:01 steve Exp $"
|
||||
#ident "$Id: vpithunk.h,v 1.5 2002/12/11 23:55:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
/* These functions are actually defined in lieu of the vpi functions
|
||||
@@ -38,7 +38,9 @@ extern void vpi_sim_vcontrol(int operation, va_list ap);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#define VPI_THUNK_MAGIC (0x87836BA4)
|
||||
/* before v0.7: 0x87836BA4 */
|
||||
/* v0.7 thunk magic is 0x87836BA5 */
|
||||
#define VPI_THUNK_MAGIC (0x87836BA5)
|
||||
|
||||
typedef struct {
|
||||
int magic;
|
||||
@@ -67,6 +69,7 @@ typedef struct {
|
||||
int (*vpi_free_object)(vpiHandle ref);
|
||||
int (*vpi_get_vlog_info)(p_vpi_vlog_info vlog_info_p);
|
||||
int (*vpi_chk_error)(p_vpi_error_info info);
|
||||
vpiHandle (*vpi_handle_by_name)(char *name, vpiHandle scope);
|
||||
} vpi_thunk, *p_vpi_thunk;
|
||||
|
||||
DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
|
||||
@@ -75,6 +78,10 @@ DLLEXPORT int vpi_register_sim(p_vpi_thunk tp);
|
||||
|
||||
/*
|
||||
* $Log: vpithunk.h,v $
|
||||
* Revision 1.5 2002/12/11 23:55:22 steve
|
||||
* Add vpi_handle_by_name to the VPI interface,
|
||||
* and bump the vpithunk magic number.
|
||||
*
|
||||
* Revision 1.4 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -10,6 +10,7 @@ Makefile
|
||||
lexor.cc
|
||||
parse.cc
|
||||
parse.cc.output
|
||||
parse.output
|
||||
parse.h
|
||||
tables.cc
|
||||
vvp
|
||||
|
||||
+22
-2
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: codes.h,v 1.49 2002/08/28 18:38:07 steve Exp $"
|
||||
#ident "$Id: codes.h,v 1.54 2002/11/21 22:43:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ extern bool of_ANDR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_D(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_V0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ASSIGN_X0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_BLEND(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_BREAKPOINT(vthread_t thr, vvp_code_t code);
|
||||
@@ -74,20 +75,24 @@ extern bool of_JOIN(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_NX(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_LOAD_X(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MOD(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MOV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MUL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_MULI(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_NAND(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_NANDR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_NOOP(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_NOR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_NORR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_OR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_ORR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_RELEASE(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_MEM(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_X(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_VEC(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SET_X0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SHIFTL_I0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SHIFTR_I0(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_SUB(vthread_t thr, vvp_code_t code);
|
||||
@@ -155,6 +160,21 @@ extern vvp_code_t codespace_index(vvp_cpoint_t ptr);
|
||||
|
||||
/*
|
||||
* $Log: codes.h,v $
|
||||
* Revision 1.54 2002/11/21 22:43:13 steve
|
||||
* %set/x0 instruction to support bounds checking.
|
||||
*
|
||||
* Revision 1.53 2002/11/08 04:59:57 steve
|
||||
* Add the %assign/v0 instruction.
|
||||
*
|
||||
* Revision 1.52 2002/11/07 02:32:39 steve
|
||||
* Add vector set and load instructions.
|
||||
*
|
||||
* Revision 1.51 2002/09/18 04:29:55 steve
|
||||
* Add support for binary NOR operator.
|
||||
*
|
||||
* Revision 1.50 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.49 2002/08/28 18:38:07 steve
|
||||
* Add the %subi instruction, and use it where possible.
|
||||
*
|
||||
|
||||
+61
-9
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compile.cc,v 1.140 2002/08/28 18:38:07 steve Exp $"
|
||||
#ident "$Id: compile.cc,v 1.146 2002/11/21 22:43:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "arith.h"
|
||||
@@ -87,8 +87,9 @@ const static struct opcode_table_s opcode_table[] = {
|
||||
{ "%and", of_AND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%and/r", of_ANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%assign", of_ASSIGN, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/d", of_ASSIGN_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/d", of_ASSIGN_D, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/m",of_ASSIGN_MEM,3,{OA_MEM_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/v0",of_ASSIGN_V0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%assign/x0",of_ASSIGN_X0,3,{OA_FUNC_PTR,OA_BIT1, OA_BIT2} },
|
||||
{ "%blend", of_BLEND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%breakpoint", of_BREAKPOINT, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
@@ -119,20 +120,24 @@ const static struct opcode_table_s opcode_table[] = {
|
||||
{ "%load", of_LOAD, 2, {OA_BIT1, OA_FUNC_PTR, OA_NONE} },
|
||||
{ "%load/m", of_LOAD_MEM,2, {OA_BIT1, OA_MEM_PTR, OA_NONE} },
|
||||
{ "%load/nx",of_LOAD_NX,3, {OA_BIT1, OA_VPI_PTR, OA_BIT2} },
|
||||
{ "%load/v", of_LOAD_VEC,3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||
{ "%load/x", of_LOAD_X, 3, {OA_BIT1, OA_FUNC_PTR, OA_BIT2} },
|
||||
{ "%mod", of_MOD, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%mov", of_MOV, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%mul", of_MUL, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%muli", of_MULI, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%nand", of_NAND, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%nand/r", of_NANDR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%noop", of_NOOP, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%nor", of_NOR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%nor/r", of_NORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%or", of_OR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%or/r", of_ORR, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
{ "%release",of_RELEASE,1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
|
||||
{ "%set", of_SET, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/m", of_SET_MEM,2, {OA_MEM_PTR, OA_BIT1, OA_NONE} },
|
||||
{ "%set/x", of_SET_X, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/v", of_SET_VEC,3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%set/x0", of_SET_X0, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
|
||||
{ "%shiftl/i0", of_SHIFTL_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
{ "%shiftr/i0", of_SHIFTR_I0, 2, {OA_BIT1,OA_NUMBER, OA_NONE} },
|
||||
{ "%sub", of_SUB, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} },
|
||||
@@ -462,6 +467,40 @@ void code_label_lookup(struct vvp_code_s *code, char *label)
|
||||
resolv_submit(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup memories.
|
||||
*/
|
||||
struct memory_resolv_list_s: public resolv_list_s {
|
||||
struct vvp_code_s *code;
|
||||
char *label;
|
||||
virtual bool resolve(bool mes);
|
||||
};
|
||||
|
||||
bool memory_resolv_list_s::resolve(bool mes)
|
||||
{
|
||||
code->mem = memory_find(label);
|
||||
if (code->mem != 0) {
|
||||
free(label);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mes)
|
||||
fprintf(stderr, "Memory unresolved: %s\n", label);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void compile_mem_lookup(struct vvp_code_s *code, char *label)
|
||||
{
|
||||
struct memory_resolv_list_s *res
|
||||
= new struct memory_resolv_list_s;
|
||||
|
||||
res->code = code;
|
||||
res->label = label;
|
||||
|
||||
resolv_submit(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* When parsing is otherwise complete, this function is called to do
|
||||
* the final stuff. Clean up deferred linking here.
|
||||
@@ -1252,12 +1291,7 @@ void compile_code(char*label, char*mnem, comp_operands_t opa)
|
||||
break;
|
||||
}
|
||||
|
||||
code->mem = memory_find(opa->argv[idx].symb.text);
|
||||
if (code->mem == 0) {
|
||||
yyerror("memory undefined");
|
||||
}
|
||||
|
||||
free(opa->argv[idx].symb.text);
|
||||
compile_mem_lookup(code, opa->argv[idx].symb.text);
|
||||
break;
|
||||
|
||||
case OA_VPI_PTR:
|
||||
@@ -1449,6 +1483,24 @@ void compile_net(char*label, char*name, int msb, int lsb, bool signed_flag,
|
||||
|
||||
/*
|
||||
* $Log: compile.cc,v $
|
||||
* Revision 1.146 2002/11/21 22:43:13 steve
|
||||
* %set/x0 instruction to support bounds checking.
|
||||
*
|
||||
* Revision 1.145 2002/11/08 04:59:58 steve
|
||||
* Add the %assign/v0 instruction.
|
||||
*
|
||||
* Revision 1.144 2002/11/07 02:32:39 steve
|
||||
* Add vector set and load instructions.
|
||||
*
|
||||
* Revision 1.143 2002/09/18 04:29:55 steve
|
||||
* Add support for binary NOR operator.
|
||||
*
|
||||
* Revision 1.142 2002/09/18 02:55:18 steve
|
||||
* Allow forward references of memories.
|
||||
*
|
||||
* Revision 1.141 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.140 2002/08/28 18:38:07 steve
|
||||
* Add the %subi instruction, and use it where possible.
|
||||
*
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output" -a -z "$CYGWIN" -a -z "$MINGW32"; then
|
||||
if test ! -z "$output" -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
|
||||
+18
-2
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_dlfcn.h,v 1.5 2002/08/12 01:35:08 steve Exp $"
|
||||
#ident "$Id: ivl_dlfcn.h,v 1.6 2002/11/05 02:11:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
@@ -45,7 +45,20 @@ inline void ivl_dlclose(ivl_dll_t dll)
|
||||
{ (void)FreeLibrary((HINSTANCE)dll);}
|
||||
|
||||
inline const char *dlerror(void)
|
||||
{ static char s[30]; sprintf(s,"DLError:%ld", GetLastError()); return s;}
|
||||
{
|
||||
static char msg[256];
|
||||
unsigned long err = GetLastError();
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &msg,
|
||||
sizeof(msg) - 1,
|
||||
NULL
|
||||
);
|
||||
return msg;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_DLFCN_H)
|
||||
inline ivl_dll_t ivl_dlopen(const char*name)
|
||||
@@ -77,6 +90,9 @@ inline const char*dlerror(void)
|
||||
|
||||
/*
|
||||
* $Log: ivl_dlfcn.h,v $
|
||||
* Revision 1.6 2002/11/05 02:11:56 steve
|
||||
* Better error message for load failure on Windows.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+5
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.cc,v 1.30 2002/08/12 01:35:08 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.31 2002/09/18 03:34:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -245,7 +245,7 @@ int main(int argc, char*argv[])
|
||||
fprintf(stderr, " %8lu resolv\n", count_functors_resolv);
|
||||
fprintf(stderr, " %8lu variable\n", count_functors_var);
|
||||
fprintf(stderr, " ... %8lu opcodes (%lu bytes)\n",
|
||||
count_opcodes, size_opcodes);
|
||||
count_opcodes, (unsigned long)size_opcodes);
|
||||
fprintf(stderr, " ... %8lu nets\n", count_vpi_nets);
|
||||
fprintf(stderr, " ... %8lu memories\n", count_vpi_memories);
|
||||
fprintf(stderr, " ... %8lu scopes\n", count_vpi_scopes);
|
||||
@@ -280,6 +280,9 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.31 2002/09/18 03:34:07 steve
|
||||
* printf size warning.
|
||||
*
|
||||
* Revision 1.30 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+10
-4
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: memory.cc,v 1.18 2002/08/12 01:35:08 steve Exp $"
|
||||
#ident "$Id: memory.cc,v 1.19 2002/09/17 00:42:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "memory.h"
|
||||
@@ -130,12 +130,15 @@ char *memory_name(vvp_memory_t mem)
|
||||
|
||||
// Compilation
|
||||
|
||||
static symbol_table_t memory_table;
|
||||
static symbol_table_t memory_table = 0;
|
||||
|
||||
vvp_memory_t memory_find(char *label)
|
||||
{
|
||||
symbol_value_t v = sym_get_value(memory_table, label);
|
||||
return (vvp_memory_t)v.ptr;
|
||||
if (memory_table == 0)
|
||||
return 0;
|
||||
|
||||
symbol_value_t v = sym_get_value(memory_table, label);
|
||||
return (vvp_memory_t)v.ptr;
|
||||
}
|
||||
|
||||
vvp_memory_t memory_create(char *label)
|
||||
@@ -507,6 +510,9 @@ void schedule_memory(vvp_memory_t mem, unsigned idx,
|
||||
|
||||
/*
|
||||
* $Log: memory.cc,v $
|
||||
* Revision 1.19 2002/09/17 00:42:22 steve
|
||||
* Proper initialization of the memories table.
|
||||
*
|
||||
* Revision 1.18 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+45
-7
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams ([email protected])
|
||||
*
|
||||
* $Id: opcodes.txt,v 1.40 2002/08/28 18:38:07 steve Exp $
|
||||
* $Id: opcodes.txt,v 1.45 2002/11/21 22:43:13 steve Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ means the following:
|
||||
|
||||
* %assign <var-label>, <delay>, <bit>
|
||||
* %assign/d <var-label>, <delay>, <bit>
|
||||
* %assign/v0 <var-label>, <delay>, <bit>
|
||||
|
||||
This does a non-blocking assignment to a variable. The <label>
|
||||
identifies the affected variable, and the <delay> gives the delay when
|
||||
@@ -60,6 +61,8 @@ The %assign/d instruction is exactly the same as the %assign
|
||||
instruction, except that the <delay> specifies one of the index
|
||||
registers, that contain a calculated delay.
|
||||
|
||||
The %assign/v0 instruction is a vector version of %assign, with the
|
||||
vector width in index register 0.
|
||||
|
||||
* %assign/m <memory-label>, <delay>, <bit>
|
||||
|
||||
@@ -297,6 +300,7 @@ ended, then the %join does not block or yield the thread.
|
||||
|
||||
|
||||
* %load <bit>, <functor-label>
|
||||
* %load/v <bit>, <functor-label>, <wid>
|
||||
|
||||
This instruction loads a value from the given functor output into the
|
||||
specified thread register bit. The functor-label can refer to a .net,
|
||||
@@ -304,6 +308,8 @@ a .var or a .functor, and may be indexed with array syntax to get at a
|
||||
functor within a vector of functors. This instruction loads only a
|
||||
single bit.
|
||||
|
||||
THe %load/v instruction is a vector version, that loads an entire
|
||||
vector, starting at the given <bit> and functor.
|
||||
|
||||
* %load/m <bit>, <memory-label>
|
||||
|
||||
@@ -359,6 +365,30 @@ This instruction is the same as %mul, but the second operand is an
|
||||
immediate value that is padded to the width of the result.
|
||||
|
||||
|
||||
* %nand <dst>, <src>, <wid>
|
||||
|
||||
Perform the bitwise NAND of the two vectors, and store the result in
|
||||
the left vector. Each bit is calculated independent of other bits. NAND
|
||||
means the following:
|
||||
|
||||
0 and ? --> 1
|
||||
? and 0 --> 1
|
||||
1 and 1 --> 0
|
||||
otherwise x
|
||||
|
||||
|
||||
* %nor <dst>, <src>, <wid>
|
||||
|
||||
Perform the bitwise nor of the vectors. Each bit in the <dst> is
|
||||
combined with the corresponding bit in the source, according to the
|
||||
truth table:
|
||||
|
||||
1 nor ? --> 0
|
||||
? nor 1 --> 0
|
||||
0 nor 0 --> 1
|
||||
otherwise x
|
||||
|
||||
|
||||
* %nor/r <dst>, <src>, <wid>
|
||||
|
||||
The %nor/r instruction is a reduction nor. That is, the <src> is a
|
||||
@@ -407,6 +437,7 @@ semantics. Like:
|
||||
|
||||
|
||||
* %set <var-label>, <bit>
|
||||
* %set/v <var-label>, <bit>, <wid>
|
||||
|
||||
This sets a bit of a variable, and is used to implement blocking
|
||||
assignments. The <label> identifies the variable to receive the new
|
||||
@@ -414,6 +445,11 @@ value. Once the set completes, the value is immediately available to
|
||||
be read out of the variable. The <bit> is the address of the thread
|
||||
register that contains the bit value to assign.
|
||||
|
||||
The %set/v instrunction is the same as the %set, but it adds a width
|
||||
for a vector. The bits are written out in order, starting at the
|
||||
addressed variable bit and working up. If the <bit> is one of the
|
||||
constant bits, then the value is repeated for the width. Otherwise,
|
||||
the vector is taken from increasing thread bit addresses.
|
||||
|
||||
* %set/m <memory-label>, <bit>
|
||||
|
||||
@@ -423,15 +459,17 @@ address zero is the LSB of the first memory word. This instruction
|
||||
sets only a single bit.
|
||||
|
||||
|
||||
* %set/x <var-label>, <bit>, <idx>
|
||||
* %set/x0 <var-label>, <bit>, <top>
|
||||
|
||||
This sets the bit of a variable functor, the address calculated by
|
||||
using the index register <idx> (0, 1, 2 or 3) to index the functor
|
||||
address of <var-label>.
|
||||
using the index register 0 to index the functor address of
|
||||
<var-label>.
|
||||
|
||||
If the index value in index register <idx> is <0 (for example if
|
||||
%ix/get converted an unknown value into the register) then the set is
|
||||
not performed.
|
||||
If the index value in index register is <0 (for example if %ix/get
|
||||
converted an unknown value into the register) then the set is not
|
||||
performed. Also, if the index value is > the immediate top value, then
|
||||
the set is not performed. The 0 and <top> values suffice to provide
|
||||
complete bounds checking.
|
||||
|
||||
|
||||
* %shiftl/i0 <bit>, <wid>
|
||||
|
||||
+39
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_callback.cc,v 1.24 2002/09/07 04:54:51 steve Exp $"
|
||||
#ident "$Id: vpi_callback.cc,v 1.25 2002/09/20 02:42:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -298,6 +298,37 @@ static struct __vpiCallback* make_sync(p_cb_data data, bool readonly_flag)
|
||||
return obj;
|
||||
}
|
||||
|
||||
static struct __vpiCallback* make_afterdelay(p_cb_data data)
|
||||
{
|
||||
struct __vpiCallback*obj = new_vpi_callback();
|
||||
obj->cb_data = *data;
|
||||
assert(data->time);
|
||||
obj->cb_time = *(data->time);
|
||||
obj->cb_data.time = &obj->cb_time;
|
||||
|
||||
obj->next = 0;
|
||||
|
||||
struct sync_cb*cb = new sync_cb;
|
||||
cb->sync_flag = false;
|
||||
cb->run = &make_sync_run;
|
||||
cb->handle = obj;
|
||||
obj->cb_sync = cb;
|
||||
|
||||
switch (obj->cb_time.type) {
|
||||
case vpiSimTime: {
|
||||
vvp_time64_t tv = vpip_timestruct_to_time(&obj->cb_time);
|
||||
schedule_generic(cb, 0, tv);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following functions are the used for pre and post simulation
|
||||
* callbacks.
|
||||
@@ -396,6 +427,10 @@ vpiHandle vpi_register_cb(p_cb_data data)
|
||||
obj = make_sync(data, false);
|
||||
break;
|
||||
|
||||
case cbAfterDelay:
|
||||
obj = make_afterdelay(data);
|
||||
break;
|
||||
|
||||
case cbEndOfCompile:
|
||||
case cbStartOfSimulation:
|
||||
case cbEndOfSimulation:
|
||||
@@ -495,6 +530,9 @@ void callback_functor_s::set(vvp_ipoint_t, bool, unsigned val, unsigned)
|
||||
|
||||
/*
|
||||
* $Log: vpi_callback.cc,v $
|
||||
* Revision 1.25 2002/09/20 02:42:11 steve
|
||||
* Add support for cbAfterDelay.
|
||||
*
|
||||
* Revision 1.24 2002/09/07 04:54:51 steve
|
||||
* Implement vpi_remove_cb for cbValueChange.
|
||||
*
|
||||
|
||||
+50
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_const.cc,v 1.19 2002/08/12 01:35:08 steve Exp $"
|
||||
#ident "$Id: vpi_const.cc,v 1.21 2002/11/03 20:33:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -335,6 +335,49 @@ static void binary_value(vpiHandle ref, p_vpi_value vp)
|
||||
break;
|
||||
}
|
||||
|
||||
case vpiVectorVal: {
|
||||
unsigned int obit = 0;
|
||||
unsigned hwid = (rfp->nbits - 1)/32 + 1;
|
||||
char*rbuf = need_result_buf(hwid*sizeof(s_vpi_vecval), RBUF_VAL);
|
||||
|
||||
s_vpi_vecval *op = (p_vpi_vecval)rbuf;
|
||||
vp->value.vector = op;
|
||||
|
||||
op->aval = op->bval = 0;
|
||||
for (unsigned idx = 0 ; idx < rfp->nbits ; idx += 1) {
|
||||
unsigned nibble = idx/4;
|
||||
unsigned shift = 2 * (idx%4);
|
||||
unsigned bit_val = (rfp->bits[nibble] >> shift) & 3;
|
||||
|
||||
switch (bit_val) {
|
||||
case 0:
|
||||
op->aval &= ~(1 << obit);
|
||||
op->bval &= ~(1 << obit);
|
||||
break;
|
||||
case 1:
|
||||
op->aval |= (1 << obit);
|
||||
op->bval &= ~(1 << obit);
|
||||
break;
|
||||
case 2:
|
||||
op->aval |= (1 << obit);
|
||||
op->bval |= (1 << obit);
|
||||
break;
|
||||
case 3:
|
||||
op->aval &= ~(1 << obit);
|
||||
op->bval |= (1 << obit);
|
||||
break;
|
||||
}
|
||||
obit++;
|
||||
if (!(obit % 32)) {
|
||||
op += 1;
|
||||
if ((op - vp->value.vector) < (long)hwid)
|
||||
op->aval = op->bval = 0;
|
||||
obit = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case vpiStringVal:
|
||||
binary_vpiStringVal(rfp, vp);
|
||||
break;
|
||||
@@ -514,6 +557,12 @@ vpiHandle vpip_make_dec_const(int value)
|
||||
|
||||
/*
|
||||
* $Log: vpi_const.cc,v $
|
||||
* Revision 1.21 2002/11/03 20:33:43 steve
|
||||
* Compiler error wrt ptrdiff_t.
|
||||
*
|
||||
* Revision 1.20 2002/11/03 02:07:24 steve
|
||||
* Get VectorVals from constant values.
|
||||
*
|
||||
* Revision 1.19 2002/08/12 01:35:08 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+17
-5
@@ -27,7 +27,7 @@
|
||||
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_memory.cc,v 1.18 2002/08/12 01:35:09 steve Exp $"
|
||||
#ident "$Id: vpi_memory.cc,v 1.20 2002/09/12 15:13:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -109,20 +109,23 @@ static char* memory_get_str(int code, vpiHandle ref)
|
||||
|
||||
struct __vpiMemory*rfp = (struct __vpiMemory*)ref;
|
||||
|
||||
char *bn = vpi_get_str(vpiFullName, &rfp->scope->base);
|
||||
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->scope->base));
|
||||
char *nm = memory_name(rfp->mem);
|
||||
|
||||
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
|
||||
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 2, RBUF_STR);
|
||||
|
||||
switch (code) {
|
||||
case vpiFullName:
|
||||
sprintf(rbuf, "%s.%s", bn, nm);
|
||||
free(bn);
|
||||
return rbuf;
|
||||
case vpiName:
|
||||
strcpy(rbuf, nm);
|
||||
free(bn);
|
||||
return rbuf;
|
||||
}
|
||||
|
||||
free(bn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -344,23 +347,26 @@ static char* memory_word_get_str(int code, vpiHandle ref)
|
||||
|
||||
struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref;
|
||||
|
||||
char *bn = vpi_get_str(vpiFullName, &rfp->mem->scope->base);
|
||||
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->mem->scope->base));
|
||||
char *nm = memory_name(rfp->mem->mem);
|
||||
|
||||
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
|
||||
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 10 + 4, RBUF_STR);
|
||||
|
||||
switch (code) {
|
||||
case vpiFullName:
|
||||
sprintf(rbuf, "%s.%s[%d]", bn, nm, rfp->index.value);
|
||||
free(bn);
|
||||
return rbuf;
|
||||
break;
|
||||
case vpiName: {
|
||||
sprintf(rbuf, "%s[%d]", nm, rfp->index.value);
|
||||
free(bn);
|
||||
return rbuf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(bn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -580,6 +586,12 @@ vpiHandle vpip_make_memory(vvp_memory_t mem)
|
||||
|
||||
/*
|
||||
* $Log: vpi_memory.cc,v $
|
||||
* Revision 1.20 2002/09/12 15:13:07 steve
|
||||
* Account for buffer overrun in memory word names.
|
||||
*
|
||||
* Revision 1.19 2002/09/11 16:06:57 steve
|
||||
* Fix wrecked rbuf in vpi_get_str of signals and memories.
|
||||
*
|
||||
* Revision 1.18 2002/08/12 01:35:09 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+11
-1
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_priv.cc,v 1.24 2002/08/24 05:02:58 steve Exp $"
|
||||
#ident "$Id: vpi_priv.cc,v 1.25 2002/12/11 23:55:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_priv.h"
|
||||
@@ -133,6 +133,12 @@ int vpi_get(int property, vpiHandle ref)
|
||||
|
||||
char* vpi_get_str(int property, vpiHandle ref)
|
||||
{
|
||||
if (ref == 0) {
|
||||
fprintf(stderr, "vpi error: vpi_get_str(%d, ...) called "
|
||||
"with null vpiHandle.\n", property);
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(ref);
|
||||
if (ref->vpi_type->vpi_get_str_ == 0)
|
||||
return 0;
|
||||
@@ -363,6 +369,10 @@ extern "C" void vpi_sim_vcontrol(int operation, va_list ap)
|
||||
|
||||
/*
|
||||
* $Log: vpi_priv.cc,v $
|
||||
* Revision 1.25 2002/12/11 23:55:22 steve
|
||||
* Add vpi_handle_by_name to the VPI interface,
|
||||
* and bump the vpithunk magic number.
|
||||
*
|
||||
* Revision 1.24 2002/08/24 05:02:58 steve
|
||||
* Fix = vs == error.
|
||||
*
|
||||
|
||||
+22
-20
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_scope.cc,v 1.20 2002/08/12 01:35:09 steve Exp $"
|
||||
#ident "$Id: vpi_scope.cc,v 1.21 2002/11/15 22:14:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compile.h"
|
||||
@@ -100,20 +100,29 @@ static vpiHandle scope_get_handle(int code, vpiHandle obj)
|
||||
/* compares vpiType's considering object classes */
|
||||
static int compare_types(int code, int type)
|
||||
{
|
||||
if ( code == type
|
||||
|| (code == vpiInternalScope &&
|
||||
/* NOTE: The Verilog VPI does not for any object support
|
||||
vpiScope as an iterator parameter, so it is used here as a
|
||||
means to scan everything in the *current* scope. */
|
||||
if (code == vpiScope)
|
||||
return 1;
|
||||
|
||||
if (code == type)
|
||||
return 1;
|
||||
|
||||
if ( code == vpiInternalScope &&
|
||||
(type == vpiModule ||
|
||||
type == vpiFunction ||
|
||||
type == vpiTask ||
|
||||
type == vpiNamedBegin ||
|
||||
type == vpiNamedFork))
|
||||
|| (code == vpiVariables &&
|
||||
type == vpiNamedFork) )
|
||||
return 1;
|
||||
|
||||
if ( code == vpiVariables &&
|
||||
(type == vpiIntegerVar ||
|
||||
type == vpiTimeVar))
|
||||
)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static vpiHandle module_iter_subset(int code, struct __vpiScope*ref)
|
||||
@@ -153,17 +162,7 @@ static vpiHandle module_iter(int code, vpiHandle obj)
|
||||
|| (obj->vpi_type->type_code == vpiNamedBegin)
|
||||
|| (obj->vpi_type->type_code == vpiNamedFork));
|
||||
|
||||
switch (code) {
|
||||
case vpiInternalScope:
|
||||
case vpiMemory:
|
||||
case vpiModule:
|
||||
case vpiNamedEvent:
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
return module_iter_subset(code, ref);
|
||||
|
||||
}
|
||||
return 0;
|
||||
return module_iter_subset(code, ref);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -407,6 +406,9 @@ void vpip_attach_to_current_scope(vpiHandle obj)
|
||||
|
||||
/*
|
||||
* $Log: vpi_scope.cc,v $
|
||||
* Revision 1.21 2002/11/15 22:14:12 steve
|
||||
* Add vpiScope iterate on vpiScope objects.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:35:09 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+62
-7
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vpi_signal.cc,v 1.47 2002/09/06 04:56:29 steve Exp $"
|
||||
#ident "$Id: vpi_signal.cc,v 1.50 2002/11/25 23:33:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -62,10 +62,11 @@ char *need_result_buf(unsigned cnt, vpi_rbuf_t type)
|
||||
|
||||
if (result_buf_size[type] == 0) {
|
||||
result_buf[type] = (char*)malloc(cnt);
|
||||
result_buf_size[type] = cnt;
|
||||
} else if (result_buf_size[type] < cnt) {
|
||||
result_buf[type] = (char*)realloc(result_buf[type], cnt);
|
||||
result_buf_size[type] = cnt;
|
||||
}
|
||||
result_buf_size[type] = cnt;
|
||||
|
||||
return result_buf[type];
|
||||
}
|
||||
@@ -109,22 +110,25 @@ static char* signal_get_str(int code, vpiHandle ref)
|
||||
|
||||
struct __vpiSignal*rfp = (struct __vpiSignal*)ref;
|
||||
|
||||
char *bn = vpi_get_str(vpiFullName, &rfp->scope->base);
|
||||
char *bn = strdup(vpi_get_str(vpiFullName, &rfp->scope->base));
|
||||
char *nm = (char*)rfp->name;
|
||||
|
||||
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 1, RBUF_STR);
|
||||
char *rbuf = need_result_buf(strlen(bn) + strlen(nm) + 2, RBUF_STR);
|
||||
|
||||
switch (code) {
|
||||
|
||||
case vpiFullName:
|
||||
sprintf(rbuf, "%s.%s", bn, nm);
|
||||
free(bn);
|
||||
return rbuf;
|
||||
|
||||
case vpiName:
|
||||
strcpy(rbuf, nm);
|
||||
free(bn);
|
||||
return rbuf;
|
||||
}
|
||||
|
||||
free(bn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -382,6 +386,7 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||
s_vpi_strengthval*op = (s_vpi_strengthval*)
|
||||
need_result_buf(wid * sizeof(s_vpi_strengthval),
|
||||
RBUF_VAL);
|
||||
vp->value.strength = op;
|
||||
|
||||
/* Convert the internal strength values of each
|
||||
functor in the vector to a PLI2.0 version. */
|
||||
@@ -414,6 +419,8 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||
op[idx].s0 = vpiHiZ;
|
||||
op[idx].s1 = vpiHiZ;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,9 +428,10 @@ static void signal_get_value(vpiHandle ref, s_vpi_value*vp)
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp internal error: signal_get_value: "
|
||||
"value type %u not implemented.\n", vp->format);
|
||||
|
||||
fprintf(stderr, "vvp internal error: get_value: "
|
||||
"value type %u not implemented."
|
||||
" Signal is %s in scope %s\n",
|
||||
vp->format, rfp->name, rfp->scope->name);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
@@ -443,6 +451,36 @@ static void functor_poke(struct __vpiSignal*rfp, unsigned idx,
|
||||
fu->put_ostr(val, str, true);
|
||||
}
|
||||
|
||||
static void signal_put_stringval(struct __vpiSignal*rfp, unsigned wid,
|
||||
const char*str)
|
||||
{
|
||||
unsigned idx;
|
||||
const char*cp;
|
||||
|
||||
cp = str + strlen(str);
|
||||
idx = 0;
|
||||
|
||||
while ((idx < wid) && (cp > str)) {
|
||||
unsigned byte = *--cp;
|
||||
int bit;
|
||||
|
||||
for (bit = 0 ; bit < 8 ; bit += 1) {
|
||||
if (byte & 1)
|
||||
functor_poke(rfp, idx, 1, St1);
|
||||
else
|
||||
functor_poke(rfp, idx, 0, St0);
|
||||
|
||||
byte >>= 1;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (idx < wid) {
|
||||
functor_poke(rfp, 0, 0, St0);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
|
||||
p_vpi_time when, int flags)
|
||||
{
|
||||
@@ -634,7 +672,15 @@ static vpiHandle signal_put_value(vpiHandle ref, s_vpi_value*vp,
|
||||
break;
|
||||
}
|
||||
|
||||
case vpiStringVal:
|
||||
signal_put_stringval(rfp, wid, vp->value.str);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "vvp internal error: put_value: "
|
||||
"value type %u not implemented."
|
||||
" Signal is %s in scope %s\n",
|
||||
vp->format, rfp->name, rfp->scope->name);
|
||||
assert(0);
|
||||
|
||||
}
|
||||
@@ -715,6 +761,15 @@ vpiHandle vpip_make_net(const char*name, int msb, int lsb,
|
||||
|
||||
/*
|
||||
* $Log: vpi_signal.cc,v $
|
||||
* Revision 1.50 2002/11/25 23:33:45 steve
|
||||
* Support put of vpiStringVal to signals.
|
||||
*
|
||||
* Revision 1.49 2002/09/11 16:06:57 steve
|
||||
* Fix wrecked rbuf in vpi_get_str of signals and memories.
|
||||
*
|
||||
* Revision 1.48 2002/09/10 02:27:11 steve
|
||||
* Actually set strength pointer when getting strength val.
|
||||
*
|
||||
* Revision 1.47 2002/09/06 04:56:29 steve
|
||||
* Add support for %v is the display system task.
|
||||
* Change the encoding of H and L outputs from
|
||||
|
||||
+256
-46
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vthread.cc,v 1.84 2002/08/28 18:38:07 steve Exp $"
|
||||
#ident "$Id: vthread.cc,v 1.95 2002/11/22 00:01:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vthread.h"
|
||||
@@ -72,7 +72,7 @@
|
||||
*
|
||||
* A --> C(zombie) --> X --> B
|
||||
*
|
||||
* If A then executes 2 %joins, it will read C and X (when it ends)
|
||||
* If A then executes 2 %joins, it will reap C and X (when it ends)
|
||||
* leaving B in purgatory. What's worse, A will block on the schedules
|
||||
* of X and C instead of C and B, possibly creating incorrect timing.
|
||||
*
|
||||
@@ -103,6 +103,7 @@ struct vthread_s {
|
||||
unsigned i_have_ended :1;
|
||||
unsigned waiting_for_event :1;
|
||||
unsigned is_scheduled :1;
|
||||
unsigned fork_count :8;
|
||||
/* This points to the sole child of the thread. */
|
||||
struct vthread_s*child;
|
||||
/* This points to my parent, if I have one. */
|
||||
@@ -213,7 +214,7 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
|
||||
thr->nbits = 4 * (CPU_WORD_BITS/2);
|
||||
thr->child = 0;
|
||||
thr->parent = 0;
|
||||
thr->wait_next = 0;
|
||||
thr->wait_next = 0;
|
||||
|
||||
/* If the target scope never held a thread, then create a
|
||||
header cell for it. This is a stub to make circular lists
|
||||
@@ -241,6 +242,7 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
|
||||
thr->i_have_ended = 0;
|
||||
thr->waiting_for_event = 0;
|
||||
thr->is_scheduled = 0;
|
||||
thr->fork_count = 0;
|
||||
|
||||
thr_put_bit(thr, 0, 0);
|
||||
thr_put_bit(thr, 1, 1);
|
||||
@@ -256,15 +258,17 @@ vthread_t vthread_new(unsigned long pc, struct __vpiScope*scope)
|
||||
*/
|
||||
static void vthread_reap(vthread_t thr)
|
||||
{
|
||||
assert(thr->wait_next == 0);
|
||||
|
||||
free(thr->bits);
|
||||
thr->bits = 0;
|
||||
|
||||
if (thr->child)
|
||||
if (thr->child) {
|
||||
assert(thr->child->parent == thr);
|
||||
thr->child->parent = thr->parent;
|
||||
if (thr->parent)
|
||||
}
|
||||
if (thr->parent) {
|
||||
assert(thr->parent->child == thr);
|
||||
thr->parent->child = thr->child;
|
||||
}
|
||||
|
||||
thr->child = 0;
|
||||
thr->parent = 0;
|
||||
@@ -277,8 +281,11 @@ static void vthread_reap(vthread_t thr)
|
||||
/* If this thread is not scheduled, then is it safe to delete
|
||||
it now. Otherwise, let the schedule event (which will
|
||||
execute the thread at of_ZOMBIE) delete the object. */
|
||||
if (thr->is_scheduled == 0)
|
||||
if ((thr->is_scheduled == 0) && (thr->waiting_for_event == 0)) {
|
||||
assert(thr->fork_count == 0);
|
||||
assert(thr->wait_next == 0);
|
||||
delete thr;
|
||||
}
|
||||
}
|
||||
|
||||
void vthread_mark_scheduled(vthread_t thr)
|
||||
@@ -480,6 +487,32 @@ bool of_ASSIGN_D(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is %assign/v0 <label>, <delay>, <bit>
|
||||
* Index register 0 contains a vector width.
|
||||
*/
|
||||
bool of_ASSIGN_V0(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned wid = thr->index[0];
|
||||
assert(wid > 0);
|
||||
assert(wid < 0x10000);
|
||||
|
||||
unsigned delay = cp->bit_idx[0];
|
||||
unsigned bit = cp->bit_idx[1];
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
|
||||
|
||||
unsigned char bit_val = thr_get_bit(thr, bit);
|
||||
schedule_assign(iptr, bit_val, delay);
|
||||
|
||||
if (bit >= 4)
|
||||
bit += 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_ASSIGN_X0(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[1]);
|
||||
@@ -752,14 +785,63 @@ bool of_DELAYX(vthread_t thr, vvp_code_t cp)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool do_disable(vthread_t thr, vthread_t match)
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
/* Pull the target thread out of its scope. */
|
||||
thr->scope_next->scope_prev = thr->scope_prev;
|
||||
thr->scope_prev->scope_next = thr->scope_next;
|
||||
|
||||
/* Turn the thread off by setting is program counter to
|
||||
zero and setting an OFF bit. */
|
||||
thr->pc = 0;
|
||||
thr->i_have_ended = 1;
|
||||
|
||||
/* Turn off all the children of the thread. Simulate a %join
|
||||
for as many times as needed to clear the results of all the
|
||||
%forks that this thread has done. */
|
||||
while (thr->fork_count > 0) {
|
||||
|
||||
vthread_t tmp = thr->child;
|
||||
assert(tmp);
|
||||
assert(tmp->parent == thr);
|
||||
tmp->schedule_parent_on_end = 0;
|
||||
if (do_disable(tmp, match))
|
||||
flag = true;
|
||||
|
||||
thr->fork_count -= 1;
|
||||
|
||||
vthread_reap(tmp);
|
||||
}
|
||||
|
||||
|
||||
if (thr->schedule_parent_on_end) {
|
||||
/* If a parent is waiting in a %join, wake it up. */
|
||||
assert(thr->parent);
|
||||
assert(thr->parent->fork_count > 0);
|
||||
|
||||
thr->parent->fork_count -= 1;
|
||||
schedule_vthread(thr->parent, 0, true);
|
||||
vthread_reap(thr);
|
||||
|
||||
} else if (thr->parent) {
|
||||
/* If the parent is yet to %join me, let its %join
|
||||
do the reaping. */
|
||||
//assert(tmp->is_scheduled == 0);
|
||||
|
||||
} else {
|
||||
/* No parent at all. Goodby. */
|
||||
vthread_reap(thr);
|
||||
}
|
||||
|
||||
return flag || (thr == match);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the %disable instruction by scanning the target scope for
|
||||
* all the target threads. Kill the target threads and wake up a
|
||||
* parent that is attempting a %join.
|
||||
*
|
||||
* XXXX BUG BUG!
|
||||
* The scheduler probably still has a pointer to me, and this reaping
|
||||
* will destroy this object. The result: dangling pointer.
|
||||
*/
|
||||
bool of_DISABLE(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
@@ -774,38 +856,14 @@ bool of_DISABLE(vthread_t thr, vvp_code_t cp)
|
||||
while (head->scope_next != head) {
|
||||
vthread_t tmp = head->scope_next;
|
||||
|
||||
/* Pull the target thread out of the scope. */
|
||||
tmp->scope_next->scope_prev = tmp->scope_prev;
|
||||
tmp->scope_prev->scope_next = tmp->scope_next;
|
||||
|
||||
/* XXXX I don't support disabling threads with children. */
|
||||
assert(tmp->child == 0);
|
||||
/* XXXX Don't know how to disable waiting threads. */
|
||||
assert(tmp->waiting_for_event == 0);
|
||||
|
||||
/* If I am disabling myself, that remember that fact so
|
||||
that I can finish this statement differently. */
|
||||
if (tmp == thr)
|
||||
disabled_myself_flag = true;
|
||||
|
||||
tmp->pc = 0;
|
||||
tmp->i_have_ended = 1;
|
||||
|
||||
if (tmp->schedule_parent_on_end) {
|
||||
/* If a parent is waiting in a %join, wake it up. */
|
||||
assert(tmp->parent);
|
||||
schedule_vthread(tmp->parent, 0, true);
|
||||
vthread_reap(tmp);
|
||||
|
||||
} else if (tmp->parent) {
|
||||
/* If the parent is yet to %join me, let its %join
|
||||
do the reaping. */
|
||||
//assert(tmp->is_scheduled == 0);
|
||||
|
||||
} else {
|
||||
/* No parent at all. Goodby. */
|
||||
vthread_reap(tmp);
|
||||
}
|
||||
if (do_disable(tmp, thr))
|
||||
disabled_myself_flag = true;
|
||||
}
|
||||
|
||||
return ! disabled_myself_flag;
|
||||
@@ -1146,7 +1204,7 @@ bool of_DIV_S(vthread_t thr, vvp_code_t cp)
|
||||
bool of_END(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
assert(! thr->waiting_for_event);
|
||||
|
||||
assert( thr->fork_count == 0 );
|
||||
thr->i_have_ended = 1;
|
||||
thr->pc = 0;
|
||||
|
||||
@@ -1155,6 +1213,9 @@ bool of_END(vthread_t thr, vvp_code_t)
|
||||
%join for the parent. */
|
||||
if (thr->schedule_parent_on_end) {
|
||||
assert(thr->parent);
|
||||
assert(thr->parent->fork_count > 0);
|
||||
|
||||
thr->parent->fork_count -= 1;
|
||||
schedule_vthread(thr->parent, 0, true);
|
||||
vthread_reap(thr);
|
||||
return false;
|
||||
@@ -1196,6 +1257,9 @@ bool of_FORK(vthread_t thr, vvp_code_t cp)
|
||||
assert(child->child->parent == thr);
|
||||
child->child->parent = child;
|
||||
}
|
||||
|
||||
thr->fork_count += 1;
|
||||
|
||||
schedule_vthread(child, 0, true);
|
||||
return true;
|
||||
}
|
||||
@@ -1327,8 +1391,12 @@ bool of_JOIN(vthread_t thr, vvp_code_t cp)
|
||||
assert(thr->child);
|
||||
assert(thr->child->parent == thr);
|
||||
|
||||
assert(thr->fork_count > 0);
|
||||
|
||||
|
||||
/* If the child has already ended, reap it now. */
|
||||
if (thr->child->i_have_ended) {
|
||||
thr->fork_count -= 1;
|
||||
vthread_reap(thr->child);
|
||||
return true;
|
||||
}
|
||||
@@ -1372,6 +1440,21 @@ bool of_LOAD_NX(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_LOAD_VEC(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[0] >= 4);
|
||||
assert(cp->bit_idx[1] > 0);
|
||||
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
|
||||
|
||||
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
|
||||
thr_put_bit(thr, bit, functor_get(iptr));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_LOAD_X(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[0] >= 4);
|
||||
@@ -1590,9 +1673,15 @@ bool of_MOV(vthread_t thr, vvp_code_t cp)
|
||||
unsigned addr2 = (test_addr) / (CPU_WORD_BITS/2);
|
||||
if (addr1 == addr2) {
|
||||
unsigned sh1 = cp->bit_idx[0] % (CPU_WORD_BITS/2);
|
||||
unsigned sh2 = (test_addr+1) % (CPU_WORD_BITS/2);
|
||||
unsigned sh2 = (test_addr % (CPU_WORD_BITS/2)) + 1;
|
||||
|
||||
unsigned long mask;
|
||||
|
||||
if ( (sh2-sh1) == CPU_WORD_BITS/2)
|
||||
mask = 0UL;
|
||||
else
|
||||
mask = ULONG_MAX << ((sh2 - sh1) * 2UL);
|
||||
|
||||
unsigned long mask = ULONG_MAX << ((sh2 - sh1) * 2UL);
|
||||
mask = (~mask) << sh1*2UL;
|
||||
|
||||
cp->number = ~mask;
|
||||
@@ -1815,6 +1904,37 @@ bool of_MULI(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_NAND(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[0] >= 4);
|
||||
|
||||
unsigned idx1 = cp->bit_idx[0];
|
||||
unsigned idx2 = cp->bit_idx[1];
|
||||
|
||||
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
|
||||
|
||||
unsigned lb = thr_get_bit(thr, idx1);
|
||||
unsigned rb = thr_get_bit(thr, idx2);
|
||||
|
||||
if ((lb == 0) || (rb == 0)) {
|
||||
thr_put_bit(thr, idx1, 1);
|
||||
|
||||
} else if ((lb == 1) && (rb == 1)) {
|
||||
thr_put_bit(thr, idx1, 0);
|
||||
|
||||
} else {
|
||||
thr_put_bit(thr, idx1, 2);
|
||||
}
|
||||
|
||||
idx1 += 1;
|
||||
if (idx2 >= 4)
|
||||
idx2 += 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool of_NOOP(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
return true;
|
||||
@@ -1992,6 +2112,36 @@ bool of_OR(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_NOR(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[0] >= 4);
|
||||
|
||||
unsigned idx1 = cp->bit_idx[0];
|
||||
unsigned idx2 = cp->bit_idx[1];
|
||||
|
||||
for (unsigned idx = 0 ; idx < cp->number ; idx += 1) {
|
||||
|
||||
unsigned lb = thr_get_bit(thr, idx1);
|
||||
unsigned rb = thr_get_bit(thr, idx2);
|
||||
|
||||
if ((lb == 1) || (rb == 1)) {
|
||||
thr_put_bit(thr, idx1, 0);
|
||||
|
||||
} else if ((lb == 0) && (rb == 0)) {
|
||||
thr_put_bit(thr, idx1, 1);
|
||||
|
||||
} else {
|
||||
thr_put_bit(thr, idx1, 2);
|
||||
}
|
||||
|
||||
idx1 += 1;
|
||||
if (idx2 >= 4)
|
||||
idx2 += 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const unsigned char strong_values[4] = {St0, St1, StX, HiZ};
|
||||
|
||||
bool of_SET(vthread_t thr, vvp_code_t cp)
|
||||
@@ -2010,6 +2160,29 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_SET_VEC(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
assert(cp->bit_idx[1] > 0);
|
||||
|
||||
unsigned bit = cp->bit_idx[0];
|
||||
if (bit >= 4) {
|
||||
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1, bit += 1) {
|
||||
unsigned char bit_val = thr_get_bit(thr, bit);
|
||||
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
|
||||
functor_set(iptr, bit_val, strong_values[bit_val], true);
|
||||
}
|
||||
|
||||
} else {
|
||||
unsigned char bit_val = strong_values[bit];
|
||||
|
||||
for (unsigned idx = 0; idx < cp->bit_idx[1]; idx += 1) {
|
||||
vvp_ipoint_t iptr = ipoint_index(cp->iptr, idx);
|
||||
functor_set(iptr, bit, bit_val, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement the %set/x instruction:
|
||||
*
|
||||
@@ -2018,17 +2191,19 @@ bool of_SET_MEM(vthread_t thr, vvp_code_t cp)
|
||||
* The single bit goes into the indexed functor. Abort the instruction
|
||||
* if the index is <0.
|
||||
*/
|
||||
bool of_SET_X(vthread_t thr, vvp_code_t cp)
|
||||
bool of_SET_X0(vthread_t thr, vvp_code_t cp)
|
||||
{
|
||||
unsigned char bit_val = thr_get_bit(thr, cp->bit_idx[0]);
|
||||
long idx = thr->index[cp->bit_idx[1]&3];
|
||||
long idx = thr->index[0];
|
||||
|
||||
/* If idx < 0, then the index value is probably generated from
|
||||
an undefined value. At any rate, this is defined to have no
|
||||
effect so quit now. */
|
||||
if (idx < 0) {
|
||||
if (idx < 0)
|
||||
return true;
|
||||
|
||||
if (idx > cp->bit_idx[1])
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Form the functor pointer from the base pointer and the
|
||||
index from the index register. */
|
||||
@@ -2046,6 +2221,8 @@ bool of_SHIFTL_I0(vthread_t thr, vvp_code_t cp)
|
||||
unsigned wid = cp->number;
|
||||
unsigned long shift = thr->index[0];
|
||||
|
||||
assert(base >= 4);
|
||||
|
||||
if (shift >= wid) {
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
thr_put_bit(thr, base+idx, 0);
|
||||
@@ -2319,6 +2496,39 @@ bool of_CALL_UFUNC(vthread_t thr, vvp_code_t cp)
|
||||
|
||||
/*
|
||||
* $Log: vthread.cc,v $
|
||||
* Revision 1.95 2002/11/22 00:01:50 steve
|
||||
* Careful of left operands to shift that are constant.
|
||||
*
|
||||
* Revision 1.94 2002/11/21 22:43:14 steve
|
||||
* %set/x0 instruction to support bounds checking.
|
||||
*
|
||||
* Revision 1.93 2002/11/08 04:59:58 steve
|
||||
* Add the %assign/v0 instruction.
|
||||
*
|
||||
* Revision 1.92 2002/11/07 03:11:43 steve
|
||||
* functor_set takes bit and strength, not 2 strengths.
|
||||
*
|
||||
* Revision 1.91 2002/11/07 02:32:39 steve
|
||||
* Add vector set and load instructions.
|
||||
*
|
||||
* Revision 1.90 2002/11/05 03:46:44 steve
|
||||
* Fix mask calculate when MOV_b is right on the word boundary.
|
||||
*
|
||||
* Revision 1.89 2002/09/21 23:47:30 steve
|
||||
* Remove some now useless asserts.
|
||||
*
|
||||
* Revision 1.88 2002/09/21 04:55:00 steve
|
||||
* Fix disable in arbitrary fork/join situations.
|
||||
*
|
||||
* Revision 1.87 2002/09/20 03:59:34 steve
|
||||
* disable threads with children.
|
||||
*
|
||||
* Revision 1.86 2002/09/18 04:29:55 steve
|
||||
* Add support for binary NOR operator.
|
||||
*
|
||||
* Revision 1.85 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.84 2002/08/28 18:38:07 steve
|
||||
* Add the %subi instruction, and use it where possible.
|
||||
*
|
||||
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: vvp_vpi.cc,v 1.5 2002/08/12 01:35:09 steve Exp $"
|
||||
#ident "$Id: vvp_vpi.cc,v 1.6 2002/12/11 23:55:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
@@ -27,6 +27,7 @@ void vvp_vpi_init()
|
||||
vvpt.vpi_iterate = vpi_iterate;
|
||||
vvpt.vpi_scan = vpi_scan;
|
||||
vvpt.vpi_handle_by_index = vpi_handle_by_index;
|
||||
vvpt.vpi_handle_by_name = vpi_handle_by_name;
|
||||
vvpt.vpi_get_time = vpi_get_time;
|
||||
vvpt.vpi_get = vpi_get;
|
||||
vvpt.vpi_get_str = vpi_get_str;
|
||||
@@ -39,6 +40,10 @@ void vvp_vpi_init()
|
||||
|
||||
/*
|
||||
* $Log: vvp_vpi.cc,v $
|
||||
* Revision 1.6 2002/12/11 23:55:22 steve
|
||||
* Add vpi_handle_by_name to the VPI interface,
|
||||
* and bump the vpithunk magic number.
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:35:09 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user