Compare commits
240 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
27be6e88bc | |
|
|
918b0a410f | |
|
|
ec85377d13 | |
|
|
a22124a198 | |
|
|
e8bc5aefb4 | |
|
|
ca5d265350 | |
|
|
113312a0c1 | |
|
|
12d5aa08e2 | |
|
|
15702f1b87 | |
|
|
9b5ef0bbb9 | |
|
|
b8d9f19eb0 | |
|
|
8d9f7e2e26 | |
|
|
65326fd6a9 | |
|
|
bb92974839 | |
|
|
7dc473db8d | |
|
|
abc2aa17d2 | |
|
|
c8bffe728a | |
|
|
d134f6f074 | |
|
|
8deb2c0b60 | |
|
|
451783056d | |
|
|
322bbed7c7 | |
|
|
e8bb9b1f76 | |
|
|
f112b77d3b | |
|
|
ddf68ca14c | |
|
|
d8fdcd5a38 | |
|
|
408e25f6bc | |
|
|
3dd2c74ebe | |
|
|
d260052940 | |
|
|
146f64992c | |
|
|
74e2343e52 | |
|
|
b4b9667def | |
|
|
5e401055e8 | |
|
|
e89bce48ed | |
|
|
cf01d1a75f | |
|
|
6df10a082b | |
|
|
22ad8c42bc | |
|
|
f418bea775 | |
|
|
568e601212 | |
|
|
b7e7d3cb04 | |
|
|
8a1543aaaf | |
|
|
c6ba9269bc | |
|
|
3af373667a | |
|
|
d49e44594b | |
|
|
4d3f592b5f | |
|
|
d1e82d3d12 | |
|
|
d70ccb6895 | |
|
|
e34647f79c | |
|
|
24b097ce89 | |
|
|
83ee7e7988 | |
|
|
f33d477166 | |
|
|
3f16d3402a | |
|
|
304a63d8e3 | |
|
|
23d56d8198 | |
|
|
a8f68fe416 | |
|
|
5dc4202929 | |
|
|
281b4edbab | |
|
|
3eb86a2376 | |
|
|
1fb93c0565 | |
|
|
bdb900b25f | |
|
|
28da79dcc3 | |
|
|
bbd61823b9 | |
|
|
0f716d6dca | |
|
|
a44236f8cb | |
|
|
4be2ccb3fa | |
|
|
9f4dc5411f | |
|
|
545d20eba5 | |
|
|
b2159d1e64 | |
|
|
4c8df2a370 | |
|
|
eed0885dd0 | |
|
|
0fc10d0262 | |
|
|
1775c78aa9 | |
|
|
85652e24e0 | |
|
|
eb4fc8fb7b | |
|
|
043b7ae684 | |
|
|
2946f30ffc | |
|
|
5530aea6a3 | |
|
|
40e09cd719 | |
|
|
c67f3b0081 | |
|
|
95254aa27e | |
|
|
468e3bb702 | |
|
|
be8c8a8eb7 | |
|
|
5cae6b64af | |
|
|
f600e774d5 | |
|
|
d16dd26660 | |
|
|
8c04d669f9 | |
|
|
5d2dcfd7f7 | |
|
|
0b3f1e4119 | |
|
|
8bd9fc7128 | |
|
|
1b551aaf94 | |
|
|
a3dda80fb2 | |
|
|
9e9d5ccfdd | |
|
|
07daee9438 | |
|
|
82808d8b5d | |
|
|
c045f51a7f | |
|
|
d72eadb885 | |
|
|
e99f0a8f51 | |
|
|
ed2cb380cd | |
|
|
dc8e941260 | |
|
|
d486b81f23 | |
|
|
59c2f16a5f | |
|
|
1470a061fd | |
|
|
c1333a21ef | |
|
|
04ef0b7d80 | |
|
|
2fc9413d1f | |
|
|
c94bdbcdb0 | |
|
|
1820cd0244 | |
|
|
aa3cbbdf99 | |
|
|
0a9b6f34ae | |
|
|
5c2c5453ac | |
|
|
0c6bb476ea | |
|
|
568924dcb5 | |
|
|
33b3f7bdda | |
|
|
3a04e0a051 | |
|
|
66ae377801 | |
|
|
898db57405 | |
|
|
0fe45b5046 | |
|
|
20cfe99457 | |
|
|
4ec8b38a5c | |
|
|
79add47002 | |
|
|
c429f4c9a7 | |
|
|
7f6a0b652a | |
|
|
9f3f9154eb | |
|
|
498fd06412 | |
|
|
6d3b780791 | |
|
|
a0ec981c50 | |
|
|
930cd598a0 | |
|
|
77adab0f33 | |
|
|
0e3768f829 | |
|
|
22884f2e64 | |
|
|
62da6aca28 | |
|
|
525ebddb0c | |
|
|
521750c007 | |
|
|
85d2833a62 | |
|
|
e2cc258283 | |
|
|
f09cf85c76 | |
|
|
c32de1dba0 | |
|
|
628b866c36 | |
|
|
08dbe801c1 | |
|
|
101810df21 | |
|
|
3877b636df | |
|
|
9d028a63f2 | |
|
|
35e5cea9df | |
|
|
ec510071f1 | |
|
|
7413c533f6 | |
|
|
dde69cebb6 | |
|
|
f942657ad5 | |
|
|
fad1620828 | |
|
|
a9931e7a58 | |
|
|
6cd4adb135 | |
|
|
9643b86ab3 | |
|
|
452eaeaea8 | |
|
|
3a6e2df958 | |
|
|
e73b7e2656 | |
|
|
469ec11190 | |
|
|
e0bbfa512c | |
|
|
94c9af2a5d | |
|
|
9f2e7df0ff | |
|
|
f02b2c9d7a | |
|
|
058dac4290 | |
|
|
ce4e21a962 | |
|
|
065d6bc1e3 | |
|
|
312d09dc1d | |
|
|
faf7f30283 | |
|
|
5d41e98c1f | |
|
|
5e8330a4ff | |
|
|
ef8964c65a | |
|
|
aa42ec381c | |
|
|
c9d4aab9cb | |
|
|
b8bc531f05 | |
|
|
79cb8c883a | |
|
|
27e633410c | |
|
|
7527c466ed | |
|
|
3ea1214160 | |
|
|
782542922d | |
|
|
1f8102c4dc | |
|
|
c4b34e8720 | |
|
|
e494be7cbf | |
|
|
eb0a78e9ce | |
|
|
e80138ec8c | |
|
|
943316c6f6 | |
|
|
52b8ed9077 | |
|
|
fc227aa3e1 | |
|
|
41993815e9 | |
|
|
c5063f5d2f | |
|
|
f28aa11936 | |
|
|
3131fa68b7 | |
|
|
def3809b3f | |
|
|
3429c24a6a | |
|
|
f47627d752 | |
|
|
9468f3d06f | |
|
|
b997de63a5 | |
|
|
f50f06ab4e | |
|
|
d5d03812cd | |
|
|
b6d5a0675e | |
|
|
e63e830d62 | |
|
|
74ca34bd82 | |
|
|
c9d480028e | |
|
|
cc89ba66af | |
|
|
05e6d51004 | |
|
|
ae583204e3 | |
|
|
018476f7cd | |
|
|
bfabeab6b9 | |
|
|
4a3f1a3641 | |
|
|
d97560caa7 | |
|
|
393102d43a | |
|
|
8e97a0e4d4 | |
|
|
4ea789a2d7 | |
|
|
354f7ad920 | |
|
|
f4a6206790 | |
|
|
fd29ba3398 | |
|
|
44fbf60885 | |
|
|
a0d69113c3 | |
|
|
86942ac592 | |
|
|
075f9cbc4b | |
|
|
9dab368880 | |
|
|
5f6027fb66 | |
|
|
53156793fe | |
|
|
4644c220e8 | |
|
|
c30cd9afea | |
|
|
a8f45a18f0 | |
|
|
6828e3e2ea | |
|
|
75eb372adf | |
|
|
3b753fe52b | |
|
|
8c73fa7840 | |
|
|
d310e656c7 | |
|
|
0510367b70 | |
|
|
3e11207a56 | |
|
|
665f31271f | |
|
|
9a2b56675c | |
|
|
c9f38f5ffa | |
|
|
5ea4152162 | |
|
|
327c897d7e | |
|
|
29ebe486b7 | |
|
|
4af0acb3be | |
|
|
8435774c26 | |
|
|
6172748c65 | |
|
|
ca0ae9040a | |
|
|
d9cdbde3f6 | |
|
|
307a97116f | |
|
|
83d2c6dfd1 |
11
LineInfo.cc
11
LineInfo.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $"
|
||||
#ident "$Id: LineInfo.cc,v 1.4.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -34,12 +34,12 @@ LineInfo::~LineInfo()
|
|||
{
|
||||
}
|
||||
|
||||
string LineInfo::get_line() const
|
||||
std::string LineInfo::get_line() const
|
||||
{
|
||||
ostringstream buf;
|
||||
std::ostringstream buf;
|
||||
buf << (file_? file_ : "") << ":" << lineno_;
|
||||
|
||||
string res = buf.str();
|
||||
std::string res = buf.str();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +61,9 @@ void LineInfo::set_lineno(unsigned n)
|
|||
|
||||
/*
|
||||
* $Log: LineInfo.cc,v $
|
||||
* Revision 1.4.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.4 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
|
|
|
|||
12
LineInfo.h
12
LineInfo.h
|
|
@ -19,11 +19,13 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.h,v 1.7 2003/01/17 05:49:03 steve Exp $"
|
||||
#ident "$Id: LineInfo.h,v 1.7.2.2 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* This class holds line information for an internal object.
|
||||
*
|
||||
|
|
@ -38,7 +40,7 @@ class LineInfo {
|
|||
LineInfo();
|
||||
~LineInfo();
|
||||
|
||||
string get_line() const;
|
||||
std::string get_line() const;
|
||||
|
||||
void set_line(const LineInfo&that);
|
||||
|
||||
|
|
@ -52,6 +54,12 @@ class LineInfo {
|
|||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.7.2.2 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.7.2.1 2005/06/14 15:33:54 steve
|
||||
* Fix gcc4 build issues.
|
||||
*
|
||||
* Revision 1.7 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
|
|
|
|||
131
Makefile.in
131
Makefile.in
|
|
@ -16,16 +16,16 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.169 2004/10/13 22:01:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.169.2.7 2007/05/30 17:48:53 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
# This version string is only used in the version message printed
|
||||
# by the compiler. It reflects the assigned version number for the
|
||||
# product as a whole. Most components also print the CVS Name: token
|
||||
# in order to get a more automatic version stamp as well.
|
||||
VERSION = 0.8
|
||||
# This string is used as an installation suffix. It modifies certain
|
||||
# key install paths/files such that a build and install of Icarus Verilog
|
||||
# with the same $(prefix) but a different $(suffix) will not interfere.
|
||||
# The normal configuratin leaves suffix empty
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
@ -37,7 +37,9 @@ VPATH = $(srcdir)
|
|||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = @includedir@
|
||||
# This is actually the directory where we install our own header files.
|
||||
# It is a little different from the generic includedir.
|
||||
includedir = @includedir@/iverilog$(suffix)
|
||||
mandir = @mandir@
|
||||
|
||||
libdir64 = @libdir64@
|
||||
|
|
@ -54,6 +56,8 @@ INSTALL_DATA = @INSTALL_DATA@
|
|||
STRIP = @STRIP@
|
||||
LEX = @LEX@
|
||||
YACC = @YACC@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
|
||||
CXXFLAGS = -Wall @CXXFLAGS@
|
||||
|
|
@ -70,7 +74,7 @@ all: dep ivl@EXEEXT@
|
|||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in ivlpp tgt-verilog tgt-stub; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
cd driver ; $(MAKE) VERSION=$(VERSION) $@
|
||||
cd driver ; $(MAKE) $@
|
||||
|
||||
# In the windows world, the installer will need a dosify program to
|
||||
# dosify text files.
|
||||
|
|
@ -103,6 +107,7 @@ distclean: clean
|
|||
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
rm -rf autom4te.cache
|
||||
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
|
||||
|
|
@ -111,7 +116,7 @@ O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
|||
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \
|
||||
elab_sig.o emit.o eval.o eval_attrib.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o net_assign.o \
|
||||
load_module.o netlist.o NetLatch.o netmisc.o net_assign.o \
|
||||
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 net_variable.o pad_to_width.o \
|
||||
|
|
@ -136,7 +141,7 @@ ivl@EXEEXT@: $O ivl.def
|
|||
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
|
||||
dlltool --dllname ivl@EXEEXT@ --def ivl.def \
|
||||
--output-lib libivl.a --output-exp ivl.exp
|
||||
$(CXX) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
|
||||
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
|
||||
else
|
||||
ivl@EXEEXT@: $O
|
||||
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
|
||||
|
|
@ -150,9 +155,13 @@ all: dep iverilog-vpi
|
|||
|
||||
iverilog-vpi: iverilog-vpi.sh
|
||||
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
|
||||
-e 's;@INCLUDEDIR@;@includedir@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);' \
|
||||
-e 's;@IVCC@;$(CC);' \
|
||||
-e 's;@IVCXX@;$(CXX);' \
|
||||
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
|
||||
-e 's;@LIBDIR64@;@libdir64@;' \
|
||||
-e 's;@VPIDIR1@;@vpidir1@;' -e 's;@VPIDIR2@;@vpidir2@;' \
|
||||
-e 's;@INCLUDEDIR@;$(includedir);' \
|
||||
-e 's;@LIBDIR@;@libdir@;' $< > $@
|
||||
chmod +x $@
|
||||
endif
|
||||
|
|
@ -161,7 +170,7 @@ dep:
|
|||
mkdir dep
|
||||
|
||||
%.o: %.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o $(DEBUGFLAGS)
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
|
||||
|
|
@ -169,10 +178,8 @@ lexor.o: lexor.cc parse.h
|
|||
|
||||
parse.o: parse.cc
|
||||
|
||||
parse.cc: $(srcdir)/parse.y
|
||||
parse.cc parse.h: $(srcdir)/parse.y
|
||||
$(YACC) --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
|
||||
|
||||
parse.h: parse.cc
|
||||
mv parse.cc.h parse.h 2>/dev/null || mv parse.hh parse.h
|
||||
|
||||
syn-rules.cc: $(srcdir)/syn-rules.y
|
||||
|
|
@ -187,46 +194,55 @@ lexor_keyword.cc: lexor_keyword.gperf
|
|||
gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
|
||||
iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man
|
||||
man -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
$(MAN) -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
|
||||
iverilog-vpi.pdf: iverilog-vpi.ps
|
||||
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
|
||||
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
|
||||
|
||||
# Build and install the iverilog-vpi.pdf only if there is a man
|
||||
# program *and* a ps2pdf program.
|
||||
ifeq (@WIN32@,yes)
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: dep iverilog-vpi.pdf
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi$(suffix).pdf $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
all: dep iverilog-vpi.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/sqrt-virtex.v $(prefix)/QUICK_START.txt
|
||||
WIN32_INSTALL =
|
||||
else
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi$(suffix)
|
||||
endif
|
||||
|
||||
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
|
||||
XNF_INSTALL = $(libdir)/ivl$(suffix)/xnf.conf $(libdir)/ivl$(suffix)/xnf-s.conf
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC) $(XNF_INSTALL)
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC) $(XNF_INSTALL)
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
|
||||
$(bindir)/iverilog-vpi: ./iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
|
||||
$(bindir)/iverilog-vpi$(suffix): ./iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi$(suffix)
|
||||
|
||||
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(STRIP) $(strip_dynamic) $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(libdir)/ivl$(suffix)/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl$(suffix)/ivl@EXEEXT@
|
||||
|
||||
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl/xnf-s.conf
|
||||
$(libdir)/ivl$(suffix)/xnf-s.conf: $(srcdir)/xnf-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl$(suffix)/xnf-s.conf
|
||||
|
||||
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf.conf $(libdir)/ivl/xnf.conf
|
||||
$(libdir)/ivl$(suffix)/xnf.conf: $(srcdir)/xnf.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf.conf $(libdir)/ivl$(suffix)/xnf.conf
|
||||
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(includedir)/ivl_target.h
|
||||
|
|
@ -243,49 +259,32 @@ $(includedir)/acc_user.h: $(srcdir)/acc_user.h
|
|||
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
|
||||
$(INSTALL_DATA) $(srcdir)/veriuser.h $(includedir)/veriuser.h
|
||||
|
||||
$(mandir)/man1/iverilog-vpi.1: $(srcdir)/iverilog-vpi.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(mandir)/man1/iverilog-vpi.1
|
||||
$(mandir)/man1/iverilog-vpi$(suffix).1: $(srcdir)/iverilog-vpi.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1
|
||||
|
||||
$(prefix)/iverilog-vpi.pdf: iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(prefix)/iverilog-vpi.pdf
|
||||
$(prefix)/iverilog-vpi$(suffix).pdf: iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
|
||||
|
||||
# In windows installations, put a few examples and the quick_start
|
||||
# into the destination directory.
|
||||
ifeq (@MINGW32@,yes)
|
||||
$(prefix)/hello.vl: $(srcdir)/examples/hello.vl
|
||||
./dosify.exe $(srcdir)/examples/hello.vl tmp.vl
|
||||
mv tmp.vl $(prefix)/hello.vl
|
||||
|
||||
$(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
|
||||
endif
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(includedir) $(libdir)/ivl \
|
||||
$(mandir) $(mandir)/man1
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl$(suffix) \
|
||||
$(DESTDIR)$(libdir)/ivl$(suffix)/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
|
||||
uninstall:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
for f in xnf.conf xnf-s.conf ivl; \
|
||||
do rm -f $(libdir)/ivl/$$f; done
|
||||
-rmdir $(libdir)/ivl
|
||||
for f in verilog iverilog-vpi gverilog@EXEEXT@; \
|
||||
do rm -f $(bindir)/$$f; done
|
||||
for f in xnf.conf xnf-s.conf ivl@EXEEXT@; \
|
||||
do rm -f $(DESTDIR)$(libdir)/ivl$(suffix)/$$f; done
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl$(suffix)/include
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl$(suffix)
|
||||
for f in verilog$(suffix) iverilog-vpi$(suffix); \
|
||||
do rm -f $(DESTDIR)$(bindir)/$$f; done
|
||||
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
|
||||
do rm -f $(includedir)/$$f; done
|
||||
rm -f $(mandir)/man1/iverilog-vpi.1
|
||||
do rm -f $(DESTDIR)$(includedir)/$$f; done
|
||||
-test X$(suffix) = X || rmdir $(DESTDIR)/$(includedir)
|
||||
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi$(suffix).1 $(DESTDIR)$(prefix)/iverilog-vpi$(suffix).pdf
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
// NetLatch.cc
|
||||
// Author: Alan M. Feldstein
|
||||
// Class NetLatch member-function definitions
|
||||
|
||||
#include "NetLatch.h" // NetLatch class definition
|
||||
#include "target.h" // target_t structure definition
|
||||
|
||||
// constructor
|
||||
NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width )
|
||||
// explicitly call base-class constructor
|
||||
: NetNode( scope, name, 2U * width + 1U )
|
||||
{
|
||||
} // end NetLatch constructor
|
||||
|
||||
unsigned NetLatch::width() const
|
||||
{
|
||||
return ( pin_count() - 1U ) / 2U;
|
||||
} // end function width
|
||||
|
||||
Link &NetLatch::pin_Data( unsigned w )
|
||||
{
|
||||
unsigned pn = 1 + 2 * w;
|
||||
assert( pn < pin_count() );
|
||||
return pin( pn );
|
||||
} // end function pin_Data
|
||||
|
||||
Link &NetLatch::pin_Q( unsigned w )
|
||||
{
|
||||
unsigned pn = 2 + 2 * w;
|
||||
assert( pn < pin_count() );
|
||||
return pin( pn );
|
||||
} // end function pin_Q
|
||||
|
||||
Link &NetLatch::pin_Gate()
|
||||
{
|
||||
return pin( 0 );
|
||||
} // end function pin_Gate
|
||||
|
||||
const Link &NetLatch::pin_Gate() const
|
||||
{
|
||||
return pin( 0 );
|
||||
} // end function pin_Gate
|
||||
|
||||
bool NetLatch::emit_node( target_t *driverPtr ) const
|
||||
{
|
||||
driverPtr->lpm_latch( this );
|
||||
return true;
|
||||
} // end function emit_node
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// NetLatch.h
|
||||
// Author: Alan M. Feldstein
|
||||
// This class represents an LPM_LATCH device. In Verilog, storage components of this type can be inferred.
|
||||
// The pinout is assigned like so:
|
||||
// 0 -- Gate
|
||||
//
|
||||
// 1 -- Data[0]
|
||||
// 2 -- Q[0]
|
||||
// ...
|
||||
#ifndef NETLATCH_H
|
||||
#define NETLATCH_H
|
||||
|
||||
#include "netlist.h" // NetNode, NetScope, Link class definitions
|
||||
#include "StringHeap.h" // perm_string class definition
|
||||
|
||||
class NetLatch : public NetNode
|
||||
{
|
||||
public:
|
||||
NetLatch( NetScope *, perm_string, unsigned );
|
||||
|
||||
unsigned width() const;
|
||||
|
||||
Link &pin_Data( unsigned );
|
||||
Link &pin_Q( unsigned );
|
||||
Link &pin_Gate();
|
||||
|
||||
const Link &pin_Data( unsigned ) const;
|
||||
const Link &pin_Q( unsigned ) const;
|
||||
const Link &pin_Gate() const;
|
||||
|
||||
virtual bool emit_node( target_t * ) const;
|
||||
}; // end class NetLatch
|
||||
|
||||
#endif
|
||||
20
PDelays.cc
20
PDelays.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PDelays.cc,v 1.11 2003/06/21 01:21:42 steve Exp $"
|
||||
#ident "$Id: PDelays.cc,v 1.11.2.1 2006/10/04 00:37:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -72,6 +72,20 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
|
|||
dex = tmp;
|
||||
}
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
if (sizeof(unsigned) <= 4 && shift > 9) {
|
||||
cerr << expr->get_line() << ": error: Precision overflow"
|
||||
<< " in scope " << scope->name() << "." << endl;
|
||||
cerr << expr->get_line() << ": :"
|
||||
<< " Units are 10e" << scope->time_unit()
|
||||
<< " minus precision 10e" << des->get_precision()
|
||||
<< " is 10e" << shift << "." << endl;
|
||||
cerr << expr->get_line() << ": : Perhaps a timescale "
|
||||
<< "is missing or incorrect?" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the delay expression is a real constant or vector
|
||||
constant, then evaluate it, scale it to the local time
|
||||
units, and return an adjusted value. */
|
||||
|
|
@ -79,7 +93,6 @@ static unsigned long calculate_val(Design*des, NetScope*scope,
|
|||
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
|
||||
verireal fn = tmp->value();
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
long delay = fn.as_long(shift);
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
|
|
@ -146,6 +159,9 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.11.2.1 2006/10/04 00:37:03 steve
|
||||
* Detect delay precision overflow.
|
||||
*
|
||||
* Revision 1.11 2003/06/21 01:21:42 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
|
|
|
|||
7
PExpr.cc
7
PExpr.cc
|
|
@ -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.35 2004/10/04 01:10:51 steve Exp $"
|
||||
#ident "$Id: PExpr.cc,v 1.35.2.1 2006/02/07 22:46:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -90,6 +90,8 @@ bool PEConcat::is_constant(Module *mod) const
|
|||
{
|
||||
bool constant = repeat_? repeat_->is_constant(mod) : true;
|
||||
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
|
||||
if (parms_[i] == 0)
|
||||
continue;
|
||||
constant = constant && parms_[i]->is_constant(mod);
|
||||
}
|
||||
return constant;
|
||||
|
|
@ -262,6 +264,9 @@ bool PEUnary::is_constant(Module*m) const
|
|||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.35.2.1 2006/02/07 22:46:23 steve
|
||||
* More robust test for concat constant-ness.
|
||||
*
|
||||
* Revision 1.35 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
16
PExpr.h
16
PExpr.h
|
|
@ -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.66 2004/10/04 01:10:51 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.66.2.2 2006/07/28 16:26:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -115,6 +115,8 @@ class PEConcat : public PExpr {
|
|||
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
|
||||
~PEConcat();
|
||||
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Concatenated Regs can be on the left of procedural
|
||||
|
|
@ -324,7 +326,7 @@ class PEString : public PExpr {
|
|||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
verinum* PEString::eval_const(const Design*, const NetScope*) const;
|
||||
verinum* eval_const(const Design*, const NetScope*) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
|
|
@ -374,7 +376,7 @@ class PEBinary : public PExpr {
|
|||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
|
@ -384,7 +386,7 @@ class PEBinary : public PExpr {
|
|||
PExpr*left_;
|
||||
PExpr*right_;
|
||||
|
||||
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
|
||||
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
|
||||
|
||||
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
|
|
@ -492,6 +494,12 @@ class PECallFunction : public PExpr {
|
|||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.66.2.2 2006/07/28 16:26:17 steve
|
||||
* Remove excess PEString:: prefix for stubborn compilers.
|
||||
*
|
||||
* Revision 1.66.2.1 2005/12/07 03:28:44 steve
|
||||
* Support constant concatenation of constants.
|
||||
*
|
||||
* Revision 1.66 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
9
PTask.h
9
PTask.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PTask.h,v 1.13 2004/05/31 23:34:36 steve Exp $"
|
||||
#ident "$Id: PTask.h,v 1.13.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
|
|
@ -70,7 +70,7 @@ class PTask : public LineInfo {
|
|||
// Elaborate the statement to finish off the task definition.
|
||||
void elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
svector<PWire*>*ports_;
|
||||
|
|
@ -106,7 +106,7 @@ class PFunction : public LineInfo {
|
|||
/* Elaborate the behavioral statement. */
|
||||
void elaborate(Design *des, NetScope*) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
|
@ -117,6 +117,9 @@ class PFunction : public LineInfo {
|
|||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.13.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.13 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
13
PUdp.h
13
PUdp.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PUdp.h,v 1.12 2004/03/08 00:47:44 steve Exp $"
|
||||
#ident "$Id: PUdp.h,v 1.12.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <map>
|
||||
|
|
@ -55,20 +55,20 @@ class PUdp {
|
|||
public:
|
||||
explicit PUdp(perm_string n, unsigned nports);
|
||||
|
||||
svector<string>ports;
|
||||
svector<std::string>ports;
|
||||
unsigned find_port(const char*name);
|
||||
|
||||
bool sequential;
|
||||
|
||||
svector<string>tinput;
|
||||
svector<std::string>tinput;
|
||||
svector<char> tcurrent;
|
||||
svector<char> toutput;
|
||||
|
||||
verinum::V initial;
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
std::map<std::string,PExpr*> attributes;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(std::ostream&out) const;
|
||||
|
||||
perm_string name_;
|
||||
private:
|
||||
|
|
@ -80,6 +80,9 @@ class PUdp {
|
|||
|
||||
/*
|
||||
* $Log: PUdp.h,v $
|
||||
* Revision 1.12.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.12 2004/03/08 00:47:44 steve
|
||||
* primitive ports can bind bi name.
|
||||
*
|
||||
|
|
|
|||
17
README.txt
17
README.txt
|
|
@ -88,10 +88,6 @@ Normally, this command automatically figures out everything it needs
|
|||
to know. It generally works pretty well. There are a few flags to the
|
||||
configure script that modify its behavior:
|
||||
|
||||
--without-ipal
|
||||
This turns off support for Icarus PAL, whether ipal
|
||||
libraries are installed or not.
|
||||
|
||||
--prefix=<root>
|
||||
The default is /usr/local, which causes the tool suite to
|
||||
be compiled for install in /usr/local/bin,
|
||||
|
|
@ -107,6 +103,17 @@ configure script that modify its behavior:
|
|||
compilation of 32bit compatible vvp (vvp32) and the vpi
|
||||
modules that match.
|
||||
|
||||
--enable-suffix
|
||||
--enable-suffix=<your-suffix>
|
||||
--disable-suffix
|
||||
Enable/disable changing the names of install files to use
|
||||
a suffix string so that this version or install can co-
|
||||
exist with other versions. This renames the installed
|
||||
commands (iverilog, iverilog-vpi, vvp) and the installed
|
||||
library files and include directory so that installations
|
||||
with the same prefix but different suffix are guaranteed
|
||||
to not interfere with each other.
|
||||
|
||||
2.2.1 Special AMD64 Instructions
|
||||
|
||||
(The Icarus Verilog RPM for x86_64 is build using these instructions.)
|
||||
|
|
@ -114,7 +121,7 @@ configure script that modify its behavior:
|
|||
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
|
||||
most out of your install, first make sure you have both 64bit and
|
||||
32bit development libraries installed. Then configure with this
|
||||
somewhat more compilcated command:
|
||||
somewhat more complex command:
|
||||
|
||||
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
|
||||
|
||||
|
|
|
|||
10
Statement.h
10
Statement.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.h,v 1.40 2004/02/20 18:53:33 steve Exp $"
|
||||
#ident "$Id: Statement.h,v 1.40.2.1 2006/07/10 00:21:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
|
@ -71,12 +71,15 @@ class PProcess : public LineInfo {
|
|||
* fact, the Statement class is abstract and represents all the
|
||||
* possible kinds of statements that exist in Verilog.
|
||||
*/
|
||||
class Statement : public LineInfo {
|
||||
class Statement : public LineInfo, public Attrib {
|
||||
|
||||
public:
|
||||
Statement() { }
|
||||
virtual ~Statement() =0;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
void dump_attributes(ostream&out, unsigned ind) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
|
@ -456,6 +459,9 @@ class PWhile : public Statement {
|
|||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.40.2.1 2006/07/10 00:21:49 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.40 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.cc,v 1.6 2004/02/18 17:11:54 steve Exp $"
|
||||
#ident "$Id: StringHeap.cc,v 1.6.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "StringHeap.h"
|
||||
|
|
@ -131,7 +131,7 @@ perm_string StringHeapLex::make(const char*text)
|
|||
return perm_string(add(text));
|
||||
}
|
||||
|
||||
perm_string StringHeapLex::make(const string&text)
|
||||
perm_string StringHeapLex::make(const std::string&text)
|
||||
{
|
||||
return perm_string(add(text.c_str()));
|
||||
}
|
||||
|
|
@ -181,6 +181,9 @@ bool operator < (perm_string a, perm_string b)
|
|||
|
||||
/*
|
||||
* $Log: StringHeap.cc,v $
|
||||
* Revision 1.6.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.6 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
12
StringHeap.h
12
StringHeap.h
|
|
@ -19,12 +19,14 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.h,v 1.5 2004/02/18 17:11:54 steve Exp $"
|
||||
#ident "$Id: StringHeap.h,v 1.5.2.2 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class perm_string {
|
||||
|
||||
public:
|
||||
|
|
@ -101,7 +103,7 @@ class StringHeapLex : private StringHeap {
|
|||
|
||||
const char*add(const char*);
|
||||
perm_string make(const char*);
|
||||
perm_string make(const string&);
|
||||
perm_string make(const std::string&);
|
||||
|
||||
unsigned add_count() const;
|
||||
unsigned add_hit_count() const;
|
||||
|
|
@ -120,6 +122,12 @@ class StringHeapLex : private StringHeap {
|
|||
|
||||
/*
|
||||
* $Log: StringHeap.h,v $
|
||||
* Revision 1.5.2.2 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.5.2.1 2005/06/14 15:33:54 steve
|
||||
* Fix gcc4 build issues.
|
||||
*
|
||||
* Revision 1.5 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
AC_DEFUN([AX_CPP_IDENT],
|
||||
[AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident,
|
||||
[AC_TRY_COMPILE([
|
||||
#ident "$Id: aclocal.m4,v 1.6 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: aclocal.m4,v 1.6.2.2 2007/05/16 23:51:42 steve Exp $"
|
||||
],[while (0) {}],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
|
||||
|
|
@ -24,6 +24,23 @@ fi
|
|||
AC_SUBST(ident_support)
|
||||
])# AC_CPP_IDENT
|
||||
|
||||
# AX_ENABLE_SUFFIX
|
||||
# ----------------
|
||||
# Create the configure option --enable-suffix[=suffix] to generate suffix
|
||||
# strings for the installed commands. This allows for shared installs of
|
||||
# different builds. Remember to change the default suffix string to some
|
||||
# value appropriate for the current version.
|
||||
AC_DEFUN([AX_ENABLE_SUFFIX],
|
||||
[AC_ARG_ENABLE([suffix],[Set the installation command suffix],[true],[enable_suffix=yes])
|
||||
if test X$enable_suffix = Xyes; then
|
||||
install_suffix='-0.8'
|
||||
elif test X$enable_suffix = Xno; then
|
||||
install_suffix=''
|
||||
else
|
||||
install_suffix="$enable_suffix"
|
||||
fi
|
||||
AC_SUBST(install_suffix)
|
||||
])# AX_ENABLE_SUFFIX
|
||||
|
||||
# _AX_C_UNDERSCORES_MATCH_IFELSE(PATTERN, ACTION-IF-MATCH, ACTION-IF-NOMATCH)
|
||||
# ------------------------------
|
||||
|
|
@ -48,7 +65,7 @@ AC_DEFUN([AX_C_UNDERSCORES_LEADING],
|
|||
[AS_VAR_SET(ax_cv_c_underscores_leading, yes)],
|
||||
[AS_VAR_SET(ax_cv_c_underscores_leading, no)])])
|
||||
if test $ax_cv_c_underscores_leading = yes -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
|
||||
AC_DEFINE(NEED_LU)
|
||||
AC_DEFINE([NEED_LU], [1], [Symbol names in object files produced by C compiler have leading underscores.])
|
||||
fi
|
||||
])# AX_C_UNDERSCORES_LEADING
|
||||
|
||||
|
|
@ -63,7 +80,7 @@ AC_DEFUN([AX_C_UNDERSCORES_TRAILING],
|
|||
[AS_VAR_SET(ax_cv_c_underscores_trailing, yes)],
|
||||
[AS_VAR_SET(ax_cv_c_underscores_trailing, no)])])
|
||||
if test $ax_cv_c_underscores_trailing = yes; then
|
||||
AC_DEFINE(NEED_TU)
|
||||
AC_DEFINE([NEED_TU], [1], [Symbol names in object files produced by C compiler have trailing underscores.])
|
||||
fi
|
||||
])# AX_C_UNDERSCORES_TRAILING
|
||||
|
||||
|
|
@ -91,13 +108,9 @@ AC_MSG_RESULT($WIN32)
|
|||
AC_DEFUN([AX_LD_EXTRALIBS],
|
||||
[AC_MSG_CHECKING([for extra libs needed])
|
||||
EXTRALIBS=
|
||||
case "${host}" in
|
||||
*-*-cygwin* )
|
||||
if test "$MINGW32" = "yes"; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test "$MINGW32" = "yes"; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
AC_SUBST(EXTRALIBS)
|
||||
AC_MSG_RESULT($EXTRALIBS)
|
||||
])# AX_LD_EXTRALIBS
|
||||
|
|
@ -109,7 +122,7 @@ AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
|
|||
[AC_MSG_CHECKING([for shared library link flag])
|
||||
shared=-shared
|
||||
case "${host}" in
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
shared="-shared -Wl,--enable-auto-image-base"
|
||||
;;
|
||||
|
||||
|
|
@ -138,7 +151,7 @@ AC_DEFUN([AX_C_PICFLAG],
|
|||
PICFLAG=-fPIC
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
PICFLAG=
|
||||
;;
|
||||
|
||||
|
|
@ -173,7 +186,7 @@ case "${host}" in
|
|||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
|
|
|
|||
14
async.cc
14
async.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $"
|
||||
#ident "$Id: async.cc,v 1.7.2.2 2007/05/30 17:48:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -66,6 +66,10 @@ bool NetEvWait::is_asynchronous()
|
|||
|
||||
NexusSet*inputs = statement_->nex_input();
|
||||
|
||||
/* All the inputs of the statement must be accounted for in
|
||||
the sensitivity list. Otherwise, there are inputs that can
|
||||
change without the event being triggered, and that implies
|
||||
a latch, not a combinational circuit. */
|
||||
if (! sense->contains(*inputs)) {
|
||||
delete sense;
|
||||
delete inputs;
|
||||
|
|
@ -85,7 +89,7 @@ bool NetProc::is_asynchronous()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NetProcTop::is_asynchronous()
|
||||
bool NetProcTop::is_asynchronous() const
|
||||
{
|
||||
if (type_ == NetProcTop::KINITIAL)
|
||||
return false;
|
||||
|
|
@ -95,6 +99,12 @@ bool NetProcTop::is_asynchronous()
|
|||
|
||||
/*
|
||||
* $Log: async.cc,v $
|
||||
* Revision 1.7.2.2 2007/05/30 17:48:53 steve
|
||||
* Support Latch synthesis (Alan Feldstein)
|
||||
*
|
||||
* Revision 1.7.2.1 2006/05/21 21:58:46 steve
|
||||
* NetESignal input is only selected bits.
|
||||
*
|
||||
* Revision 1.7 2004/01/18 23:26:54 steve
|
||||
* The is_combinational function really need not recurse.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -70,6 +70,14 @@ warning.)
|
|||
|
||||
* Other Attributes
|
||||
|
||||
(* ivl_full_case *)
|
||||
|
||||
This attribute only has meaning when attached to case statements,
|
||||
and only when doing synthesis. The statement means to ignore the
|
||||
possibility that some cases are not defined. Presume that the
|
||||
device really is fully specified and do not emit any warnings
|
||||
about missing guards.
|
||||
|
||||
[ none defined yet ]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@
|
|||
echo "Autoconf in root..."
|
||||
autoconf
|
||||
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-fpga libveriuser cadpli
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-edif tgt-fpga libveriuser cadpli
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd ./$dir ; autoconf --include=.. )
|
||||
( cd ./$dir ; autoconf -f --include=.. )
|
||||
done
|
||||
|
||||
echo "Precompiling lexor_keyword.gperf"
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.11 2004/10/04 01:09:07 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.11.2.1 2005/02/23 18:40:23 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
@ -33,7 +33,7 @@ bindir = @bindir@
|
|||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
vpidir = @libdir@/ivl/@vpidir1@
|
||||
vpidir = @libdir@/ivl$(suffix)/@vpidir1@
|
||||
|
||||
strip_dynamic=@strip_dynamic@
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ SHARED = @shared@
|
|||
all:
|
||||
|
||||
ifeq (@enable_vvp32@,yes)
|
||||
vpidir32 = $(libdir)/ivl/@vpidir2@
|
||||
vpidir32 = $(libdir)/ivl$(suffix)/@vpidir2@
|
||||
ALL32 = all32
|
||||
INSTALL32 = install32
|
||||
UNINSTALL32 = uninistall32
|
||||
|
|
@ -86,6 +86,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ AC_SUBST(EXEEXT)
|
|||
# Combined check for Microsoft-related bogosities; sets WIN32 if found
|
||||
AX_WIN32
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# vvp32 is by default disabled
|
||||
|
|
@ -37,7 +39,7 @@ AC_SUBST(DLLIB)
|
|||
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
# Linker option used when compiling the target
|
||||
|
|
|
|||
16
compiler.h
16
compiler.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compiler.h,v 1.26 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: compiler.h,v 1.26.2.3 2006/06/12 00:16:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
|
|
@ -78,12 +78,17 @@ extern bool warn_timescale;
|
|||
/* Warn about legal but questionable module port bindings. */
|
||||
extern bool warn_portbinding;
|
||||
|
||||
/* Warn about unused or unassigned variables. */
|
||||
extern bool warn_unused;
|
||||
|
||||
/* This is true if verbose output is requested. */
|
||||
extern bool verbose_flag;
|
||||
|
||||
extern bool debug_scopes;
|
||||
extern bool debug_eval_tree;
|
||||
extern bool debug_elaborate;
|
||||
extern bool debug_synth;
|
||||
extern bool debug_cprop;
|
||||
|
||||
/* Path to a directory useful for finding subcomponents. */
|
||||
extern const char*basedir;
|
||||
|
|
@ -136,6 +141,15 @@ extern int load_sys_func_table(const char*path);
|
|||
|
||||
/*
|
||||
* $Log: compiler.h,v $
|
||||
* Revision 1.26.2.3 2006/06/12 00:16:50 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.26.2.2 2006/04/23 04:25:45 steve
|
||||
* Add cprop debugging.
|
||||
*
|
||||
* Revision 1.26.2.1 2006/04/01 01:37:24 steve
|
||||
* Add synth debug flag
|
||||
*
|
||||
* Revision 1.26 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
14
configure.in
14
configure.in
|
|
@ -9,6 +9,9 @@ AC_PROG_CC
|
|||
AC_PROG_CXX
|
||||
AC_CHECK_TOOL(STRIP, strip, true)
|
||||
AC_CHECK_PROGS(XGPERF,gperf,none)
|
||||
AC_CHECK_PROGS(MAN,man,none)
|
||||
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
|
||||
|
||||
if test "$XGPERF" = "none"
|
||||
then
|
||||
echo ""
|
||||
|
|
@ -56,9 +59,12 @@ AC_CHECK_LIB(z, gzwrite, HAVE_LIBZ=yes, HAVE_LIBZ=no)
|
|||
AC_SUBST(HAVE_LIBZ)
|
||||
if test "$WIN32" = "yes"; then
|
||||
AC_CHECK_LIB(bz2, main)
|
||||
AC_CHECK_LIB(bz2, main, HAVE_LIBBZ2=yes, HAVE_LIBBZ2=no)
|
||||
else
|
||||
AC_CHECK_LIB(bz2, BZ2_bzdopen)
|
||||
AC_CHECK_LIB(bz2, BZ2_bzdopen, HAVE_LIBBZ2=yes, HAVE_LIBBZ2=no)
|
||||
fi
|
||||
AC_SUBST(HAVE_LIBBZ2)
|
||||
|
||||
AC_MSG_CHECKING(for sys/times)
|
||||
AC_TRY_LINK(
|
||||
|
|
@ -66,7 +72,7 @@ AC_TRY_LINK(
|
|||
#include <sys/times.h>
|
||||
,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);},
|
||||
do_times=yes
|
||||
AC_DEFINE(HAVE_TIMES,1),
|
||||
AC_DEFINE([HAVE_TIMES], [1], [The times system call is available in the host operating system.]),
|
||||
do_times=no
|
||||
)
|
||||
AC_MSG_RESULT($do_times)
|
||||
|
|
@ -91,9 +97,11 @@ AC_C_BIGENDIAN
|
|||
|
||||
# $host
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
AX_LD_EXTRALIBS
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
# CFLAGS inherited by cadpli/Makefile?
|
||||
AX_C_PICFLAG
|
||||
|
||||
|
|
@ -141,6 +149,6 @@ AC_SUBST(vpidir1)
|
|||
AC_SUBST(vpidir2)
|
||||
AC_MSG_RESULT(${vpidir1} ${vpidir2})
|
||||
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-fpga libveriuser cadpli)
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-edif tgt-fpga libveriuser cadpli)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
|
|
|||
414
cprop.cc
414
cprop.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2006 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: cprop.cc,v 1.47 2004/02/20 18:53:34 steve Exp $"
|
||||
#ident "$Id: cprop.cc,v 1.47.2.7 2007/02/26 19:51:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "functor.h"
|
||||
# include "compiler.h"
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
|
|
@ -47,6 +48,9 @@ struct cprop_functor : public functor_t {
|
|||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||
virtual void lpm_mux(Design*des, NetMux*obj);
|
||||
virtual void lpm_mux_large(Design*des, NetMux*obj);
|
||||
virtual void lpm_ram_dq(Design*des, NetRamDq*obj);
|
||||
bool lpm_ram_dq_const_address_(Design*des, NetRamDq*obj);
|
||||
};
|
||||
|
||||
void cprop_functor::signal(Design*des, NetNet*obj)
|
||||
|
|
@ -842,84 +846,378 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
|||
|
||||
/*
|
||||
* This detects the case where the mux selects between a value and
|
||||
* Vz. In this case, replace the device with a bufif with the sel
|
||||
* Vz. In this case, replace the device with a MOS with the sel
|
||||
* input used to enable the output.
|
||||
*/
|
||||
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
{
|
||||
if (obj->size() > 2) {
|
||||
lpm_mux_large(des, obj);
|
||||
return;
|
||||
}
|
||||
if (obj->size() != 2)
|
||||
return;
|
||||
if (obj->sel_width() != 1)
|
||||
return;
|
||||
|
||||
/* If the first input is all constant Vz, then replace the
|
||||
NetMux with an array of BUFIF1 devices, with the enable
|
||||
connected to the select input. */
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! obj->pin_Data(idx, 0).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
bool cflag_a = obj->pin_Data(idx, 0).nexus()->drivers_constant();
|
||||
bool cflag_b = obj->pin_Data(idx, 1).nexus()->drivers_constant();
|
||||
|
||||
if (obj->pin_Data(idx, 0).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
/* If both data inputs are constant, we'll be able to do
|
||||
a substitution. */
|
||||
if (cflag_a && cflag_b)
|
||||
continue;
|
||||
|
||||
verinum::V va = cflag_a
|
||||
? obj->pin_Data(idx, 0).nexus()->driven_value()
|
||||
: verinum::Vx;
|
||||
verinum::V vb = cflag_b
|
||||
? obj->pin_Data(idx, 1).nexus()->driven_value()
|
||||
: verinum::Vx;
|
||||
|
||||
/* If only one Data input is constant, but a constant
|
||||
HiZ, then we will be able to do a MOS
|
||||
substitution. */
|
||||
if (cflag_a && va==verinum::Vz)
|
||||
continue;
|
||||
|
||||
if (cflag_b && vb==verinum::Vz)
|
||||
continue;
|
||||
|
||||
/* Otherwise, we cannot accurately do a substitution. If
|
||||
one input is non-constant, then that input may have a
|
||||
HiZ value, and there is no Verilog logic other then a
|
||||
MUX that can pass a HiZ value. */
|
||||
flag = false;
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
NetScope*scope = obj->scope();
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF1);
|
||||
if (! flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(obj->pin_Result(idx), tmp->pin(0));
|
||||
/* Create a temporary net to hold the result value that we
|
||||
build up. When we are done, we will connect this to the
|
||||
Result pins of the mux, then delete the mux *and* this
|
||||
net. That will cause all the proper connectivity to
|
||||
happen. */
|
||||
NetNet result_tmp(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, obj->width());
|
||||
|
||||
/* We know that every slice has at least one constant. Run
|
||||
through the slices again, creating boolean devices to
|
||||
replace the MUX slice. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
|
||||
/* If the Sel==0 input is constant Z, make a NMOS. */
|
||||
if (obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 0).nexus()->driven_value()==verinum::Vz) {
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::NMOS);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
count += 1;
|
||||
delete obj;
|
||||
return;
|
||||
}
|
||||
/* If the Sel==1 input is constant Z, make a PMOS. */
|
||||
if (obj->pin_Data(idx, 1).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->driven_value()==verinum::Vz) {
|
||||
|
||||
/* If instead the second input is all constant Vz, replace the
|
||||
NetMux with an array of BUFIF0 devices. */
|
||||
flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! obj->pin_Data(idx, 1).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj->pin_Data(idx, 1).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
NetScope*scope = obj->scope();
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF0);
|
||||
|
||||
connect(obj->pin_Result(idx), tmp->pin(0));
|
||||
3, NetLogic::PMOS);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
count += 1;
|
||||
delete obj;
|
||||
/* At this point, the only cases that are left are where
|
||||
the data inputs are both constant, and neither are
|
||||
HiZ. From this we know how to generate the output
|
||||
from only the S input. */
|
||||
if (! (obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->drivers_constant())) {
|
||||
cerr << obj->get_line() << ": internal error: "
|
||||
<< "Drivers not constant where expected?"
|
||||
<< " obj->width()=" << obj->width()
|
||||
<< " idx=" << idx
|
||||
<< endl;
|
||||
obj->dump_node(cerr, 4);
|
||||
}
|
||||
assert(obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->drivers_constant());
|
||||
|
||||
|
||||
verinum::V a = obj->pin_Data(idx, 0).nexus()->driven_value();
|
||||
verinum::V b = obj->pin_Data(idx, 1).nexus()->driven_value();
|
||||
|
||||
if (a == b) {
|
||||
connect(result_tmp.pin(idx), obj->pin_Data(idx,0));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a == verinum::V0 && b == verinum::V1) {
|
||||
connect(result_tmp.pin(idx), obj->pin_Sel(0));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a == verinum::V1 && b == verinum::V0) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Sel(0), tmp->pin(1));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* A==0: Q = B & S */
|
||||
if (a == verinum::V0) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* B==1: Q = A | S */
|
||||
if (b == verinum::V1) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::OR);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
/* A==1: Q = B | ~S */
|
||||
if (a == verinum::V1) {
|
||||
NetLogic*inv = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
NetNet*invs = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::TRI, 1);
|
||||
invs->local_flag(true);
|
||||
connect(inv->pin(0), invs->pin(0));
|
||||
connect(inv->pin(1), obj->pin_Sel(0));
|
||||
des->add_node(inv);
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::OR);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(inv->pin(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
/* B==0: Q = A & ~S */
|
||||
if (b == verinum::V0) {
|
||||
NetLogic*inv = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
NetNet*invs = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::TRI, 1);
|
||||
invs->local_flag(true);
|
||||
connect(inv->pin(0), invs->pin(0));
|
||||
connect(inv->pin(1), obj->pin_Sel(0));
|
||||
des->add_node(inv);
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(inv->pin(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
connect(result_tmp.pin(idx), obj->pin_Result(idx));
|
||||
|
||||
delete obj;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_mux_large(Design*des, NetMux*obj)
|
||||
{
|
||||
NetScope*scope = obj->scope();
|
||||
unsigned width = obj->width();
|
||||
unsigned size = obj->size();
|
||||
|
||||
/* This test looks for bit slices that are constant
|
||||
throughout. If we find any, we can reduce the width of the
|
||||
MUX to eliminate the fixed value. */
|
||||
|
||||
/* After the following for loop, this array of bools will
|
||||
contain "true" for each bit slice that is constant and
|
||||
identical, and "false" otherwise. The reduce_width will
|
||||
count the number of true entries in the flags array. */
|
||||
bool*flags = new bool[width];
|
||||
unsigned reduce_width = 0;
|
||||
|
||||
for (unsigned bit = 0 ; bit < width ; bit += 1) {
|
||||
|
||||
flags[bit] = true;
|
||||
|
||||
/* If not even the first selection is constant, then the
|
||||
slice cannot be reduced. */
|
||||
if (! obj->pin_Data(bit, 0).nexus()->drivers_constant()) {
|
||||
flags[bit] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If any of the remaining selections in non-consant, or
|
||||
constant with a different value, then this slice
|
||||
cannot be reduced. */
|
||||
verinum::V val = obj->pin_Data(bit, 0).nexus()->driven_value();
|
||||
|
||||
for (unsigned idx = 1; flags[bit] && idx < size ; idx += 1) {
|
||||
|
||||
if (!obj->pin_Data(bit,idx).nexus()->drivers_constant()) {
|
||||
flags[bit] = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val != obj->pin_Data(bit,idx).nexus()->driven_value()) {
|
||||
flags[bit] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! flags[bit]) {
|
||||
/* This bit slice is too complex. Go on. */
|
||||
continue;
|
||||
}
|
||||
|
||||
reduce_width += 1;
|
||||
}
|
||||
|
||||
/* If no slices can be reduced, then we are finished. */
|
||||
if (reduce_width == 0) {
|
||||
delete[]flags;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle the very special case that all the slices can be
|
||||
reduced. We don't need a MUX at all! */
|
||||
if (reduce_width == width) {
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(obj->pin_Result(idx), obj->pin_Data(idx,0));
|
||||
|
||||
delete obj;
|
||||
count += 1;
|
||||
delete[]flags;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a reduced mux with the same name and size, but fewer
|
||||
slices. Connect all the slices that we are keeping. */
|
||||
NetMux*tmp = new NetMux(scope, obj->name(),
|
||||
width-reduce_width, size, obj->sel_width());
|
||||
tmp->set_line(*obj);
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->sel_width() ; idx += 1)
|
||||
connect(obj->pin_Sel(idx), tmp->pin_Sel(idx));
|
||||
|
||||
unsigned dst_bit = 0;
|
||||
|
||||
for (unsigned bit = 0 ; bit < width ; bit += 1) {
|
||||
if (flags[bit]) {
|
||||
connect(obj->pin_Result(bit), obj->pin_Data(bit,0));
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(obj->pin_Result(bit), tmp->pin_Result(dst_bit));
|
||||
|
||||
for (unsigned idx = 0 ; idx < size ; idx += 1)
|
||||
connect(obj->pin_Data(bit,idx), tmp->pin_Data(dst_bit,idx));
|
||||
|
||||
dst_bit += 1;
|
||||
}
|
||||
|
||||
/* Add the new node. Delete the old node. Signal that we
|
||||
change the design and may use a rescan. */
|
||||
des->add_node(tmp);
|
||||
delete obj;
|
||||
delete[]flags;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_ram_dq(Design*des, NetRamDq*obj)
|
||||
{
|
||||
if (lpm_ram_dq_const_address_(des,obj))
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to evaluate a constant address input. If we find it, then
|
||||
* replace the NetRamDq with a direct link to the addressed word.
|
||||
*/
|
||||
bool cprop_functor::lpm_ram_dq_const_address_(Design*des, NetRamDq*obj)
|
||||
{
|
||||
NetMemory*mem = obj->mem();
|
||||
NetNet* reg = mem->reg_from_explode();
|
||||
|
||||
/* I only know how to do this on exploded memories. */
|
||||
if (reg == 0)
|
||||
return false;
|
||||
|
||||
verinum sel (0UL, obj->awidth());
|
||||
for (unsigned idx = 0 ; idx < obj->awidth() ; idx += 1) {
|
||||
if (! obj->pin_Address(idx).nexus()->drivers_constant())
|
||||
return false;
|
||||
|
||||
sel.set(idx, obj->pin_Address(idx).nexus()->driven_value());
|
||||
}
|
||||
|
||||
unsigned long address = sel.as_ulong();
|
||||
|
||||
/* If the address is outside the ram, then leave this to the
|
||||
code generator to figure out. */
|
||||
if (address >= obj->size())
|
||||
return false;
|
||||
|
||||
|
||||
unsigned base = address * obj->width();
|
||||
assert(base+obj->width() <= reg->pin_count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
connect(reg->pin(base+idx), obj->pin_Q(idx));
|
||||
|
||||
if (debug_cprop) {
|
||||
cerr << obj->get_line() << ": debug: Replace read port with"
|
||||
<< " fixed link to word " << address << "." << endl;
|
||||
}
|
||||
|
||||
delete obj;
|
||||
count += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This functor looks to see if the constant is connected to nothing
|
||||
* but signals. If that is the case, delete the dangling constant and
|
||||
|
|
@ -1038,6 +1336,24 @@ void cprop(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.47.2.7 2007/02/26 19:51:38 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.47.2.6 2006/11/12 01:20:45 steve
|
||||
* Prevent constant mux outputs from confusing itself.
|
||||
*
|
||||
* Revision 1.47.2.5 2006/04/23 04:26:13 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.47.2.4 2005/09/11 02:50:51 steve
|
||||
* Fix overly agressive constant propagation through MUX causing lost Z bits.
|
||||
*
|
||||
* Revision 1.47.2.3 2005/08/28 22:00:39 steve
|
||||
* Reduce mux slices that are constant throughout range.
|
||||
*
|
||||
* Revision 1.47.2.2 2005/08/28 19:51:02 steve
|
||||
* More thorough constant propagation through MUX devices.
|
||||
*
|
||||
* Revision 1.47 2004/02/20 18:53:34 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.149 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.149.2.7 2006/08/23 04:09:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -77,6 +77,8 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
|||
o << " (local)";
|
||||
if (signed_)
|
||||
o << " signed";
|
||||
if (mref_)
|
||||
o << " mref_=" << mref_->name();
|
||||
switch (port_type_) {
|
||||
case NetNet::NOT_A_PORT:
|
||||
break;
|
||||
|
|
@ -171,7 +173,8 @@ void NetObj::dump_node_pins(ostream&o, unsigned ind) const
|
|||
|
||||
if (pin(idx).is_linked()) {
|
||||
const Nexus*nex = pin(idx).nexus();
|
||||
o << nex << " " << nex->name();
|
||||
const char*nex_name = nex->name();
|
||||
o << nex << " " << (nex_name? nex_name : "????");
|
||||
}
|
||||
o << endl;
|
||||
|
||||
|
|
@ -216,6 +219,23 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
|
|||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDecode::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_DECODE (NetDecode): " << name()
|
||||
<< " ff=" << ff_->name() << ", word width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDemux::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_DEMUX (NetDemux): " << name()
|
||||
<< " bus width=" << width() << ", address width=" << awidth()
|
||||
<< ", word count=" << size() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDivide::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NET_DIVIDE (NetDivide): " << name() << endl;
|
||||
|
|
@ -240,6 +260,7 @@ void NetMux::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
|
||||
<< " scope=" << scope()->name() << endl;
|
||||
o << setw(ind+6) << "" << "source=" << get_line() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
@ -272,7 +293,12 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
|
|||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
<< " aset_value=" << aset_value_
|
||||
<< " sset_value=" << sset_value_;
|
||||
|
||||
if (demux_) o << " demux=" << demux_->name();
|
||||
|
||||
o << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
|
|
@ -355,8 +381,16 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
|
|||
|
||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
|
||||
<< name() << endl;
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (";
|
||||
|
||||
if (mem_)
|
||||
if (NetNet*tmp = mem_->reg_from_explode())
|
||||
o << "exploded mem=" << tmp->name();
|
||||
else
|
||||
o << "mem=" << mem_->name();
|
||||
|
||||
o << "): " << name() << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
|
@ -432,7 +466,7 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
|
|||
void NetAssign_::dump_lval(ostream&o) const
|
||||
{
|
||||
if (sig_) {
|
||||
o << sig_->name();
|
||||
o << "sig=" << sig_->name();
|
||||
if (bmux_) {
|
||||
o << "[" << *bmux_ << "]";
|
||||
|
||||
|
|
@ -443,7 +477,7 @@ void NetAssign_::dump_lval(ostream&o) const
|
|||
// Is there an obvious way to flag memories in the dump
|
||||
// as different from the _real_ bit mux case?
|
||||
// o << "**memory**";
|
||||
o << mem_->name() << "[";
|
||||
o << "mem=" << mem_->name() << "[";
|
||||
if (bmux_) o << *bmux_;
|
||||
else o << "**oops**";
|
||||
o << "]";
|
||||
|
|
@ -537,6 +571,8 @@ void NetCase::dump(ostream&o, unsigned ind) const
|
|||
break;
|
||||
}
|
||||
|
||||
dump_proc_attr(o, ind+2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
o << setw(ind+2) << "";
|
||||
if (items_[idx].guard)
|
||||
|
|
@ -842,6 +878,15 @@ void NetProc::dump(ostream&o, unsigned ind) const
|
|||
o << setw(ind) << "" << "// " << typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
void NetProc::dump_proc_attr(ostream&o, unsigned ind) const
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < attr_cnt() ; idx += 1) {
|
||||
o << setw(ind) << "" << "(* " << attr_key(idx) << " = "
|
||||
<< attr_value(idx) << " *)" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump an expression that no one wrote a dump method for. */
|
||||
void NetExpr::dump(ostream&o) const
|
||||
{
|
||||
|
|
@ -1089,6 +1134,27 @@ void Design::dump(ostream&o) const
|
|||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.149.2.7 2006/08/23 04:09:14 steve
|
||||
* missing sig diagnostics.
|
||||
*
|
||||
* Revision 1.149.2.6 2006/07/10 00:21:50 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.149.2.5 2006/04/16 19:26:37 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.149.2.4 2006/03/26 23:09:21 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.149.2.3 2006/03/12 07:34:16 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.149.2.2 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.149.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.149 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.7 2004/10/13 22:01:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.7.2.1 2006/10/04 17:08:59 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.8
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
@ -29,6 +29,8 @@ srcdir = @srcdir@
|
|||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
|
|
@ -41,14 +43,14 @@ INSTALL = @INSTALL@
|
|||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS = @ident_support@ -I. -I$(srcdir)/.. @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: iverilog-vpi@EXEEXT@
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f *.o config.h
|
||||
rm -f iverilog-vpi@EXEEXT@
|
||||
|
||||
distclean: clean
|
||||
|
|
@ -60,21 +62,27 @@ iverilog-vpi@EXEEXT@: $O
|
|||
$(CC) $(LDFLAGS) $O -o iverilog-vpi@EXEEXT@ @EXTRALIBS@
|
||||
|
||||
|
||||
main.o: main.c
|
||||
main.o: main.c config.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/main.c
|
||||
|
||||
config.h: config.h.in
|
||||
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);g' \
|
||||
-e 's;@IVLCFLAGS@;@CXXFLAGS@;' \
|
||||
-e 's;@SHARED@;@shared@;' $< > $@
|
||||
|
||||
# Windows specific...
|
||||
res.o: res.rc
|
||||
windres -i res.rc -o res.o
|
||||
#
|
||||
|
||||
install: all installdirs $(bindir)/iverilog-vpi@EXEEXT@
|
||||
install: all installdirs $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
|
||||
$(bindir)/iverilog-vpi@EXEEXT@: ./iverilog-vpi@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi@EXEEXT@
|
||||
$(bindir)/iverilog-vpi$(suffix)@EXEEXT@: ./iverilog-vpi@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi@EXEEXT@ $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir)
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog-vpi@EXEEXT@
|
||||
rm -f $(bindir)/iverilog-vpi$(suffix)@EXEEXT@
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
/* For now do not put the Icarus Verilog include or library paths here.
|
||||
* They are generated from a registry entry the user must set (-ivl=).
|
||||
* This may change in the future once I have thought about it more. */
|
||||
#define IVERILOG_VPI_CC "@IVLCC@"
|
||||
#define IVERILOG_VPI_CXX "@IVLCXX@"
|
||||
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
|
||||
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
|
||||
#define IVERILOG_SUFFIX "@SUFFIX@"
|
||||
|
|
@ -32,28 +32,28 @@
|
|||
|
||||
#include <windows.h>
|
||||
|
||||
/* Macros used for compiling and linking */
|
||||
static void setup_ivl_environment();
|
||||
static void assign(char **ptr, char *str);
|
||||
|
||||
#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 */
|
||||
/* The compile options: compiler, flags, etc. are in here */
|
||||
#include "config.h"
|
||||
|
||||
/* pointers to global strings */
|
||||
|
||||
static struct global_strings {
|
||||
char *pCCSRC; /* list of C source files */
|
||||
char *pCXSRC; /* list of C++ source files */
|
||||
char *pCCSRC; /* list of C source files (*.c) */
|
||||
char *pCXSRC; /* list of C++ source files (*.cc, *.cpp) */
|
||||
char *pOBJ; /* list of object files */
|
||||
char *pLIB; /* list of library files */
|
||||
char *pINCS; /* list of include directories */
|
||||
char *pDEFS; /* list of definitions */
|
||||
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 */
|
||||
char *pLD; /* what to use for a linker */
|
||||
} gstr;
|
||||
|
||||
|
||||
|
|
@ -70,12 +70,15 @@ static void myExit(int exitVal)
|
|||
deInitDynString(gstr.pCXSRC);
|
||||
deInitDynString(gstr.pOBJ);
|
||||
deInitDynString(gstr.pLIB);
|
||||
deInitDynString(gstr.pINCS);
|
||||
deInitDynString(gstr.pDEFS);
|
||||
deInitDynString(gstr.pOUT);
|
||||
deInitDynString(gstr.pMINGW);
|
||||
deInitDynString(gstr.pIVL);
|
||||
deInitDynString(gstr.pCFLAGS);
|
||||
deInitDynString(gstr.pLDLIBS);
|
||||
deInitDynString(gstr.pNewPath);
|
||||
free(gstr.pLD);
|
||||
|
||||
exit(exitVal);
|
||||
}
|
||||
|
|
@ -84,9 +87,9 @@ static void myExit(int exitVal)
|
|||
|
||||
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");
|
||||
fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
|
||||
myExit(1);
|
||||
}
|
||||
|
||||
|
|
@ -110,12 +113,16 @@ static void init()
|
|||
initDynString(&gstr.pCXSRC);
|
||||
initDynString(&gstr.pOBJ);
|
||||
initDynString(&gstr.pLIB);
|
||||
initDynString(&gstr.pINCS);
|
||||
initDynString(&gstr.pDEFS);
|
||||
initDynString(&gstr.pOUT);
|
||||
initDynString(&gstr.pMINGW);
|
||||
initDynString(&gstr.pIVL);
|
||||
initDynString(&gstr.pCFLAGS);
|
||||
initDynString(&gstr.pLDLIBS);
|
||||
initDynString(&gstr.pNewPath);
|
||||
/* By default use the C compiler to link the programs. */
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CC);
|
||||
}
|
||||
|
||||
/* return true if "str" is terminated with with "end", case insensitive */
|
||||
|
|
@ -277,63 +284,124 @@ static int parse(int argc, char *argv[])
|
|||
|
||||
char dot_c_ext[] = ".c";
|
||||
char dot_cc_ext[] = ".cc";
|
||||
char dot_cpp_ext[] = ".cpp";
|
||||
char dot_o_ext[] = ".o";
|
||||
char name_option[] = "--name=";
|
||||
char lib_option[] = "-l";
|
||||
char inc_option[] = "-I";
|
||||
char mingw_option[] = "-mingw=";
|
||||
char ivl_option[] = "-ivl=";
|
||||
char def_option[] = "-D";
|
||||
|
||||
if (argc == 1)
|
||||
return 0;
|
||||
if (argc == 1) return 0;
|
||||
|
||||
for (idx=1; idx<argc; ++idx) {
|
||||
if (endsIn(dot_c_ext,argv[idx])) { /* check for C source files */
|
||||
/* Check for C source files (*.c) */
|
||||
if (endsIn(dot_c_ext, argv[idx])) {
|
||||
++srcFileCnt;
|
||||
append(&gstr.pCCSRC,argv[idx]);
|
||||
append(&gstr.pCCSRC," ");
|
||||
append(&gstr.pCCSRC, argv[idx]);
|
||||
append(&gstr.pCCSRC, " ");
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_c_ext));
|
||||
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 */
|
||||
/* Check for C++ source files (*.cc) */
|
||||
else if (endsIn(dot_cc_ext, argv[idx])) {
|
||||
/* We need to link with the C++ compiler. */
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CXX);
|
||||
++srcFileCnt;
|
||||
append(&gstr.pCXSRC,argv[idx]);
|
||||
append(&gstr.pCXSRC," ");
|
||||
append(&gstr.pCXSRC, argv[idx]);
|
||||
append(&gstr.pCXSRC, " ");
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext));
|
||||
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 */
|
||||
/* Check for C++ source files (*.cpp) */
|
||||
else if (endsIn(dot_cpp_ext, argv[idx])) {
|
||||
/* We need to link with the C++ compiler. */
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CXX);
|
||||
++srcFileCnt;
|
||||
append(&gstr.pCXSRC, argv[idx]);
|
||||
append(&gstr.pCXSRC, " ");
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT, argv[idx],
|
||||
strlen(argv[idx])-strlen(dot_cpp_ext));
|
||||
}
|
||||
/* Check for compiled object files */
|
||||
else if (endsIn(dot_o_ext, argv[idx])) {
|
||||
++srcFileCnt;
|
||||
append(&gstr.pOBJ,argv[idx]);
|
||||
append(&gstr.pOBJ," ");
|
||||
append(&gstr.pOBJ, argv[idx]);
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_o_ext));
|
||||
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));
|
||||
/* Check for the -mingw option */
|
||||
else if (startsWith(mingw_option, argv[idx]))
|
||||
assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1,
|
||||
strlen(argv[idx])-(sizeof(mingw_option)-1));
|
||||
/* Check for the -ivl option */
|
||||
else if (startsWith(ivl_option, argv[idx]))
|
||||
assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1,
|
||||
strlen(argv[idx])-(sizeof(ivl_option)-1));
|
||||
/* Check for the --name option */
|
||||
else if (startsWith(name_option, argv[idx])) {
|
||||
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," ");
|
||||
/* Check for the -l option */
|
||||
else if (startsWith(lib_option, argv[idx])) {
|
||||
append(&gstr.pLIB, " ");
|
||||
append(&gstr.pLIB, argv[idx]);
|
||||
}
|
||||
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 */
|
||||
/* Check for the -I option */
|
||||
else if (startsWith(inc_option, argv[idx])) {
|
||||
append(&gstr.pINCS, " ");
|
||||
append(&gstr.pINCS, argv[idx]);
|
||||
}
|
||||
/* Check for the -D option */
|
||||
else if (startsWith(def_option, argv[idx])) {
|
||||
append(&gstr.pDEFS, " ");
|
||||
append(&gstr.pDEFS, argv[idx]);
|
||||
}
|
||||
/* Check for the --cflags option */
|
||||
else if (stricmp("--cflags", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\n", gstr.pCFLAGS);
|
||||
myExit(0);
|
||||
}
|
||||
/* Check for the --ldflags option */
|
||||
else if (stricmp("--ldflags", argv[idx]) == 0) {
|
||||
printf("%s\n", IVERILOG_VPI_LDFLAGS);
|
||||
myExit(0);
|
||||
}
|
||||
/* Check for the --ldlibs option */
|
||||
else if (stricmp("--ldlibs", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\n", gstr.pLDLIBS);
|
||||
myExit(0);
|
||||
}
|
||||
/* Check for the --install-dir option */
|
||||
else if (stricmp("--install-dir", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL);
|
||||
myExit(0);
|
||||
}
|
||||
/* This is different than iverilog-vpi.sh, we don't
|
||||
* ignore unknown arguments */
|
||||
else return 0;
|
||||
}
|
||||
|
||||
if (0 == srcFileCnt)
|
||||
assign(&gstr.pOUT,""); /* in case they used --name with no source files */
|
||||
/* In case there is a --name without source/object files */
|
||||
if (0 == srcFileCnt) assign(&gstr.pOUT,"");
|
||||
|
||||
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," ");
|
||||
}
|
||||
/* Normally it's an error if there are no source or object files */
|
||||
/* Unless we are setting the IVL or MinGW registry entries */
|
||||
if (!*gstr.pOUT) {
|
||||
if (!*gstr.pMINGW && !*gstr.pIVL) return 0;
|
||||
} else
|
||||
/* We have a valid result file so add the .vpi extension */
|
||||
append(&gstr.pOUT, ".vpi");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -376,14 +444,14 @@ static void checkIvlDir(char *root)
|
|||
initDynString(&path);
|
||||
assign(&path,gstr.pIVL);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\vvp.exe");
|
||||
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".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," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " 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");
|
||||
|
|
@ -403,9 +471,7 @@ static void setup_mingw_environment()
|
|||
if (*gstr.pMINGW) {
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
|
||||
}
|
||||
else
|
||||
if (!GetRegistryKey(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");
|
||||
|
|
@ -414,13 +480,16 @@ static void setup_mingw_environment()
|
|||
myExit(5);
|
||||
}
|
||||
|
||||
assign(&gstr.pNewPath,"PATH="); /* create new path */
|
||||
/* Create new path with MinGW in it */
|
||||
assign(&gstr.pNewPath,"PATH=");
|
||||
append(&gstr.pNewPath,gstr.pMINGW);
|
||||
appendBackSlash(&gstr.pNewPath);
|
||||
append(&gstr.pNewPath, "\\");
|
||||
append(&gstr.pNewPath,"bin;");
|
||||
append(&gstr.pNewPath,pOldPATH);
|
||||
|
||||
_putenv(gstr.pNewPath); /* place new path in environment variable */
|
||||
/* Place new path in environment */
|
||||
_putenv(gstr.pNewPath);
|
||||
}
|
||||
|
||||
/* see if we can find iverilog root */
|
||||
|
|
@ -432,67 +501,73 @@ 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)) {
|
||||
} 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," of iverilog-vpi" IVERILOG_SUFFIX " 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");
|
||||
/* Build up the CFLAGS option string */
|
||||
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I");
|
||||
append(&gstr.pCFLAGS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCFLAGS);
|
||||
append(&gstr.pCFLAGS,"include");
|
||||
|
||||
/* build up the LDFLAGS option string */
|
||||
append(&gstr.pCFLAGS,"\\include\\\\iverilog" IVERILOG_SUFFIX);
|
||||
|
||||
/* 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);
|
||||
append(&gstr.pLDLIBS,"\\lib " IVERILOG_VPI_LDLIBS);
|
||||
}
|
||||
|
||||
/* compile source modules */
|
||||
|
||||
static void compile(char *pSource, char **pObject, char *ext, int *compile_errors, char *compiler)
|
||||
static void compile(char *pSource, char **pObject, int *compile_errors, char *compiler)
|
||||
{
|
||||
char *ptr1 = pSource;
|
||||
char *ptr2 = strchr(pSource,' ');
|
||||
char *buf=0,*src=0,*obj=0;
|
||||
char *ptr2 = strchr(ptr1, ' ');
|
||||
char *buf=0, *src=0, *obj=0;
|
||||
|
||||
while (ptr2) {
|
||||
int len = ptr2 - ptr1;
|
||||
assignn(&src,ptr1,len);
|
||||
char *ostart;
|
||||
int olen;
|
||||
assignn(&src, ptr1, len);
|
||||
|
||||
assignn(&obj,ptr1,len-strlen(ext)); /* strip off the extension */
|
||||
append (&obj,".o");
|
||||
/* Build the object file name */
|
||||
ostart = strrchr(ptr1, '/');
|
||||
if (ostart == NULL) ostart = ptr1;
|
||||
else ostart += 1;
|
||||
olen = strrchr(ptr1, '.') - ostart;
|
||||
assignn(&obj, ostart, olen);
|
||||
append(&obj, ".o");
|
||||
|
||||
assign (&buf,compiler);
|
||||
append (&buf," -c -o ");
|
||||
append (&buf,obj);
|
||||
append (&buf," ");
|
||||
append (&buf,gstr.pCFLAGS);
|
||||
append (&buf," ");
|
||||
append (&buf,src);
|
||||
/* Build the compile line */
|
||||
assign(&buf, compiler);
|
||||
append(&buf, " -c -o ");
|
||||
append(&buf, obj);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pDEFS);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pCFLAGS);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pINCS);
|
||||
append(&buf, " ");
|
||||
append(&buf, src);
|
||||
|
||||
append (pObject,obj);
|
||||
append (pObject," ");
|
||||
append (pObject, " ");
|
||||
append (pObject, obj);
|
||||
|
||||
printf("%s\n",buf);
|
||||
printf("Compiling %s...\n", src);
|
||||
|
||||
if (system(buf))
|
||||
++*compile_errors;
|
||||
if (system(buf)) ++*compile_errors;
|
||||
|
||||
ptr1 = ptr2 + 1; /* advance to next token */
|
||||
ptr2 = strchr(ptr1,' ');
|
||||
/* advance to next token */
|
||||
ptr1 = ptr2 + 1;
|
||||
ptr2 = strchr(ptr1, ' ');
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
|
@ -507,43 +582,44 @@ 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 */
|
||||
/* To make the output match iverilog-vpi.sh do not print out the
|
||||
* root directories */
|
||||
|
||||
printf("info: %s will be used as the MinGW root directory.\n",gstr.pMINGW);
|
||||
// printf("MinGW root directory: %s.\n", gstr.pMINGW);
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
|
||||
printf("info: %s will be used as the Icarus Verilog root directory.\n",gstr.pIVL);
|
||||
// printf("Icarus Verilog root directory: %s.\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 */
|
||||
/* compile the C source files (*.c) */
|
||||
compile(gstr.pCCSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
|
||||
/* compile the C++ source files (*.cc, *.cpp) */
|
||||
compile(gstr.pCXSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
|
||||
|
||||
if (compile_errors) {
|
||||
fprintf(stderr,"iverilog-vpi: Some %d files failed to compile.\n",compile_errors);
|
||||
fprintf(stderr,"iverilog-vpi: %d file(s) failed to compile.\n",
|
||||
compile_errors);
|
||||
myExit(2);
|
||||
}
|
||||
|
||||
/* link */
|
||||
/* link */
|
||||
assign(&buf, gstr.pLD);
|
||||
append(&buf, " -o ");
|
||||
append(&buf, gstr.pOUT);
|
||||
append(&buf, " ");
|
||||
append(&buf, IVERILOG_VPI_LDFLAGS);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pOBJ);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pLIB);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pLDLIBS);
|
||||
|
||||
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);
|
||||
printf("Making %s from %s...\n", gstr.pOUT,gstr.pOBJ);
|
||||
|
||||
iRet = system(buf);
|
||||
|
||||
free(buf);
|
||||
|
||||
if (iRet)
|
||||
myExit(3);
|
||||
if (iRet) myExit(3);
|
||||
}
|
||||
|
||||
/* program execution starts here */
|
||||
|
|
@ -552,14 +628,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
init();
|
||||
|
||||
if (!parse(argc,argv))
|
||||
usage();
|
||||
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();
|
||||
/* are there any source or object files specified */
|
||||
if (*gstr.pOUT) compile_and_link();
|
||||
|
||||
myExit(0);
|
||||
return 0; // eliminate warnings.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.24 2004/10/13 22:01:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.24.2.3 2007/05/30 17:48:26 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.8
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
@ -40,8 +40,10 @@ CC = @CC@
|
|||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
|
|
@ -54,6 +56,7 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
rm -rf autom4te.cache
|
||||
|
||||
O = main.o substit.o cflexor.o cfparse.o
|
||||
|
||||
|
|
@ -68,41 +71,49 @@ cfparse.h cfparse.c: cfparse.y
|
|||
|
||||
|
||||
main.o: main.c globals.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl$(suffix)"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(DEBUGFLAGS) $(srcdir)/main.c
|
||||
|
||||
build_string.o: build_string.c globals.h
|
||||
cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
|
||||
cfparse.o: cfparse.c globals.h cfparse_misc.h
|
||||
|
||||
iverilog.ps: $(srcdir)/iverilog.man
|
||||
man -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
$(MAN) -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
|
||||
iverilog.pdf: iverilog.ps
|
||||
ps2pdf iverilog.ps iverilog.pdf
|
||||
$(PS2PDF) iverilog.ps iverilog.pdf
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: iverilog.pdf
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog$(suffix).pdf $(mandir)/man1/iverilog$(suffix).1
|
||||
all: iverilog.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog$(suffix).1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
install: all installdirs $(bindir)/iverilog@EXEEXT@ $(INSTALL_DOC)
|
||||
install: all installdirs $(bindir)/iverilog$(suffix)@EXEEXT@ $(INSTALL_DOC)
|
||||
|
||||
$(bindir)/iverilog@EXEEXT@: ./iverilog@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog@EXEEXT@
|
||||
$(bindir)/iverilog$(suffix)@EXEEXT@: ./iverilog@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./iverilog@EXEEXT@ $(bindir)/iverilog$(suffix)@EXEEXT@
|
||||
|
||||
$(mandir)/man1/iverilog.1: $(srcdir)/iverilog.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog.1
|
||||
$(mandir)/man1/iverilog$(suffix).1: $(srcdir)/iverilog.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog.man $(mandir)/man1/iverilog$(suffix).1
|
||||
|
||||
$(prefix)/iverilog.pdf: iverilog.pdf
|
||||
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog.pdf
|
||||
$(prefix)/iverilog$(suffix).pdf: iverilog.pdf
|
||||
$(INSTALL_DATA) iverilog.pdf $(prefix)/iverilog$(suffix).pdf
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(bindir) $(INSTALL_DOCDIR)
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog@EXEEXT@
|
||||
rm -f $(mandir)/man1/iverilog.1
|
||||
rm -f $(bindir)/iverilog$(suffix)@EXEEXT@
|
||||
rm -f $(mandir)/man1/iverilog$(suffix).1
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH iverilog 1 "$Date: 2004/10/04 01:10:56 $" Version "$Date: 2004/10/04 01:10:56 $"
|
||||
.TH iverilog 1 "$Date: 2006/06/12 00:16:53 $" Version "$Date: 2006/06/12 00:16:53 $"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
|
|
@ -212,6 +212,12 @@ inherit timescale from another file. Both probably mean that
|
|||
timescales are inconsistent, and simulation timing can be confusing
|
||||
and dependent on compilation order.
|
||||
|
||||
.TP 8
|
||||
.B unused
|
||||
This enables warnings for unused variables. This may detect variables
|
||||
that are not assigned, or variables and nets that are not used, or
|
||||
similar possible misuses of variables and nets.
|
||||
|
||||
.SH "SYSTEM FUNCTION TABLE FILES"
|
||||
If the source file name as a \fB.sft\fP suffix, then it is taken to be
|
||||
a system function table file. A System function table file is used to
|
||||
|
|
|
|||
165
driver/main.c
165
driver/main.c
|
|
@ -17,10 +17,11 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.65 2004/06/17 14:47:22 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.65.2.6 2007/05/30 17:48:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "version.h"
|
||||
|
||||
const char NOTICE[] =
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
|
|
@ -88,6 +89,10 @@ extern const char*optarg;
|
|||
# define IVL_ROOT "."
|
||||
#endif
|
||||
|
||||
#ifndef IVL_ROOT_VARIABLE
|
||||
# define IVL_ROOT_VARIABLE "IVERILOG_ROOT"
|
||||
#endif
|
||||
|
||||
# include "globals.h"
|
||||
#include "cfparse_misc.h" /* cfparse() */
|
||||
|
||||
|
|
@ -262,15 +267,72 @@ static int t_default(char*cmd, unsigned ncmd)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
char *original_cmd = malloc( strlen( cmd ) + (size_t)1 );
|
||||
strcpy( original_cmd, cmd );
|
||||
|
||||
cmd = realloc( cmd, strlen( original_cmd ) + (size_t)19 ); /* more than enough memory for the ivlpp command and ">/tmp/ivlpp_stdout" */
|
||||
if( cmd == NULL ){
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
char *debug_ivl = malloc( strlen( original_cmd ) + (size_t)5 ); /* more than enough memory for "gdb " and ivl program_name */
|
||||
strcpy( debug_ivl, "gdb " );
|
||||
|
||||
static char whitespace[] = " \t\f\r\v\n";
|
||||
char *token;
|
||||
int found_pipe = 0;
|
||||
unsigned long token_counter = 0UL;
|
||||
|
||||
strcpy( cmd, "" );
|
||||
for( token = strtok( original_cmd, whitespace ); token != NULL; token = strtok( NULL, whitespace ) ){
|
||||
|
||||
if( strcmp( token, "|" ) == 0 ){
|
||||
found_pipe = 1;
|
||||
}
|
||||
|
||||
if( found_pipe ){
|
||||
token_counter++;
|
||||
}
|
||||
|
||||
if( token_counter == 0UL ){
|
||||
strcat( cmd, token );
|
||||
strcat( cmd, " " ); /* harmless space after last token, and it was already there anyway */
|
||||
}
|
||||
|
||||
if( token_counter == 2UL ){
|
||||
strcat( debug_ivl, token );
|
||||
}
|
||||
|
||||
if( token_counter > 2UL ){
|
||||
printf( "%s\n", token );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free( original_cmd );
|
||||
strcat( cmd, ">/tmp/ivlpp_stdout" );
|
||||
#endif
|
||||
|
||||
if (verbose_flag)
|
||||
printf("translate: %s\n", cmd);
|
||||
|
||||
|
||||
rc = system(cmd);
|
||||
#ifdef DEBUG
|
||||
if( verbose_flag ){
|
||||
printf( "%s\n", debug_ivl );
|
||||
}
|
||||
|
||||
system( debug_ivl ); /* For simplicity, ignore any return value, which is implementation dependent anyway. */
|
||||
free( debug_ivl );
|
||||
#endif
|
||||
remove(source_path);
|
||||
if ( ! getenv("IVERILOG_ICONFIG"))
|
||||
remove(iconfig_path);
|
||||
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
|
||||
return rc;
|
||||
#else
|
||||
if (rc != 0) {
|
||||
if (rc == 127) {
|
||||
fprintf(stderr, "Failed to execute: %s\n", cmd);
|
||||
|
|
@ -285,13 +347,14 @@ static int t_default(char*cmd, unsigned ncmd)
|
|||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void process_warning_switch(const char*name)
|
||||
{
|
||||
if (strcmp(name,"all") == 0) {
|
||||
strcat(warning_flags, "ipt");
|
||||
strcat(warning_flags, "iptu");
|
||||
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags+2, 'i'))
|
||||
|
|
@ -302,6 +365,9 @@ static void process_warning_switch(const char*name)
|
|||
} else if (strcmp(name,"timescale") == 0) {
|
||||
if (! strchr(warning_flags+2, 't'))
|
||||
strcat(warning_flags, "t");
|
||||
} else if (strcmp(name,"unused") == 0) {
|
||||
if (! strchr(warning_flags+2, 'u'))
|
||||
strcat(warning_flags, "u");
|
||||
} else if (strcmp(name,"no-implicit") == 0) {
|
||||
char*cp = strchr(warning_flags+2, 'i');
|
||||
if (cp) while (*cp) {
|
||||
|
|
@ -320,6 +386,12 @@ static void process_warning_switch(const char*name)
|
|||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-unused") == 0) {
|
||||
char*cp = strchr(warning_flags+2, 'u');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -409,14 +481,13 @@ int process_generation(const char*name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
/*
|
||||
* This function fills in th ivl_root directory with the appropriate
|
||||
* path, based on operating system, build time configuration, and
|
||||
* environment.
|
||||
*/
|
||||
static char* get_root_dir()
|
||||
{
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
{ char * s;
|
||||
char basepath[1024];
|
||||
|
|
@ -443,16 +514,56 @@ int main(int argc, char **argv)
|
|||
s = strrchr(ivl_root, sep);
|
||||
if (s) *s = 0;
|
||||
strcat(ivl_root, "\\lib\\ivl");
|
||||
|
||||
base = ivl_root;
|
||||
}
|
||||
|
||||
#else
|
||||
/* In a UNIX environment, the IVL_ROOT from the Makefile is
|
||||
dependable. It points to the $prefix/lib/ivl directory,
|
||||
where the sub-parts are installed. */
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
base = ivl_root;
|
||||
|
||||
{ char*var = 0;
|
||||
|
||||
/* In other systems, use the configured root. */
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
|
||||
/* In any case, the IVL_ROOT variable can be used to override
|
||||
the install location at run time. If it is set, use that
|
||||
value instead. */
|
||||
if ( (var = getenv(IVL_ROOT_VARIABLE)) ) {
|
||||
strncpy(ivl_root, var, MAXSIZE);
|
||||
strcat(ivl_root, "/lib/ivl");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ivl_root;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
|
||||
base = get_root_dir();
|
||||
|
||||
#ifdef __MINGW32__
|
||||
/* Under Windows, there is no point checking the root
|
||||
directory. */
|
||||
#else
|
||||
/* On other systems, check that the root directory seems
|
||||
reasonable. */
|
||||
{ size_t tmp_len = strlen(base) + 16;
|
||||
char* tmp = malloc(tmp_len);
|
||||
snprintf(tmp, tmp_len, "%s%civl", base, sep);
|
||||
|
||||
if (0 != access(tmp, F_OK)) {
|
||||
fprintf(stderr, "%s: INSTALLATION ERROR: Directory %s"
|
||||
" does not contain ivl files.\n", argv[0], base);
|
||||
fprintf(stderr, "%s: : Check installation"
|
||||
" or set " IVL_ROOT_VARIABLE " correctly.\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create a temporary file for communicating input parameters
|
||||
|
|
@ -594,7 +705,7 @@ int main(int argc, char **argv)
|
|||
pbase = base;
|
||||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION " ($Name: $)\n");
|
||||
printf("Icarus Verilog version " VERSION "\n\n");
|
||||
printf("Copyright 1998-2003 Stephen Williams\n");
|
||||
puts(NOTICE);
|
||||
|
||||
|
|
@ -735,6 +846,24 @@ int main(int argc, char **argv)
|
|||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.65.2.6 2007/05/30 17:48:26 steve
|
||||
* DEBUG aids. (Alan Feldstein)
|
||||
*
|
||||
* Revision 1.65.2.5 2006/07/07 21:31:50 steve
|
||||
* Root dir variable does not include lib/ivl components.
|
||||
*
|
||||
* Revision 1.65.2.4 2006/06/27 01:30:20 steve
|
||||
* Fix unused var warning for mingw32 build.
|
||||
*
|
||||
* Revision 1.65.2.3 2006/06/14 03:01:49 steve
|
||||
* Remove redundant call to get_root_dir.
|
||||
*
|
||||
* Revision 1.65.2.2 2006/06/12 00:16:53 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.65.2.1 2006/03/26 21:47:26 steve
|
||||
* More installation directory flexibility.
|
||||
*
|
||||
* Revision 1.65 2004/06/17 14:47:22 steve
|
||||
* Add a .sft file for the system functions.
|
||||
*
|
||||
|
|
|
|||
11
dup_expr.cc
11
dup_expr.cc
|
|
@ -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.18 2004/06/17 16:06:18 steve Exp $"
|
||||
#ident "$Id: dup_expr.cc,v 1.18.2.2 2006/11/02 02:13:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -29,6 +29,7 @@ NetEBComp* NetEBComp::dup_expr() const
|
|||
{
|
||||
NetEBComp*result = new NetEBComp(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
result->set_line(*this);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +91,7 @@ NetESignal* NetESignal::dup_expr() const
|
|||
NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
|
||||
assert(tmp);
|
||||
tmp->expr_width(expr_width());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +120,7 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
|||
tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms);
|
||||
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +146,12 @@ NetEVariable* NetEVariable::dup_expr() const
|
|||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.18.2.2 2006/11/02 02:13:15 steve
|
||||
* Error message for condit expression not synthesized.
|
||||
*
|
||||
* Revision 1.18.2.1 2006/06/12 00:16:50 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.18 2004/06/17 16:06:18 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
|
|
|
|||
105
elab_expr.cc
105
elab_expr.cc
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2006 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: elab_expr.cc,v 1.91 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.91.2.2 2006/11/02 02:13:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -43,7 +43,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, bool) const
|
|||
* and right sides, and creating one of a variety of different NetExpr
|
||||
* types.
|
||||
*/
|
||||
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
{
|
||||
assert(left_);
|
||||
assert(right_);
|
||||
|
|
@ -73,7 +73,7 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
}
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
|
||||
NetExpr*tmp = elaborate_expr_base_(des, lp, rp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
@ -82,11 +82,11 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
* operands are elaborated as necessary, and all I need to do is make
|
||||
* the correct NetEBinary object and connect the parameters.
|
||||
*/
|
||||
NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
NetExpr*lp, NetExpr*rp) const
|
||||
NetExpr* PEBinary::elaborate_expr_base_(Design*des,
|
||||
NetExpr*lp, NetExpr*rp) const
|
||||
{
|
||||
bool flag;
|
||||
NetEBinary*tmp;
|
||||
NetExpr*tmp;
|
||||
|
||||
switch (op_) {
|
||||
default:
|
||||
|
|
@ -112,6 +112,51 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
|||
break;
|
||||
|
||||
case 'l': // <<
|
||||
if (NetEConst*lpc = dynamic_cast<NetEConst*> (lp)) {
|
||||
if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
|
||||
// Handle the super-special case that both
|
||||
// operands are constants. Precalculate the
|
||||
// entire value here.
|
||||
verinum lpval = lpc->value();
|
||||
unsigned shift = rpc->value().as_ulong();
|
||||
verinum result = lpc->value() << shift;
|
||||
// If the l-value has explicit size, use that.
|
||||
if (lpval.has_len()) {
|
||||
result = verinum(result, lpval.len());
|
||||
}
|
||||
|
||||
tmp = new NetEConst(result);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Precalculate " << *this
|
||||
<< " to constant " << *tmp << endl;
|
||||
|
||||
} else {
|
||||
// Handle the special case that the left
|
||||
// operand is constant. If it is unsized, we
|
||||
// may have to expand it to an integer width.
|
||||
verinum lpval = lpc->value();
|
||||
if (lpval.len() < 32 && !lpval.has_len()) {
|
||||
lpval = verinum(lpval, 32);
|
||||
lpc = new NetEConst(lpval);
|
||||
lpc->set_line(*lp);
|
||||
}
|
||||
|
||||
tmp = new NetEBShift(op_, lpc, rp);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Adjust " << *this
|
||||
<< " to this " << *tmp
|
||||
<< " to allow for integer widths." << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Left side is not constant, so handle it the
|
||||
// default way.
|
||||
tmp = new NetEBShift(op_, lp, rp);
|
||||
}
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
case 'r': // >>
|
||||
case 'R': // >>>
|
||||
tmp = new NetEBShift(op_, lp, rp);
|
||||
|
|
@ -387,13 +432,16 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
if (NetNet*res = dscope->find_signal(dscope->basename())) {
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
|
||||
eres->set_line(*this);
|
||||
func->set_line(*this);
|
||||
return func;
|
||||
}
|
||||
|
||||
if (NetVariable*res = dscope->find_variable(dscope->basename())) {
|
||||
NetEVariable*eres = new NetEVariable(res);
|
||||
eres->set_line(*res);
|
||||
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
|
||||
eres->set_line(*res);
|
||||
func->set_line(*this);
|
||||
return func;
|
||||
}
|
||||
|
||||
|
|
@ -425,6 +473,29 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (!rep->value().is_defined()) {
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
<< "may not be undefined (" << rep->value()
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rep->value().is_negative()) {
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
<< "may not be negative (" << rep->value().as_long()
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rep->value().is_zero()) {
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
<< "may not be zero." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = rep;
|
||||
}
|
||||
|
||||
|
|
@ -497,6 +568,17 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
net, mem, var, par, eve);
|
||||
|
||||
if (net && mem) {
|
||||
assert(net == mem->reg_from_explode());
|
||||
net = 0;
|
||||
}
|
||||
|
||||
if (net && net->mref()) {
|
||||
mem = net->mref();
|
||||
assert(net == mem->reg_from_explode());
|
||||
net = 0;
|
||||
}
|
||||
|
||||
// If the identifier name is a parameter name, then return
|
||||
// a reference to the parameter expression.
|
||||
if (par != 0) {
|
||||
|
|
@ -742,6 +824,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
assert(idx_ == 0);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
|
|
@ -1005,6 +1088,12 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
|||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.91.2.2 2006/11/02 02:13:15 steve
|
||||
* Error message for condit expression not synthesized.
|
||||
*
|
||||
* Revision 1.91.2.1 2006/06/12 00:16:50 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.91 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
77
elab_net.cc
77
elab_net.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_net.cc,v 1.138 2004/10/04 03:09:38 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.138.2.3 2005/09/11 02:56:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
# include "compiler.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <cstring>
|
||||
|
||||
/*
|
||||
* This is a state flag that determines whether an elaborate_net must
|
||||
|
|
@ -498,7 +499,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
use of the situation, or 0 if it cannot. */
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(rexp)) {
|
||||
|
||||
lsig = lexp->synthesize(des);
|
||||
lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
if (lsig == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
"Cannot elaborate net for " << *lexp << endl;
|
||||
|
|
@ -518,7 +519,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(lexp)) {
|
||||
|
||||
rsig = rexp->synthesize(des);
|
||||
rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
assert(rsig);
|
||||
delete rexp;
|
||||
|
||||
|
|
@ -532,13 +533,13 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
|||
}
|
||||
|
||||
if (lsig == 0) {
|
||||
lsig = lexp->synthesize(des);
|
||||
lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
assert(lsig);
|
||||
delete lexp;
|
||||
}
|
||||
|
||||
if (rsig == 0) {
|
||||
rsig = rexp->synthesize(des);
|
||||
rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
assert(rsig);
|
||||
delete rexp;
|
||||
}
|
||||
|
|
@ -1216,6 +1217,13 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
|||
return sub;
|
||||
}
|
||||
|
||||
if (path_.peek_name(0)[0] == '$') {
|
||||
cerr << get_line() << ": sorry: System functions " << path_ <<
|
||||
" not supported in continuous assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look up the function definition. */
|
||||
NetFuncDef*def = des->find_function(scope, path_);
|
||||
if (def == 0) {
|
||||
|
|
@ -1312,21 +1320,47 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
|||
unsigned repeat = 1;
|
||||
|
||||
if (repeat_) {
|
||||
verinum*rep = repeat_->eval_const(des, scope);
|
||||
if (rep == 0) {
|
||||
auto_ptr<NetExpr> etmp (elab_and_eval(des, scope, repeat_));
|
||||
assert(etmp.get());
|
||||
NetEConst*erep = dynamic_cast<NetEConst*>(etmp.get());
|
||||
|
||||
if (erep == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to "
|
||||
<< "evaluate constant repeat expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = rep->as_ulong();
|
||||
repeat = erep->value().as_ulong();
|
||||
|
||||
if (repeat == 0) {
|
||||
cerr << get_line() << ": error: Invalid repeat value."
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
"may not be 0."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
delete rep;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!erep->value().is_defined()) {
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
<< "may not be undefined (" << erep->value()
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (erep->value().is_negative()) {
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
<< "may not be negative (" << erep->value().as_long()
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (erep->value().is_zero()) {
|
||||
cerr << get_line() << ": error: Concatenation repeat "
|
||||
<< "may not be zero." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1435,6 +1469,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
|||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(), 1,
|
||||
sig_width, sel->pin_count());
|
||||
mux->set_line(*this);
|
||||
|
||||
/* Connect the signal bits to the mux. Account for the
|
||||
direction of the numbering (lsb to msb vs. msb to lsb) by
|
||||
|
|
@ -2268,6 +2303,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
|||
(true) connected to tru_sig. */
|
||||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(), dwidth, 2, 1);
|
||||
mux->set_line(*this);
|
||||
connect(mux->pin_Sel(0), expr_sig->pin(0));
|
||||
|
||||
/* Connect the data inputs. */
|
||||
|
|
@ -2413,6 +2449,9 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
reduction=true; gtype = NetLogic::XNOR; break;
|
||||
|
||||
case '-': // Unary 2's complement.
|
||||
if (owidth == 0)
|
||||
owidth = sub_sig->pin_count();
|
||||
|
||||
sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, owidth);
|
||||
sig->local_flag(true);
|
||||
|
|
@ -2459,15 +2498,15 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
default:
|
||||
NetAddSub*sub = new NetAddSub(scope, scope->local_symbol(),
|
||||
sig->pin_count());
|
||||
owidth);
|
||||
sub->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
|
||||
|
||||
des->add_node(sub);
|
||||
|
||||
for (unsigned idx = 0 ; idx < sig->pin_count(); idx += 1)
|
||||
for (unsigned idx = 0 ; idx < owidth ; idx += 1)
|
||||
connect(sig->pin(idx), sub->pin_Result(idx));
|
||||
|
||||
for (unsigned idx = 0; idx < sub_sig->pin_count(); idx += 1)
|
||||
for (unsigned idx = 0; idx < owidth; idx += 1)
|
||||
connect(sub_sig->pin(idx), sub->pin_DataB(idx));
|
||||
|
||||
verinum tmp_num (verinum::V0, sub->width(), true);
|
||||
|
|
@ -2477,8 +2516,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
des->add_node(tmp_con);
|
||||
|
||||
NetNet*tmp_sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE,
|
||||
sub_sig->pin_count());
|
||||
NetNet::WIRE, owidth);
|
||||
tmp_sig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) {
|
||||
|
|
@ -2513,6 +2551,15 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.138.2.3 2005/09/11 02:56:37 steve
|
||||
* Attach line numbers to NetMux devices.
|
||||
*
|
||||
* Revision 1.138.2.2 2005/02/19 16:39:30 steve
|
||||
* Spellig fixes.
|
||||
*
|
||||
* Revision 1.138.2.1 2005/01/29 00:18:23 steve
|
||||
* Fix evaluate of constants in netlist concatenation repeats.
|
||||
*
|
||||
* Revision 1.138 2004/10/04 03:09:38 steve
|
||||
* Fix excessive error message.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
|
||||
NetExpr*tmp = elaborate_expr_base_(des, lp, rp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
# include "compiler.h"
|
||||
# include <iostream>
|
||||
# include <stdio.h>
|
||||
# include <cstring>
|
||||
|
||||
/*
|
||||
* Elaboration happens in two passes, generally. The first scans the
|
||||
|
|
@ -432,6 +433,9 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
|||
; cur != replace.end() ; cur ++ ) {
|
||||
|
||||
PExpr*tmp = (*cur).second;
|
||||
// No expression means that the parameter is not
|
||||
// replaced at all.
|
||||
if (tmp == 0) continue;
|
||||
NetExpr*val = tmp->elaborate_pexpr(des, sc);
|
||||
bool flag = my_scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
|
|
@ -444,7 +448,11 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
|||
|
||||
/* Stash the instance array of scopes into the parent
|
||||
scope. Later elaboration passes will use this vector to
|
||||
further elaborate the array. */
|
||||
further elaborate the array.
|
||||
|
||||
Note that the array is ordered from LSB to MSB. We will use
|
||||
that fact in the main elaborate to connect things in the
|
||||
correct order. */
|
||||
sc->instance_arrays[get_name()] = instances;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
|
||||
# include "Module.h"
|
||||
# include "PExpr.h"
|
||||
|
|
|
|||
317
elaborate.cc
317
elaborate.cc
|
|
@ -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.308 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.308.2.6 2006/11/27 01:47:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -67,6 +67,21 @@ void PGate::elaborate(Design*des, NetScope*scope) const
|
|||
typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
void process_attributes(Design*des, NetScope*scope,
|
||||
Attrib*dest, const map<perm_string,PExpr*>&table)
|
||||
{
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(table, attrib_list_n,
|
||||
des, scope);
|
||||
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
dest->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
delete[]attrib_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the continuous assign. (This is *not* the procedural
|
||||
* assign.) Elaborate the lvalue and rvalue, and do the assignment.
|
||||
|
|
@ -354,76 +369,212 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
switch (type()) {
|
||||
case AND:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::AND);
|
||||
if (pin_count() < 2) {
|
||||
cerr << get_line() << ": error: the AND "
|
||||
"primitive must have an input." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::AND);
|
||||
}
|
||||
break;
|
||||
case BUF:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUF);
|
||||
if (pin_count() < 2) {
|
||||
cerr << get_line() << ": error: the BUF "
|
||||
"primitive must have an input." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else if (pin_count() > 2) {
|
||||
cerr << get_line() << ": sorry: the BUF "
|
||||
"primitive may only have one output in V0.8." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUF);
|
||||
}
|
||||
break;
|
||||
case BUFIF0:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUFIF0);
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_line() << ": error: the BUFIF0 "
|
||||
"primitive must have three arguments." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUFIF0);
|
||||
}
|
||||
break;
|
||||
case BUFIF1:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUFIF1);
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_line() << ": error: the BUFIF1 "
|
||||
"primitive must have three arguments." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::BUFIF1);
|
||||
}
|
||||
break;
|
||||
case NAND:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NAND);
|
||||
if (pin_count() < 2) {
|
||||
cerr << get_line() << ": error: the NAND "
|
||||
"primitive must have an input." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NAND);
|
||||
}
|
||||
break;
|
||||
case NMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NMOS);
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_line() << ": error: the NMOS "
|
||||
"primitive must have three arguments." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NMOS);
|
||||
}
|
||||
break;
|
||||
case NOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOR);
|
||||
if (pin_count() < 2) {
|
||||
cerr << get_line() << ": error: the NOR "
|
||||
"primitive must have an input." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOR);
|
||||
}
|
||||
break;
|
||||
case NOT:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOT);
|
||||
if (pin_count() < 2) {
|
||||
cerr << get_line() << ": error: the NOT "
|
||||
"primitive must have an input." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else if (pin_count() > 2) {
|
||||
cerr << get_line() << ": sorry: the NOT "
|
||||
"primitive may only have one output in V0.8." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOT);
|
||||
}
|
||||
break;
|
||||
case NOTIF0:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOTIF0);
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_line() << ": error: the NOTIF0 "
|
||||
"primitive must have three arguments." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOTIF0);
|
||||
}
|
||||
break;
|
||||
case NOTIF1:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOTIF1);
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_line() << ": error: the NOTIF1 "
|
||||
"primitive must have three arguments." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::NOTIF1);
|
||||
}
|
||||
break;
|
||||
case OR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::OR);
|
||||
if (pin_count() < 2) {
|
||||
cerr << get_line() << ": error: the OR "
|
||||
"primitive must have an input." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::OR);
|
||||
}
|
||||
break;
|
||||
case RNMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::RNMOS);
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_line() << ": error: the RNMOS "
|
||||
"primitive must have three arguments." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::RNMOS);
|
||||
}
|
||||
break;
|
||||
case RPMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::RPMOS);
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_line() << ": error: the RPMOS "
|
||||
"primitive must have three arguments." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::RPMOS);
|
||||
}
|
||||
break;
|
||||
case PMOS:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PMOS);
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_line() << ": error: the PMOS "
|
||||
"primitive must have three arguments." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PMOS);
|
||||
}
|
||||
break;
|
||||
case PULLDOWN:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PULLDOWN);
|
||||
if (pin_count() != 1) {
|
||||
cerr << get_line() << ": sorry: the PULLDOWN "
|
||||
"primitive may only have one output in V0.8." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PULLDOWN);
|
||||
}
|
||||
break;
|
||||
case PULLUP:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PULLUP);
|
||||
if (pin_count() != 1) {
|
||||
cerr << get_line() << ": sorry: the PULLUP "
|
||||
"primitive may only have one output in V0.8." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::PULLUP);
|
||||
}
|
||||
break;
|
||||
case XNOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XNOR);
|
||||
if (pin_count() < 2) {
|
||||
cerr << get_line() << ": error: the XNOR "
|
||||
"primitive must have an input." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XNOR);
|
||||
}
|
||||
break;
|
||||
case XOR:
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XOR);
|
||||
if (pin_count() < 2) {
|
||||
cerr << get_line() << ": error: the XOR "
|
||||
"primitive must have an input." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XOR);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cerr << get_line() << ": internal error: unhandled "
|
||||
|
|
@ -454,6 +605,12 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
const PExpr*ex = pin(idx);
|
||||
if (ex == 0) {
|
||||
cerr << get_line() << ": error: Logic gate port "
|
||||
"expressions are not optional." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
NetNet*sig = (idx == 0)
|
||||
? ex->elaborate_lnet(des, scope, true)
|
||||
: ex->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
|
|
@ -642,7 +799,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
|||
unsigned prts_pin_count = 0;
|
||||
|
||||
for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) {
|
||||
NetScope*inst_scope = instance[inst];
|
||||
// Scan the instances from MSB to LSB. The port
|
||||
// will be assembled in that order as well.
|
||||
NetScope*inst_scope = instance[instance.count()-inst-1];
|
||||
|
||||
// Scan the module sub-ports for this instance...
|
||||
for (unsigned ldx = 0 ; ldx < mport.count() ; ldx += 1) {
|
||||
|
|
@ -1179,6 +1338,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
tmp->set_line(*this);
|
||||
|
||||
NetESignal*sig = new NetESignal(tmp);
|
||||
sig->set_line(*this);
|
||||
|
||||
/* Generate an assignment of the l-value to the temporary... */
|
||||
string n = scope->local_hsymbol();
|
||||
|
|
@ -1215,6 +1375,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* And build up the complex statement. */
|
||||
NetBlock*bl = new NetBlock(NetBlock::SEQU, 0);
|
||||
bl->set_line(*this);
|
||||
bl->append(a1);
|
||||
bl->append(st);
|
||||
|
||||
|
|
@ -1318,6 +1479,7 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
NetBlock*cur = new NetBlock(type, nscope);
|
||||
cur->set_line(*this);
|
||||
bool fail_flag = false;
|
||||
|
||||
if (nscope == 0)
|
||||
|
|
@ -1388,6 +1550,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
NetCase*res = new NetCase(type_, expr, icount);
|
||||
res->set_line(*this);
|
||||
process_attributes(des, scope, res, attributes);
|
||||
|
||||
/* Iterate over all the case items (guard/statement pairs)
|
||||
elaborating them. If the guard has no expression, then this
|
||||
|
|
@ -1403,8 +1566,12 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
|||
/* If there are no expressions, then this is the
|
||||
default case. */
|
||||
NetProc*st = 0;
|
||||
if (cur->stat)
|
||||
if (cur->stat) {
|
||||
st = cur->stat->elaborate(des, scope);
|
||||
} else {
|
||||
st = new NetBlock(NetBlock::SEQU, scope);
|
||||
st->set_line(*this);
|
||||
}
|
||||
|
||||
res->set_case(inum, 0, st);
|
||||
inum += 1;
|
||||
|
|
@ -1413,16 +1580,19 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
|||
|
||||
/* If there are one or more expressions, then
|
||||
iterate over the guard expressions, elaborating
|
||||
a separate case for each. (Yes, the statement
|
||||
will be elaborated again for each.) */
|
||||
a separate case for each. If the statement is
|
||||
nul, then put an appropriate stub in place. */
|
||||
NetExpr*gu = 0;
|
||||
NetProc*st = 0;
|
||||
assert(cur->expr[e]);
|
||||
gu = elab_and_eval(des, scope, cur->expr[e]);
|
||||
|
||||
if (cur->stat)
|
||||
if (cur->stat) {
|
||||
st = cur->stat->elaborate(des, scope);
|
||||
|
||||
} else {
|
||||
st = new NetBlock(NetBlock::SEQU, scope);
|
||||
st->set_line(*this);
|
||||
}
|
||||
res->set_case(inum, gu, st);
|
||||
inum += 1;
|
||||
}
|
||||
|
|
@ -1451,12 +1621,26 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
|||
if (NetEConst*ce = dynamic_cast<NetEConst*>(expr)) {
|
||||
verinum val = ce->value();
|
||||
delete expr;
|
||||
if (val[0] == verinum::V1)
|
||||
return if_->elaborate(des, scope);
|
||||
|
||||
verinum::V val_reduced = verinum::V0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
val_reduced = val_reduced | val[idx];
|
||||
|
||||
if (val_reduced == verinum::V1)
|
||||
if (if_) {
|
||||
return if_->elaborate(des, scope);
|
||||
} else {
|
||||
NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
else if (else_)
|
||||
return else_->elaborate(des, scope);
|
||||
else
|
||||
return new NetBlock(NetBlock::SEQU, 0);
|
||||
else {
|
||||
NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// If the condition expression is more then 1 bits, then
|
||||
|
|
@ -1625,6 +1809,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
NetBlock*block = new NetBlock(NetBlock::SEQU, 0);
|
||||
block->set_line(*this);
|
||||
|
||||
|
||||
/* Detect the case where the definition of the task is known
|
||||
|
|
@ -1702,6 +1887,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
|||
continue;
|
||||
|
||||
NetESignal*sig = new NetESignal(port);
|
||||
sig->set_line(*this);
|
||||
|
||||
/* Generate the assignment statement. */
|
||||
NetAssign*ass = new NetAssign(lv, sig);
|
||||
|
|
@ -1922,10 +2108,15 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
|||
|
||||
if (expr_.count() == 0) {
|
||||
assert(enet);
|
||||
NexusSet*nset = enet->nex_input();
|
||||
/* For synthesis we want just the inputs, but for the rest we
|
||||
* want inputs and outputs that may cause a value to change. */
|
||||
extern bool synthesis; /* Synthesis flag from main.cc */
|
||||
bool rem_out = false;
|
||||
if (synthesis) rem_out = true;
|
||||
NexusSet*nset = enet->nex_input(rem_out);
|
||||
if (nset == 0) {
|
||||
cerr << get_line() << ": internal error: No NexusSet"
|
||||
<< " from statement." << endl;
|
||||
cerr << get_line() << ": error: Unable to elaborate:"
|
||||
<< endl;
|
||||
enet->dump(cerr, 6);
|
||||
des->errors += 1;
|
||||
return enet;
|
||||
|
|
@ -2314,6 +2505,13 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
the for loop. This is also a very specific assignment
|
||||
statement. Put this into the "body" block. */
|
||||
sig = des->find_signal(scope, id2->path());
|
||||
if (sig == 0) {
|
||||
cerr << get_line() << ": error: Unable to find variable "
|
||||
<< id2->path() << " in for-loop increment expression." << endl;
|
||||
des->errors += 1;
|
||||
return body;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
lv = new NetAssign_(sig);
|
||||
|
||||
|
|
@ -2481,6 +2679,7 @@ void PTask::elaborate(Design*des, NetScope*task) const
|
|||
NetProc*st;
|
||||
if (statement_ == 0) {
|
||||
st = new NetBlock(NetBlock::SEQU, 0);
|
||||
st->set_line(*this);
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -2769,6 +2968,24 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.308.2.6 2006/11/27 01:47:14 steve
|
||||
* Fix crash handling constant true conditional.
|
||||
*
|
||||
* Revision 1.308.2.5 2006/11/27 01:32:24 steve
|
||||
* Fix evaluate of constant condition expressions.
|
||||
*
|
||||
* Revision 1.308.2.4 2006/07/10 00:21:50 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.308.2.3 2006/06/12 00:16:51 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.308.2.2 2005/12/10 03:30:50 steve
|
||||
* Fix crash on block with assignments that assign lval to self.
|
||||
*
|
||||
* Revision 1.308.2.1 2005/11/13 22:28:14 steve
|
||||
* Do not panic if case statement is nul.
|
||||
*
|
||||
* Revision 1.308 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
19
emit.cc
19
emit.cc
|
|
@ -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.77 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.77.2.2 2006/03/26 23:09:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
# include "netlist.h"
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
# include <cstring>
|
||||
|
||||
bool NetNode::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
|
|
@ -86,6 +87,16 @@ bool NetConst::emit_node(struct target_t*tgt) const
|
|||
return tgt->net_const(this);
|
||||
}
|
||||
|
||||
bool NetDecode::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_decode(this);
|
||||
}
|
||||
|
||||
bool NetDemux::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_demux(this);
|
||||
}
|
||||
|
||||
bool NetDivide::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_divide(this);
|
||||
|
|
@ -511,6 +522,12 @@ bool emit(const Design*des, const char*type)
|
|||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.77.2.2 2006/03/26 23:09:21 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.77.2.1 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.77 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
37
eval.cc
37
eval.cc
|
|
@ -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.36 2003/06/21 01:21:43 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.36.2.3 2006/09/20 20:27:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -112,7 +112,10 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
|||
case 'l': { // left shift (<<)
|
||||
assert(r->is_defined());
|
||||
unsigned long rv = r->as_ulong();
|
||||
res = new verinum(verinum::V0, l->len());
|
||||
unsigned use_wid = l->len();
|
||||
if (! l->has_len())
|
||||
use_wid += rv;
|
||||
res = new verinum(verinum::V0, use_wid);
|
||||
if (rv < res->len()) {
|
||||
unsigned cnt = res->len() - rv;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
|
|
@ -143,6 +146,27 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
|||
return res;
|
||||
}
|
||||
|
||||
verinum* PEConcat::eval_const(const Design*des, const NetScope*scope) const
|
||||
{
|
||||
verinum*accum = parms_[0]->eval_const(des, scope);
|
||||
if (accum == 0)
|
||||
return 0;
|
||||
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
verinum*tmp = parms_[idx]->eval_const(des, scope);
|
||||
/* Oops, found an argument that is not constant. Give up. */
|
||||
if (tmp == 0) {
|
||||
delete accum;
|
||||
return 0;
|
||||
}
|
||||
assert(tmp);
|
||||
|
||||
*accum = concat(*accum, *tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return accum;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate an identifier as a constant expression. This is only
|
||||
|
|
@ -240,6 +264,15 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
|
|||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.36.2.3 2006/09/20 20:27:02 steve
|
||||
* Fix left shift of small unsized constants.
|
||||
*
|
||||
* Revision 1.36.2.2 2005/12/18 21:06:01 steve
|
||||
* Properly fail when concat is not actually constant.
|
||||
*
|
||||
* Revision 1.36.2.1 2005/12/07 03:28:44 steve
|
||||
* Support constant concatenation of constants.
|
||||
*
|
||||
* Revision 1.36 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
|
|
|
|||
130
eval_tree.cc
130
eval_tree.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_tree.cc,v 1.62 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.62.2.5 2007/03/23 23:02:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -215,6 +215,11 @@ NetEConst* NetEBComp::eval_eqeq_()
|
|||
|
||||
NetEConst* NetEBComp::eval_less_()
|
||||
{
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(false, false);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(false, false);
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
|
|
@ -224,12 +229,24 @@ NetEConst* NetEBComp::eval_less_()
|
|||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (left_->expr_width() == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Having trouble evaluating left expression of < op."
|
||||
<< endl;
|
||||
cerr << get_line() << ": : "
|
||||
<< "Expression is: "
|
||||
<< *this << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
if (lv < rv) {
|
||||
verinum lv (verinum::V1, left_->expr_width() + 1);
|
||||
lv.set(left_->expr_width(), verinum::V0);
|
||||
lv.has_sign( left_->has_sign() );
|
||||
if ((lv < rv) == verinum::V1) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
|
@ -259,7 +276,7 @@ NetEConst* NetEBComp::eval_less_()
|
|||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_real_()
|
||||
NetEConst* NetEBComp::eval_leeq_real_(bool gt_flag, bool include_eq_flag)
|
||||
{
|
||||
NetEConst*vtmp;
|
||||
NetECReal*rtmp;
|
||||
|
|
@ -308,7 +325,16 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
|||
assert(0);
|
||||
}
|
||||
|
||||
verinum result((lv <= rv)? verinum::V1 : verinum::V0, 1);
|
||||
/* This function supports < and <=. If the eq_flag is true,
|
||||
then include <=. Otherwise, include only <. */
|
||||
bool flag;
|
||||
if (gt_flag)
|
||||
flag = include_eq_flag? (lv >= rv) : (lv > rv);
|
||||
else
|
||||
flag = include_eq_flag? (lv <= rv) : (lv < rv);
|
||||
|
||||
|
||||
verinum result(flag? verinum::V1 : verinum::V0, 1);
|
||||
vtmp = new NetEConst(result);
|
||||
vtmp->set_line(*this);
|
||||
|
||||
|
|
@ -318,9 +344,9 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
|||
NetEConst* NetEBComp::eval_leeq_()
|
||||
{
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_();
|
||||
return eval_leeq_real_(false, true);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_();
|
||||
return eval_leeq_real_(false, true);
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
|
@ -337,11 +363,17 @@ NetEConst* NetEBComp::eval_leeq_()
|
|||
cerr << get_line() << ": : " << *this << endl;
|
||||
}
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
/* Detect the case where the right side is greater than or
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
verinum lv (verinum::V1, left_->expr_width() + 1);
|
||||
if (left_->has_sign() && rv.has_sign()) {
|
||||
lv.set(lv.len()-1, verinum::V0);
|
||||
lv.has_sign(true);
|
||||
}
|
||||
lv.set(left_->expr_width(), verinum::V0);
|
||||
lv.has_sign( left_->has_sign() );
|
||||
if (lv <= rv) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
|
|
@ -374,23 +406,10 @@ NetEConst* NetEBComp::eval_leeq_()
|
|||
|
||||
NetEConst* NetEBComp::eval_gt_()
|
||||
{
|
||||
if ((left_->expr_type() == NetExpr::ET_REAL)
|
||||
&& (right_->expr_type() == NetExpr::ET_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
if (tmpl == 0)
|
||||
return 0;
|
||||
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmpr == 0)
|
||||
return 0;
|
||||
|
||||
double ll = tmpl->value().as_double();
|
||||
double rr = tmpr->value().as_double();
|
||||
|
||||
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, false);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, false);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
|
@ -450,23 +469,10 @@ NetEConst* NetEBComp::eval_gt_()
|
|||
|
||||
NetEConst* NetEBComp::eval_gteq_()
|
||||
{
|
||||
if ((left_->expr_type() == NetExpr::ET_REAL)
|
||||
&& (right_->expr_type() == NetExpr::ET_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
if (tmpl == 0)
|
||||
return 0;
|
||||
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmpr == 0)
|
||||
return 0;
|
||||
|
||||
double ll = tmpl->value().as_double();
|
||||
double rr = tmpr->value().as_double();
|
||||
|
||||
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, true);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, true);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
|
|
@ -1069,6 +1075,12 @@ NetEConst* NetEConcat::eval_tree()
|
|||
val = verinum(val.as_string());
|
||||
}
|
||||
|
||||
// Normally, concatenations are unsigned. However, the
|
||||
// $signed() function works by marking the expression as
|
||||
// signed, so we really have to check.
|
||||
val.has_sign( this->has_sign() );
|
||||
|
||||
|
||||
NetEConst*res = new NetEConst(val);
|
||||
res->set_width(val.len());
|
||||
return res;
|
||||
|
|
@ -1477,6 +1489,7 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
|
||||
verinum val = rval->value();
|
||||
verinum::V res;
|
||||
bool invert = false;
|
||||
|
||||
switch (op_) {
|
||||
|
||||
|
|
@ -1505,6 +1518,8 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
break;
|
||||
}
|
||||
|
||||
case 'A':
|
||||
invert = true;
|
||||
case '&': {
|
||||
res = verinum::V1;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
|
|
@ -1512,6 +1527,8 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
break;
|
||||
}
|
||||
|
||||
case 'N':
|
||||
invert = true;
|
||||
case '|': {
|
||||
res = verinum::V0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
|
|
@ -1519,6 +1536,8 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
break;
|
||||
}
|
||||
|
||||
case 'X':
|
||||
invert = true;
|
||||
case '^': {
|
||||
/* Reduction XOR. */
|
||||
unsigned ones = 0, unknown = 0;
|
||||
|
|
@ -1534,23 +1553,38 @@ NetEConst* NetEUReduce::eval_tree()
|
|||
break;
|
||||
}
|
||||
|
||||
if (unknown)
|
||||
return new NetEConst(verinum(verinum::Vx,1,true));
|
||||
if (ones%2)
|
||||
return new NetEConst(verinum(verinum::V1,1,true));
|
||||
return new NetEConst(verinum(verinum::V0,1,true));
|
||||
if (unknown) res = verinum::Vx;
|
||||
else if (ones%2) res = verinum::V1;
|
||||
else res = verinum::V0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (invert) res = ~res;
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.62.2.5 2007/03/23 23:02:31 steve
|
||||
* Fix compile time eval of <= comparison.
|
||||
*
|
||||
* Revision 1.62.2.4 2007/03/23 20:59:25 steve
|
||||
* Fix compile time evaluation of < operator.
|
||||
*
|
||||
* Revision 1.62.2.3 2005/09/09 02:17:08 steve
|
||||
* Evaluate magnitude compare with real operands.
|
||||
*
|
||||
* Revision 1.62.2.2 2005/09/04 15:41:54 steve
|
||||
* More explicit internal error message.
|
||||
*
|
||||
* Revision 1.62.2.1 2005/09/04 15:39:19 steve
|
||||
* More explicit internal error message.
|
||||
*
|
||||
* Revision 1.62 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* $Id: sqrt-virtex.v,v 1.4 2003/11/25 18:35:31 steve Exp $"
|
||||
* $Id: sqrt-virtex.v,v 1.4.2.2 2005/02/23 18:37:52 steve Exp $"
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module is a synthesizeable square-root function. It is also a
|
||||
* detailed example of how to target Xilinx Virtex parts using
|
||||
* Icarus Verilog. In fact, for no particular reason other then to
|
||||
* Icarus Verilog. In fact, for no particular reason other than to
|
||||
* be excessively specific, I will step through the process of
|
||||
* generating a design for a Spartan-II XC2S15-VQ100, and also how to
|
||||
* generate a generic library part for larger Virtex designs.
|
||||
|
|
@ -129,8 +129,8 @@
|
|||
* This command creates from the chip.ngd the file "chip_root.v" that
|
||||
* contains Verilog code that simulates the mapped design. This output
|
||||
* Verilog has the single root module "chip_root", which came from the
|
||||
* name of the root module when we were making hte EDIF file in the
|
||||
* first place. The module has ports named just line the ports of the
|
||||
* name of the root module when we were making the EDIF file in the
|
||||
* first place. The module has ports named just like the ports of the
|
||||
* chip_root module below.
|
||||
*
|
||||
* The generated Verilog uses the library in the directory
|
||||
|
|
|
|||
343
expr_synth.cc
343
expr_synth.cc
|
|
@ -17,24 +17,65 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.59 2004/06/30 02:16:26 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.59.2.11 2007/02/26 19:51:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <typeinfo>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": internal error: cannot synthesize expression: "
|
||||
<< *this << endl;
|
||||
cerr << get_line() << ": : typeid="
|
||||
<< typeid(*this).name() << endl;
|
||||
des->errors += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the NetEBitSel expression, create a NetMux node that selects a
|
||||
* bit from the input.
|
||||
*/
|
||||
NetNet* NetEBitSel::synthesize(Design*des)
|
||||
{
|
||||
NetNet*net = sig_->synthesize(des);
|
||||
assert(net);
|
||||
|
||||
NetNet*adr = idx_->synthesize(des);
|
||||
if (adr == 0)
|
||||
return 0;
|
||||
|
||||
NetScope*scope = adr->scope();
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
1, net->pin_count(), adr->pin_count());
|
||||
mux->set_line(*this);
|
||||
des->add_node(mux);
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
connect(mux->pin_Data(0, idx), net->pin(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
|
||||
connect(mux->pin_Sel(idx), adr->pin(idx));
|
||||
|
||||
connect(mux->pin_Result(0), osig->pin(0));
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make an LPM_ADD_SUB device from addition operators.
|
||||
*/
|
||||
|
|
@ -408,7 +449,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
|||
|
||||
default: {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "NetEBDiv has unexpeced op() code: "
|
||||
<< "NetEBDiv has unexpected op() code: "
|
||||
<< op() << endl;
|
||||
des->errors += 1;
|
||||
|
||||
|
|
@ -472,13 +513,18 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
|||
perm_string oname = scope->local_symbol();
|
||||
|
||||
olog = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
olog->set_line(*this);
|
||||
|
||||
connect(osig->pin(0), olog->pin(0));
|
||||
des->add_node(olog);
|
||||
|
||||
/* XXXX Here, I need to reduce the parameters with
|
||||
reduction or. */
|
||||
/* Here, I need to reduce the parameters with
|
||||
reduction or. Only do this if we must. */
|
||||
if (lsig->pin_count() > 1)
|
||||
lsig = reduction_or(des, lsig);
|
||||
|
||||
if (rsig->pin_count() > 1)
|
||||
rsig = reduction_or(des, rsig);
|
||||
|
||||
/* By this point, the left and right parameters have been
|
||||
reduced to single bit values. Now we just connect them to
|
||||
|
|
@ -486,6 +532,11 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
|||
assert(lsig->pin_count() == 1);
|
||||
connect(lsig->pin(0), olog->pin(1));
|
||||
|
||||
if (rsig->pin_count() != 1) {
|
||||
cerr << olog->get_line() << ": internal error: "
|
||||
<< "right argument not reduced. expr=" << *this << endl;
|
||||
}
|
||||
|
||||
assert(rsig->pin_count() == 1);
|
||||
connect(rsig->pin(0), olog->pin(2));
|
||||
}
|
||||
|
|
@ -566,7 +617,6 @@ NetNet* NetEBShift::synthesize(Design*des)
|
|||
NetNet::IMPLICIT, expr_width());
|
||||
osig->local_flag(true);
|
||||
|
||||
assert(op() == 'l');
|
||||
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
|
||||
osig->pin_count(),
|
||||
rsig->pin_count(),
|
||||
|
|
@ -640,6 +690,71 @@ NetNet* NetEConst::synthesize(Design*des)
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEMemory::synthesize(Design*des)
|
||||
{
|
||||
NetScope*scope = mem_->scope();
|
||||
|
||||
NetNet*explode = mem_->explode_to_reg();
|
||||
unsigned width = expr_width();
|
||||
|
||||
assert(idx_);
|
||||
NetNet*addr = idx_->synthesize(des);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT,
|
||||
width);
|
||||
osig->set_line(*this);
|
||||
|
||||
if (explode) {
|
||||
if (debug_synth)
|
||||
cerr << get_line() << ": debug: synthesize read of "
|
||||
<< explode->pin_count() << " bit exploded memory." << endl;
|
||||
|
||||
/* Only make a mux big enough to address the words that
|
||||
the address can generate. (If the address is
|
||||
0-extended, then only the low words are addressable.) */
|
||||
unsigned use_count = mem_->count();
|
||||
if (use_count > (1U << addr->pin_count())) {
|
||||
use_count = 1 << addr->pin_count();
|
||||
|
||||
if (debug_synth)
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Index expression can only address "
|
||||
<< use_count << " of "
|
||||
<< mem_->count() << " words." << endl;
|
||||
}
|
||||
|
||||
/* This is a reference to an exploded memory. So locate
|
||||
the reg vector and use the addr expression as a
|
||||
select into a MUX. */
|
||||
NetMux*mux = new NetMux(scope, scope->local_symbol(),
|
||||
width, use_count, addr->pin_count());
|
||||
des->add_node(mux);
|
||||
mux->set_line(*this);
|
||||
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(mux->pin_Result(idx), osig->pin(idx));
|
||||
for (unsigned idx = 0 ; idx < mux->sel_width() ; idx += 1)
|
||||
connect(mux->pin_Sel(idx), addr->pin(idx));
|
||||
|
||||
for (unsigned wrd = 0 ; wrd < use_count ; wrd += 1)
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1) {
|
||||
unsigned bit = wrd*width + idx;
|
||||
connect(mux->pin_Data(idx, wrd), explode->pin(bit));
|
||||
}
|
||||
|
||||
if (debug_synth)
|
||||
cerr << get_line() << ": debug: synthesis done." << endl;
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": internal error: Synthesize memory "
|
||||
<< "expression that is not exploded?" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetECReal::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": error: Real constants are "
|
||||
|
|
@ -684,6 +799,97 @@ NetNet* NetEUBits::synthesize(Design*des)
|
|||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEUFunc::synthesize(Design*des)
|
||||
{
|
||||
assert(func_);
|
||||
|
||||
NetFuncDef* def = func_->func_def();
|
||||
assert(def);
|
||||
|
||||
assert(parms_.count() == def->port_count());
|
||||
|
||||
svector<NetNet*> inports (parms_.count());
|
||||
|
||||
unsigned errors = 0;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
inports[idx] = parms_[idx]->synthesize(des);
|
||||
if (inports[idx] == 0)
|
||||
errors += 1;
|
||||
}
|
||||
|
||||
if (errors > 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "Cannot continue with function instance synthesis."
|
||||
<< endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet*out = def->synthesize(des, inports);
|
||||
|
||||
if (! out) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "User defined functions do not synthesize." << endl;
|
||||
def->dump(cerr, 4);
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
NetNet* NetFuncDef::synthesize(Design*des, const svector<NetNet*>&inports_)
|
||||
{
|
||||
|
||||
/* First run synthesis for the function definition as if this
|
||||
where a toplevel process. This will create the logic that
|
||||
the function represents, but connected to the port nets for
|
||||
the function definition. We will detach those common ports
|
||||
later. */
|
||||
NexusSet nex_set;
|
||||
statement_->nex_output(nex_set);
|
||||
|
||||
const perm_string tmp1 = scope()->local_symbol();
|
||||
NetNet*nex_out = new NetNet(scope(), tmp1, NetNet::WIRE,
|
||||
nex_set.count());
|
||||
for (unsigned idx = 0 ; idx < nex_out->pin_count() ; idx += 1)
|
||||
connect(nex_set[idx], nex_out->pin(idx));
|
||||
|
||||
bool flag = statement_->synth_async_noaccum(des, scope(), false, 0,
|
||||
nex_out, nex_out);
|
||||
|
||||
if (!flag) {
|
||||
delete nex_out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Connect the inports_ vectors to the input ports and detach
|
||||
the static arg ports themselves. This moves the input from
|
||||
the synthesized device from the static ports to the actual
|
||||
ports from the instance context. */
|
||||
for (unsigned idx = 0 ; idx < port_count() ; idx += 1) {
|
||||
NetNet*in = inports_[idx];
|
||||
NetNet*arg = ports_[idx];
|
||||
|
||||
in = pad_to_width(des, in, arg->pin_count());
|
||||
|
||||
for (unsigned pin = 0 ; pin < arg->pin_count() ; pin += 1) {
|
||||
connect(in->pin(pin), arg->pin(pin));
|
||||
arg->pin(pin).unlink();
|
||||
}
|
||||
}
|
||||
|
||||
/* Detach the output signal from the synthesized result. We
|
||||
use instead the nex_out that was returned from the
|
||||
synthesis of the function. This is how we account for the
|
||||
fact that the function may be synthesized multiple times to
|
||||
go into multiple expression. Each synthesis needs a unique
|
||||
output. */
|
||||
for (unsigned idx = 0 ; idx < result_sig_->pin_count() ; idx += 1)
|
||||
result_sig_->pin(idx).unlink();
|
||||
|
||||
return nex_out;
|
||||
}
|
||||
|
||||
NetNet* NetEUReduce::synthesize(Design*des)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
|
@ -811,6 +1017,7 @@ NetNet* NetETernary::synthesize(Design *des)
|
|||
|
||||
perm_string oname = csig->scope()->local_symbol();
|
||||
NetMux *mux = new NetMux(csig->scope(), oname, width, 2, 1);
|
||||
mux->set_line(*this);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
connect(tsig->pin(idx), mux->pin_Data(idx, 1));
|
||||
connect(fsig->pin(idx), mux->pin_Data(idx, 0));
|
||||
|
|
@ -854,6 +1061,21 @@ NetNet* NetETernary::synthesize(Design *des)
|
|||
*/
|
||||
NetNet* NetESignal::synthesize(Design*des)
|
||||
{
|
||||
if (warn_unused) {
|
||||
if (net_->peek_lref() == 0 && net_->type()==NetNet::REG) {
|
||||
cerr << get_line() << ": warning: "
|
||||
<< "reg " << net_->name()
|
||||
<< " is used by logic but never assigned." << endl;
|
||||
}
|
||||
|
||||
if (net_->peek_lref() == 0 && net_->type()==NetNet::INTEGER) {
|
||||
cerr << get_line() << ": warning: "
|
||||
<< "reg " << net_->name()
|
||||
<< " is used by logic but never assigned." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is no part select, then the synthesis is trivial. */
|
||||
if ((lsi_ == 0) && (msi_ == (net_->pin_count() - 1)))
|
||||
return net_;
|
||||
|
||||
|
|
@ -866,6 +1088,7 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
perm_string name = scope->local_symbol();
|
||||
NetNet*tmp = new NetNet(scope, name, NetNet::WIRE, wid);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), net_->pin(idx+lsi_));
|
||||
|
|
@ -875,6 +1098,39 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.59.2.11 2007/02/26 19:51:38 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.59.2.10 2006/11/26 01:54:05 steve
|
||||
* Add synthesis of user defined functions.
|
||||
*
|
||||
* Revision 1.59.2.9 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.59.2.8 2006/06/15 01:57:26 steve
|
||||
* Handle simple memory addressing in expression synthesis.
|
||||
*
|
||||
* Revision 1.59.2.7 2006/06/14 03:02:54 steve
|
||||
* synthesis for NetEBitSel.
|
||||
*
|
||||
* Revision 1.59.2.6 2006/06/12 00:16:52 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.59.2.5 2006/05/15 03:55:22 steve
|
||||
* Fix synthesis of expressions with land of vectors.
|
||||
*
|
||||
* Revision 1.59.2.4 2006/04/10 03:43:39 steve
|
||||
* Exploded memories accessed by constant indices.
|
||||
*
|
||||
* Revision 1.59.2.3 2006/03/16 05:39:20 steve
|
||||
* Right shifts really are allowed.
|
||||
*
|
||||
* Revision 1.59.2.2 2005/09/11 02:56:37 steve
|
||||
* Attach line numbers to NetMux devices.
|
||||
*
|
||||
* Revision 1.59.2.1 2005/02/19 16:39:31 steve
|
||||
* Spellig fixes.
|
||||
*
|
||||
* Revision 1.59 2004/06/30 02:16:26 steve
|
||||
* Implement signed divide and signed right shift in nets.
|
||||
*
|
||||
|
|
@ -883,82 +1139,5 @@ NetNet* NetESignal::synthesize(Design*des)
|
|||
*
|
||||
* Revision 1.57 2004/06/12 15:00:02 steve
|
||||
* Support / and % in synthesized contexts.
|
||||
*
|
||||
* Revision 1.56 2004/06/01 01:04:57 steve
|
||||
* Fix synthesis method for logical and/or
|
||||
*
|
||||
* Revision 1.55 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.54 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.53 2004/02/15 04:23:48 steve
|
||||
* Fix evaluation of compare to constant expression.
|
||||
*
|
||||
* Revision 1.52 2003/11/10 19:39:20 steve
|
||||
* Remove redundant scope tokens.
|
||||
*
|
||||
* Revision 1.51 2003/10/27 06:04:21 steve
|
||||
* More flexible width handling for synthesized add.
|
||||
*
|
||||
* Revision 1.50 2003/09/26 02:44:27 steve
|
||||
* Assure ternary arguments are wide enough.
|
||||
*
|
||||
* Revision 1.49 2003/09/03 23:31:36 steve
|
||||
* Support synthesis of constant downshifts.
|
||||
*
|
||||
* Revision 1.48 2003/08/28 04:11:18 steve
|
||||
* Spelling patch.
|
||||
*
|
||||
* Revision 1.47 2003/08/09 03:23:40 steve
|
||||
* Add support for IVL_LPM_MULT device.
|
||||
*
|
||||
* Revision 1.46 2003/07/26 03:34:42 steve
|
||||
* Start handling pad of expressions in code generators.
|
||||
*
|
||||
* Revision 1.45 2003/06/24 01:38:02 steve
|
||||
* Various warnings fixed.
|
||||
*
|
||||
* Revision 1.44 2003/04/19 04:52:56 steve
|
||||
* Less picky about expression widths while synthesizing ternary.
|
||||
*
|
||||
* Revision 1.43 2003/04/08 05:07:15 steve
|
||||
* Detect constant shift distances in synthesis.
|
||||
*
|
||||
* Revision 1.42 2003/04/08 04:33:55 steve
|
||||
* Synthesize shift expressions.
|
||||
*
|
||||
* Revision 1.41 2003/03/06 00:28:41 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.40 2003/02/26 01:29:24 steve
|
||||
* LPM objects store only their base names.
|
||||
*
|
||||
* Revision 1.39 2003/01/30 16:23:07 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.38 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Revision 1.35 2002/07/07 22:31:39 steve
|
||||
* Smart synthesis of binary AND expressions.
|
||||
*
|
||||
* Revision 1.34 2002/07/05 21:26:17 steve
|
||||
* Avoid emitting to vvp local net symbols.
|
||||
*
|
||||
* Revision 1.33 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*/
|
||||
|
||||
|
|
|
|||
13
functor.cc
13
functor.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.cc,v 1.32 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: functor.cc,v 1.32.2.1 2006/04/23 04:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -79,6 +79,9 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
|
|||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_ram_dq(class Design*, class NetRamDq*)
|
||||
{
|
||||
}
|
||||
|
||||
void NetScope::run_functor(Design*des, functor_t*fun)
|
||||
{
|
||||
|
|
@ -206,6 +209,11 @@ void NetMux::functor_node(Design*des, functor_t*fun)
|
|||
fun->lpm_mux(des, this);
|
||||
}
|
||||
|
||||
void NetRamDq::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_ram_dq(des, this);
|
||||
}
|
||||
|
||||
proc_match_t::~proc_match_t()
|
||||
{
|
||||
}
|
||||
|
|
@ -267,6 +275,9 @@ int proc_match_t::event_wait(NetEvWait*)
|
|||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.32.2.1 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.32 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.h,v 1.20 2002/08/12 01:34:59 steve Exp $"
|
||||
#ident "$Id: functor.h,v 1.20.2.1 2006/04/23 04:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -77,6 +77,9 @@ struct functor_t {
|
|||
|
||||
/* This method is called for each MUX. */
|
||||
virtual void lpm_mux(class Design*des, class NetMux*);
|
||||
|
||||
/* This is called for eacm RamDq device. */
|
||||
virtual void lpm_ram_dq(class Design*des, class NetRamDq*);
|
||||
};
|
||||
|
||||
struct proc_match_t {
|
||||
|
|
@ -92,6 +95,9 @@ struct proc_match_t {
|
|||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.20.2.1 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@ first source file is named \fIfoo.c\fP, the output becomes
|
|||
Include the named library in the link of the VPI module. This allows
|
||||
VPI modules to further reference external libraries.
|
||||
|
||||
.TP 8
|
||||
.B -I\fIdirectory\fP
|
||||
Add \fIdirectory\fP to the list of directories that will be search for
|
||||
header files.
|
||||
|
||||
.TP 8
|
||||
.B -D\fIdefine\fP
|
||||
Define a macro named \fIdefine\fP.
|
||||
|
||||
.TP 8
|
||||
.B --name=\fIname\fP
|
||||
Normally, the output VPI module will be named after the first source
|
||||
|
|
@ -39,6 +48,10 @@ This flag causes the program to print the install directory for VPI
|
|||
modules, then exit. It is a convenience for makefiles or automated
|
||||
plug-in installers.
|
||||
|
||||
.TP 8
|
||||
.B --cflags, --ldflags and -ldlibs
|
||||
These flags provide compile time information.
|
||||
|
||||
.SH "PC-ONLY OPTIONS"
|
||||
|
||||
The PC port of \fIiverilog-vpi\fP includes two special flags needed to
|
||||
|
|
|
|||
|
|
@ -17,19 +17,20 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.14 2004/05/20 00:40:34 steve Exp $"
|
||||
|
||||
# These are the variables used for compiling files
|
||||
CC=gcc
|
||||
CXX=gcc
|
||||
CFLAGS="@PIC@ -O -I@INCLUDEDIR@"
|
||||
CC=@IVCC@
|
||||
CXX=@IVCXX@
|
||||
CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
|
||||
|
||||
SUFFIX=@SUFFIX@
|
||||
|
||||
# These are used for linking...
|
||||
LD=gcc
|
||||
LD=$CC
|
||||
LDFLAGS32="@SHARED@ -L@LIBDIR@"
|
||||
LDFLAGS64="@SHARED@ -L@LIBDIR64@"
|
||||
LDFLAGS="$LDFLAGS64"
|
||||
LDLIBS="-lveriuser -lvpi"
|
||||
LDLIBS="-lveriuser$SUFFIX -lvpi$SUFFIX"
|
||||
|
||||
INSTDIR64="@VPIDIR1@"
|
||||
INSTDIR32="@VPIDIR2@"
|
||||
|
|
@ -46,6 +47,7 @@ OBJ=
|
|||
LIB=
|
||||
OUT=
|
||||
INCOPT=
|
||||
DEFS=
|
||||
|
||||
# --
|
||||
# parse the command line switches. This collects the source files
|
||||
|
|
@ -63,11 +65,19 @@ do
|
|||
;;
|
||||
|
||||
*.cc) CXSRC="$CXSRC $parm"
|
||||
LD=$CXX
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .cc`
|
||||
fi
|
||||
;;
|
||||
|
||||
*.cpp) CXSRC="$CXSRC $parm"
|
||||
LD=$CXX
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .cpp`
|
||||
fi
|
||||
;;
|
||||
|
||||
*.o) OBJ="$OBJ $parm"
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .o`
|
||||
|
|
@ -82,7 +92,9 @@ do
|
|||
;;
|
||||
|
||||
-I*) INCOPT="$INCOPT $parm"
|
||||
echo "$parm"
|
||||
;;
|
||||
|
||||
-D*) DEFS="$DEFS $parm"
|
||||
;;
|
||||
|
||||
-m32) LDFLAGS="-m32 $LDFLAGS32"
|
||||
|
|
@ -106,7 +118,7 @@ do
|
|||
;;
|
||||
|
||||
--install-dir)
|
||||
echo "@LIBDIR@/ivl/$INSTDIR"
|
||||
echo "@LIBDIR@/ivl$SUFFIX/$INSTDIR"
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
|
@ -130,7 +142,7 @@ do
|
|||
obj=$base".o"
|
||||
|
||||
echo "Compiling $src..."
|
||||
$CC -c -o $obj $CFLAGS $INCOPT $src || compile_errors=`expr $compile_errors + 1`
|
||||
$CC -c -o $obj $DEFS $CFLAGS $INCOPT $src || compile_errors=`expr $compile_errors + 1`
|
||||
OBJ="$OBJ $obj"
|
||||
done
|
||||
|
||||
|
|
@ -140,13 +152,13 @@ do
|
|||
obj=$base".o"
|
||||
|
||||
echo "Compiling $src..."
|
||||
$CXX -c -o $obj $CFLAGS $INCOPT $src || compile_errors=`expr $compile_errors + 1`
|
||||
$CXX -c -o $obj $DEFS $CFLAGS $INCOPT $src || compile_errors=`expr $compile_errors + 1`
|
||||
OBJ="$OBJ $obj"
|
||||
done
|
||||
|
||||
if test $compile_errors -gt 0
|
||||
then
|
||||
echo "Some ($compile_errors) files failed to compile."
|
||||
echo "$0: $compile_errors file(s) failed to compile."
|
||||
exit $compile_errors
|
||||
fi
|
||||
|
||||
|
|
|
|||
3
ivl.def
3
ivl.def
|
|
@ -62,12 +62,15 @@ ivl_logic_udp
|
|||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
ivl_lpm_attr_cnt
|
||||
ivl_lpm_attr_val
|
||||
ivl_lpm_basename
|
||||
ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
ivl_lpm_datab
|
||||
ivl_lpm_data2
|
||||
ivl_lpm_data2_width
|
||||
ivl_lpm_decode
|
||||
ivl_lpm_define
|
||||
ivl_lpm_enable
|
||||
ivl_lpm_memory
|
||||
|
|
|
|||
114
ivl_target.h
114
ivl_target.h
|
|
@ -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.126 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.126.2.5 2006/04/16 19:26:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -226,8 +226,11 @@ typedef enum ivl_lpm_type_e {
|
|||
IVL_LPM_CMP_GE = 1,
|
||||
IVL_LPM_CMP_GT = 2,
|
||||
IVL_LPM_CMP_NE = 11,
|
||||
IVL_LPM_DECODE = 15,
|
||||
IVL_LPM_DEMUX = 16,
|
||||
IVL_LPM_DIVIDE = 12,
|
||||
IVL_LPM_FF = 3,
|
||||
IVL_LPM_LATCH = 17,
|
||||
IVL_LPM_MOD = 13,
|
||||
IVL_LPM_MULT = 4,
|
||||
IVL_LPM_MUX = 5,
|
||||
|
|
@ -629,6 +632,11 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* the LPM type, but it generally has to do with the width of the
|
||||
* output data path.
|
||||
*
|
||||
* ivl_lpm_attr_cnt
|
||||
* ivl_lpm_attr_val
|
||||
* These functions access attributes attached to LPM devices. These
|
||||
* attributes may be explicit attributes collected from the Verilog
|
||||
* source, or implicit attributes generated by the compiler.
|
||||
*
|
||||
* These functions apply to a subset of the LPM devices, or may have
|
||||
* varying meaning depending on the device:
|
||||
|
|
@ -642,13 +650,18 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* Return the input data nexus for device types that have a second
|
||||
* input vector. For example, arithmetic devices are like this.
|
||||
*
|
||||
* ivl_lpm_decode
|
||||
* Return the DECODER associated with this LPM_FF device. The
|
||||
* decoder for a FF takes an input address and generates an enable
|
||||
* input for no more then 1 bit (can be none) of the FF device.
|
||||
*
|
||||
* ivl_lpm_q
|
||||
* Return the output data nexus for device types that have a single
|
||||
* output vector. This is most devices, it turns out.
|
||||
*
|
||||
* ivl_lpm_selects
|
||||
* This is the size of the select input for a LPM_MUX device, or the
|
||||
* address bus width of an LPM_RAM.
|
||||
* This is the size of the select input for a LPM_MUX or LPM_DECODE
|
||||
* device, or the address bus width of an LPM_RAM.
|
||||
*
|
||||
* ivl_lpm_signed
|
||||
* Arithmetic LPM devices may be signed or unsigned if there is a
|
||||
|
|
@ -658,6 +671,64 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
|||
* In addition to a width, some devices have a size. The size is
|
||||
* often the number of inputs per out, i.e., the number of inputs
|
||||
* per bit for a MUX.
|
||||
*
|
||||
* SEMANTIC NOTES:
|
||||
*
|
||||
* - IVL_LPM_FF
|
||||
* The IVL_LPM_FF and IVL_LPM_DECODE devices are closely related. If
|
||||
* the ivl_lpm_decode function returns a non-nil value, then the
|
||||
* decoder represents an extra ENABLE-like input, where exactly <N>
|
||||
* bits of the width of the FF is enabled. The ivl_lpm_width of the
|
||||
* decoder defines <N>.
|
||||
*
|
||||
* The decoder inputs are the address that selects the FF to be
|
||||
* enabled, and the ivl_lpm_selects for the decoder gives the width of
|
||||
* the address. The address of the LSB of the memory, then, is the
|
||||
* word width times the input address. For a simple l-value bit
|
||||
* select, the word width <N> will be 1, and the address goes directly
|
||||
* to the bit. Otherwise, <N>*address gets to the first bit of the word.
|
||||
*
|
||||
* The core compiler generates these attributes in certain cases:
|
||||
*
|
||||
* - ivl:clock_polarity
|
||||
* If present, the string value can be "INVERT". That indicates
|
||||
* that the clock is negedge sensitive instead of the default
|
||||
* posedge sensitive.
|
||||
*
|
||||
* - IVL_LPM_RAM
|
||||
* The IVL_LPM_RAM may also appear as a READ port for a FF array. In
|
||||
* this case, the IVL_LPM_RAM device has an ivl_lpm_width that is the
|
||||
* width of the word, and an ivl_lpm_size that is the number of words
|
||||
* in the array. In effect, the IVL_LPM_RAM reorganizes a vector into
|
||||
* an array of words. If this is happening, then the ivl_lpm_memory
|
||||
* will return 0.
|
||||
*
|
||||
* The ivl_lpm_q function gets the output nexa of the read port. The
|
||||
* "q" port has as many bits as the width. The ivl_lpm_data2 function
|
||||
* gets the nexa of the input, with the sdx the word address and the
|
||||
* idx the bit within the word.
|
||||
*
|
||||
* - IVL_LPM_DEMUX
|
||||
* This device is a form of bit replacement. The device has a data bus
|
||||
* width (ivl_lpm_width) and an address width. The Data outputs are
|
||||
* ivl_lpm_q and have the data bus width. The ivl_lpm_data functions are
|
||||
* inputs to the device. Normally, the device passes the data inputs
|
||||
* through to the Q output.
|
||||
*
|
||||
* The IVL_LPM_DEMUX also has a size (ivl_lpm_size) which is the
|
||||
* number of addressable units in the device. If the device is bit-
|
||||
* addressable, then the size is the same as the width. I.e. if
|
||||
* ivl_lpm_width == ivl_lpm_size, then the address selects a single
|
||||
* bit. If ivl_lpm_width/ivl_lpm_size == 8, then the address selects
|
||||
* words of 8 bits and there are ivl_lpm_size of them. The
|
||||
* ivl_lpm_width will always be an exact multiple of
|
||||
* ivl_lpm_size. This is slightly different from the meaning of width
|
||||
* in memory ports, but reflects that the DEMUX manipulates fixed
|
||||
* width ranges within a single vector.
|
||||
*
|
||||
* The ivl_lpm_select inputs address a bit of the device. The
|
||||
* addressed bit is substituted by the replacement bit. This
|
||||
* replacement bit comes from the ivl_lpm_datab(net,0) nexus.
|
||||
*/
|
||||
|
||||
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
|
||||
|
|
@ -667,6 +738,9 @@ extern int ivl_lpm_signed(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);
|
||||
|
||||
extern unsigned ivl_lpm_attr_cnt(ivl_lpm_t net);
|
||||
extern ivl_attribute_t ivl_lpm_attr_val(ivl_lpm_t net, unsigned idx);
|
||||
|
||||
/* 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);
|
||||
|
|
@ -676,26 +750,31 @@ extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
|
|||
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_LATCH */
|
||||
extern ivl_nexus_t ivl_lpm_gate( ivl_lpm_t netPtr );
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT */
|
||||
/* IVL_LPM_RAM IVL_LPM_SUB IVL_LPM_LATCH */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_MUX IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
/* IVL_LPM_ADD IVL_LPM_DEMUX IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC IVL_LPM_LATCH */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
|
||||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX IVL_LPM_DECODE IVL_LPM_DEMUX IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX */
|
||||
/* IVL_LPM_DEMUX, IVL_LPM_MUX, IVL_LPM_RAM */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
/* IVL_LPM_RAM */
|
||||
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
|
|
@ -1236,6 +1315,21 @@ _END_DECL
|
|||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.126.2.5 2006/04/16 19:26:37 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.126.2.4 2006/03/26 23:09:22 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.126.2.3 2006/03/12 07:34:16 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.126.2.2 2006/02/25 05:03:28 steve
|
||||
* Add support for negedge FFs by using attributes.
|
||||
*
|
||||
* Revision 1.126.2.1 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.126 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
@ -63,16 +63,16 @@ lexor.c: lexor.lex
|
|||
parse.h parse.c: parse.y
|
||||
bison --verbose -t -d -o parse.c $(srcdir)/parse.y
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivlpp
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/ivlpp
|
||||
|
||||
$(libdir)/ivl/ivlpp: ivlpp
|
||||
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp
|
||||
$(libdir)/ivl$(suffix)/ivlpp@EXEEXT@: ivlpp@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl$(suffix)
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/ivlpp
|
||||
rm -f $(libdir)/ivl$(suffix)/ivlpp@EXEEXT@
|
||||
|
||||
lexor.o: lexor.c parse.h globals.h
|
||||
main.o: main.c globals.h
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ valid options include:
|
|||
Predefine the symbol ``name'' to have the specified
|
||||
value. If the value is not specified, then ``1'' is
|
||||
used. This is mostly of use for controlling conditional
|
||||
compilaiton.
|
||||
compilation.
|
||||
|
||||
This option does *not* override existing `define
|
||||
directives in the source file.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.46 2004/09/10 00:15:45 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.46.2.1 2007/05/25 18:35:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -93,7 +93,7 @@ static void ifdef_enter(void)
|
|||
|
||||
cur = (struct ifdef_stack_t*)
|
||||
calloc(1, sizeof(struct ifdef_stack_t));
|
||||
cur->path = strdup(istack->path);
|
||||
if (istack->path) cur->path = strdup(istack->path);
|
||||
cur->lineno = istack->lineno;
|
||||
cur->next = ifdef_stack;
|
||||
ifdef_stack = cur;
|
||||
|
|
@ -108,7 +108,10 @@ static void ifdef_leave(void)
|
|||
cur = ifdef_stack;
|
||||
ifdef_stack = cur->next;
|
||||
|
||||
if (strcmp(istack->path,cur->path) != 0) {
|
||||
/* If either path is from a non-file context e.g.(macro expansion)
|
||||
* we assume that the non-file part is from this file. */
|
||||
if (istack->path != NULL && cur->path != NULL &&
|
||||
strcmp(istack->path,cur->path) != 0) {
|
||||
fprintf(stderr, "%s:%u: warning: "
|
||||
"This `endif matches an ifdef in another file.\n",
|
||||
istack->path, istack->lineno);
|
||||
|
|
@ -142,6 +145,7 @@ static int comment_enter = 0;
|
|||
%x PPINCLUDE
|
||||
%x PPDEFINE
|
||||
%x CCOMMENT
|
||||
%x IFCCOMMENT
|
||||
%x PCOMENT
|
||||
%x CSTRING
|
||||
%x ERROR_LINE
|
||||
|
|
@ -309,11 +313,37 @@ W [ \t\b\f]+
|
|||
yy_push_state(IFDEF_SUPR);
|
||||
}
|
||||
|
||||
<IFDEF_TRUE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
BEGIN(IFDEF_SUPR);
|
||||
}
|
||||
<IFDEF_FALSE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char*name = strchr(yytext, '`');
|
||||
assert(name);
|
||||
name += 6;
|
||||
name += strspn(name, " \t\b\f");
|
||||
|
||||
if (is_defined(name)) {
|
||||
BEGIN(IFDEF_TRUE);
|
||||
} else {
|
||||
BEGIN(IFDEF_FALSE);
|
||||
}
|
||||
}
|
||||
<IFDEF_SUPR>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { }
|
||||
|
||||
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
|
||||
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>`else { }
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>"//"[^\r\n]* { }
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>"/*" { comment_enter = YY_START; BEGIN(IFCCOMMENT); }
|
||||
<IFCCOMMENT>[^\r\n] { }
|
||||
<IFCCOMMENT>\n\r { istack->lineno += 1; }
|
||||
<IFCCOMMENT>\r\n { istack->lineno += 1; }
|
||||
<IFCCOMMENT>\n { istack->lineno += 1; }
|
||||
<IFCCOMMENT>\r { istack->lineno += 1; }
|
||||
<IFCCOMMENT>"*/" { BEGIN(comment_enter); }
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>[^\r\n] { }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>\n\r { istack->lineno += 1; fputc('\n', yyout); }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>\r\n { istack->lineno += 1; fputc('\n', yyout); }
|
||||
|
|
@ -322,8 +352,44 @@ W [ \t\b\f]+
|
|||
|
||||
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif { ifdef_leave(); yy_pop_state(); }
|
||||
|
||||
`ifdef {
|
||||
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`ifndef {
|
||||
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`elsif {
|
||||
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`else {
|
||||
fprintf(stderr, "%s:%u: `else without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`endif {
|
||||
fprintf(stderr, "%s:%u: `endif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
|
@ -854,6 +920,7 @@ void reset_lexor(FILE*out, char*paths[])
|
|||
isp->path = strdup(paths[0]);
|
||||
isp->file = fopen(paths[0], "r");
|
||||
isp->str = 0;
|
||||
isp->lineno = 0;
|
||||
if (isp->file == 0) {
|
||||
perror(paths[0]);
|
||||
exit(1);
|
||||
|
|
@ -876,8 +943,10 @@ void reset_lexor(FILE*out, char*paths[])
|
|||
for (idx = 1 ; paths[idx] ; idx += 1) {
|
||||
isp = malloc(sizeof(struct include_stack_t));
|
||||
isp->path = strdup(paths[idx]);
|
||||
isp->file = 0;
|
||||
isp->str = 0;
|
||||
isp->next = 0;
|
||||
isp->lineno = 0;
|
||||
if (tail)
|
||||
tail->next = isp;
|
||||
else
|
||||
|
|
|
|||
14
ivlpp/main.c
14
ivlpp/main.c
|
|
@ -17,10 +17,11 @@ const char COPYRIGHT[] =
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.20 2004/09/10 00:15:45 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.20.2.1 2006/06/27 01:37:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "version.h"
|
||||
|
||||
const char NOTICE[] =
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
|
|
@ -38,8 +39,6 @@ const char NOTICE[] =
|
|||
" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA\n"
|
||||
;
|
||||
|
||||
const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
|
|
@ -126,8 +125,8 @@ int main(int argc, char*argv[])
|
|||
int opt, idx;
|
||||
const char*flist_path = 0;
|
||||
unsigned flag_errors = 0;
|
||||
char*out_path = 0;
|
||||
char *dep_path = NULL;
|
||||
const char*out_path = 0;
|
||||
const char*dep_path = NULL;
|
||||
FILE*out;
|
||||
|
||||
/* Define preprocessor keywords that I plan to just pass. */
|
||||
|
|
@ -213,7 +212,7 @@ int main(int argc, char*argv[])
|
|||
break;
|
||||
|
||||
case 'v':
|
||||
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n",
|
||||
fprintf(stderr, "Icarus Verilog Preprocessor version %s\n\n",
|
||||
VERSION);
|
||||
fprintf(stderr, "%s\n", COPYRIGHT);
|
||||
fputs(NOTICE, stderr);
|
||||
|
|
@ -290,6 +289,9 @@ int main(int argc, char*argv[])
|
|||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.20.2.1 2006/06/27 01:37:14 steve
|
||||
* Fix const/non-const warnings.
|
||||
*
|
||||
* Revision 1.20 2004/09/10 00:15:45 steve
|
||||
* Remove bad casts.
|
||||
*
|
||||
|
|
|
|||
55
lexor.lex
55
lexor.lex
|
|
@ -1,4 +1,6 @@
|
|||
|
||||
%option never-interactive
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
|
|
@ -19,7 +21,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.86 2004/06/13 04:56:54 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.86.2.4 2007/02/09 05:29:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -90,6 +92,7 @@ static int dec_buf_div2(char *buf);
|
|||
static void process_timescale(const char*txt);
|
||||
|
||||
static int comment_enter;
|
||||
static bool in_module = false;
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
|
|
@ -99,6 +102,7 @@ static int comment_enter;
|
|||
%s UDPTABLE
|
||||
%x PPTIMESCALE
|
||||
%x PPDEFAULT_NETTYPE
|
||||
%s EDGES
|
||||
|
||||
W [ \t\b\f\r]+
|
||||
|
||||
|
|
@ -156,11 +160,12 @@ W [ \t\b\f\r]+
|
|||
with "*" and return that. */
|
||||
"(*"{W}*")" { return '*'; }
|
||||
|
||||
|
||||
<EDGES>"]" { BEGIN(0); return yytext[0]; }
|
||||
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
|
||||
|
||||
\" { BEGIN(CSTRING); }
|
||||
<CSTRING>\\\" { yymore(); }
|
||||
<CSTRING>\\\\ { yymore(); /* Catch \\, which is a \ escaping itself */ }
|
||||
<CSTRING>\\\" { yymore(); /* Catch \", which is an escaped quote */ }
|
||||
<CSTRING>\n { BEGIN(0);
|
||||
yylval.text = strdup(yytext);
|
||||
VLerror(yylloc, "Missing close quote of string.");
|
||||
|
|
@ -179,6 +184,8 @@ W [ \t\b\f\r]+
|
|||
<UDPTABLE>\(01\) { return 'r'; }
|
||||
<UDPTABLE>\(0[xX]\) { return 'Q'; }
|
||||
<UDPTABLE>\(b[xX]\) { return 'q'; }
|
||||
<UDPTABLE>\(b0\) { return 'f'; /* b0 is 10|00, but only 10 is meaningful */}
|
||||
<UDPTABLE>\(b1\) { return 'r'; /* b1 is 11|01, but only 01 is meaningful */}
|
||||
<UDPTABLE>\(0\?\) { return 'P'; }
|
||||
<UDPTABLE>\(10\) { return 'f'; }
|
||||
<UDPTABLE>\(1[xX]\) { return 'M'; }
|
||||
|
|
@ -196,14 +203,42 @@ W [ \t\b\f\r]+
|
|||
<UDPTABLE>[pP] { return 'p'; }
|
||||
<UDPTABLE>[01\?\*\-] { return yytext[0]; }
|
||||
|
||||
<EDGES>"01" { return K_edge_descriptor; }
|
||||
<EDGES>"0x" { return K_edge_descriptor; }
|
||||
<EDGES>"0z" { return K_edge_descriptor; }
|
||||
<EDGES>"10" { return K_edge_descriptor; }
|
||||
<EDGES>"1x" { return K_edge_descriptor; }
|
||||
<EDGES>"1z" { return K_edge_descriptor; }
|
||||
<EDGES>"x0" { return K_edge_descriptor; }
|
||||
<EDGES>"x1" { return K_edge_descriptor; }
|
||||
<EDGES>"z0" { return K_edge_descriptor; }
|
||||
<EDGES>"z1" { return K_edge_descriptor; }
|
||||
|
||||
[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
int rc = lexor_keyword_code(yytext, yyleng);
|
||||
if (rc == IDENTIFIER) {
|
||||
switch (rc) {
|
||||
case IDENTIFIER:
|
||||
yylval.text = strdup(yytext);
|
||||
if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
|
||||
rc = PATHPULSE_IDENTIFIER;
|
||||
} else {
|
||||
break;
|
||||
|
||||
case K_edge:
|
||||
BEGIN(EDGES);
|
||||
break;
|
||||
|
||||
case K_module:
|
||||
case K_macromodule:
|
||||
in_module = true;
|
||||
break;
|
||||
|
||||
case K_endmodule:
|
||||
in_module = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
yylval.text = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
@ -262,6 +297,12 @@ W [ \t\b\f\r]+
|
|||
^{W}?`timescale { BEGIN(PPTIMESCALE); }
|
||||
<PPTIMESCALE>.* { process_timescale(yytext); }
|
||||
<PPTIMESCALE>\n {
|
||||
if (in_module) {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line << ": error: "
|
||||
"`timescale directive can not be inside a module "
|
||||
"definition." << endl;
|
||||
error_count += 1;
|
||||
}
|
||||
yylloc.first_line += 1;
|
||||
BEGIN(0); }
|
||||
|
||||
|
|
@ -276,10 +317,10 @@ W [ \t\b\f\r]+
|
|||
^{W}?`disable_portfaults{W}?.* { }
|
||||
^{W}?`enable_portfaults{W}?.* { }
|
||||
^{W}?`endcelldefine{W}?.* { }
|
||||
^{W}?`endprotect{W}?.* { }
|
||||
`endprotect { }
|
||||
^{W}?`nosuppress_faults{W}?.* { }
|
||||
^{W}?`nounconnected_drive{W}?.* { }
|
||||
^{W}?`protect{W}?.* { }
|
||||
`protect { }
|
||||
^{W}?`resetall{W}?.* { }
|
||||
^{W}?`suppress_faults{W}?.* { }
|
||||
^{W}?`unconnected_drive{W}?.* { }
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ function, K_function
|
|||
highz0, K_highz0
|
||||
highz1, K_highz1
|
||||
if, K_if
|
||||
ifnone, K_ifnone
|
||||
initial, K_initial
|
||||
inout, K_inout
|
||||
input, K_input
|
||||
|
|
|
|||
|
|
@ -16,11 +16,12 @@
|
|||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.34 2004/10/04 01:10:07 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.34.2.1 2005/02/23 18:40:24 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
@ -93,17 +94,18 @@ clean:
|
|||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
|
||||
install:: all installdirs $(libdir64)/libveriuser$(suffix).a $(INSTALL32)
|
||||
|
||||
$(libdir64)/libveriuser.a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(libdir64)/libveriuser.a
|
||||
$(libdir64)/libveriuser$(suffix).a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(libdir64)/libveriuser$(suffix).a
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir64)
|
||||
|
||||
uninstall::
|
||||
rm -f $(libdir64)/libveriuser.a
|
||||
rm -f $(libdir64)/libveriuser$(suffix).a
|
||||
|
||||
ifeq (@enable_vvp32@,yes)
|
||||
all32: bin32 bin32/libveriuser.a
|
||||
|
|
@ -122,10 +124,13 @@ bin32/libveriuser.a: bin32/libveriuser.o
|
|||
ar cvq $@ bin32/libveriuser.o
|
||||
$(RANLIB) $@
|
||||
|
||||
install32: $(libdir)/libveriuser.a
|
||||
install32: $(libdir)/libveriuser$(suffix).a
|
||||
|
||||
$(libdir)/libveriuser.a: bin32/libveriuser.a
|
||||
$(INSTALL_DATA) bin32/libveriuser.a $(libdir)/libveriuser.a
|
||||
$(libdir)/libveriuser$(suffix).a: bin32/libveriuser.a
|
||||
$(INSTALL_DATA) bin32/libveriuser.a $(libdir)/libveriuser$(suffix).a
|
||||
|
||||
uninstall::
|
||||
rm -f $(DESTDIR)$(libdir)/libveriuser$(suffix).a
|
||||
|
||||
-include $(patsubst bin32/%.o, bin32/%.d, $(addprefix bin32/,$O))
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
|
|||
|
||||
/* trace */
|
||||
if (pli_trace) {
|
||||
int *ip;
|
||||
PLI_INT32 *ip;
|
||||
fprintf(pli_trace, "acc_next(%p <", type);
|
||||
for (ip = type; *ip; ip++) {
|
||||
fprintf(pli_trace, "%s%d", ip != type ? "," : "", *ip);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
AC_INIT(Makefile.in)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
|
|
@ -12,6 +14,8 @@ AX_CPP_IDENT
|
|||
#enable_vvp32=no
|
||||
AC_SUBST(enable_vvp32)
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
|
|
@ -21,7 +25,7 @@ AC_CHECK_SIZEOF(unsigned)
|
|||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
AC_SUBST(EXEEXT)
|
||||
|
|
|
|||
|
|
@ -44,9 +44,9 @@ typedef struct t_pli_data {
|
|||
int paramvc; /* parameter number for misctf */
|
||||
} s_pli_data, *p_pli_data;
|
||||
|
||||
static int compiletf(char *);
|
||||
static int calltf(char *);
|
||||
static int callback(p_cb_data);
|
||||
static PLI_INT32 compiletf(char *);
|
||||
static PLI_INT32 calltf(char *);
|
||||
static PLI_INT32 callback(p_cb_data);
|
||||
|
||||
/*
|
||||
* Register veriusertfs routines/wrappers. Iterate over the tfcell
|
||||
|
|
@ -109,7 +109,7 @@ void veriusertfs_register_table(p_tfcell vtable)
|
|||
tf_data.tfname = tf->tfname;
|
||||
tf_data.compiletf = compiletf;
|
||||
tf_data.calltf = calltf;
|
||||
tf_data.sizetf = tf->sizetf;
|
||||
tf_data.sizetf = (PLI_INT32 (*)(char *))tf->sizetf;
|
||||
tf_data.user_data = (char *)data;
|
||||
|
||||
if (pli_trace) {
|
||||
|
|
@ -139,7 +139,7 @@ void veriusertfs_register_table(p_tfcell vtable)
|
|||
* This function calls the veriusertfs checktf and sets up all the
|
||||
* callbacks misctf requires.
|
||||
*/
|
||||
static int compiletf(char *data)
|
||||
static PLI_INT32 compiletf(char *data)
|
||||
{
|
||||
p_pli_data pli;
|
||||
p_tfcell tf;
|
||||
|
|
@ -221,7 +221,7 @@ static int compiletf(char *data)
|
|||
/*
|
||||
* This function is the wrapper for the veriusertfs calltf routine.
|
||||
*/
|
||||
static int calltf(char *data)
|
||||
static PLI_INT32 calltf(char *data)
|
||||
{
|
||||
int rc = 0;
|
||||
p_pli_data pli;
|
||||
|
|
@ -249,7 +249,7 @@ static int calltf(char *data)
|
|||
*/
|
||||
extern int async_misctf_enable;
|
||||
|
||||
static int callback(p_cb_data data)
|
||||
static PLI_INT32 callback(p_cb_data data)
|
||||
{
|
||||
p_pli_data pli;
|
||||
p_tfcell tf;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: load_module.cc,v 1.12 2003/06/05 04:31:09 steve Exp $"
|
||||
#ident "$Id: load_module.cc,v 1.12.2.1 2005/03/22 15:53:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -31,6 +31,8 @@
|
|||
# include <dirent.h>
|
||||
# include <ctype.h>
|
||||
# include <assert.h>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
|
||||
/*
|
||||
* The module library items are maps of key names to file name within
|
||||
|
|
@ -88,7 +90,7 @@ bool load_module(const char*type)
|
|||
cerr << "Executing: " << cmdline << endl;
|
||||
|
||||
pform_parse(path, file);
|
||||
fclose(file);
|
||||
pclose(file);
|
||||
free(cmdline);
|
||||
|
||||
} else {
|
||||
|
|
@ -193,6 +195,9 @@ int build_library_index(const char*path, bool key_case_sensitive)
|
|||
|
||||
/*
|
||||
* $Log: load_module.cc,v $
|
||||
* Revision 1.12.2.1 2005/03/22 15:53:12 steve
|
||||
* popen must be matched by pclose.
|
||||
*
|
||||
* Revision 1.12 2003/06/05 04:31:09 steve
|
||||
* INclude missing assert.h in load_module.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
|
||||
Icarus Verilog for Mac OS X
|
||||
|
||||
NOTE: Icarus Verilog version 0.8 is known to compile "out of the
|
||||
box" on MacOSX 10.3. OSX 10.3 users need only the developer tools
|
||||
included with new systems or available for free download from
|
||||
Apple. Install Xcode and skip directly to step #3.
|
||||
|
||||
This file describes the procedure to build and install Icarus Verilog
|
||||
on Mac OS X. I assume that you have experience with Unix and
|
||||
Terminal.app and a basic knowledge of how to download, compile and
|
||||
|
|
|
|||
41
main.cc
41
main.cc
|
|
@ -19,7 +19,7 @@ const char COPYRIGHT[] =
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.cc,v 1.86 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.86.2.3 2006/06/12 00:16:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -59,6 +59,7 @@ const char NOTICE[] =
|
|||
# include "netlist.h"
|
||||
# include "target.h"
|
||||
# include "compiler.h"
|
||||
# include "version.h"
|
||||
|
||||
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
|
||||
extern "C" int getopt(int argc, char*argv[], const char*fmt);
|
||||
|
|
@ -75,8 +76,6 @@ extern "C" const char*optarg;
|
|||
/* Count errors detected in flag processing. */
|
||||
unsigned flag_errors = 0;
|
||||
|
||||
const char VERSION[] = "$Name: $";
|
||||
|
||||
const char*basedir = ".";
|
||||
|
||||
const char*target = "null";
|
||||
|
|
@ -103,6 +102,7 @@ FILE *depend_file = NULL;
|
|||
bool warn_implicit = false;
|
||||
bool warn_timescale = false;
|
||||
bool warn_portbinding = false;
|
||||
bool warn_unused = false;
|
||||
|
||||
bool error_implicit = false;
|
||||
|
||||
|
|
@ -112,6 +112,9 @@ bool error_implicit = false;
|
|||
bool debug_scopes = false;
|
||||
bool debug_eval_tree = false;
|
||||
bool debug_elaborate = false;
|
||||
bool debug_synth = false;
|
||||
bool debug_cprop = false;
|
||||
|
||||
/*
|
||||
* Verbose messages enabled.
|
||||
*/
|
||||
|
|
@ -132,6 +135,11 @@ const bool CASE_SENSITIVE = false;
|
|||
const bool CASE_SENSITIVE = true;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Are we doing synthesis?
|
||||
*/
|
||||
bool synthesis = false;
|
||||
|
||||
extern void cprop(Design*des);
|
||||
extern void synth(Design*des);
|
||||
extern void synth2(Design*des);
|
||||
|
|
@ -314,6 +322,12 @@ static void read_iconfig_file(const char*ipath)
|
|||
} else if (strcmp(cp,"elaborate") == 0) {
|
||||
debug_elaborate = true;
|
||||
cerr << "debug: Enable elaborate debug" << endl;
|
||||
} else if (strcmp(cp,"synth") == 0) {
|
||||
debug_synth = true;
|
||||
cerr << "debug: Enable synthesis debug" << endl;
|
||||
} else if (strcmp(cp,"cprop") == 0) {
|
||||
debug_cprop = true;
|
||||
cerr << "debug: Enable cprop debug" << endl;
|
||||
} else {
|
||||
}
|
||||
|
||||
|
|
@ -325,6 +339,9 @@ static void read_iconfig_file(const char*ipath)
|
|||
parm_to_flagmap(parm);
|
||||
|
||||
} else if (strcmp(buf,"functor") == 0) {
|
||||
if (strncmp(cp, "synth", 5) == 0) {
|
||||
synthesis = true; // We are doing synthesis.
|
||||
}
|
||||
net_func tmp = name_to_net_func(cp);
|
||||
if (tmp == 0) {
|
||||
cerr << "No such design transform function ``"
|
||||
|
|
@ -376,6 +393,9 @@ static void read_iconfig_file(const char*ipath)
|
|||
case 't':
|
||||
warn_timescale = true;
|
||||
break;
|
||||
case 'u':
|
||||
warn_unused = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -483,7 +503,7 @@ int main(int argc, char*argv[])
|
|||
# endif
|
||||
break;
|
||||
case 'V':
|
||||
cout << "Icarus Verilog version " << VERSION << endl;
|
||||
cout << "Icarus Verilog version " << VERSION << endl << endl;
|
||||
cout << COPYRIGHT << endl;
|
||||
cout << endl << NOTICE << endl;
|
||||
return 0;
|
||||
|
|
@ -496,8 +516,8 @@ int main(int argc, char*argv[])
|
|||
return flag_errors;
|
||||
|
||||
if (help_flag) {
|
||||
cout << "Icarus Verilog version " << VERSION << endl <<
|
||||
"usage: ivl <options> <file>\n"
|
||||
cout << "Icarus Verilog version " << VERSION << endl << endl <<
|
||||
"Usage: ivl <options> <file>\n"
|
||||
"options:\n"
|
||||
"\t-C <name> Config file from driver.\n"
|
||||
"\t-h Print usage information, and exit.\n"
|
||||
|
|
@ -744,6 +764,15 @@ int main(int argc, char*argv[])
|
|||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.86.2.3 2006/06/12 00:16:53 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.86.2.2 2006/04/23 04:25:45 steve
|
||||
* Add cprop debugging.
|
||||
*
|
||||
* Revision 1.86.2.1 2006/04/01 01:37:24 steve
|
||||
* Add synth debug flag
|
||||
*
|
||||
* Revision 1.86 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
217
mingw.txt
217
mingw.txt
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
MINGW PORT OF ICARUS VERILOG
|
||||
|
||||
Copyright 2003 Stephen Williams <steve@icarus.com>
|
||||
Copyright 2006 Stephen Williams <steve@icarus.com>
|
||||
|
||||
|
||||
Icarus Verilog source can be compiled with the mingw C/C++ compilers
|
||||
|
|
@ -12,13 +12,13 @@ or without Cygwin, so this is the preferred Windows distribution form.
|
|||
The configure scripts automatically detect that the compilers in use
|
||||
are the mingw compilers and will configure the Makefiles appropriately.
|
||||
|
||||
However, the mingw tools do not include all the other tools around the
|
||||
compiler, including the shell interpreter for the configure script,
|
||||
bison, flex, gperf, etc. Therefore, you still need Cygwin to compile
|
||||
Icarus Verilog, even if you don't need the Cygwin compilers. There are
|
||||
also a few precompiled library prerequisites that you need.
|
||||
The mingw patch doesn't contain tools beyond the compiler, but there
|
||||
is the "msys" package that the makers of Mingw publish that has enough
|
||||
extra tools to get most everything else working. There are a few extra
|
||||
packages needed beyond mingw and msys, and the following instructions
|
||||
explain how to get them and install them.
|
||||
|
||||
* Some Preliminary Comments
|
||||
* Some Preliminary Comments -- PLEASE READ ME --
|
||||
|
||||
The Windows port of Icarus Verilog is the most difficult of all the
|
||||
ports. The Windows system off the shelf is completely stripped, devoid
|
||||
|
|
@ -26,7 +26,15 @@ of any support for software development. Everything needed to compile
|
|||
Icarus Verilog must be collected from various sources and stitched
|
||||
together by hand. Normal human beings with a basic understanding of
|
||||
software development can do this, but some patience (and access to the
|
||||
Internet) is required. You may choose to print these instructions.
|
||||
Internet) is required. You may choose to print these instructions. FOR
|
||||
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
|
||||
|
||||
NOTE that if you have Cygwin installed, it is best to not use a cygwin
|
||||
window to do the build, as the Cygwin tools will intermix with the
|
||||
mingw tools such that it is hard to be sure you are using the right
|
||||
compiler. Thus, it is recommended that these steps be *not* done in a
|
||||
Cygwin window. Use an MSYS window instead, and be careful that your
|
||||
msys/mingw tools are not masked by paths that point to Cygwin binaries.
|
||||
|
||||
I have no plans to intentionally support MSVC++ compilation. Don't ask.
|
||||
|
||||
|
|
@ -36,13 +44,15 @@ This is a brief list of prerequisite packages, along with the URL
|
|||
where each can be found. In most cases, the specific version is not
|
||||
critical, but these are the versions I use.
|
||||
|
||||
Cygwin <http://cygwin.com>
|
||||
Mingw32-2.0.0 <http://www.mingw.org>
|
||||
msys-1.0 <http://www.mingw/org>
|
||||
msysDTK-1.0 <http://www.mingw.org>
|
||||
Mingw32-5.x <http://www.mingw.org>
|
||||
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
|
||||
bzip2-1.0.2-bin.zip <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.1.4-bin.zip <http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.2-lib.zip <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.1.4-lib.zip <http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
|
||||
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
|
||||
bison-2.1 <http://gnuwin32.sourceforge.net>
|
||||
flex-2.5.4a <http://gnuwin32.sourceforge.net>
|
||||
|
||||
The above table lists the packages required. It is convenient to
|
||||
install them in the above order. Many of these packages are also
|
||||
|
|
@ -55,59 +65,38 @@ installation of Icarus Verilog is complete. These are only needed to
|
|||
build the compiler. The Mingw32 package can be used to compile VPI
|
||||
modules if you choose.
|
||||
|
||||
* Install Cygwin
|
||||
* Install MSYS and msysDTK
|
||||
|
||||
So, step 1 is "Download and Install Cygwin." See the web page
|
||||
http://www.cygwin.com for instructions and the files to do
|
||||
this. Cygwin *is* a kool package, and is worth having anyhow. There is
|
||||
a convenient setup program that you download first. You execute the
|
||||
setup program, and that prompts you to select the package you want.
|
||||
The msys package is available from the mingw download site. This is
|
||||
not the compiler but a collection of *nix tools ported to Windows and
|
||||
wrapped in a convenient installer. The msys package is all the various
|
||||
basic tools (shells, file utils, etc) and the msysDTK is extra
|
||||
developer tools other then the compiler.
|
||||
|
||||
You need in particular the Cygwin base, bison (see notes) flex, make
|
||||
and gperf. If you are compiling from CVS, you also need cvs, rcs and
|
||||
automake packages. You will also need tar and gunzip, but these are
|
||||
hard to not install. I recommend installing the "which" package as
|
||||
well. Beyond the basics, be sure to install these Cygwin packages:
|
||||
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
|
||||
self-installing packages. Install msys first, and then msysDTC. Most
|
||||
likely, you want to install them in c:/msys. (The msysDTK is installed
|
||||
in the same location, as it is an add-on.)
|
||||
|
||||
bison (*not* 1.875. See Notes.)
|
||||
flex
|
||||
ghostscript (makes the documentation)
|
||||
gperf
|
||||
gzip
|
||||
make
|
||||
strip
|
||||
tar (tar and gunzip for unpacking the source)
|
||||
unzip (For unpacking zip compressed packages.)
|
||||
which
|
||||
This install should be easy and reliable.
|
||||
|
||||
NOTES:
|
||||
bison-1.875 is broken, it generates invalid C/C++ code. You
|
||||
don't want that version for anything you do. If you have that
|
||||
version (use "bison -V" to check the version) then use the
|
||||
Cygwin setup program to get a different version. I've downgraded
|
||||
to 1.75 and couldn't be happier. In fact, a whole host of insane
|
||||
bison bugs can be avoided that way.
|
||||
|
||||
There is a mingw32 runtime package included in the Cygwin
|
||||
distribution. You do *not* need that, as you will be getting
|
||||
everything from the mingw32 distribution itself.
|
||||
|
||||
Other then the install of mingw32, most of the remaining steps are
|
||||
best done in a Cygwin window. When you installed Cygwin, a start menu
|
||||
entry was created to allow you to start up the Cygwin window. I'll use
|
||||
the string "$ " to represent a command prompt in this window, because
|
||||
that is the usual bash prompt.
|
||||
The installation will leave an "msys" icon on your desktop and in the
|
||||
mingw sub-menu of your Start menu. This icon brings up a shell window
|
||||
(a command line) that has paths all set up for executing msys and
|
||||
mingw commands. This is what you will want to use while executing
|
||||
commands below.
|
||||
|
||||
* Install Mingw32
|
||||
|
||||
The obvious step 2, then, is install the mingw compilers. These can be
|
||||
found at the web page <http://www.mingw.org>. The Mingw-2.x.x version
|
||||
comes prepackaged in a convenient, Windows style, installer. I
|
||||
recommend you download this package instead of picking and choosing
|
||||
bits.
|
||||
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
|
||||
is a convenient remote installer. Download this program and run
|
||||
it. The installer will ask wich components you want to install. You
|
||||
need only the base C compiler and the C++ compiler. (You may install
|
||||
other languages if you wish.)
|
||||
|
||||
When I install Mingw32 (using the installer) I typically set a
|
||||
destination directory of d:\mingw-2.0.0 or the like. You will be using
|
||||
destination directory of d:\mingw or the like. You will be using
|
||||
that path later.
|
||||
|
||||
NOTES:
|
||||
|
|
@ -115,6 +104,10 @@ that path later.
|
|||
need Mingw32, even if you are using a precompiled binary. VPI
|
||||
modules only require Mingw32, and none of the other libraries.
|
||||
|
||||
Finally, as part of installing the mingw32 compilers, remember to add
|
||||
the mingw/bin directory to your path. You will need that to be able to
|
||||
find the compilers later.
|
||||
|
||||
* Install Mingw32 Packages
|
||||
|
||||
There is a collection of precompiled libraries and add-on packages
|
||||
|
|
@ -123,86 +116,94 @@ with simplified Windows installers, but they are pretty easy to
|
|||
install by hand. Icarus Verilog uses the readline-4.2 package from
|
||||
that collection.
|
||||
|
||||
Since I installed Mingw32 in d:\mingw-2.0.0, I also created a
|
||||
Mingw-packages directory called d:\mingw-packages. The install, then,
|
||||
Since I installed Mingw32 in c:\mingw, I also created a
|
||||
Mingw-packages directory called c:\mingw-packages. The install, then,
|
||||
is as easy as this:
|
||||
|
||||
<cygwin shell>
|
||||
$ cd d:/mingw-packages
|
||||
<msys shell>
|
||||
$ cd c:/mingw-packages
|
||||
$ unzip readline-4.2-20010727.zip
|
||||
[lots of inflating...]
|
||||
|
||||
There is no need to adjust your execution path for this package as we
|
||||
are only using a library out of here. However, do remember the
|
||||
directory name, as you will need it later.
|
||||
|
||||
Done. On to the next packages.
|
||||
|
||||
* Install GnuWin32 Packages
|
||||
|
||||
The GnuWin32 project is a collections of open source programs and
|
||||
libraries ported to Windows. These also work well with the Mingw
|
||||
compiler, and in fact Icarus Verilog uses a few libraries from this
|
||||
compiler, and in fact Icarus Verilog uses a few pieces from this
|
||||
collection.
|
||||
|
||||
You will need these gnuwin32 packages to compile Icarus Verilog:
|
||||
|
||||
<http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.2-lib.zip
|
||||
bzip2-1.0.2-bin.zip
|
||||
zlib-1.1.4-lib.zip
|
||||
zlib-1.1.4-bin.zip
|
||||
bzip2-1.0.3.exe
|
||||
zlib-1.2.3.exe
|
||||
gperf-3.0.1.exe
|
||||
bison-2.1.exe
|
||||
flex-2.5.4a.exe
|
||||
|
||||
I suggest creating a common directory for holding all your gnuwin32
|
||||
packages. I use D:\gnuwin32.
|
||||
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
|
||||
has a "setup" link for each of these packages. Click the setup to
|
||||
download the installer for each of the desired programes, then execute
|
||||
the downloaded .exe files to invoke the installer. Install into the
|
||||
c:\gunwin32 directory.
|
||||
|
||||
After downloading these packages, put the .zip files in your gnuwin32
|
||||
directory and install them like so:
|
||||
NOTES:
|
||||
You need the binaries and the developer files, but you do not
|
||||
need the source to these packages. The installer gives you the
|
||||
choice.
|
||||
|
||||
<cygwin shell>
|
||||
$ cd d:/gnuwin32
|
||||
$ unzip bzip2-1.0.2-bin.zip
|
||||
[lots of inflating...]
|
||||
$ unzip bzip2-1.0.2-lib.zip
|
||||
[lots of inflating...]
|
||||
$ unzip zlib-1.1.4-bin.zip
|
||||
[lots of inflating...]
|
||||
$ unzip zlib-1.1.4-lib.zip
|
||||
[lots of inflating...]
|
||||
|
||||
Done.
|
||||
After you are done installing the gnuwin32 tools, you should add the
|
||||
c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
|
||||
your Windows path. The msys shell will pick up your Windows path.
|
||||
|
||||
* Unpack Icarus Verilog source
|
||||
|
||||
Unpack the compressed tar file (.tar.gz) of the source with a command
|
||||
like this:
|
||||
|
||||
$ gunzip -d verilog-20030303.tar.gz | tar xvf -
|
||||
$ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
|
||||
|
||||
This will create a directory "verilog-20030303" that contains all the
|
||||
This will create a directory "verilog-xxxxxxxx" that contains all the
|
||||
source for Icarus Verilog. Descend into that directory, as that is
|
||||
where we will work from now on.
|
||||
|
||||
$ cd verilog-20030303
|
||||
$ cd verilog-xxxxxxxx
|
||||
|
||||
NOTE:
|
||||
NOTES:
|
||||
The exact name of the file will vary according to the
|
||||
snapshot. The 20030303 name is only an example.
|
||||
|
||||
* Select the mingw compilers
|
||||
Unpack the source into a directory that has no spaces. The
|
||||
makefiles included in the source get confused by white space in
|
||||
directory names.
|
||||
|
||||
In your cygwin window, if you type "which c++" you might get the
|
||||
response path "/usr/bin/c++" which is the cygwin compiler. This is not
|
||||
the one we want to use, however. Tell the shell where the mingw
|
||||
compilers are by setting the search path like so:
|
||||
* Preconfigure Icarus Verilog (Not normally needed)
|
||||
|
||||
$ PATH=/cygdrive/d/mingw-2.0.0/bin:$PATH
|
||||
Under certain cases, you may need to "preconfigure" the Icarus Verilog
|
||||
source tree. You should only need to do this if you are getting the
|
||||
Icarus Verilog source tree from CVS, or you are using an existing
|
||||
source tree that you've patched to cause configure.in files to change.
|
||||
|
||||
This assumes that you installed mingw in D:\mingw-2.0.0. The actual
|
||||
programs are in the bin directory under the root. After this command,
|
||||
check that you are now getting the right compilers with this "which"
|
||||
command:
|
||||
NOTE: If you are building from a fresh, bundled source tree that
|
||||
you downloaded from an FTP site, then SKIP THIS STEP. Go on to
|
||||
the "Configure Icarus Verilog" step below.
|
||||
|
||||
$ which c++
|
||||
/cygdrive/d/mingw-2.0.0/bin/c++
|
||||
First, remove any autom4te.cache directories that may exist in your
|
||||
source tree. These can make a mess of autoconf runs. Then, generate
|
||||
configure scripts with this command:
|
||||
|
||||
Good!
|
||||
$ sh autoconf.sh
|
||||
|
||||
This script will run the "autoconf" command (part of the msysDTK) to
|
||||
generate all the necessary "configure" scripts. This will take a few
|
||||
minutes. This should go smoothly.
|
||||
|
||||
* Configure Icarus Verilog
|
||||
|
||||
|
|
@ -215,10 +216,10 @@ without white space.
|
|||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run these commands:
|
||||
|
||||
$ CPPFLAGS="-Id:/gnuwin32/include -Id:/mingw-packages/include"
|
||||
$ LDFLAGS="-Ld:/gnuwin32/lib -Ld:/mingw-packages/include"
|
||||
$ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include"
|
||||
$ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib"
|
||||
$ export CPPFLAGS LDFLAGS
|
||||
$ ./configure --prefix=d:/iverilog
|
||||
$ ./configure --prefix=c:/iverilog
|
||||
|
||||
NOTES:
|
||||
The CPPFLAGS and LDFLAGS variables tell configure where
|
||||
|
|
@ -267,10 +268,10 @@ directory you chose) and away you go.
|
|||
You may find that you need to put some of the prerequisite DLLs into
|
||||
the d:\iverilog\bin directory. These include:
|
||||
|
||||
d:\mingw-2.0.0\bin\mingw10.dll
|
||||
d:\mingw-packages\bin\libreadline.dll
|
||||
d:\gnuwin32\bin\bzip2.dll
|
||||
d:\gnuwin32\bin\zlib.dll
|
||||
c:\mingw\bin\mingw10.dll
|
||||
c:\mingw-packages\bin\libreadline.dll
|
||||
c:\gnuwin32\bin\bzip2.dll
|
||||
c:\gnuwin32\bin\zlib.dll
|
||||
|
||||
If you already have these in your Windows path (i.e. your system32
|
||||
directory) then you do not need to copy them into the iverilog
|
||||
|
|
@ -279,14 +280,14 @@ files.
|
|||
|
||||
* Running Icarus Verilog
|
||||
|
||||
Finally, put the D:\iverilog\bin directory in your Windows path, and
|
||||
Finally, put the C:\iverilog\bin directory in your Windows path, and
|
||||
you should be able to run the iverilog and vvp commands to your
|
||||
heart's content.
|
||||
|
||||
Currently, the iverilog.exe uses the path to itself to locate the
|
||||
libraries and modules associated with itself. In other words, if you
|
||||
execute the D:\iverilog\bin\iverilog.exe program, it will locate its
|
||||
subparts in the D:\iverilog directory and subdirectories below
|
||||
execute the C:\iverilog\bin\iverilog.exe program, it will locate its
|
||||
subparts in the C:\iverilog directory and subdirectories below
|
||||
that. This means you can move the Icarus Verilog installation by
|
||||
simply moving the root directory and all its contents.
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_assign.cc,v 1.18 2004/08/28 15:08:31 steve Exp $"
|
||||
#ident "$Id: net_assign.cc,v 1.18.2.3 2006/05/02 02:00:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -45,6 +45,7 @@ NetAssign_::NetAssign_(NetNet*s)
|
|||
lwid_ = sig_->pin_count();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetMemory*s)
|
||||
|
|
@ -53,6 +54,7 @@ NetAssign_::NetAssign_(NetMemory*s)
|
|||
loff_ = 0;
|
||||
lwid_ = mem_->width();
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetVariable*s)
|
||||
|
|
@ -61,6 +63,7 @@ NetAssign_::NetAssign_(NetVariable*s)
|
|||
loff_ = 0;
|
||||
lwid_ = 0;
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::~NetAssign_()
|
||||
|
|
@ -71,6 +74,14 @@ NetAssign_::~NetAssign_()
|
|||
sig_->type(NetNet::WIRE);
|
||||
}
|
||||
|
||||
if (mem_) {
|
||||
NetNet*exp = mem_->reg_from_explode();
|
||||
if (exp && mem_lref_) {
|
||||
exp->decr_lref();
|
||||
if (turn_sig_to_wire_on_release_ && exp->peek_lref() == 0)
|
||||
exp->type(NetNet::WIRE);
|
||||
}
|
||||
}
|
||||
assert( more == 0 );
|
||||
if (bmux_) delete bmux_;
|
||||
}
|
||||
|
|
@ -111,7 +122,10 @@ perm_string NetAssign_::name() const
|
|||
|
||||
NetNet* NetAssign_::sig() const
|
||||
{
|
||||
return sig_;
|
||||
if (mem_)
|
||||
return 0;
|
||||
else
|
||||
return sig_;
|
||||
}
|
||||
|
||||
NetMemory* NetAssign_::mem() const
|
||||
|
|
@ -124,6 +138,16 @@ NetVariable* NetAssign_::var() const
|
|||
return var_;
|
||||
}
|
||||
|
||||
void NetAssign_::incr_mem_lref()
|
||||
{
|
||||
if (! mem_lref_) {
|
||||
assert(mem_);
|
||||
NetNet*exp = mem_->reg_from_explode();
|
||||
assert(exp);
|
||||
exp->incr_lref();
|
||||
mem_lref_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NetAssign_::set_part(unsigned lo, unsigned lw)
|
||||
{
|
||||
|
|
@ -261,6 +285,15 @@ NetAssignNB::~NetAssignNB()
|
|||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.18.2.3 2006/05/02 02:00:15 steve
|
||||
* Fix uninitialized mem_lref_ member.
|
||||
*
|
||||
* Revision 1.18.2.2 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.18.2.1 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.18 2004/08/28 15:08:31 steve
|
||||
* Do not change reg to wire in NetAssign_ unless synthesizing.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.45 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: net_design.cc,v 1.45.2.1 2006/10/04 00:34:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -33,6 +33,7 @@
|
|||
# include "util.h"
|
||||
# include "compiler.h"
|
||||
# include <sstream>
|
||||
# include <cstring>
|
||||
|
||||
Design:: Design()
|
||||
: errors(0), nodes_(0), procs_(0), lcounter_(0)
|
||||
|
|
@ -279,7 +280,7 @@ void NetScope::run_defparams(Design*des)
|
|||
continue;
|
||||
}
|
||||
|
||||
bool flag = targ_scope->replace_parameter(perm_name, val);
|
||||
bool flag = targ_scope->replace_parameter(perm_name, val->dup_expr());
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< perm_name << " not found in "
|
||||
|
|
@ -396,6 +397,7 @@ void NetScope::evaluate_parameters(Design*des)
|
|||
<< ": internal error: "
|
||||
"unable to evaluate real parameter values: " <<
|
||||
*expr << endl;
|
||||
cerr << "FYI: V0.8 cannot evaluate constant real expressions." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -422,10 +424,6 @@ void NetScope::evaluate_parameters(Design*des)
|
|||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.expr = nexpr;
|
||||
|
||||
// Set the signedness flag.
|
||||
(*cur).second.expr
|
||||
->cast_signed( (*cur).second.signed_flag );
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -438,7 +436,9 @@ void NetScope::evaluate_parameters(Design*des)
|
|||
}
|
||||
|
||||
/* If the parameter has range information, then make
|
||||
sure the value is set right. */
|
||||
sure the value is set right. Note that if the
|
||||
parameter doesn't have an explicit range, then it
|
||||
will get the signedness from the expression itself. */
|
||||
if (range_flag) {
|
||||
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
|
|
@ -618,6 +618,9 @@ void Design::delete_process(NetProcTop*top)
|
|||
|
||||
/*
|
||||
* $Log: net_design.cc,v $
|
||||
* Revision 1.45.2.1 2006/10/04 00:34:45 steve
|
||||
* Fix a dangling reference to NetEParam objects in defparams.
|
||||
*
|
||||
* Revision 1.45 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
192
net_link.cc
192
net_link.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_link.cc,v 1.14 2004/02/18 17:11:56 steve Exp $"
|
||||
#ident "$Id: net_link.cc,v 1.14.2.6 2006/08/23 04:09:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
# include "netlist.h"
|
||||
# include <sstream>
|
||||
# include <string>
|
||||
# include <cstring>
|
||||
# include <typeinfo>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
|
|
@ -40,30 +41,33 @@ void connect(Nexus*l, Link&r)
|
|||
if (l == r.nexus_)
|
||||
return;
|
||||
|
||||
|
||||
Nexus*tmp = r.nexus_;
|
||||
|
||||
while (Link*cur = tmp->list_) {
|
||||
tmp->list_ = cur->next_;
|
||||
cur->nexus_ = 0;
|
||||
cur->next_ = 0;
|
||||
cur->prev_ = 0;
|
||||
l->relink(cur);
|
||||
}
|
||||
|
||||
l->driven_ = Nexus::NO_GUESS;
|
||||
|
||||
assert(tmp->list_ == 0);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
void connect(Link&l, Link&r)
|
||||
{
|
||||
assert(&l != &r);
|
||||
connect(l.nexus_, r);
|
||||
if (r.is_linked() && !l.is_linked())
|
||||
connect(r.nexus_, l);
|
||||
else if (r.nexus_->list_len_ > l.nexus_->list_len_)
|
||||
connect(r.nexus_, l);
|
||||
else
|
||||
connect(l.nexus_, r);
|
||||
}
|
||||
|
||||
Link::Link()
|
||||
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
|
||||
inst_(0), next_(0), nexus_(0)
|
||||
inst_(0), next_(0), prev_(0), nexus_(0)
|
||||
{
|
||||
(new Nexus()) -> relink(this);
|
||||
}
|
||||
|
|
@ -215,6 +219,7 @@ Nexus::Nexus()
|
|||
{
|
||||
name_ = 0;
|
||||
list_ = 0;
|
||||
list_len_ = 0;
|
||||
driven_ = NO_GUESS;
|
||||
t_cookie_ = 0;
|
||||
}
|
||||
|
|
@ -241,6 +246,18 @@ verinum::V Nexus::get_init() const
|
|||
return verinum::Vz;
|
||||
}
|
||||
|
||||
int Nexus::is_driven() const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() == Link::OUTPUT)
|
||||
count += 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void Nexus::unlink(Link*that)
|
||||
{
|
||||
if (name_) {
|
||||
|
|
@ -254,22 +271,32 @@ void Nexus::unlink(Link*that)
|
|||
driven_ = NO_GUESS;
|
||||
|
||||
assert(that);
|
||||
assert(that->nexus_ == this);
|
||||
if (list_ == that) {
|
||||
assert(that->prev_ == 0);
|
||||
// Move the second item the front of the list.
|
||||
list_ = that->next_;
|
||||
if (list_)
|
||||
list_->prev_ = 0;
|
||||
list_len_ -= 1;
|
||||
// Clear the pointers for the link.
|
||||
that->next_ = 0;
|
||||
that->prev_ = 0;
|
||||
that->nexus_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Link*cur = list_;
|
||||
while (cur->next_ != that) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
|
||||
Link*cur = that->prev_;
|
||||
assert(cur->nexus_ == this);
|
||||
|
||||
cur->next_ = that->next_;
|
||||
if (cur->next_)
|
||||
cur->next_->prev_ = cur;
|
||||
that->nexus_ = 0;
|
||||
that->next_ = 0;
|
||||
that->prev_ = 0;
|
||||
list_len_ -= 1;
|
||||
}
|
||||
|
||||
void Nexus::relink(Link*that)
|
||||
|
|
@ -287,8 +314,13 @@ void Nexus::relink(Link*that)
|
|||
assert(that->nexus_ == 0);
|
||||
assert(that->next_ == 0);
|
||||
that->next_ = list_;
|
||||
that->prev_ = 0;
|
||||
if (that->next_)
|
||||
that->next_->prev_ = that;
|
||||
|
||||
that->nexus_ = this;
|
||||
list_ = that;
|
||||
list_len_ += 1;
|
||||
}
|
||||
|
||||
Link* Nexus::first_nlink()
|
||||
|
|
@ -360,8 +392,9 @@ const char* Nexus::name() const
|
|||
obj->name() << " pin " << pin << "(" <<
|
||||
lnk->get_name() << "<" << lnk->get_inst() << ">)"
|
||||
" type=" << typeid(*obj).name() << "?" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
ostringstream tmp;
|
||||
tmp << sig->name();
|
||||
|
|
@ -378,6 +411,7 @@ const char* Nexus::name() const
|
|||
NexusSet::NexusSet()
|
||||
{
|
||||
items_ = 0;
|
||||
index_ = 0;
|
||||
nitems_ = 0;
|
||||
}
|
||||
|
||||
|
|
@ -386,8 +420,11 @@ NexusSet::~NexusSet()
|
|||
if (nitems_ > 0) {
|
||||
assert(items_ != 0);
|
||||
delete[] items_;
|
||||
assert(index_ != 0);
|
||||
delete[] index_;
|
||||
} else {
|
||||
assert(items_ == 0);
|
||||
assert(index_ == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -396,25 +433,44 @@ unsigned NexusSet::count() const
|
|||
return nitems_;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the Nexus to the nexus set at the *end* of the array. This
|
||||
* preserves order, which is used in a few cases by the
|
||||
* synthesizer. But for efficiency, also create a sorted index.
|
||||
*/
|
||||
void NexusSet::add(Nexus*that)
|
||||
{
|
||||
/* Handle the special case that the set is empty. */
|
||||
if (nitems_ == 0) {
|
||||
assert(items_ == 0);
|
||||
assert(index_ == 0);
|
||||
items_ = (Nexus**)malloc(sizeof(Nexus*));
|
||||
items_[0] = that;
|
||||
index_ = (unsigned*)malloc(sizeof(unsigned));
|
||||
index_[0] = 0;
|
||||
nitems_ = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if ((ptr < nitems_) && (items_[ptr] == that))
|
||||
if (ptr < nitems_ && items_[index_[ptr]] == that) {
|
||||
assert(items_[index_[ptr]] == that);
|
||||
return;
|
||||
}
|
||||
|
||||
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*));
|
||||
for (unsigned idx = nitems_ ; idx > ptr ; idx -= 1)
|
||||
items_[idx] = items_[idx-1];
|
||||
items_ = (Nexus**) realloc(items_, (nitems_+1) * sizeof(Nexus*));
|
||||
index_ = (unsigned*)realloc(index_, (nitems_+1) * sizeof(unsigned));
|
||||
|
||||
items_[nitems_] = that;
|
||||
|
||||
unsigned dest = nitems_;
|
||||
for (unsigned idx = ptr ; idx < nitems_ ; idx += 1) {
|
||||
unsigned tmp = index_[idx];
|
||||
index_[idx] = dest;
|
||||
dest = tmp;
|
||||
}
|
||||
index_[nitems_] = dest;
|
||||
|
||||
items_[ptr] = that;
|
||||
nitems_ += 1;
|
||||
}
|
||||
|
||||
|
|
@ -430,20 +486,31 @@ void NexusSet::rem(Nexus*that)
|
|||
return;
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if ((ptr >= nitems_) || (items_[ptr] != that))
|
||||
if (ptr >= nitems_ || items_[index_[ptr]] != that)
|
||||
return;
|
||||
|
||||
if (nitems_ == 1) {
|
||||
free(items_);
|
||||
free(index_);
|
||||
items_ = 0;
|
||||
index_ = 0;
|
||||
nitems_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
unsigned index_ptr = index_[ptr];
|
||||
for (unsigned idx = index_ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
items_[idx] = items_[idx+1];
|
||||
|
||||
items_ = (Nexus**)realloc(items_, (nitems_-1) * sizeof(Nexus*));
|
||||
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
index_[idx] = index_[idx+1];
|
||||
|
||||
for (unsigned idx = 0 ; idx < (nitems_-1) ; idx += 1)
|
||||
if (index_[idx] > index_ptr)
|
||||
index_[idx] -= 1;
|
||||
|
||||
items_ = (Nexus**) realloc(items_, (nitems_-1) * sizeof(Nexus*));
|
||||
index_ = (unsigned*)realloc(index_, (nitems_-1) * sizeof(unsigned));
|
||||
nitems_ -= 1;
|
||||
}
|
||||
|
||||
|
|
@ -459,16 +526,37 @@ Nexus* NexusSet::operator[] (unsigned idx) const
|
|||
return items_[idx];
|
||||
}
|
||||
|
||||
/*
|
||||
* This method uses binary search to locate the item in the list of
|
||||
* nexus pointers. If the item is in the set, then this method returns
|
||||
* the index where it exists in the *index* array. If the item is not
|
||||
* in the set, the index points to where in the array the item should go.
|
||||
*/
|
||||
unsigned NexusSet::bsearch_(Nexus*that) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
if (items_[idx] < that)
|
||||
continue;
|
||||
|
||||
return idx;
|
||||
unsigned low = 0, hig = nitems_;
|
||||
|
||||
while (low < hig) {
|
||||
unsigned mid = (low + hig) / 2;
|
||||
if (mid == hig) mid -= 1;
|
||||
assert(mid >= low);
|
||||
assert(mid < hig);
|
||||
|
||||
if (items_[index_[mid]] == that) {
|
||||
return mid;
|
||||
|
||||
} else if (items_[index_[mid]] > that) {
|
||||
hig = mid;
|
||||
|
||||
} else {
|
||||
low = mid+1;
|
||||
}
|
||||
}
|
||||
|
||||
return nitems_;
|
||||
assert(low == hig);
|
||||
assert(low == nitems_ || items_[index_[low]] >= that);
|
||||
return low;
|
||||
}
|
||||
|
||||
bool NexusSet::contains(const NexusSet&that) const
|
||||
|
|
@ -477,7 +565,7 @@ bool NexusSet::contains(const NexusSet&that) const
|
|||
unsigned where = bsearch_(that[idx]);
|
||||
if (where == nitems_)
|
||||
return false;
|
||||
if (items_[where] != that[idx])
|
||||
if (items_[index_[where]] != that[idx])
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -490,7 +578,7 @@ bool NexusSet::intersect(const NexusSet&that) const
|
|||
unsigned where = bsearch_(that[idx]);
|
||||
if (where == nitems_)
|
||||
continue;
|
||||
if (items_[where] == that[idx])
|
||||
if (items_[index_[where]] == that[idx])
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -499,6 +587,24 @@ bool NexusSet::intersect(const NexusSet&that) const
|
|||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.14.2.6 2006/08/23 04:09:14 steve
|
||||
* missing sig diagnostics.
|
||||
*
|
||||
* Revision 1.14.2.5 2006/08/15 03:41:24 steve
|
||||
* Improve performance of unlink of heavily connected nexa.
|
||||
*
|
||||
* Revision 1.14.2.4 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.14.2.3 2006/07/23 19:42:33 steve
|
||||
* Handle statement output override better in blocks.
|
||||
*
|
||||
* Revision 1.14.2.2 2006/01/27 02:05:46 steve
|
||||
* Speed up processing of connect when one side is empty.
|
||||
*
|
||||
* Revision 1.14.2.1 2005/09/25 23:30:31 steve
|
||||
* More predictable ordering of items in NexusSet.
|
||||
*
|
||||
* Revision 1.14 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
@ -523,35 +629,5 @@ bool NexusSet::intersect(const NexusSet&that) const
|
|||
* Revision 1.7 2002/06/24 01:49:39 steve
|
||||
* Make link_drive_constant cache its results in
|
||||
* the Nexus, to improve cprop performance.
|
||||
*
|
||||
* Revision 1.6 2002/04/21 04:59:08 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.5 2001/07/25 03:10:49 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.4 2000/10/06 23:46:50 steve
|
||||
* ivl_target updates, including more complete
|
||||
* handling of ivl_nexus_t objects. Much reduced
|
||||
* dependencies on pointers to netlist objects.
|
||||
*
|
||||
* Revision 1.3 2000/08/26 00:54:03 steve
|
||||
* Get at gate information for ivl_target interface.
|
||||
*
|
||||
* Revision 1.2 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.1 2000/06/25 19:59:42 steve
|
||||
* Redesign Links to include the Nexus class that
|
||||
* carries properties of the connected set of links.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
163
net_nex_input.cc
163
net_nex_input.cc
|
|
@ -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.12 2004/09/04 04:24:15 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.12.2.1 2006/05/21 21:58:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
NexusSet* NetExpr::nex_input()
|
||||
NexusSet* NetExpr::nex_input(bool rem_out)
|
||||
{
|
||||
cerr << get_line()
|
||||
<< ": internal error: nex_input not implemented: "
|
||||
|
|
@ -37,7 +37,7 @@ NexusSet* NetExpr::nex_input()
|
|||
return 0;
|
||||
}
|
||||
|
||||
NexusSet* NetProc::nex_input()
|
||||
NexusSet* NetProc::nex_input(bool rem_out)
|
||||
{
|
||||
cerr << get_line()
|
||||
<< ": internal error: NetProc::nex_input not implemented"
|
||||
|
|
@ -45,29 +45,34 @@ NexusSet* NetProc::nex_input()
|
|||
return 0;
|
||||
}
|
||||
|
||||
NexusSet* NetEBinary::nex_input()
|
||||
NexusSet* NetEBinary::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = left_->nex_input();
|
||||
NexusSet*tmp = right_->nex_input();
|
||||
NexusSet*result = left_->nex_input(rem_out);
|
||||
NexusSet*tmp = right_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEBitSel::nex_input()
|
||||
NexusSet* NetEBitSel::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = sig_->nex_input();
|
||||
NexusSet*tmp = idx_->nex_input();
|
||||
NexusSet*result = sig_->nex_input(rem_out);
|
||||
NexusSet*tmp = idx_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEConcat::nex_input()
|
||||
NexusSet* NetEConcat::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = parms_[0]->nex_input();
|
||||
if (parms_[0] == NULL) return NULL;
|
||||
NexusSet*result = parms_[0]->nex_input(rem_out);
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
NexusSet*tmp = parms_[idx]->nex_input();
|
||||
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
|
||||
if (tmp == NULL) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
|
@ -77,19 +82,19 @@ NexusSet* NetEConcat::nex_input()
|
|||
/*
|
||||
* A constant has not inputs, so always return an empty set.
|
||||
*/
|
||||
NexusSet* NetEConst::nex_input()
|
||||
NexusSet* NetEConst::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetECReal::nex_input()
|
||||
NexusSet* NetECReal::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetEMemory::nex_input()
|
||||
NexusSet* NetEMemory::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = idx_->nex_input();
|
||||
NexusSet*result = idx_->nex_input(rem_out);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -97,74 +102,79 @@ NexusSet* NetEMemory::nex_input()
|
|||
* A parameter by definition has no inputs. It represents a constant
|
||||
* value, even if that value is a constant expression.
|
||||
*/
|
||||
NexusSet* NetEParam::nex_input()
|
||||
NexusSet* NetEParam::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetEEvent::nex_input()
|
||||
NexusSet* NetEEvent::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetEScope::nex_input()
|
||||
NexusSet* NetEScope::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetESelect::nex_input()
|
||||
NexusSet* NetESelect::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = base_? base_->nex_input() : new NexusSet();
|
||||
NexusSet*tmp = expr_->nex_input();
|
||||
NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet();
|
||||
NexusSet*tmp = expr_->nex_input(rem_out);
|
||||
if (tmp == NULL) {
|
||||
delete result;
|
||||
return NULL;
|
||||
}
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetESFunc::nex_input()
|
||||
NexusSet* NetESFunc::nex_input(bool rem_out)
|
||||
{
|
||||
if (nparms_ == 0)
|
||||
return new NexusSet;
|
||||
|
||||
NexusSet*result = parms_[0]->nex_input();
|
||||
NexusSet*result = parms_[0]->nex_input(rem_out);
|
||||
for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) {
|
||||
NexusSet*tmp = parms_[idx]->nex_input();
|
||||
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetESignal::nex_input()
|
||||
NexusSet* NetESignal::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = new NexusSet;
|
||||
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
|
||||
assert(msi_ <= net_->pin_count());
|
||||
for (unsigned idx = lsi_ ; idx <= msi_ ; idx += 1)
|
||||
result->add(net_->pin(idx).nexus());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetETernary::nex_input()
|
||||
NexusSet* NetETernary::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*tmp;
|
||||
NexusSet*result = cond_->nex_input();
|
||||
NexusSet*result = cond_->nex_input(rem_out);
|
||||
|
||||
tmp = true_val_->nex_input();
|
||||
tmp = true_val_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
tmp = false_val_->nex_input();
|
||||
tmp = false_val_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEUFunc::nex_input()
|
||||
NexusSet* NetEUFunc::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = new NexusSet;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
NexusSet*tmp = parms_[idx]->nex_input();
|
||||
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
|
@ -172,33 +182,33 @@ NexusSet* NetEUFunc::nex_input()
|
|||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEUnary::nex_input()
|
||||
NexusSet* NetEUnary::nex_input(bool rem_out)
|
||||
{
|
||||
return expr_->nex_input();
|
||||
return expr_->nex_input(rem_out);
|
||||
}
|
||||
|
||||
NexusSet* NetEVariable::nex_input()
|
||||
NexusSet* NetEVariable::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetAssign_::nex_input()
|
||||
NexusSet* NetAssign_::nex_input(bool rem_out)
|
||||
{
|
||||
if (bmux_ == 0)
|
||||
return new NexusSet;
|
||||
else
|
||||
return bmux_->nex_input();
|
||||
return bmux_->nex_input(rem_out);
|
||||
}
|
||||
|
||||
NexusSet* NetAssignBase::nex_input()
|
||||
NexusSet* NetAssignBase::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = rval_->nex_input();
|
||||
NexusSet*result = rval_->nex_input(rem_out);
|
||||
|
||||
/* It is possible that the lval_ can hav nex_input values. In
|
||||
particular, index expressions are statement inputs as well,
|
||||
so should be addressed here. */
|
||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
||||
NexusSet*tmp = cur->nex_input();
|
||||
NexusSet*tmp = cur->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
|
@ -223,7 +233,7 @@ NexusSet* NetAssignBase::nex_input()
|
|||
* In this example, "t" should not be in the input set because it is
|
||||
* used by the sequence as a temporary value.
|
||||
*/
|
||||
NexusSet* NetBlock::nex_input()
|
||||
NexusSet* NetBlock::nex_input(bool rem_out)
|
||||
{
|
||||
if (last_ == 0)
|
||||
return new NexusSet;
|
||||
|
|
@ -243,24 +253,24 @@ NexusSet* NetBlock::nex_input()
|
|||
|
||||
do {
|
||||
/* Get the inputs for the current statement. */
|
||||
NexusSet*tmp = cur->nex_input();
|
||||
NexusSet*tmp = cur->nex_input(rem_out);
|
||||
|
||||
/* Remove from the input set those bits that are outputs
|
||||
from previous statements. They aren't really inputs
|
||||
to the block, just internal intermediate values. */
|
||||
tmp->rem(*prev);
|
||||
|
||||
/* Add the corrected set to the accumulated input set. */
|
||||
/* Add the current input set to the accumulated input set. */
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
/* Add the current outputs to the accumulated output
|
||||
set, for processing of later statements. */
|
||||
/* Add the current outputs to the accumulated output set,
|
||||
so they can be removed from the input set below. */
|
||||
cur->nex_output(*prev);
|
||||
|
||||
cur = cur->next_;
|
||||
} while (cur != last_->next_);
|
||||
|
||||
/* Remove from the input set those bits that are outputs
|
||||
from other statements. They aren't really inputs
|
||||
to the block, just internal intermediate values. */
|
||||
if (rem_out) result->rem(*prev);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -269,9 +279,9 @@ NexusSet* NetBlock::nex_input()
|
|||
* the inputs to all the guards, and the inputs to all the guarded
|
||||
* statements.
|
||||
*/
|
||||
NexusSet* NetCase::nex_input()
|
||||
NexusSet* NetCase::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = expr_->nex_input();
|
||||
NexusSet*result = expr_->nex_input(rem_out);
|
||||
if (result == 0)
|
||||
return 0;
|
||||
|
||||
|
|
@ -281,7 +291,7 @@ NexusSet* NetCase::nex_input()
|
|||
if (items_[idx].statement == 0)
|
||||
continue;
|
||||
|
||||
NexusSet*tmp = items_[idx].statement->nex_input();
|
||||
NexusSet*tmp = items_[idx].statement->nex_input(rem_out);
|
||||
assert(tmp);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
|
@ -290,7 +300,7 @@ NexusSet* NetCase::nex_input()
|
|||
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();
|
||||
tmp = items_[idx].guard->nex_input(rem_out);
|
||||
assert(tmp);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
|
@ -300,24 +310,24 @@ NexusSet* NetCase::nex_input()
|
|||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetCAssign::nex_input()
|
||||
NexusSet* NetCAssign::nex_input(bool rem_out)
|
||||
{
|
||||
cerr << get_line() << ": internal warning: NetCAssign::nex_input()"
|
||||
<< " not implemented." << endl;
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetCondit::nex_input()
|
||||
NexusSet* NetCondit::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = expr_->nex_input();
|
||||
NexusSet*result = expr_->nex_input(rem_out);
|
||||
if (if_ != 0) {
|
||||
NexusSet*tmp = if_->nex_input();
|
||||
NexusSet*tmp = if_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
if (else_ != 0) {
|
||||
NexusSet*tmp = else_->nex_input();
|
||||
NexusSet*tmp = else_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
|
@ -325,16 +335,16 @@ NexusSet* NetCondit::nex_input()
|
|||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetForce::nex_input()
|
||||
NexusSet* NetForce::nex_input(bool rem_out)
|
||||
{
|
||||
cerr << get_line() << ": internal warning: NetForce::nex_input()"
|
||||
<< " not implemented." << endl;
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetForever::nex_input()
|
||||
NexusSet* NetForever::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = statement_->nex_input();
|
||||
NexusSet*result = statement_->nex_input(rem_out);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -347,29 +357,29 @@ NexusSet* NetForever::nex_input()
|
|||
* include the input set of the <expr> because it does not affect the
|
||||
* result.
|
||||
*/
|
||||
NexusSet* NetPDelay::nex_input()
|
||||
NexusSet* NetPDelay::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = statement_->nex_input();
|
||||
NexusSet*result = statement_->nex_input(rem_out);
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetRepeat::nex_input()
|
||||
NexusSet* NetRepeat::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = statement_->nex_input();
|
||||
NexusSet*tmp = expr_->nex_input();
|
||||
NexusSet*result = statement_->nex_input(rem_out);
|
||||
NexusSet*tmp = expr_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetSTask::nex_input()
|
||||
NexusSet* NetSTask::nex_input(bool rem_out)
|
||||
{
|
||||
if (parms_.count() == 0)
|
||||
return new NexusSet;
|
||||
|
||||
NexusSet*result = parms_[0]->nex_input();
|
||||
NexusSet*result = parms_[0]->nex_input(rem_out);
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
NexusSet*tmp = parms_[idx]->nex_input();
|
||||
NexusSet*tmp = parms_[idx]->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
|
@ -382,15 +392,15 @@ NexusSet* NetSTask::nex_input()
|
|||
* parameters to consider, because the compiler already removed them
|
||||
* and converted them to blocking assignments.
|
||||
*/
|
||||
NexusSet* NetUTask::nex_input()
|
||||
NexusSet* NetUTask::nex_input(bool rem_out)
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetWhile::nex_input()
|
||||
NexusSet* NetWhile::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = proc_->nex_input();
|
||||
NexusSet*tmp = cond_->nex_input();
|
||||
NexusSet*result = proc_->nex_input(rem_out);
|
||||
NexusSet*tmp = cond_->nex_input(rem_out);
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
|
|
@ -398,6 +408,9 @@ NexusSet* NetWhile::nex_input()
|
|||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.12.2.1 2006/05/21 21:58:47 steve
|
||||
* NetESignal input is only selected bits.
|
||||
*
|
||||
* Revision 1.12 2004/09/04 04:24:15 steve
|
||||
* PR1026: assignment statements can have sensitivities in the l-values.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.11 2004/09/16 03:17:33 steve Exp $"
|
||||
#ident "$Id: net_nex_output.cc,v 1.11.2.8 2006/08/08 02:17:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -47,10 +47,55 @@ void NetAssignBase::nex_output(NexusSet&out)
|
|||
{
|
||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
||||
if (NetNet*lsig = cur->sig()) {
|
||||
|
||||
if (cur->bmux()) {
|
||||
for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1) {
|
||||
out.add(lsig->pin(idx).nexus());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle l-value signals. We don't need to worry
|
||||
here about whether there is a bmux, because the
|
||||
synthesizer will detect that mux and create a
|
||||
decoder between the expression and the signal. */
|
||||
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
|
||||
unsigned off = cur->get_loff() + idx;
|
||||
out.add(lsig->pin(off).nexus());
|
||||
}
|
||||
|
||||
} else if (NetMemory*lmem = cur->mem()) {
|
||||
|
||||
/* Memories here are treated as a bunch of reg
|
||||
devices. Use the explode_to_reg method to get
|
||||
access to the FF version of the memory and use
|
||||
that in our l-value management. */
|
||||
NetNet*tmp = lmem->explode_to_reg();
|
||||
|
||||
if (NetEConst*ae = dynamic_cast<NetEConst*>(cur->bmux())) {
|
||||
/* The address is constant, so simply
|
||||
connect to the right pins and we are
|
||||
done. */
|
||||
long adr_s = ae->value().as_long();
|
||||
unsigned adr = lmem->index_to_address(adr_s) * lmem->width();
|
||||
|
||||
if (adr >= lmem->count()*lmem->width()) {
|
||||
/* Skip assignments with constant
|
||||
addresses that are outside the
|
||||
range of memories. */
|
||||
} else {
|
||||
for (unsigned idx=0; idx<cur->lwidth(); idx += 1)
|
||||
out.add(tmp->pin(adr+idx).nexus());
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Put all the bits of the memory into the
|
||||
set. The synthesis will generate a
|
||||
decoder to handle this. */
|
||||
for (unsigned idx = 0; idx < tmp->pin_count(); idx+=1)
|
||||
out.add(tmp->pin(idx).nexus());
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Quoting from netlist.h comments for class NetMemory:
|
||||
* "This is not a node because memory objects can only be
|
||||
|
|
@ -69,11 +114,11 @@ void NetBlock::nex_output(NexusSet&out)
|
|||
if (last_ == 0)
|
||||
return;
|
||||
|
||||
NetProc*cur = last_;
|
||||
NetProc*cur = last_->next_;
|
||||
do {
|
||||
cur = cur->next_;
|
||||
cur->nex_output(out);
|
||||
} while (cur != last_);
|
||||
cur = cur->next_;
|
||||
} while (cur != last_->next_);
|
||||
}
|
||||
|
||||
void NetCase::nex_output(NexusSet&out)
|
||||
|
|
@ -114,6 +159,15 @@ void NetSTask::nex_output(NexusSet&out)
|
|||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Consider a task call to not have any outputs. This is not quite
|
||||
* right, we should be listing as outputs all the output ports, but for
|
||||
* the purposes that this method is used, this will do for now.
|
||||
*/
|
||||
void NetUTask::nex_output(NexusSet&out)
|
||||
{
|
||||
}
|
||||
|
||||
void NetWhile::nex_output(NexusSet&out)
|
||||
{
|
||||
if (proc_ != 0)
|
||||
|
|
@ -122,6 +176,30 @@ void NetWhile::nex_output(NexusSet&out)
|
|||
|
||||
/*
|
||||
* $Log: net_nex_output.cc,v $
|
||||
* Revision 1.11.2.8 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.11.2.7 2006/06/02 23:42:48 steve
|
||||
* Compilation warnings.
|
||||
*
|
||||
* Revision 1.11.2.6 2006/06/01 03:01:48 steve
|
||||
* Handle condit clauses with unassigned outputs.
|
||||
*
|
||||
* Revision 1.11.2.5 2006/05/18 01:47:12 steve
|
||||
* Fix synthesis of l-value bit select in block.
|
||||
*
|
||||
* Revision 1.11.2.4 2006/05/05 01:56:36 steve
|
||||
* Handle memory assignments out of range during synthesis
|
||||
*
|
||||
* Revision 1.11.2.3 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.11.2.2 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.11.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.11 2004/09/16 03:17:33 steve
|
||||
* net_output handles l-value concatenations.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_scope.cc,v 1.33 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: net_scope.cc,v 1.33.2.1 2005/02/19 16:39:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
# include "netlist.h"
|
||||
# include <sstream>
|
||||
# include <cstring>
|
||||
|
||||
/*
|
||||
* The NetScope class keeps a scope tree organized. Each node of the
|
||||
|
|
@ -194,7 +195,7 @@ const NetFuncDef* NetScope::func_def() const
|
|||
void NetScope::set_module_name(perm_string n)
|
||||
{
|
||||
assert(type_ == MODULE);
|
||||
module_name_ = n; /* NOTE: n mus have been permallocated. */
|
||||
module_name_ = n; /* NOTE: n must have been permallocated. */
|
||||
}
|
||||
|
||||
perm_string NetScope::module_name() const
|
||||
|
|
@ -467,6 +468,9 @@ string NetScope::local_hsymbol()
|
|||
|
||||
/*
|
||||
* $Log: net_scope.cc,v $
|
||||
* Revision 1.33.2.1 2005/02/19 16:39:31 steve
|
||||
* Spellig fixes.
|
||||
*
|
||||
* Revision 1.33 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
271
netlist.cc
271
netlist.cc
|
|
@ -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.226 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.226.2.7 2006/04/23 04:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -229,7 +229,7 @@ NetNode::~NetNode()
|
|||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
: NetObj(s, n, npins), sig_next_(0), sig_prev_(0),
|
||||
type_(t), port_type_(NOT_A_PORT), signed_(false), msb_(npins-1), lsb_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
local_flag_(false), eref_count_(0), lref_count_(0), mref_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
||||
|
|
@ -270,7 +270,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
|||
: NetObj(s, n, ((ms>ls)?ms-ls:ls-ms) + 1),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
port_type_(NOT_A_PORT), signed_(false), msb_(ms), lsb_(ls),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
local_flag_(false), eref_count_(0), lref_count_(0), mref_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
||||
|
|
@ -322,6 +322,14 @@ NetNet::~NetNet()
|
|||
dump_net(cerr, 4);
|
||||
}
|
||||
assert(lref_count_ == 0);
|
||||
if (mref_ != 0) {
|
||||
cerr << get_line() << ": internal error: attempt to delete "
|
||||
<< "signal ``" << name() << "'' which has "
|
||||
<< "memory explode references." << endl;
|
||||
dump_net(cerr, 4);
|
||||
}
|
||||
assert(mref_ == 0);
|
||||
|
||||
if (scope())
|
||||
scope()->rem_signal(this);
|
||||
|
||||
|
|
@ -462,6 +470,23 @@ unsigned NetNet::get_refs() const
|
|||
return lref_count_ + eref_count_;
|
||||
}
|
||||
|
||||
void NetNet::mref(NetMemory*mem)
|
||||
{
|
||||
assert(mref_ == 0);
|
||||
assert(mem != 0);
|
||||
mref_ = mem;
|
||||
}
|
||||
|
||||
NetMemory*NetNet::mref()
|
||||
{
|
||||
return mref_;
|
||||
}
|
||||
|
||||
const NetMemory* NetNet::mref() const
|
||||
{
|
||||
return mref_;
|
||||
}
|
||||
|
||||
|
||||
NetSubnet::NetSubnet(NetNet*sig, unsigned off, unsigned wid)
|
||||
: NetNet(sig->scope(), sig->scope()->local_symbol(), sig->type(), wid)
|
||||
|
|
@ -533,6 +558,8 @@ const NetScope* NetProcTop::scope() const
|
|||
NetFF::NetFF(NetScope*s, perm_string n, unsigned wid)
|
||||
: NetNode(s, n, 8 + 2*wid)
|
||||
{
|
||||
demux_ = 0;
|
||||
|
||||
pin_Clock().set_dir(Link::INPUT);
|
||||
pin_Clock().set_name(perm_string::literal("Clock"), 0);
|
||||
pin_Enable().set_dir(Link::INPUT);
|
||||
|
|
@ -684,6 +711,118 @@ const verinum& NetFF::sset_value() const
|
|||
return sset_value_;
|
||||
}
|
||||
|
||||
unsigned NetDecode::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
unsigned NetDecode::awidth() const
|
||||
{
|
||||
return pin_count();
|
||||
}
|
||||
|
||||
NetDemux::NetDemux(NetScope*s, perm_string name,
|
||||
unsigned bus_width, unsigned address_width, unsigned size)
|
||||
: NetNode(s, name, bus_width*2+address_width+bus_width/size)
|
||||
{
|
||||
width_ = bus_width;
|
||||
awidth_ = address_width;
|
||||
size_ = size;
|
||||
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
||||
pin_Q(idx).set_dir(Link::OUTPUT);
|
||||
pin_Q(idx).set_name(perm_string::literal("Q"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_ ; idx += 1) {
|
||||
pin_Data(idx).set_dir(Link::INPUT);
|
||||
pin_Data(idx).set_name(perm_string::literal("Data"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < awidth_ ; idx += 1) {
|
||||
pin_Address(idx).set_dir(Link::INPUT);
|
||||
pin_Address(idx).set_name(perm_string::literal("Address"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_/size_ ; idx += 1) {
|
||||
pin_WriteData(idx).set_dir(Link::INPUT);
|
||||
pin_WriteData(idx).set_name(perm_string::literal("Writedata"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetDemux::~NetDemux()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetDemux::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
unsigned NetDemux::awidth() const
|
||||
{
|
||||
return awidth_;
|
||||
}
|
||||
|
||||
unsigned NetDemux::size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Q(unsigned idx)
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Q(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Data(unsigned idx)
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(width_+idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Data(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_);
|
||||
return pin(width_+idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_Address(unsigned idx)
|
||||
{
|
||||
assert(idx < awidth_);
|
||||
return pin(width_+width_+idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_Address(unsigned idx) const
|
||||
{
|
||||
assert(idx < awidth_);
|
||||
return pin(width_+width_+idx);
|
||||
}
|
||||
|
||||
Link& NetDemux::pin_WriteData(unsigned idx)
|
||||
{
|
||||
assert(idx < width_/size_);
|
||||
return pin(width_+width_+awidth_+idx);
|
||||
}
|
||||
|
||||
const Link& NetDemux::pin_WriteData(unsigned idx) const
|
||||
{
|
||||
assert(idx < width_/size_);
|
||||
return pin(width_+width_+awidth_+idx);
|
||||
}
|
||||
|
||||
NetDecode* NetFF::get_demux()
|
||||
{
|
||||
return demux_;
|
||||
}
|
||||
|
||||
const NetDecode* NetFF::get_demux() const
|
||||
{
|
||||
return demux_;
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
|
||||
|
|
@ -1060,6 +1199,40 @@ const Link& NetCompare::pin_DataB(unsigned idx) const
|
|||
return pin(8+width_+idx);
|
||||
}
|
||||
|
||||
NetDecode::NetDecode(NetScope*s, perm_string name, NetFF*mem,
|
||||
unsigned awid, unsigned word_width)
|
||||
: NetNode(s, name, awid)
|
||||
{
|
||||
width_ = word_width;
|
||||
assert( mem->width() % width_ == 0 );
|
||||
|
||||
ff_ = mem;
|
||||
ff_->demux_ = this;
|
||||
make_pins_(awid);
|
||||
}
|
||||
|
||||
NetDecode::~NetDecode()
|
||||
{
|
||||
}
|
||||
|
||||
void NetDecode::make_pins_(unsigned awid)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < awid ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("Address"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
Link& NetDecode::pin_Address(unsigned idx)
|
||||
{
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetDecode::pin_Address(unsigned idx) const
|
||||
{
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
NetDivide::NetDivide(NetScope*sc, perm_string n, unsigned wr,
|
||||
unsigned wa, unsigned wb)
|
||||
: NetNode(sc, n, wr+wa+wb),
|
||||
|
|
@ -1385,10 +1558,7 @@ const Link& NetMux::pin_Data(unsigned w, unsigned s) const
|
|||
return pin(2+width_+swidth_+s*width_+w);
|
||||
}
|
||||
|
||||
|
||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||
: NetNode(s, n, 3+2*mem->width()+awid),
|
||||
mem_(mem), awidth_(awid)
|
||||
void NetRamDq::make_pins_(unsigned wid)
|
||||
{
|
||||
pin(0).set_dir(Link::INPUT); pin(0).set_name(perm_string::literal("InClock"), 0);
|
||||
pin(1).set_dir(Link::INPUT); pin(1).set_name(perm_string::literal("OutClock"), 0);
|
||||
|
|
@ -1399,39 +1569,49 @@ NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
|||
pin(3+idx).set_name(perm_string::literal("Address"), idx);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
pin(3+awidth_+idx).set_dir(Link::INPUT);
|
||||
pin(3+awidth_+idx).set_name(perm_string::literal("Data"), idx);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < width() ; idx += 1) {
|
||||
pin(3+awidth_+width()+idx).set_dir(Link::OUTPUT);
|
||||
pin(3+awidth_+width()+idx).set_name(perm_string::literal("Q"), idx);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1) {
|
||||
pin(3+awidth_+wid+idx).set_dir(Link::OUTPUT);
|
||||
pin(3+awidth_+wid+idx).set_name(perm_string::literal("Q"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||
: NetNode(s, n, 3+2*mem->width()+awid),
|
||||
mem_(mem), awidth_(awid)
|
||||
{
|
||||
make_pins_(mem->width());
|
||||
next_ = mem_->ram_list_;
|
||||
mem_->ram_list_ = this;
|
||||
}
|
||||
|
||||
NetRamDq::~NetRamDq()
|
||||
{
|
||||
if (mem_->ram_list_ == this) {
|
||||
mem_->ram_list_ = next_;
|
||||
if (mem_) {
|
||||
if (mem_->ram_list_ == this) {
|
||||
mem_->ram_list_ = next_;
|
||||
|
||||
} else {
|
||||
NetRamDq*cur = mem_->ram_list_;
|
||||
while (cur->next_ != this) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
} else {
|
||||
NetRamDq*cur = mem_->ram_list_;
|
||||
while (cur->next_ != this) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
assert(cur->next_ == this);
|
||||
cur->next_ = next_;
|
||||
}
|
||||
assert(cur->next_ == this);
|
||||
cur->next_ = next_;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetRamDq::width() const
|
||||
{
|
||||
return mem_->width();
|
||||
if (mem_) return mem_->width();
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned NetRamDq::awidth() const
|
||||
|
|
@ -1441,7 +1621,13 @@ unsigned NetRamDq::awidth() const
|
|||
|
||||
unsigned NetRamDq::size() const
|
||||
{
|
||||
return mem_->count();
|
||||
if (mem_) return mem_->count();
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetMemory* NetRamDq::mem()
|
||||
{
|
||||
return mem_;
|
||||
}
|
||||
|
||||
const NetMemory* NetRamDq::mem() const
|
||||
|
|
@ -2003,6 +2189,7 @@ NetMemory::NetMemory(NetScope*sc, perm_string n, long w, long s, long e)
|
|||
: width_(w), idxh_(s), idxl_(e), ram_list_(0), scope_(sc)
|
||||
{
|
||||
name_ = n;
|
||||
explode_ = 0;
|
||||
scope_->add_memory(this);
|
||||
}
|
||||
|
||||
|
|
@ -2033,7 +2220,26 @@ unsigned NetMemory::index_to_address(long idx) const
|
|||
return idx - idxl_;
|
||||
}
|
||||
|
||||
NetNet* NetMemory::explode_to_reg()
|
||||
{
|
||||
if (explode_)
|
||||
return explode_;
|
||||
|
||||
explode_ = new NetNet(scope_, name_, NetNet::REG, count()*width_);
|
||||
explode_->mref(this);
|
||||
//explode_->incr_lref();
|
||||
return explode_;
|
||||
}
|
||||
|
||||
NetNet* NetMemory::reg_from_explode()
|
||||
{
|
||||
return explode_;
|
||||
}
|
||||
|
||||
const NetNet* NetMemory::reg_from_explode() const
|
||||
{
|
||||
return explode_;
|
||||
}
|
||||
|
||||
NetEMemory* NetEMemory::dup_expr() const
|
||||
{
|
||||
|
|
@ -2281,6 +2487,27 @@ const NetProc*NetTaskDef::proc() const
|
|||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.226.2.7 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.226.2.6 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.226.2.5 2006/03/26 23:09:22 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.226.2.4 2006/03/16 05:40:18 steve
|
||||
* Fix crash when memory exploding doesnot work
|
||||
*
|
||||
* Revision 1.226.2.3 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.226.2.2 2006/02/19 00:11:32 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.226.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.226 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
390
netlist.h
390
netlist.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.321 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.321.2.25 2007/05/30 17:48:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -48,6 +48,7 @@ class ostream;
|
|||
class Design;
|
||||
class Link;
|
||||
class Nexus;
|
||||
class NetMemory;
|
||||
class NetNode;
|
||||
class NetProc;
|
||||
class NetProcTop;
|
||||
|
|
@ -58,12 +59,22 @@ class NetEvProbe;
|
|||
class NetExpr;
|
||||
class NetESignal;
|
||||
class NetEVariable;
|
||||
class NetFF;
|
||||
class NetFuncDef;
|
||||
|
||||
class NetRamDq;
|
||||
class NetEvTrig;
|
||||
class NetEvWait;
|
||||
|
||||
struct target;
|
||||
struct functor_t;
|
||||
|
||||
struct sync_accounting_cell {
|
||||
NetProc*proc;
|
||||
NetFF*ff;
|
||||
unsigned pin;
|
||||
};
|
||||
|
||||
/* =========
|
||||
* A NetObj is anything that has any kind of behavior in the
|
||||
* netlist. Nodes can be gates, registers, etc. and are linked
|
||||
|
|
@ -86,7 +97,6 @@ struct functor_t;
|
|||
*/
|
||||
class NetObj : public Attrib, public virtual LineInfo {
|
||||
|
||||
public:
|
||||
public:
|
||||
// The name of the object must be a permallocated string. A
|
||||
// lex_strings string, for example.
|
||||
|
|
@ -215,7 +225,7 @@ class Link {
|
|||
unsigned inst_;
|
||||
|
||||
private:
|
||||
Link *next_;
|
||||
Link *next_, *prev_;
|
||||
Nexus*nexus_;
|
||||
|
||||
private: // not implemented
|
||||
|
|
@ -253,6 +263,9 @@ class Nexus {
|
|||
Link*first_nlink();
|
||||
const Link* first_nlink()const;
|
||||
|
||||
/* Return the number of drivers, or 0 if undriven. */
|
||||
int is_driven() const;
|
||||
|
||||
/* This method returns true if all the possible drivers of
|
||||
this nexus are constant. It will also return true if there
|
||||
are no drivers at all. */
|
||||
|
|
@ -267,6 +280,7 @@ class Nexus {
|
|||
|
||||
private:
|
||||
Link*list_;
|
||||
int list_len_;
|
||||
void unlink(Link*);
|
||||
void relink(Link*);
|
||||
|
||||
|
|
@ -307,6 +321,7 @@ class NexusSet {
|
|||
|
||||
private:
|
||||
Nexus**items_;
|
||||
unsigned*index_;
|
||||
unsigned nitems_;
|
||||
|
||||
unsigned bsearch_(Nexus*that) const;
|
||||
|
|
@ -424,6 +439,11 @@ class NetNet : public NetObj {
|
|||
|
||||
unsigned get_refs() const;
|
||||
|
||||
/* This may be and explode of a memory. */
|
||||
void mref(NetMemory*ref);
|
||||
NetMemory*mref();
|
||||
const NetMemory*mref() const;
|
||||
|
||||
virtual void dump_net(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
|
|
@ -448,6 +468,7 @@ class NetNet : public NetObj {
|
|||
bool local_flag_;
|
||||
unsigned eref_count_;
|
||||
unsigned lref_count_;
|
||||
NetMemory*mref_;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -581,6 +602,87 @@ class NetCompare : public NetNode {
|
|||
bool signed_flag_;
|
||||
};
|
||||
|
||||
/*
|
||||
* A decoder takes an address input and activates (high) the single
|
||||
* Q bit that is addressed. This can be used, for example, to
|
||||
* generate an enable for a FF from an array of FFs.
|
||||
*/
|
||||
class NetDecode : public NetNode {
|
||||
|
||||
public:
|
||||
NetDecode(NetScope*s, perm_string name, NetFF*mem,
|
||||
unsigned awid, unsigned word_width);
|
||||
~NetDecode();
|
||||
|
||||
// This is the width of the word. The width of the NetFF mem
|
||||
// is an even multiple of this.
|
||||
unsigned width() const;
|
||||
// This is the width of the address. The address value for the
|
||||
// base of a word is the address * width().
|
||||
unsigned awidth() const;
|
||||
|
||||
const NetFF*ff() const;
|
||||
|
||||
Link& pin_Address(unsigned idx);
|
||||
|
||||
const Link& pin_Address(unsigned idx) const;
|
||||
const Link& pin_Q(unsigned idx) const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
NetFF* ff_;
|
||||
|
||||
private:
|
||||
void make_pins_(unsigned awid);
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetDemux is similar to the NetDecode, except that it is
|
||||
* combinational. The inputs are an address, Data, and WriteData.
|
||||
* The Q output is the same as the Data input, except for the bit that
|
||||
* is addressed by the address input, which gets WriteData instead.
|
||||
*/
|
||||
class NetDemux : public NetNode {
|
||||
|
||||
public:
|
||||
NetDemux(NetScope*s, perm_string name,
|
||||
unsigned bus_width, unsigned address_width,
|
||||
unsigned size);
|
||||
~NetDemux();
|
||||
|
||||
// This is the width of the bus that passes through the
|
||||
// device. The address addresses into this width.
|
||||
unsigned width() const;
|
||||
// This is the width of the address. The address value for the
|
||||
// base of a word is the address * width().
|
||||
unsigned awidth() const;
|
||||
// This is the number of words in the width that can be
|
||||
// addressed. This implies (by division) the width of a word.
|
||||
unsigned size() const;
|
||||
|
||||
Link& pin_Address(unsigned idx);
|
||||
Link& pin_Data(unsigned idx);
|
||||
Link& pin_Q(unsigned idx);
|
||||
Link& pin_WriteData(unsigned idx);
|
||||
|
||||
const Link& pin_Address(unsigned idx) const;
|
||||
const Link& pin_Data(unsigned idx) const;
|
||||
const Link& pin_Q(unsigned idx) const;
|
||||
const Link& pin_WriteData(unsigned idx) const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
unsigned width_, awidth_, size_;
|
||||
|
||||
private:
|
||||
void make_pins_(unsigned wid, unsigned awid);
|
||||
};
|
||||
|
||||
/*
|
||||
* This class represents a theoretical (though not necessarily
|
||||
* practical) integer divider gate. This is not to represent any real
|
||||
|
|
@ -703,10 +805,19 @@ class NetFF : public NetNode {
|
|||
void sset_value(const verinum&val);
|
||||
const verinum& sset_value() const;
|
||||
|
||||
NetDecode* get_demux();
|
||||
const NetDecode* get_demux() 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:
|
||||
// If there is a demux associated with this gate, the demux_
|
||||
// member will point to the decoder.
|
||||
friend class NetDecode;
|
||||
NetDecode*demux_;
|
||||
|
||||
private:
|
||||
verinum aset_value_;
|
||||
verinum sset_value_;
|
||||
|
|
@ -735,6 +846,7 @@ class NetMemory {
|
|||
|
||||
// NetScope*scope();
|
||||
const NetScope*scope() const { return scope_; };
|
||||
NetScope*scope() { return scope_; };
|
||||
|
||||
// This is the number of memory positions.
|
||||
unsigned count() const;
|
||||
|
|
@ -744,6 +856,13 @@ class NetMemory {
|
|||
// that are not zero based.
|
||||
unsigned index_to_address(long idx) const;
|
||||
|
||||
// This method returns a NetNet::REG that has the same number
|
||||
// of bits as the memory as a whole. This is used to represent
|
||||
// memories that are synthesized to individual bits.
|
||||
NetNet* explode_to_reg();
|
||||
NetNet* reg_from_explode();
|
||||
const NetNet* reg_from_explode() const;
|
||||
|
||||
void dump(ostream&o, unsigned lm) const;
|
||||
|
||||
private:
|
||||
|
|
@ -753,12 +872,14 @@ class NetMemory {
|
|||
long idxl_;
|
||||
|
||||
friend class NetRamDq;
|
||||
NetRamDq* ram_list_;
|
||||
class NetRamDq* ram_list_;
|
||||
|
||||
friend class NetScope;
|
||||
NetMemory*snext_, *sprev_;
|
||||
NetScope*scope_;
|
||||
|
||||
NetNet*explode_;
|
||||
|
||||
private: // not implemented
|
||||
NetMemory(const NetMemory&);
|
||||
NetMemory& operator= (const NetMemory&);
|
||||
|
|
@ -878,6 +999,8 @@ class NetRamDq : public NetNode {
|
|||
unsigned width() const;
|
||||
unsigned awidth() const;
|
||||
unsigned size() const;
|
||||
|
||||
NetMemory*mem();
|
||||
const NetMemory*mem() const;
|
||||
|
||||
Link& pin_InClock();
|
||||
|
|
@ -908,11 +1031,15 @@ class NetRamDq : public NetNode {
|
|||
// that are ports to the attached memory.
|
||||
unsigned count_partners() const;
|
||||
|
||||
void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
NetMemory*mem_;
|
||||
NetRamDq*next_;
|
||||
unsigned awidth_;
|
||||
|
||||
private:
|
||||
void make_pins_(unsigned wid);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1003,7 +1130,7 @@ class NetExpr : public LineInfo {
|
|||
// Get the Nexus that are the input to this
|
||||
// expression. Normally this descends down to the reference to
|
||||
// a signal that reads from its input.
|
||||
virtual NexusSet* nex_input() =0;
|
||||
virtual NexusSet* nex_input(bool rem_out = true) =0;
|
||||
|
||||
// Return a version of myself that is structural. This is used
|
||||
// for converting expressions to gates.
|
||||
|
|
@ -1044,7 +1171,7 @@ class NetEConst : public NetExpr {
|
|||
|
||||
virtual NetEConst* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
private:
|
||||
verinum value_;
|
||||
|
|
@ -1096,7 +1223,7 @@ class NetECReal : public NetExpr {
|
|||
|
||||
virtual NetECReal* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
private:
|
||||
verireal value_;
|
||||
|
|
@ -1315,7 +1442,7 @@ class NetUDP : public NetNode {
|
|||
* linked into the netlist. However, elaborating a process may cause
|
||||
* special nodes to be created to handle things like events.
|
||||
*/
|
||||
class NetProc : public virtual LineInfo {
|
||||
class NetProc : public virtual LineInfo, public Attrib {
|
||||
|
||||
public:
|
||||
explicit NetProc();
|
||||
|
|
@ -1324,7 +1451,7 @@ class NetProc : public virtual LineInfo {
|
|||
// Find the Nexa that are input by the statement. This is used
|
||||
// for example by @* to find the inputs to the process for the
|
||||
// sensitivity list.
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
// Find the nexa that are set by the statement. Add the output
|
||||
// values to the set passed as a parameter.
|
||||
|
|
@ -1346,15 +1473,33 @@ class NetProc : public virtual LineInfo {
|
|||
// 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);
|
||||
// synthesize as asynchronous logic, and return true. The
|
||||
// sync_flag is used to tell the async synthesizer that the
|
||||
// output nex_map is ultimately connected to a DFF Q
|
||||
// output. This can affect how cycles are handled.
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
bool synth_async_noaccum(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
|
||||
|
||||
// Synthesize synchronous logic, and return true. The nex_out
|
||||
// is where outputs are actually connected, and the nex_map
|
||||
// maps nexa to bit positions. The ff is the initial DFF that
|
||||
// was created to receive the Data inputs. The method *may*
|
||||
// delete that DFF in favor of multiple smaller devices, but
|
||||
// in that case it will set the ff argument to nil.
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
void dump_proc_attr(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
friend class NetBlock;
|
||||
|
|
@ -1432,11 +1577,13 @@ class NetAssign_ {
|
|||
// into a wire.
|
||||
void turn_sig_to_wire_on_release();
|
||||
|
||||
void incr_mem_lref();
|
||||
|
||||
// It is possible that l-values can have *inputs*, as well as
|
||||
// being outputs. For example foo[idx] = ... is the l-value
|
||||
// (NetAssign_ object) with a foo l-value and the input
|
||||
// expression idx.
|
||||
NexusSet* nex_input();
|
||||
NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
// This pointer is for keeping simple lists.
|
||||
NetAssign_* more;
|
||||
|
|
@ -1452,6 +1599,7 @@ class NetAssign_ {
|
|||
bool turn_sig_to_wire_on_release_;
|
||||
unsigned loff_;
|
||||
unsigned lwid_;
|
||||
bool mem_lref_;
|
||||
};
|
||||
|
||||
class NetAssignBase : public NetProc {
|
||||
|
|
@ -1474,7 +1622,7 @@ class NetAssignBase : public NetProc {
|
|||
void set_delay(NetExpr*);
|
||||
const NetExpr* get_delay() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&o);
|
||||
|
||||
|
||||
|
|
@ -1482,13 +1630,24 @@ class NetAssignBase : public NetProc {
|
|||
// accounts for any grouping of NetAssign_ objects that might happen.
|
||||
unsigned lwidth() const;
|
||||
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
// This dumps all the lval structures.
|
||||
void dump_lval(ostream&) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
bool synth_async_mem_sync_(Design*des, NetScope*scope,
|
||||
NetAssign_*cur, NetNet*rsig, unsigned&roff,
|
||||
NetNet*nex_map, NetNet*nex_out);
|
||||
|
||||
private:
|
||||
NetAssign_*lval_;
|
||||
NetExpr *rval_;
|
||||
|
|
@ -1549,11 +1708,13 @@ class NetBlock : public NetProc {
|
|||
|
||||
|
||||
// synthesize as asynchronous logic, and return true.
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
// This version of emit_recurse scans all the statements of
|
||||
|
|
@ -1561,7 +1722,7 @@ class NetBlock : public NetProc {
|
|||
// for sequential blocks.
|
||||
void emit_recurse(struct target_t*) const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual int match_proc(struct proc_match_t*);
|
||||
|
|
@ -1601,15 +1762,21 @@ class NetCase : public NetProc {
|
|||
const NetExpr*expr(unsigned idx) const { return items_[idx].guard;}
|
||||
const NetProc*stat(unsigned idx) const { return items_[idx].statement; }
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
bool synth_async_1hot_(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in,
|
||||
NetNet*esig, unsigned hot_items);
|
||||
private:
|
||||
|
||||
TYPE type_;
|
||||
|
|
@ -1642,7 +1809,7 @@ class NetCAssign : public NetProc, public NetNode {
|
|||
|
||||
const Link& lval_pin(unsigned) const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
|
|
@ -1682,21 +1849,30 @@ class NetCondit : public NetProc {
|
|||
bool emit_recurse_if(struct target_t*) const;
|
||||
bool emit_recurse_else(struct target_t*) const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&o);
|
||||
|
||||
bool is_asynchronous();
|
||||
bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum, bool latch_inferred = false, NetNet *gsig = 0);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
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;
|
||||
|
||||
private:
|
||||
int connect_set_clr_range_( struct sync_accounting_cell*nex_ff,
|
||||
unsigned bits, NetNet*rst,
|
||||
const verinum&val);
|
||||
int connect_enable_range_(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
unsigned bits, NetNet*ce);
|
||||
private:
|
||||
NetExpr* expr_;
|
||||
NetProc*if_;
|
||||
|
|
@ -1845,12 +2021,12 @@ class NetEvent : public LineInfo {
|
|||
NetEvProbe*probes_;
|
||||
|
||||
// Use these methods to list the triggers attached to me.
|
||||
NetEvTrig* trig_;
|
||||
class NetEvTrig* trig_;
|
||||
|
||||
// Use This member to count references by NetEvWait objects.
|
||||
unsigned waitref_;
|
||||
struct wcell_ {
|
||||
NetEvWait*obj;
|
||||
class NetEvWait*obj;
|
||||
struct wcell_*next;
|
||||
};
|
||||
struct wcell_ *wlist_;
|
||||
|
|
@ -1911,11 +2087,14 @@ class NetEvWait : public NetProc {
|
|||
|
||||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
const NetNet*nex_map, NetNet*nex_out);
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
const NetNet*nex_map, NetNet*nex_out,
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out,
|
||||
const svector<NetEvProbe*>&events);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
|
@ -1974,7 +2153,7 @@ class NetForce : public NetProc, public NetNode {
|
|||
|
||||
const NetNet*lval() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
|
|
@ -1997,7 +2176,7 @@ class NetForever : public NetProc {
|
|||
|
||||
void emit_recurse(struct target_t*) const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
|
|
@ -2035,6 +2214,8 @@ class NetFuncDef {
|
|||
const NetNet*return_sig() const;
|
||||
const NetVariable*return_var() const;
|
||||
|
||||
NetNet* synthesize(Design*des, const svector<NetNet*>&inports_);
|
||||
|
||||
void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
|
|
@ -2069,7 +2250,7 @@ class NetPDelay : public NetProc {
|
|||
unsigned long delay() const;
|
||||
const NetExpr*expr() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&);
|
||||
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
|
|
@ -2095,7 +2276,7 @@ class NetRepeat : public NetProc {
|
|||
const NetExpr*expr() const;
|
||||
void emit_recurse(struct target_t*) const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
|
|
@ -2147,7 +2328,7 @@ class NetSTask : public NetProc {
|
|||
|
||||
const NetExpr* parm(unsigned idx) const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
|
@ -2253,7 +2434,9 @@ class NetEUFunc : public NetExpr {
|
|||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEUFunc*dup_expr() const;
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
private:
|
||||
NetScope*func_;
|
||||
|
|
@ -2281,7 +2464,8 @@ class NetUTask : public NetProc {
|
|||
|
||||
const NetScope* task() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
|
|
@ -2304,11 +2488,15 @@ class NetWhile : public NetProc {
|
|||
|
||||
void emit_proc_recurse(struct target_t*) const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope, bool sync_flag,
|
||||
struct sync_accounting_cell*nex_ff,
|
||||
NetNet*nex_map, NetNet*nex_out, NetNet*accum_in, bool latch_inferred = false, NetNet *gsig = 0);
|
||||
|
||||
private:
|
||||
NetExpr* cond_;
|
||||
NetProc*proc_;
|
||||
|
|
@ -2336,14 +2524,14 @@ class NetProcTop : public LineInfo, public Attrib {
|
|||
const NetScope*scope() const;
|
||||
|
||||
/* Return true if this process represents combinational logic. */
|
||||
bool is_asynchronous();
|
||||
bool is_asynchronous() const;
|
||||
|
||||
/* 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();
|
||||
bool is_synchronous() const;
|
||||
|
||||
/* Create synchronous logic from this thread and return true,
|
||||
or return false if that cannot be done. */
|
||||
|
|
@ -2410,7 +2598,7 @@ class NetEBinary : public NetExpr {
|
|||
virtual bool has_width() const;
|
||||
|
||||
virtual NetEBinary* dup_expr() const;
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
|
@ -2523,7 +2711,7 @@ class NetEBComp : public NetEBinary {
|
|||
NetEConst*eval_eqeq_();
|
||||
NetEConst*eval_less_();
|
||||
NetEConst*eval_leeq_();
|
||||
NetEConst*eval_leeq_real_();
|
||||
NetEConst*eval_leeq_real_(bool gt_flag, bool include_eq_flag);
|
||||
NetEConst*eval_gt_();
|
||||
NetEConst*eval_gteq_();
|
||||
NetEConst*eval_neeq_();
|
||||
|
|
@ -2628,7 +2816,7 @@ class NetEConcat : public NetExpr {
|
|||
unsigned nparms() const { return parms_.count() ; }
|
||||
NetExpr* parm(unsigned idx) const { return parms_[idx]; }
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual bool has_width() const;
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual NetEConcat* dup_expr() const;
|
||||
|
|
@ -2661,7 +2849,7 @@ class NetEVariable : public NetExpr {
|
|||
void dump(ostream&) const;
|
||||
|
||||
NetEVariable*dup_expr() const;
|
||||
NexusSet* nex_input();
|
||||
NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
private:
|
||||
NetVariable*var_;
|
||||
|
|
@ -2682,7 +2870,7 @@ class NetEParam : public NetExpr {
|
|||
NetEParam(class Design*des, NetScope*scope, perm_string name);
|
||||
~NetEParam();
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual bool has_width() const;
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
|
|
@ -2718,7 +2906,7 @@ class NetESelect : public NetExpr {
|
|||
const NetExpr*sub_expr() const;
|
||||
const NetExpr*select() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual bool set_width(unsigned w);
|
||||
virtual bool has_width() const;
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
|
|
@ -2745,7 +2933,7 @@ class NetEEvent : public NetExpr {
|
|||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEEvent* dup_expr() const;
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
virtual void dump(ostream&os) const;
|
||||
|
||||
|
|
@ -2768,7 +2956,7 @@ class NetEScope : public NetExpr {
|
|||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEScope* dup_expr() const;
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
virtual void dump(ostream&os) const;
|
||||
|
||||
|
|
@ -2796,7 +2984,7 @@ class NetESFunc : public NetExpr {
|
|||
const NetExpr* parm(unsigned idx) const;
|
||||
|
||||
virtual TYPE expr_type() const;
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual bool set_width(unsigned);
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -2834,7 +3022,7 @@ class NetETernary : public NetExpr {
|
|||
virtual NetETernary* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet*synthesize(Design*);
|
||||
|
|
@ -2874,7 +3062,7 @@ class NetEUnary : public NetExpr {
|
|||
virtual NetEUnary* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -2924,11 +3112,11 @@ class NetEMemory : public NetExpr {
|
|||
const NetExpr* index() const;
|
||||
|
||||
virtual bool set_width(unsigned);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
NetExpr* eval_tree();
|
||||
virtual NetEMemory*dup_expr() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -2962,7 +3150,7 @@ class NetESignal : public NetExpr {
|
|||
|
||||
virtual NetESignal* dup_expr() const;
|
||||
NetNet* synthesize(Design*des);
|
||||
NexusSet* nex_input();
|
||||
NexusSet* nex_input(bool rem_out = true);
|
||||
|
||||
// These methods actually reference the properties of the
|
||||
// NetNet object that I point to.
|
||||
|
|
@ -3004,8 +3192,9 @@ class NetEBitSel : public NetExpr {
|
|||
const NetNet* sig() const;
|
||||
|
||||
NetEBitSel* dup_expr() const;
|
||||
NetNet* synthesize(Design*des);
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
|
|
@ -3357,6 +3546,81 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.321.2.25 2007/05/30 17:48:53 steve
|
||||
* Support Latch synthesis (Alan Feldstein)
|
||||
*
|
||||
* Revision 1.321.2.24 2006/11/26 01:54:05 steve
|
||||
* Add synthesis of user defined functions.
|
||||
*
|
||||
* Revision 1.321.2.23 2006/08/15 03:41:24 steve
|
||||
* Improve performance of unlink of heavily connected nexa.
|
||||
*
|
||||
* Revision 1.321.2.22 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.321.2.21 2006/07/23 19:42:33 steve
|
||||
* Handle statement output override better in blocks.
|
||||
*
|
||||
* Revision 1.321.2.20 2006/07/10 00:21:51 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.321.2.19 2006/06/23 03:49:46 steve
|
||||
* synthesis of NetCondit handles partial resets.
|
||||
*
|
||||
* Revision 1.321.2.18 2006/06/14 03:02:54 steve
|
||||
* synthesis for NetEBitSel.
|
||||
*
|
||||
* Revision 1.321.2.17 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.321.2.16 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.321.2.15 2006/04/10 03:43:39 steve
|
||||
* Exploded memories accessed by constant indices.
|
||||
*
|
||||
* Revision 1.321.2.14 2006/03/26 23:09:23 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.321.2.13 2006/03/18 18:43:21 steve
|
||||
* Better error messages when synthesis fails.
|
||||
*
|
||||
* Revision 1.321.2.12 2006/03/16 05:40:18 steve
|
||||
* Fix crash when memory exploding doesnot work
|
||||
*
|
||||
* Revision 1.321.2.11 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.321.2.10 2006/02/19 00:11:32 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.321.2.9 2006/01/21 21:42:31 steve
|
||||
* When mux has wide select but sparse choices, use 1hot translation.
|
||||
*
|
||||
* Revision 1.321.2.8 2006/01/18 01:23:24 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.321.2.7 2005/12/31 04:28:14 steve
|
||||
* Fix crashes caused bu synthesis of sqrt32.v.
|
||||
*
|
||||
* Revision 1.321.2.6 2005/12/14 00:54:29 steve
|
||||
* Account for sync vs async muxes.
|
||||
*
|
||||
* Revision 1.321.2.5 2005/11/13 22:28:48 steve
|
||||
* Allow for block output to be set throughout the statements.
|
||||
*
|
||||
* Revision 1.321.2.4 2005/09/09 02:17:08 steve
|
||||
* Evaluate magnitude compare with real operands.
|
||||
*
|
||||
* Revision 1.321.2.3 2005/08/22 01:00:41 steve
|
||||
* Add support for implicit defaults in case and conditions.
|
||||
*
|
||||
* Revision 1.321.2.2 2005/08/13 00:45:54 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.321.2.1 2005/07/06 22:41:34 steve
|
||||
* Fix compile errors with g++-4.
|
||||
*
|
||||
* Revision 1.321 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
25
netmisc.cc
25
netmisc.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.cc,v 1.8 2004/02/20 18:53:35 steve Exp $"
|
||||
#ident "$Id: netmisc.cc,v 1.8.2.1 2006/05/15 03:55:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -72,6 +72,26 @@ NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
|||
return res;
|
||||
}
|
||||
|
||||
NetNet* reduction_or(Design*des, NetNet*isig)
|
||||
{
|
||||
NetScope*scope = isig->scope();
|
||||
|
||||
NetLogic*olog = new NetLogic(scope, scope->local_symbol(),
|
||||
isig->pin_count()+1, NetLogic::OR);
|
||||
olog->set_line(*isig);
|
||||
des->add_node(olog);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->local_flag(true);
|
||||
osig->set_line(*isig);
|
||||
|
||||
connect(olog->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < isig->pin_count() ; idx += 1)
|
||||
connect(olog->pin(1+idx), isig->pin(idx));
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
||||
{
|
||||
|
|
@ -90,6 +110,9 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
|
|||
|
||||
/*
|
||||
* $Log: netmisc.cc,v $
|
||||
* Revision 1.8.2.1 2006/05/15 03:55:23 steve
|
||||
* Fix synthesis of expressions with land of vectors.
|
||||
*
|
||||
* Revision 1.8 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
10
netmisc.h
10
netmisc.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.h,v 1.19 2004/03/07 20:04:11 steve Exp $"
|
||||
#ident "$Id: netmisc.h,v 1.19.2.1 2006/05/15 03:55:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -57,6 +57,11 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
|
|||
*/
|
||||
extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
|
||||
|
||||
/*
|
||||
* Calculate the reduction OR from the input signal.
|
||||
*/
|
||||
extern NetNet*reduction_or(Design*des, NetNet*sig);
|
||||
|
||||
/*
|
||||
* In some cases the lval is accessible as a pointer to the head of
|
||||
* a list of NetAssign_ objects. This function returns the width of
|
||||
|
|
@ -75,6 +80,9 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
|
|||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.19.2.1 2006/05/15 03:55:23 steve
|
||||
* Fix synthesis of expressions with land of vectors.
|
||||
*
|
||||
* Revision 1.19 2004/03/07 20:04:11 steve
|
||||
* MOre thorough use of elab_and_eval function.
|
||||
*
|
||||
|
|
|
|||
14
nodangle.cc
14
nodangle.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: nodangle.cc,v 1.21 2004/02/20 18:53:35 steve Exp $"
|
||||
#ident "$Id: nodangle.cc,v 1.21.2.2 2006/08/23 04:08:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -109,6 +109,9 @@ void nodangle_f::signal(Design*des, NetNet*sig)
|
|||
if (sig->get_refs() > 0)
|
||||
return;
|
||||
|
||||
if (sig->mref())
|
||||
return;
|
||||
|
||||
/* Cannot delete the ports of tasks or functions. There are
|
||||
too many places where they are referenced. */
|
||||
if ((sig->port_type() != NetNet::NOT_A_PORT)
|
||||
|
|
@ -160,6 +163,9 @@ void nodangle_f::signal(Design*des, NetNet*sig)
|
|||
if (cursig == 0)
|
||||
continue;
|
||||
|
||||
if (cursig == sig)
|
||||
continue;
|
||||
|
||||
if (cursig->local_flag())
|
||||
continue;
|
||||
|
||||
|
|
@ -205,6 +211,12 @@ void nodangle(Design*des)
|
|||
|
||||
/*
|
||||
* $Log: nodangle.cc,v $
|
||||
* Revision 1.21.2.2 2006/08/23 04:08:55 steve
|
||||
* Do not count self as signifincant in nodangle.
|
||||
*
|
||||
* Revision 1.21.2.1 2006/03/16 05:40:19 steve
|
||||
* Fix crash when memory exploding doesnot work
|
||||
*
|
||||
* Revision 1.21 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
|
|
|
|||
234
parse.y
234
parse.y
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse.y,v 1.201 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.201.2.8 2007/04/26 00:50:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -134,9 +134,10 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
|||
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
|
||||
%token K_always K_and K_assign K_begin K_buf K_bufif0 K_bufif1 K_case
|
||||
%token K_casex K_casez K_cmos K_deassign K_default K_defparam K_disable
|
||||
%token K_edge K_else K_end K_endcase K_endfunction K_endmodule
|
||||
%token K_edge K_edge_descriptor
|
||||
%token K_else K_end K_endcase K_endfunction K_endmodule
|
||||
%token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for
|
||||
%token K_force K_forever K_fork K_function K_highz0 K_highz1 K_if
|
||||
%token K_force K_forever K_fork K_function K_highz0 K_highz1 K_if K_ifnone
|
||||
%token K_initial K_inout K_input K_integer K_join K_large K_localparam
|
||||
%token K_macromodule
|
||||
%token K_medium K_module K_nand K_negedge K_nmos K_nor K_not K_notif0
|
||||
|
|
@ -191,11 +192,11 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
|
|||
%type <gate> gate_instance
|
||||
%type <gates> gate_instance_list
|
||||
|
||||
%type <expr> expression expr_primary
|
||||
%type <expr> expression expr_primary expr_mintypmax
|
||||
%type <expr> lavalue lpvalue
|
||||
%type <expr> delay_value delay_value_simple
|
||||
%type <exprs> delay1 delay3 delay3_opt
|
||||
%type <exprs> expression_list
|
||||
%type <exprs> expression_list expression_list_proper
|
||||
%type <exprs> assign assign_list
|
||||
|
||||
%type <exprs> range range_opt
|
||||
|
|
@ -287,7 +288,7 @@ attribute
|
|||
}
|
||||
| IDENTIFIER '=' expression
|
||||
{ PExpr*tmp = $3;
|
||||
if (!pform_expression_is_constant(tmp)) {
|
||||
if (tmp && !pform_expression_is_constant(tmp)) {
|
||||
yyerror(@3, "error: attribute value "
|
||||
"expression must be constant.");
|
||||
delete tmp;
|
||||
|
|
@ -308,17 +309,14 @@ attribute
|
|||
integers. This rule matches those declarations. The containing
|
||||
rule has presumably set up the scope. */
|
||||
block_item_decl
|
||||
: attribute_list_opt K_reg signed_opt range register_variable_list ';'
|
||||
{ pform_set_net_range($5, $4, $3);
|
||||
if ($1) delete $1;
|
||||
: K_reg signed_opt range register_variable_list ';'
|
||||
{ pform_set_net_range($4, $3, $2);
|
||||
}
|
||||
| attribute_list_opt K_reg signed_opt register_variable_list ';'
|
||||
{ pform_set_net_range($4, 0, $3);
|
||||
if ($1) delete $1;
|
||||
| K_reg signed_opt register_variable_list ';'
|
||||
{ pform_set_net_range($3, 0, $2);
|
||||
}
|
||||
| attribute_list_opt K_integer register_variable_list ';'
|
||||
{ pform_set_reg_integer($3);
|
||||
if ($1) delete $1;
|
||||
| K_integer register_variable_list ';'
|
||||
{ pform_set_reg_integer($2);
|
||||
}
|
||||
| K_time register_variable_list ';'
|
||||
{ pform_set_reg_time($2);
|
||||
|
|
@ -335,15 +333,13 @@ block_item_decl
|
|||
/* Recover from errors that happen within variable lists. Use the
|
||||
trailing semi-colon to resync the parser. */
|
||||
|
||||
| attribute_list_opt K_reg error ';'
|
||||
{ yyerror(@2, "error: syntax error in reg variable list.");
|
||||
| K_reg error ';'
|
||||
{ yyerror(@1, "error: syntax error in reg variable list.");
|
||||
yyerrok;
|
||||
if ($1) delete $1;
|
||||
}
|
||||
| attribute_list_opt K_integer error ';'
|
||||
{ yyerror(@2, "error: syntax error in integer variable list.");
|
||||
| K_integer error ';'
|
||||
{ yyerror(@1, "error: syntax error in integer variable list.");
|
||||
yyerrok;
|
||||
if ($1) delete $1;
|
||||
}
|
||||
| K_time error ';'
|
||||
{ yyerror(@1, "error: syntax error in time variable list.");
|
||||
|
|
@ -882,6 +878,30 @@ expression
|
|||
}
|
||||
;
|
||||
|
||||
expr_mintypmax
|
||||
: expression
|
||||
{ $$ = $1; }
|
||||
| expression ':' expression ':' expression
|
||||
{ switch (min_typ_max_flag) {
|
||||
case MIN:
|
||||
$$ = $1;
|
||||
delete $3;
|
||||
delete $5;
|
||||
break;
|
||||
case TYP:
|
||||
delete $1;
|
||||
$$ = $3;
|
||||
delete $5;
|
||||
break;
|
||||
case MAX:
|
||||
delete $1;
|
||||
delete $3;
|
||||
$$ = $5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/* Many contexts take a comma separated list of expressions. Null
|
||||
expressions can happen anywhere in the list, so there are two
|
||||
|
|
@ -910,6 +930,19 @@ expression_list
|
|||
}
|
||||
;
|
||||
|
||||
expression_list_proper
|
||||
: expression_list_proper ',' expression
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| expression
|
||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
||||
(*tmp)[0] = $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
expr_primary
|
||||
: number
|
||||
|
|
@ -975,12 +1008,20 @@ expr_primary
|
|||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| '(' expression ')'
|
||||
| '(' expr_mintypmax ')'
|
||||
{ $$ = $2; }
|
||||
| '{' expression_list '}'
|
||||
{ PEConcat*tmp = new PEConcat(*$2);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
for (unsigned idx = 0 ; idx < (*$2).count() ; idx += 1) {
|
||||
PExpr*ex = (*$2)[idx];
|
||||
if (ex == 0) {
|
||||
yyerror(@1, "error: Null arguments not allowed"
|
||||
" in repeat expressions.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -990,7 +1031,6 @@ expr_primary
|
|||
yyerror(@2, "error: Repeat expression "
|
||||
"must be constant.");
|
||||
delete rep;
|
||||
delete $2;
|
||||
rep = 0;
|
||||
}
|
||||
PEConcat*tmp = new PEConcat(*$4, rep);
|
||||
|
|
@ -1028,6 +1068,14 @@ function_item
|
|||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have output ports.");
|
||||
}
|
||||
| K_output K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have output ports.");
|
||||
}
|
||||
| K_inout range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, false,
|
||||
|
|
@ -1036,7 +1084,15 @@ function_item
|
|||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have inout ports.");
|
||||
}
|
||||
| block_item_decl
|
||||
| K_inout K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
yyerror(@1, "Functions may not have inout ports.");
|
||||
}
|
||||
| attribute_list_opt block_item_decl
|
||||
{ $$ = 0; }
|
||||
;
|
||||
|
||||
|
|
@ -1583,7 +1639,8 @@ module_item
|
|||
/* block_item_decl rule is shared with task blocks and named
|
||||
begin/end. */
|
||||
|
||||
| block_item_decl
|
||||
| attribute_list_opt block_item_decl
|
||||
{ ; }
|
||||
|
||||
/* */
|
||||
|
||||
|
|
@ -2265,8 +2322,11 @@ specify_item
|
|||
| K_if '(' expression ')' specify_edge_path_decl ';'
|
||||
{
|
||||
}
|
||||
| K_ifnone specify_simple_path_decl ';'
|
||||
{
|
||||
}
|
||||
| K_Shold '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Speriod '(' spec_reference_event ',' delay_value
|
||||
|
|
@ -2274,11 +2334,11 @@ specify_item
|
|||
{ delete $5;
|
||||
}
|
||||
| K_Srecovery '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Ssetup '(' spec_reference_event ',' spec_reference_event
|
||||
',' expression spec_notifier_opt ')' ';'
|
||||
',' delay_value spec_notifier_opt ')' ';'
|
||||
{ delete $7;
|
||||
}
|
||||
| K_Ssetuphold '(' spec_reference_event ',' spec_reference_event
|
||||
|
|
@ -2296,14 +2356,18 @@ specify_item
|
|||
{ delete $5;
|
||||
delete $7;
|
||||
}
|
||||
| K_Swidth '(' spec_reference_event ',' expression ')' ';'
|
||||
| K_Swidth '(' spec_reference_event ',' delay_value ')' ';'
|
||||
{ delete $5;
|
||||
}
|
||||
;
|
||||
|
||||
specify_delay_value_list
|
||||
: delay_value { }
|
||||
| specify_delay_value_list ',' delay_value { }
|
||||
: delay_value
|
||||
{ delete $1;
|
||||
}
|
||||
| specify_delay_value_list ',' delay_value
|
||||
{ delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
specify_item_list
|
||||
|
|
@ -2316,15 +2380,19 @@ specify_edge_path_decl
|
|||
| specify_edge_path '=' delay_value_simple
|
||||
;
|
||||
|
||||
specify_edge_operator
|
||||
: K_posedge
|
||||
| K_negedge
|
||||
;
|
||||
|
||||
/* The first two rules are not in development. */
|
||||
specify_edge_path
|
||||
: '(' K_posedge specify_path_identifiers spec_polarity K_EG IDENTIFIER ')'
|
||||
| '(' K_posedge specify_path_identifiers spec_polarity K_EG '(' expr_primary polarity_operator expression ')' ')'
|
||||
| '(' K_posedge specify_path_identifiers spec_polarity K_SG IDENTIFIER ')'
|
||||
| '(' K_posedge specify_path_identifiers spec_polarity K_SG '(' expr_primary polarity_operator expression ')' ')'
|
||||
| '(' K_negedge specify_path_identifiers spec_polarity K_EG IDENTIFIER ')'
|
||||
| '(' K_negedge specify_path_identifiers spec_polarity K_EG '(' expr_primary polarity_operator expression ')' ')'
|
||||
| '(' K_negedge specify_path_identifiers spec_polarity K_SG IDENTIFIER ')'
|
||||
| '(' K_negedge specify_path_identifiers spec_polarity K_SG '(' expr_primary polarity_operator expression ')' ')'
|
||||
: '(' specify_edge_operator specify_path_identifiers spec_polarity K_EG IDENTIFIER ')'
|
||||
| '(' specify_edge_operator specify_path_identifiers spec_polarity K_SG IDENTIFIER ')'
|
||||
| '(' specify_path_identifiers spec_polarity K_EG '(' specify_path_identifiers polarity_operator expression ')' ')'
|
||||
| '(' specify_edge_operator specify_path_identifiers spec_polarity K_EG '(' specify_path_identifiers polarity_operator expression ')' ')'
|
||||
| '(' specify_path_identifiers spec_polarity K_SG '(' specify_path_identifiers polarity_operator expression ')' ')'
|
||||
| '(' specify_edge_operator specify_path_identifiers spec_polarity K_SG '(' specify_path_identifiers polarity_operator expression ')' ')'
|
||||
;
|
||||
|
||||
polarity_operator
|
||||
|
|
@ -2436,6 +2504,12 @@ spec_reference_event
|
|||
{ delete $2;
|
||||
delete $4;
|
||||
}
|
||||
| K_edge '[' edge_descriptor_list ']' expr_primary
|
||||
{ delete $5; }
|
||||
| K_edge '[' edge_descriptor_list ']' expr_primary K_TAND expression
|
||||
{ delete $5;
|
||||
delete $7;
|
||||
}
|
||||
| expr_primary K_TAND expression
|
||||
{ delete $1;
|
||||
delete $3;
|
||||
|
|
@ -2444,6 +2518,11 @@ spec_reference_event
|
|||
{ delete $1; }
|
||||
;
|
||||
|
||||
edge_descriptor_list
|
||||
: edge_descriptor_list ',' K_edge_descriptor
|
||||
| K_edge_descriptor
|
||||
;
|
||||
|
||||
spec_notifier_opt
|
||||
: /* empty */
|
||||
{ }
|
||||
|
|
@ -2458,7 +2537,10 @@ spec_notifier
|
|||
| spec_notifier ','
|
||||
{ }
|
||||
| spec_notifier ',' identifier
|
||||
{ delete $3;
|
||||
{ delete $3; }
|
||||
| spec_notifier ',' identifier '[' expr_primary ']'
|
||||
{ delete $3;
|
||||
delete $5;
|
||||
}
|
||||
| IDENTIFIER
|
||||
{ delete $1; }
|
||||
|
|
@ -2541,9 +2623,9 @@ statement
|
|||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_begin error K_end
|
||||
/* | K_begin error K_end
|
||||
{ yyerrok; }
|
||||
|
||||
*/
|
||||
/* fork-join blocks are very similar to begin-end blocks. In fact,
|
||||
from the parser's perspective there is no real difference. All we
|
||||
need to do is remember that this is a parallel block so that the
|
||||
|
|
@ -2690,28 +2772,34 @@ statement
|
|||
tmp->set_lineno(@1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| event_control statement_opt
|
||||
| event_control attribute_list_opt statement_opt
|
||||
{ PEventStatement*tmp = $1;
|
||||
if (tmp == 0) {
|
||||
yyerror(@1, "error: Invalid event control.");
|
||||
$$ = 0;
|
||||
} else {
|
||||
tmp->set_statement($2);
|
||||
pform_attach_attributes($3, $2);
|
||||
tmp->set_statement($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
if ($2) delete $2;
|
||||
}
|
||||
| '@' '*' statement_opt
|
||||
| '@' '*' attribute_list_opt statement_opt
|
||||
{ PEventStatement*tmp = new PEventStatement;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
tmp->set_statement($3);
|
||||
pform_attach_attributes($4, $3);
|
||||
tmp->set_statement($4);
|
||||
if ($3) delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| '@' '(' '*' ')' statement_opt
|
||||
| '@' '(' '*' ')' attribute_list_opt statement_opt
|
||||
{ PEventStatement*tmp = new PEventStatement;
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
tmp->set_statement($5);
|
||||
pform_attach_attributes($6, $5);
|
||||
tmp->set_statement($6);
|
||||
if ($5) delete $5;
|
||||
$$ = tmp;
|
||||
}
|
||||
| lpvalue '=' expression ';'
|
||||
|
|
@ -2796,7 +2884,7 @@ statement
|
|||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier '(' expression_list ')' ';'
|
||||
| identifier '(' expression_list_proper ')' ';'
|
||||
{ PCallTask*tmp = new PCallTask(*$1, *$3);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
|
|
@ -2804,6 +2892,19 @@ statement
|
|||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
/* NOTE: The standard doesn't really support an empty argument list
|
||||
between parentheses, but it seems natural, and people commonly
|
||||
want it. So accept it explicitly. */
|
||||
|
||||
| identifier '(' ')' ';'
|
||||
{ svector<PExpr*>pt (0);
|
||||
PCallTask*tmp = new PCallTask(*$1, pt);
|
||||
tmp->set_file(@1.text);
|
||||
tmp->set_lineno(@1.first_line);
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
| identifier ';'
|
||||
{ svector<PExpr*>pt (0);
|
||||
PCallTask*tmp = new PCallTask(*$1, pt);
|
||||
|
|
@ -2820,14 +2921,18 @@ statement
|
|||
;
|
||||
|
||||
statement_list
|
||||
: statement_list statement
|
||||
{ svector<Statement*>*tmp = new svector<Statement*>(*$1, $2);
|
||||
: statement_list attribute_list_opt statement
|
||||
{ pform_attach_attributes($3, $2);
|
||||
svector<Statement*>*tmp = new svector<Statement*>(*$1, $3);
|
||||
delete $1;
|
||||
if ($2) delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| statement
|
||||
{ svector<Statement*>*tmp = new svector<Statement*>(1);
|
||||
(*tmp)[0] = $1;
|
||||
| attribute_list_opt statement
|
||||
{ pform_attach_attributes($2, $1);
|
||||
svector<Statement*>*tmp = new svector<Statement*>(1);
|
||||
(*tmp)[0] = $2;
|
||||
if ($1) delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
@ -2848,6 +2953,13 @@ task_item
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_input K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINPUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT, false,
|
||||
|
|
@ -2855,6 +2967,13 @@ task_item
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_output K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::POUTPUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT, false,
|
||||
|
|
@ -2862,6 +2981,13 @@ task_item
|
|||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_inout K_signed range_opt list_of_identifiers ';'
|
||||
{ svector<PWire*>*tmp
|
||||
= pform_make_task_ports(NetNet::PINOUT, true,
|
||||
$3, $4,
|
||||
@1.text, @1.first_line);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
||||
task_item_list
|
||||
|
|
|
|||
11
parse_api.h
11
parse_api.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: parse_api.h,v 1.3 2004/02/18 17:11:57 steve Exp $"
|
||||
#ident "$Id: parse_api.h,v 1.3.2.1 2005/08/13 00:45:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
|
@ -35,8 +35,8 @@ class PUdp;
|
|||
* Verilog source into pform for elaboration. The parser adds modules
|
||||
* to these maps as it compiles modules in the verilog source.
|
||||
*/
|
||||
extern map<perm_string,Module*> pform_modules;
|
||||
extern map<perm_string,PUdp*> pform_primitives;
|
||||
extern std::map<perm_string,Module*> pform_modules;
|
||||
extern std::map<perm_string,PUdp*> pform_primitives;
|
||||
|
||||
/*
|
||||
* This code actually invokes the parser to make modules. The first
|
||||
|
|
@ -47,10 +47,13 @@ extern map<perm_string,PUdp*> pform_primitives;
|
|||
*/
|
||||
extern int pform_parse(const char*path, FILE*file =0);
|
||||
|
||||
extern string vl_file;
|
||||
extern std::string vl_file;
|
||||
|
||||
/*
|
||||
* $Log: parse_api.h,v $
|
||||
* Revision 1.3.2.1 2005/08/13 00:45:54 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.3 2004/02/18 17:11:57 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
|
|
|||
18
pform.cc
18
pform.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.cc,v 1.129 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.129.2.1 2006/07/10 00:21:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -203,6 +203,19 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
|||
return res;
|
||||
}
|
||||
|
||||
void pform_attach_attributes(Statement*obj, svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
if (obj == 0)
|
||||
return;
|
||||
if (attr == 0)
|
||||
return;
|
||||
|
||||
for (unsigned idx = 0 ; idx < attr->count() ; idx += 1) {
|
||||
named_pexpr_t*tmp = (*attr)[idx];
|
||||
obj->attributes[tmp->name] = tmp->parm;
|
||||
}
|
||||
}
|
||||
|
||||
void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
|
|
@ -1597,6 +1610,9 @@ int pform_parse(const char*path, FILE*file)
|
|||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.129.2.1 2006/07/10 00:21:53 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.129 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
9
pform.h
9
pform.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.h,v 1.81 2004/08/26 04:02:04 steve Exp $"
|
||||
#ident "$Id: pform.h,v 1.81.2.1 2006/07/10 00:21:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
|
@ -37,6 +37,8 @@
|
|||
# include <string>
|
||||
# include <list>
|
||||
# include <stdio.h>
|
||||
# include <cstring>
|
||||
# include <cstdlib>
|
||||
|
||||
/*
|
||||
* These classes implement the parsed form (P-form for short) of the
|
||||
|
|
@ -219,6 +221,8 @@ extern void pform_set_attrib(perm_string name, perm_string key,
|
|||
extern void pform_set_type_attrib(perm_string name, const string&key,
|
||||
char*value);
|
||||
|
||||
extern void pform_attach_attributes(Statement*obj, svector<named_pexpr_t*>*attr);
|
||||
|
||||
extern void pform_set_parameter(perm_string name,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
|
|
@ -298,6 +302,9 @@ extern void pform_dump(ostream&out, Module*mod);
|
|||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.81.2.1 2006/07/10 00:21:53 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.81 2004/08/26 04:02:04 steve
|
||||
* Add support for localparam ranges.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.88 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: pform_dump.cc,v 1.88.2.1 2006/07/10 00:21:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -360,10 +360,14 @@ void PGModule::dump(ostream&out) const
|
|||
out << " " << type_ << " ";
|
||||
|
||||
// If parameters are overridden by order, dump them.
|
||||
if (overrides_) {
|
||||
if (overrides_ && overrides_->count() > 0) {
|
||||
assert(parms_ == 0);
|
||||
out << "#(";
|
||||
out << *((*overrides_)[0]);
|
||||
|
||||
if ((*overrides_)[0] == 0)
|
||||
out << "<nil>";
|
||||
else
|
||||
out << *((*overrides_)[0]);
|
||||
for (unsigned idx = 1 ; idx < overrides_->count() ; idx += 1) {
|
||||
out << "," << *((*overrides_)[idx]);
|
||||
}
|
||||
|
|
@ -418,6 +422,19 @@ void Statement::dump(ostream&out, unsigned ind) const
|
|||
out << setw(ind) << "";
|
||||
out << "/* " << get_line() << ": " << typeid(*this).name()
|
||||
<< " */ ;" << endl;
|
||||
dump_attributes(out, ind+2);
|
||||
}
|
||||
|
||||
void Statement::dump_attributes(ostream&out, unsigned ind) const
|
||||
{
|
||||
for (map<perm_string,PExpr*>::const_iterator idx = attributes.begin()
|
||||
; idx != attributes.end()
|
||||
; idx ++) {
|
||||
out << setw(ind) << "" << "(* " << (*idx).first;
|
||||
if ((*idx).second)
|
||||
out << " = " << *(*idx).second;
|
||||
out << " *)" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PAssign::dump(ostream&out, unsigned ind) const
|
||||
|
|
@ -487,6 +504,8 @@ void PCase::dump(ostream&out, unsigned ind) const
|
|||
}
|
||||
out << " (" << *expr_ << ") /* " << get_line() << " */" << endl;
|
||||
|
||||
dump_attributes(out, ind+2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
||||
PCase::Item*cur = (*items_)[idx];
|
||||
|
||||
|
|
@ -909,6 +928,9 @@ void PUdp::dump(ostream&out) const
|
|||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.88.2.1 2006/07/10 00:21:54 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.88 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# This is a debug conf file that the scripts/devel-stub.sh script uses
|
||||
# to control the ivl core. The contents of this file are normally written
|
||||
# to a temporary file by the driver program, but for devel purposes, where
|
||||
# the driver program is not used, this config substitutes.
|
||||
#
|
||||
# NOTE: DO NOT INSTALL THIS FILE!
|
||||
#
|
||||
iwidth:32
|
||||
sys_func:vpi/system.sft
|
||||
warnings:implicit
|
||||
debug:eval_tree
|
||||
debug:elaborate
|
||||
debug:scope
|
||||
debug:synth
|
||||
debug:cprop
|
||||
out:a.out
|
||||
ivlpp:./ivlpp/ivlpp -D__ICARUS__ -L -Pfoo.pp
|
||||
sys_func:scripts/devel-stub.sft
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
# This is an example function table.
|
||||
$realtime vpiSysFuncReal
|
||||
|
||||
$verywide vpiSysFuncSized 128 signed
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
# This is a little developer convenience script to run the ivl core program
|
||||
# in place with the stub target. It runs the ivl core verbose, with diagnostic
|
||||
# output files enable, and without the driver program or preprocessor.
|
||||
# It is useful only for development of the ivl core program.
|
||||
#
|
||||
# Run this script in the source directory for the ivl core program so that
|
||||
# the patch to the other components is correct.
|
||||
#
|
||||
# NOTE: DO NOT INSTALL THIS FILE.
|
||||
|
||||
./ivl -v -Ctgt-stub/stub.conf -C./scripts/devel-stub.conf -Pa.pf -Na.net -fDLL=tgt-stub/stub.tgt foo.vl
|
||||
|
||||
echo "*** ivl command completed, rc=$?"
|
||||
14
set_width.cc
14
set_width.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: set_width.cc,v 1.34 2003/08/28 04:11:19 steve Exp $"
|
||||
#ident "$Id: set_width.cc,v 1.34.2.1 2005/03/05 01:36:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -167,12 +167,13 @@ bool NetEBDiv::set_width(unsigned w)
|
|||
return w == expr_width();
|
||||
}
|
||||
|
||||
/*
|
||||
* The logical binary operators do not care what the widths of their
|
||||
* operands are, the output is always 1 bit. The operands are
|
||||
* self-determined, so a set_width is stopped here.
|
||||
*/
|
||||
bool NetEBLogic::set_width(unsigned w)
|
||||
{
|
||||
bool flag;
|
||||
flag = left_->set_width(right_->expr_width());
|
||||
if (!flag)
|
||||
flag = right_->set_width(left_->expr_width());
|
||||
return (w == 1);
|
||||
}
|
||||
|
||||
|
|
@ -411,6 +412,9 @@ bool NetEUReduce::set_width(unsigned w)
|
|||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.34.2.1 2005/03/05 01:36:16 steve
|
||||
* Fix set_width to allow binary logical operands to be self determined.
|
||||
*
|
||||
* Revision 1.34 2003/08/28 04:11:19 steve
|
||||
* Spelling patch.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# $Id: README-solaris_pkg.txt,v 1.2 2004/10/04 01:10:56 steve Exp $
|
||||
# $Id: README-solaris_pkg.txt,v 1.2.2.1 2007/02/26 19:51:39 steve Exp $
|
||||
|
||||
Notes about the solaris package.
|
||||
|
||||
I. Installing a prebuild solaris package
|
||||
I. Installing a prebuilt solaris package
|
||||
-----------------------------------------
|
||||
|
||||
To install the solaris package do the following as root on your machine:
|
||||
|
|
@ -24,10 +24,10 @@ To install the solaris package do the following as root on your machine:
|
|||
this will install the package. The package will be registered under the
|
||||
name "IVLver"
|
||||
|
||||
II. Deinstalling the solaris package
|
||||
II. Uninstalling the solaris package
|
||||
-------------------------------------
|
||||
|
||||
To deinstall an installed solaris package do the following as root on your machine:
|
||||
To uninstall an installed solaris package do the following as root on your machine:
|
||||
|
||||
pkgrm IVLver
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
PKG="IVLver"
|
||||
NAME="verilog"
|
||||
ARCH="sparc"
|
||||
VERSION="0.7"
|
||||
VERSION="0.8"
|
||||
CATEGORY="application"
|
||||
VENDOR="Icarus.com"
|
||||
EMAIL="steve@icarus.com"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ f none bin/iverilog 0755 bin bin
|
|||
f none bin/iverilog-vpi 0755 bin bin
|
||||
f none bin/vvp 0755 bin bin
|
||||
d none include 0755 bin bin
|
||||
f none include/_pli_types.h 0644 bin bin
|
||||
f none include/acc_user.h 0644 bin bin
|
||||
f none include/ivl_target.h 0644 bin bin
|
||||
f none include/veriuser.h 0644 bin bin
|
||||
|
|
@ -11,12 +12,21 @@ f none include/vpi_user.h 0644 bin bin
|
|||
d none lib 0755 bin bin
|
||||
d none lib/ivl 0755 bin bin
|
||||
f none lib/ivl/fpga.tgt 0644 bin bin
|
||||
f none lib/ivl/fpga.conf 0644 bin bin
|
||||
f none lib/ivl/fpga-s.conf 0644 bin bin
|
||||
f none lib/ivl/iverilog.conf 0644 bin bin
|
||||
f none lib/ivl/ivl 0755 bin bin
|
||||
f none lib/ivl/ivlpp 0755 bin bin
|
||||
f none lib/ivl/null.tgt 0644 bin bin
|
||||
f none lib/ivl/null.conf 0644 bin bin
|
||||
f none lib/ivl/null-s.conf 0644 bin bin
|
||||
f none lib/ivl/system.vpi 0644 bin bin
|
||||
f none lib/ivl/system.sft 0644 bin bin
|
||||
f none lib/ivl/vvp.tgt 0644 bin bin
|
||||
f none lib/ivl/vvp.conf 0644 bin bin
|
||||
f none lib/ivl/vvp-s.conf 0644 bin bin
|
||||
f none lib/ivl/xnf.conf 0644 bin bin
|
||||
f none lib/ivl/xnf-s.conf 0644 bin bin
|
||||
f none lib/libveriuser.a 0644 bin bin
|
||||
f none lib/libvpi.a 0644 bin bin
|
||||
d none man 0755 bin bin
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: svector.h,v 1.9 2003/07/23 02:35:44 steve Exp $"
|
||||
#ident "$Id: svector.h,v 1.9.2.1 2005/06/14 15:33:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -101,14 +101,17 @@ template <class TYPE> class svector {
|
|||
* Override the implementation of the above template for the string
|
||||
* type parameter. The initialization to nil works different here.
|
||||
*/
|
||||
inline svector<string>::svector<string>(unsigned size)
|
||||
: nitems_(size), items_(new string[size])
|
||||
template <> inline svector<std::string>::svector(unsigned size)
|
||||
: nitems_(size), items_(new std::string[size])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: svector.h,v $
|
||||
* Revision 1.9.2.1 2005/06/14 15:33:54 steve
|
||||
* Fix gcc4 build issues.
|
||||
*
|
||||
* Revision 1.9 2003/07/23 02:35:44 steve
|
||||
* Inline the svector<string> constructor.
|
||||
*
|
||||
|
|
|
|||
7
sync.cc
7
sync.cc
|
|
@ -17,7 +17,7 @@
|
|||
* 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 $"
|
||||
#ident "$Id: sync.cc,v 1.3.2.1 2007/05/30 17:48:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -57,7 +57,7 @@ bool NetEvWait::is_synchronous()
|
|||
return true; //statement_->is_asynchronous();
|
||||
}
|
||||
|
||||
bool NetProcTop::is_synchronous()
|
||||
bool NetProcTop::is_synchronous() const
|
||||
{
|
||||
if (type_ == NetProcTop::KINITIAL)
|
||||
return false;
|
||||
|
|
@ -67,6 +67,9 @@ bool NetProcTop::is_synchronous()
|
|||
|
||||
/*
|
||||
* $Log: sync.cc,v $
|
||||
* Revision 1.3.2.1 2007/05/30 17:48:54 steve
|
||||
* Support Latch synthesis (Alan Feldstein)
|
||||
*
|
||||
* Revision 1.3 2002/09/24 00:58:35 steve
|
||||
* More detailed check of process edge events.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
# include <stdio.h>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
|
||||
/*
|
||||
* Manage the information about system functions. This information is
|
||||
|
|
|
|||
139
t-dll-api.cc
139
t-dll-api.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.108 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.108.2.5 2006/04/16 19:26:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -28,6 +28,9 @@
|
|||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include <stdexcept>
|
||||
using std::invalid_argument;
|
||||
|
||||
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
|
||||
|
||||
extern "C" const char*ivl_design_flag(ivl_design_t des, const char*key)
|
||||
|
|
@ -481,6 +484,7 @@ extern "C" unsigned long ivl_expr_uvalue(ivl_expr_t net)
|
|||
|
||||
default:
|
||||
assert(0);
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -620,6 +624,19 @@ extern "C" const char* ivl_udp_name(ivl_udp_t net)
|
|||
return net->name;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lpm_attr_cnt(ivl_lpm_t net)
|
||||
{
|
||||
return net->nattr;
|
||||
}
|
||||
|
||||
extern "C" ivl_attribute_t ivl_lpm_attr_val(ivl_lpm_t net, unsigned idx)
|
||||
{
|
||||
if (idx >= net->nattr)
|
||||
return 0;
|
||||
else
|
||||
return net->attr + idx;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_lpm_basename(ivl_lpm_t net)
|
||||
{
|
||||
return net->name;
|
||||
|
|
@ -686,6 +703,21 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_gate( ivl_lpm_t netPtr )
|
||||
{
|
||||
assert( netPtr );
|
||||
|
||||
switch ( netPtr->type )
|
||||
{
|
||||
case IVL_LPM_LATCH:
|
||||
return netPtr->u_.latch.gatePtr;
|
||||
default:
|
||||
assert( false );
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
|
@ -752,6 +784,10 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.a[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.width);
|
||||
return net->u_.demux.d[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.width);
|
||||
|
|
@ -765,6 +801,20 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.ff.d.pins[idx];
|
||||
|
||||
case IVL_LPM_LATCH:
|
||||
|
||||
if( idx >= net->u_.latch.width )
|
||||
{
|
||||
throw invalid_argument( "idx too high" );
|
||||
}
|
||||
|
||||
if ( net->u_.latch.width != 1U )
|
||||
{
|
||||
throw invalid_argument( "Only 1-wide latches are currently supported." );
|
||||
}
|
||||
|
||||
return net->u_.latch.dataPtr;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -788,6 +838,10 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
|
|||
assert(idx < net->u_.arith.width);
|
||||
return net->u_.arith.b[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.width/net->u_.demux.size);
|
||||
return net->u_.demux.bit_in[idx];
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -813,6 +867,22 @@ extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
|
|||
return net->u_.ufunc.pins[base+idx];
|
||||
}
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
if (net->u_.ff.a.mem == 0) {
|
||||
// This is an exploded RAM, so we use sdx and idx
|
||||
// to address a nexa into the exploded ram.
|
||||
if (sdx >= net->u_.ff.scnt)
|
||||
return 0;
|
||||
if (idx >= net->u_.ff.width)
|
||||
return 0;
|
||||
unsigned adr = sdx * net->u_.ff.width + idx;
|
||||
return net->u_.ff.d.pins[adr];
|
||||
|
||||
} else {
|
||||
// Normal RAM port does not have data2 nexa
|
||||
return 0;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -833,6 +903,18 @@ extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_lpm_t ivl_lpm_decode(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.a.decode;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the hierarchical name for the LPM device. The
|
||||
* name needs to be built up from the scope name and the lpm base
|
||||
|
|
@ -891,6 +973,20 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.ff.q.pins[idx];
|
||||
|
||||
case IVL_LPM_LATCH:
|
||||
|
||||
if ( idx >= net->u_.latch.width )
|
||||
{
|
||||
throw invalid_argument( "idx too high" );
|
||||
}
|
||||
|
||||
if ( net->u_.latch.width != 1U )
|
||||
{
|
||||
throw invalid_argument( "Only 1-wide latches are currently supported." );
|
||||
}
|
||||
|
||||
return net->u_.latch.qPtr;
|
||||
|
||||
case IVL_LPM_MUX:
|
||||
assert(idx < net->u_.mux.width);
|
||||
if (net->u_.mux.width == 1)
|
||||
|
|
@ -898,6 +994,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.mux.q.pins[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.width);
|
||||
return net->u_.demux.q[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.width);
|
||||
|
|
@ -929,6 +1029,7 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.ff.s.pins[idx];
|
||||
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
assert(idx < net->u_.mux.swid);
|
||||
if (net->u_.mux.swid == 1)
|
||||
|
|
@ -936,6 +1037,10 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net, unsigned idx)
|
|||
else
|
||||
return net->u_.mux.s.pins[idx];
|
||||
|
||||
case IVL_LPM_DEMUX:
|
||||
assert(idx < net->u_.demux.awid);
|
||||
return net->u_.demux.a[idx];
|
||||
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
assert(idx < net->u_.shift.select);
|
||||
|
|
@ -952,8 +1057,11 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
|||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.swid;
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.swid;
|
||||
case IVL_LPM_DEMUX:
|
||||
return net->u_.demux.awid;
|
||||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.select;
|
||||
|
|
@ -970,6 +1078,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
case IVL_LPM_MUX:
|
||||
case IVL_LPM_DEMUX:
|
||||
return 0;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
|
|
@ -984,7 +1093,7 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
case IVL_LPM_SHIFTL:
|
||||
case IVL_LPM_SHIFTR:
|
||||
return net->u_.shift.signed_flag;
|
||||
return 0;
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_UFUNC:
|
||||
return 0;
|
||||
default:
|
||||
|
|
@ -996,8 +1105,12 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
|||
extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
|
||||
{
|
||||
switch (net->type) {
|
||||
case IVL_LPM_DEMUX:
|
||||
return net->u_.demux.size;
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.size;
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.scnt;
|
||||
case IVL_LPM_UFUNC:
|
||||
return net->u_.ufunc.ports - 1;
|
||||
default:
|
||||
|
|
@ -1018,8 +1131,13 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
|||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.width;
|
||||
case IVL_LPM_LATCH:
|
||||
return net->u_.latch.width;
|
||||
case IVL_LPM_DECODE:
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.width;
|
||||
case IVL_LPM_DEMUX:
|
||||
return net->u_.demux.width;
|
||||
case IVL_LPM_ADD:
|
||||
case IVL_LPM_CMP_EQ:
|
||||
case IVL_LPM_CMP_GE:
|
||||
|
|
@ -1046,7 +1164,7 @@ extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
|
|||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.mem;
|
||||
return net->u_.ff.a.mem;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
|
|
@ -1935,6 +2053,21 @@ extern "C" ivl_variable_type_t ivl_variable_type(ivl_variable_t net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.108.2.5 2006/04/16 19:26:40 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.108.2.4 2006/03/26 23:09:24 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.108.2.3 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.108.2.2 2006/02/25 05:03:29 steve
|
||||
* Add support for negedge FFs by using attributes.
|
||||
*
|
||||
* Revision 1.108.2.1 2006/02/19 00:11:33 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.108 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-expr.cc,v 1.39 2004/06/17 16:06:19 steve Exp $"
|
||||
#ident "$Id: t-dll-expr.cc,v 1.39.2.2 2006/09/15 23:56:05 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -30,7 +30,8 @@
|
|||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
|
||||
/*
|
||||
* This is a little convenience function for converting a NetExpr
|
||||
|
|
@ -222,12 +223,73 @@ void dll_target::expr_memory(const NetEMemory*net)
|
|||
ivl_expr_t cur = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(cur);
|
||||
|
||||
cur->type_ = IVL_EX_MEMORY;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_= net->expr_width();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
|
||||
cur->u_.memory_.idx_ = expr_;
|
||||
const NetMemory*mem = net->memory();
|
||||
|
||||
if (const NetNet*reg = mem->reg_from_explode()) {
|
||||
|
||||
if (expr_ == 0) {
|
||||
// If there is no index expression for the
|
||||
// exploded memory, then replace it with the
|
||||
// entire exploded reg.
|
||||
cur->type_ = IVL_EX_SIGNAL;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_= reg->pin_count();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
cur->u_.signal_.sig = find_signal(des_, reg);
|
||||
cur->u_.signal_.lsi = 0;
|
||||
cur->u_.signal_.msi = cur->width_ - 1;
|
||||
|
||||
} else {
|
||||
cur->type_ = IVL_EX_SELECT;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_ = net->expr_width();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
|
||||
// Create an expression form of the exploded
|
||||
// memory. This is what the select will apply to.
|
||||
ivl_expr_t sig = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
sig->type_ = IVL_EX_SIGNAL;
|
||||
sig->value_ = IVL_VT_VECTOR;
|
||||
sig->width_ = reg->pin_count();
|
||||
sig->signed_ = 0;
|
||||
sig->u_.signal_.sig = find_signal(des_, reg);
|
||||
assert(sig->u_.signal_.sig);
|
||||
sig->u_.signal_.lsi = 0;
|
||||
sig->u_.signal_.msi = reg->pin_count()-1;
|
||||
cur->u_.binary_.lef_ = sig;
|
||||
|
||||
// Create an expression of the address calculation.
|
||||
cur->u_.binary_.rig_ = expr_;
|
||||
|
||||
if (cur->width_ > 1) {
|
||||
ivl_expr_t mul = (ivl_expr_t)calloc(2, sizeof(struct ivl_expr_s));
|
||||
ivl_expr_t fac = mul+1;
|
||||
|
||||
fac->type_ = IVL_EX_ULONG;
|
||||
fac->value_ = IVL_VT_VECTOR;
|
||||
fac->width_ = 8*sizeof(cur->width_);
|
||||
fac->signed_= 0;
|
||||
fac->u_.ulong_.value = cur->width_;
|
||||
|
||||
mul->type_ = IVL_EX_BINARY;
|
||||
mul->value_ = IVL_VT_VECTOR;
|
||||
mul->width_ = fac->width_;
|
||||
mul->signed_= 0;
|
||||
mul->u_.binary_.op_ = '*';
|
||||
mul->u_.binary_.lef_ = cur->u_.binary_.rig_;
|
||||
mul->u_.binary_.rig_ = fac;
|
||||
cur->u_.binary_.rig_ = mul;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
cur->type_ = IVL_EX_MEMORY;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_= net->expr_width();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
|
||||
cur->u_.memory_.idx_ = expr_;
|
||||
}
|
||||
|
||||
expr_ = cur;
|
||||
}
|
||||
|
|
@ -604,6 +666,12 @@ void dll_target::expr_variable(const NetEVariable*net)
|
|||
|
||||
/*
|
||||
* $Log: t-dll-expr.cc,v $
|
||||
* Revision 1.39.2.2 2006/09/15 23:56:05 steve
|
||||
* Special handling of exploded memory arguments.
|
||||
*
|
||||
* Revision 1.39.2.1 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.39 2004/06/17 16:06:19 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@
|
|||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
|
||||
|
||||
bool dll_target::process(const NetProcTop*net)
|
||||
|
|
|
|||
253
t-dll.cc
253
t-dll.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.cc,v 1.131 2004/10/04 01:10:55 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.131.2.8 2006/07/23 19:42:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -31,7 +31,11 @@
|
|||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <cstdlib>
|
||||
# include <cstring>
|
||||
|
||||
#include <new> // standard operator new
|
||||
using std::bad_alloc;
|
||||
|
||||
#if defined(__WIN32__)
|
||||
|
||||
|
|
@ -940,6 +944,8 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
|||
obj->delay[1] = net->fall_time();
|
||||
obj->delay[2] = net->decay_time();
|
||||
|
||||
logic_attributes(obj,net);
|
||||
|
||||
scope_add_logic(scope, obj);
|
||||
}
|
||||
|
||||
|
|
@ -965,6 +971,8 @@ bool dll_target::net_function(const NetUserFunc*net)
|
|||
obj->type = IVL_LPM_UFUNC;
|
||||
obj->name = net->name();
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(obj->scope);
|
||||
|
||||
/* Get the definition of the function and save it. */
|
||||
|
|
@ -1104,9 +1112,11 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
|||
obj->type = IVL_LPM_SUB;
|
||||
else
|
||||
obj->type = IVL_LPM_ADD;
|
||||
obj->name = net->name(); // NetAddSub names are permallocated.
|
||||
obj->name = net->name(); // NetAddSub names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.arith.signed_flag = 0;
|
||||
|
|
@ -1176,6 +1186,8 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_SHIFTL;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -1243,6 +1255,8 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
|||
void dll_target::lpm_compare(const NetCompare*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->name = net->name(); // NetCompare names are permallocated
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
|
|
@ -1357,6 +1371,8 @@ void dll_target::lpm_divide(const NetDivide*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_DIVIDE;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -1427,6 +1443,8 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_MOD;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -1489,16 +1507,131 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
|||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_decode(const NetDecode*net)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ivl_lpm_t dll_target::lpm_decode_ff_(const NetDecode*net)
|
||||
{
|
||||
if (net == 0)
|
||||
return 0;
|
||||
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_DECODE;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
|
||||
obj->u_.mux.swid = net->awidth();
|
||||
obj->u_.mux.size = 0;
|
||||
obj->u_.mux.width = net->width();
|
||||
obj->u_.mux.d = 0;
|
||||
|
||||
if (obj->u_.mux.swid > 1) {
|
||||
obj->u_.mux.s.pins = new ivl_nexus_t[obj->u_.mux.swid];
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->u_.mux.swid ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Address(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.mux.s.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.s.pins[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
} else {
|
||||
assert(obj->u_.mux.swid == 1);
|
||||
const Nexus*nex = net->pin_Address(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.mux.s.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.s.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool dll_target::lpm_demux(const NetDemux*net)
|
||||
{
|
||||
unsigned idx;
|
||||
unsigned width = net->width();
|
||||
unsigned awid = net->awidth();
|
||||
unsigned size = net->size();
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_DEMUX;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.demux.width = width;
|
||||
obj->u_.demux.awid = awid;
|
||||
obj->u_.demux.size = net->size();
|
||||
|
||||
ivl_nexus_t*tmp = new ivl_nexus_t [2*width + awid + width/size];
|
||||
obj->u_.demux.q = tmp;
|
||||
obj->u_.demux.d = tmp + width;
|
||||
obj->u_.demux.a = tmp + 2*width;
|
||||
obj->u_.demux.bit_in = tmp + 2*width + awid;
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Q(idx).nexus();
|
||||
obj->u_.demux.q[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
|
||||
/* It is possible, but unlikely, that the Q is unused. */
|
||||
if (obj->u_.demux.q[idx])
|
||||
nexus_lpm_add(obj->u_.demux.q[idx], obj, idx,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Data(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.d[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.d[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < awid ; idx += 1) {
|
||||
const Nexus*nex = net->pin_Address(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.a[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.a[idx], obj, idx,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
for (idx = 0 ; idx < width/size ; idx += 1) {
|
||||
const Nexus*nex = net->pin_WriteData(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.demux.bit_in[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.demux.bit_in[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
|
||||
obj->nattr = net->attr_cnt();
|
||||
obj->attr = fill_in_attributes(net);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
void dll_target::lpm_ff(const NetFF*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_FF;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
obj->u_.ff.a.decode = lpm_decode_ff_(net->get_demux());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
|
||||
obj->nattr = net->attr_cnt();
|
||||
obj->attr = fill_in_attributes(net);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
const Nexus*nex;
|
||||
|
|
@ -1605,18 +1738,52 @@ void dll_target::lpm_ff(const NetFF*net)
|
|||
}
|
||||
}
|
||||
|
||||
void dll_target::lpm_latch( const NetLatch *latchPtr )
|
||||
{
|
||||
try
|
||||
{
|
||||
ivl_lpm_s *objPtr = new ivl_lpm_s;
|
||||
objPtr->type = IVL_LPM_LATCH;
|
||||
objPtr->name = latchPtr->name();
|
||||
objPtr->scope = find_scope( des_, latchPtr->scope() );
|
||||
assert( objPtr->scope ); // C++ programmers prefer using exceptions rather than assertions.
|
||||
|
||||
objPtr->u_.latch.width = latchPtr->width();
|
||||
|
||||
objPtr->nattr = latchPtr->attr_cnt();
|
||||
objPtr->attr = fill_in_attributes( latchPtr );
|
||||
|
||||
scope_add_lpm( objPtr->scope, objPtr );
|
||||
|
||||
// Set the gate signal to point to the nexus, and the nexus to point back to this device.
|
||||
const Nexus *const nexPtr = latchPtr->pin_Gate().nexus();
|
||||
}
|
||||
catch ( bad_alloc &memoryAllocationException )
|
||||
{
|
||||
cerr << "Exception occurred: " << memoryAllocationException.what() << endl;
|
||||
}
|
||||
|
||||
} // end function lpm_latch
|
||||
|
||||
void dll_target::lpm_ram_dq(const NetRamDq*net)
|
||||
{
|
||||
ivl_memory_t mem = find_memory(des_, net->mem());
|
||||
assert(mem);
|
||||
|
||||
const NetNet*ereg = net->mem()->reg_from_explode();
|
||||
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_RAM;
|
||||
obj->name = net->name();
|
||||
obj->u_.ff.mem = find_memory(des_, net->mem());
|
||||
assert(obj->u_.ff.mem);
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->u_.ff.a.mem = ereg? 0 : mem;
|
||||
obj->scope = find_scope(des_, net->mem()->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->u_.ff.width = net->width();
|
||||
obj->u_.ff.swid = net->awidth();
|
||||
obj->u_.ff.scnt = net->mem()->count();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
|
|
@ -1626,6 +1793,7 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
|
|||
// the clock input.
|
||||
|
||||
bool has_write_port = net->pin_InClock().is_linked();
|
||||
assert( ereg? !has_write_port : 1 );
|
||||
|
||||
// Connect the write clock and write enable
|
||||
|
||||
|
|
@ -1717,6 +1885,21 @@ void dll_target::lpm_ram_dq(const NetRamDq*net)
|
|||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
}
|
||||
}
|
||||
|
||||
if (ereg) {
|
||||
unsigned count = obj->u_.ff.width * obj->u_.ff.scnt;
|
||||
assert(ereg->pin_count() == count);
|
||||
|
||||
obj->u_.ff.d.pins = new ivl_nexus_t [count];
|
||||
|
||||
for (unsigned idx = 0 ; idx < count ; idx += 1) {
|
||||
nex = ereg->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.d.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.d.pins[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dll_target::lpm_mult(const NetMult*net)
|
||||
|
|
@ -1724,6 +1907,8 @@ void dll_target::lpm_mult(const NetMult*net)
|
|||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_MULT;
|
||||
obj->name = net->name();
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
assert(net->scope());
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
|
@ -1803,7 +1988,9 @@ void dll_target::lpm_mux(const NetMux*net)
|
|||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_MUX;
|
||||
obj->name = net->name(); // The NetMux perallocates its name.
|
||||
obj->name = net->name(); // NetMux names are permallocated
|
||||
obj->attr = 0;
|
||||
obj->nattr = 0;
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
|
|
@ -1828,10 +2015,34 @@ void dll_target::lpm_mux(const NetMux*net)
|
|||
|
||||
for (unsigned idx = 0 ; idx < obj->u_.mux.width ; idx += 1) {
|
||||
nex = net->pin_Result(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
#if 0
|
||||
if (! nex->t_cookie()) {
|
||||
cerr << net->get_line() << ": internal error: "
|
||||
<< "broken mux. name=" << net->name()
|
||||
<< ", width=" << obj->u_.mux.width
|
||||
<< ", swid=" << obj->u_.mux.swid << endl;
|
||||
for (unsigned tmp = 0; tmp < obj->u_.mux.width; tmp += 1) {
|
||||
const Nexus*tmpn = net->pin_Result(tmp).nexus();
|
||||
if (tmpn->t_cookie() == 0)
|
||||
continue;
|
||||
|
||||
cerr << net->get_line() << ": XXXX "
|
||||
<< "Result(" << tmp << ") : "
|
||||
<< tmpn->name() << endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
obj->u_.mux.q.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
/* It is possible (although unlikely) that the
|
||||
result bit of the mux is not used. This can
|
||||
happen, for example, if the output is
|
||||
overridden in the HDL. In that case, skip
|
||||
it. But if the bit is used, then add it to the
|
||||
nexus. */
|
||||
if (obj->u_.mux.q.pins[idx])
|
||||
nexus_lpm_add(obj->u_.mux.q.pins[idx], obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2180,6 +2391,30 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
|||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.131.2.8 2006/07/23 19:42:35 steve
|
||||
* Handle statement output override better in blocks.
|
||||
*
|
||||
* Revision 1.131.2.7 2006/04/16 19:26:40 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.131.2.6 2006/03/26 23:09:24 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.131.2.5 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.131.2.4 2006/02/25 05:03:29 steve
|
||||
* Add support for negedge FFs by using attributes.
|
||||
*
|
||||
* Revision 1.131.2.3 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.131.2.2 2006/01/21 21:42:33 steve
|
||||
* When mux has wide select but sparse choices, use 1hot translation.
|
||||
*
|
||||
* Revision 1.131.2.1 2005/02/19 16:39:31 steve
|
||||
* Spellig fixes.
|
||||
*
|
||||
* Revision 1.131 2004/10/04 01:10:55 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
47
t-dll.h
47
t-dll.h
|
|
@ -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.115 2004/10/04 01:10:56 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.115.2.5 2006/04/16 19:26:40 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
|
|
@ -76,8 +76,11 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
void lpm_add_sub(const NetAddSub*);
|
||||
void lpm_clshift(const NetCLShift*);
|
||||
void lpm_compare(const NetCompare*);
|
||||
bool lpm_decode(const NetDecode*);
|
||||
bool lpm_demux(const NetDemux*);
|
||||
void lpm_divide(const NetDivide*);
|
||||
void lpm_ff(const NetFF*);
|
||||
void lpm_latch( const NetLatch * );
|
||||
void lpm_modulo(const NetModulo*);
|
||||
void lpm_mult(const NetMult*);
|
||||
void lpm_mux(const NetMux*);
|
||||
|
|
@ -162,6 +165,8 @@ struct dll_target : public target_t, public expr_scan_t {
|
|||
|
||||
void add_root(ivl_design_s &des_, const NetScope *s);
|
||||
|
||||
ivl_lpm_t lpm_decode_ff_(const NetDecode*);
|
||||
|
||||
void sub_off_from_expr_(long);
|
||||
void mul_expr_by_const_(long);
|
||||
|
||||
|
|
@ -290,10 +295,14 @@ struct ivl_lpm_s {
|
|||
ivl_scope_t scope;
|
||||
perm_string name;
|
||||
|
||||
struct ivl_attribute_s*attr;
|
||||
unsigned nattr;
|
||||
|
||||
union {
|
||||
struct ivl_lpm_ff_s {
|
||||
unsigned width;
|
||||
unsigned swid; // ram only
|
||||
unsigned scnt;
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
ivl_nexus_t aclr;
|
||||
|
|
@ -312,11 +321,22 @@ struct ivl_lpm_s {
|
|||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} s;
|
||||
ivl_memory_t mem; // ram only
|
||||
union {
|
||||
ivl_memory_t mem; // ram only
|
||||
ivl_lpm_t decode; // FF only
|
||||
} a;
|
||||
ivl_expr_t aset_value;
|
||||
ivl_expr_t sset_value;
|
||||
} ff;
|
||||
|
||||
struct ivl_lpm_latch_s
|
||||
{
|
||||
unsigned width;
|
||||
ivl_nexus_s *gatePtr;
|
||||
ivl_nexus_s *qPtr;
|
||||
ivl_nexus_s *dataPtr;
|
||||
} latch;
|
||||
|
||||
struct ivl_lpm_mux_s {
|
||||
unsigned width;
|
||||
unsigned size;
|
||||
|
|
@ -332,6 +352,14 @@ struct ivl_lpm_s {
|
|||
} s;
|
||||
} mux;
|
||||
|
||||
struct ivl_lpm_demux_s {
|
||||
unsigned width;
|
||||
unsigned awid;
|
||||
unsigned size;
|
||||
ivl_nexus_t*bit_in;
|
||||
ivl_nexus_t *q,*d,*a;
|
||||
} demux;
|
||||
|
||||
struct ivl_lpm_shift_s {
|
||||
unsigned width;
|
||||
unsigned select;
|
||||
|
|
@ -684,6 +712,21 @@ struct ivl_variable_s {
|
|||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.115.2.5 2006/04/16 19:26:40 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.115.2.4 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.115.2.3 2006/03/12 07:34:19 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.115.2.2 2006/02/25 05:03:30 steve
|
||||
* Add support for negedge FFs by using attributes.
|
||||
*
|
||||
* Revision 1.115.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.115 2004/10/04 01:10:56 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
|
|
|||
27
target.cc
27
target.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.cc,v 1.69 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.69.2.2 2006/03/26 23:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -101,6 +101,20 @@ void target_t::lpm_compare(const NetCompare*)
|
|||
"Unhandled NetCompare." << endl;
|
||||
}
|
||||
|
||||
bool target_t::lpm_decode(const NetDecode*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetDecode." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool target_t::lpm_demux(const NetDemux*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetDemux." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::lpm_divide(const NetDivide*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -119,6 +133,11 @@ void target_t::lpm_ff(const NetFF*)
|
|||
"Unhandled NetFF." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_latch( const NetLatch * )
|
||||
{
|
||||
cerr << "target (" << typeid( *this ).name() << "): Unhandled NetLatch." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_mult(const NetMult*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
|
|
@ -420,6 +439,12 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
|||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.69.2.2 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.69.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.69 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
12
target.h
12
target.h
|
|
@ -19,10 +19,11 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.h,v 1.65 2004/05/31 23:34:39 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.65.2.2 2006/03/26 23:09:25 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
#include "NetLatch.h"
|
||||
|
||||
/*
|
||||
* This header file describes the types and constants used to describe
|
||||
|
|
@ -79,9 +80,12 @@ struct target_t {
|
|||
virtual void lpm_add_sub(const NetAddSub*);
|
||||
virtual void lpm_clshift(const NetCLShift*);
|
||||
virtual void lpm_compare(const NetCompare*);
|
||||
virtual bool lpm_decode(const NetDecode*);
|
||||
virtual bool lpm_demux(const NetDemux*);
|
||||
virtual void lpm_divide(const NetDivide*);
|
||||
virtual void lpm_modulo(const NetModulo*);
|
||||
virtual void lpm_ff(const NetFF*);
|
||||
virtual void lpm_latch( const NetLatch * );
|
||||
virtual void lpm_mult(const NetMult*);
|
||||
virtual void lpm_mux(const NetMux*);
|
||||
virtual void lpm_ram_dq(const NetRamDq*);
|
||||
|
|
@ -170,6 +174,12 @@ extern const struct target *target_table[];
|
|||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.65.2.2 2006/03/26 23:09:25 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.65.2.1 2006/02/19 00:11:34 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.65 2004/05/31 23:34:39 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
configure
|
||||
Makefile
|
||||
edif.tgt
|
||||
dep
|
||||
config.status
|
||||
config.log
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
The tgt-edif files are licensed differently from the rest of Icarus
|
||||
Verilog. These files are:
|
||||
|
||||
--
|
||||
|
||||
Copyright (c) 2005 Stephen Williams
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
--
|
||||
|
||||
The purpose of the different license here is to allow licensees to use
|
||||
these files to make EDIF based code generators that use these common
|
||||
functions without statically linking to GPL files from elsewhere
|
||||
within Icarus Verilog.
|
||||
|
||||
As a reminder, while this more relaxed license is here to allow
|
||||
entities to make closed source (binary) code generators, this is not
|
||||
intended to effect the GPL standing of the rest of Icarus Verilog
|
||||
source. THIS RELAXED LICENSE APPLIES ONLY TO FILES SPECIFICALLY MARKED
|
||||
WITH THIS NEW LICENSE. Furthermore, all rights remain reserved. Note
|
||||
specifically the requirement for you to reproduce notices in your
|
||||
documentation.
|
||||
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
#
|
||||
# Copyright (c) 2005 Stephen Williams
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.1.2.3 2006/05/08 04:33:36 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
suffix = @install_suffix@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
mandir = @mandir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
RANLIB = @RANLIB@
|
||||
MAN = @MAN@
|
||||
PS2pdf = @ps2pdf@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: dep edif.tgt
|
||||
|
||||
dep:
|
||||
mkdir dep
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
D = d-lpm.o d-virtex.o xilinx.o
|
||||
O = edif.o device.o target.o gates.o generic.o $D
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
TGTDEPLIBS=../libivl.a
|
||||
else
|
||||
TGTLDFLAGS=
|
||||
TGTDEPLIBS=
|
||||
endif
|
||||
|
||||
|
||||
edif.tgt: tables.o libedif_tgt.a $(TGTDEPLIBS)
|
||||
$(CC) @shared@ -o $@ tables.o libedif_tgt.a $(TGTLDFLAGS)
|
||||
|
||||
libedif_tgt.a: $O
|
||||
rm -f libedif_tgt.a
|
||||
ar cqv libedif_tgt.a $O
|
||||
$(RANLIB) libedif_tgt.a
|
||||
|
||||
iverilog-edif.ps: $(srcdir)/iverilog-edif.man
|
||||
$(MAN) -t $(srcdir)/iverilog-edif.man > iverilog-edif.ps
|
||||
|
||||
iverilog-edif.pdf: iverilog-edif.ps
|
||||
$(PS2PDF) iverilog-edif.ps iverilog-edif.pdf
|
||||
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
clean:
|
||||
rm -rf *.o dep edif.tgt
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
check: all
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC =
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
#INSTALL_DOC = $(mandir)/man1/iverilog-edif.1
|
||||
else
|
||||
#INSTALL_DOC = $(prefix)/iverilog-edif.pdf $(mandir)/man1/iverilog-edif.1
|
||||
#all: iverilog-edif.pdf
|
||||
endif
|
||||
endif
|
||||
else
|
||||
#INSTALL_DOC = $(prefix)/iverilog-edif.pdf $(mandir)/man1/iverilog-edif.1
|
||||
#INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
install: all installdirs $(libdir)/ivl$(suffix)/edif.tgt $(INSTALL_DOC) $(libdir)/ivl$(suffix)/edif.conf $(libdir)/ivl$(suffix)/edif-s.conf
|
||||
|
||||
$(libdir)/ivl$(suffix)/edif.tgt: ./edif.tgt
|
||||
$(INSTALL_PROGRAM) ./edif.tgt $(libdir)/ivl$(suffix)/edif.tgt
|
||||
|
||||
$(libdir)/ivl$(suffix)/edif.conf: $(srcdir)/edif.conf
|
||||
$(INSTALL_DATA) $(srcdir)/edif.conf $(libdir)/ivl$(suffix)/edif.conf
|
||||
|
||||
$(libdir)/ivl$(suffix)/edif-s.conf: $(srcdir)/edif-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/edif-s.conf $(libdir)/ivl$(suffix)/edif-s.conf
|
||||
|
||||
|
||||
$(mandir)/man1/iverilog-edif$(suffix).1: $(srcdir)/iverilog-edif.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-edif.man $(mandir)/man1/iverilog-edif$(suffix).1
|
||||
|
||||
$(prefix)/iverilog-edif$(suffix).pdf: iverilog-edif.pdf
|
||||
$(INSTALL_DATA) iverilog-edif.pdf $(prefix)/iverilog-edif$(suffix).pdf
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl$(suffix)
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl$(suffix)/edif.tgt
|
||||
rm -f $(INSTALL_DOC)
|
||||
rm -f $(libdir)/ivl$(suffix)/edif-s.conf
|
||||
rm -f $(libdir)/ivl$(suffix)/edif.conf
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(edif.conf)
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_RANLIB
|
||||
AC_PROG_INSTALL
|
||||
AC_CHECK_PROGS(MAN,man,none)
|
||||
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
# $host
|
||||
|
||||
AX_ENABLE_SUFFIX
|
||||
|
||||
# Combined check for Microsoft-related bogosities; sets WIN32 if found
|
||||
AX_WIN32
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
# linker options when building a shared library
|
||||
AX_LD_SHAREDLIB_OPTS
|
||||
|
||||
AX_CPP_IDENT
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue