mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 06:16:47 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
380d5620e6 | ||
|
|
aae17041ef | ||
|
|
1d7cf5bb8c | ||
|
|
8696a4363a | ||
|
|
59c240bc9b | ||
|
|
d751b05cec | ||
|
|
843af31958 | ||
|
|
5aea537ab9 | ||
|
|
b734ecf02f | ||
|
|
5b52c384d6 | ||
|
|
2cba0a50f3 | ||
|
|
b354cf68b8 | ||
|
|
a9264d71c6 | ||
|
|
e0873f6c14 | ||
|
|
b8ddbcf62b | ||
|
|
bd09bed662 | ||
|
|
1ee4015aa8 | ||
|
|
a8d787bd66 | ||
|
|
e77bcf6910 | ||
|
|
2bc8f79e0f | ||
|
|
e58be1b128 | ||
|
|
ee180f6cf0 | ||
|
|
ce0b97a8f0 | ||
|
|
cf8d17a6ab | ||
|
|
e6bd088984 | ||
|
|
9b3c3b6e7a | ||
|
|
dc5bd8ea59 | ||
|
|
121b6c2ecb | ||
|
|
57d28e4f86 | ||
|
|
d84b72609d | ||
|
|
ef98be1192 | ||
|
|
3b9dedbc86 | ||
|
|
aa8908c52f | ||
|
|
3d1ffced57 | ||
|
|
f37f69f160 | ||
|
|
fac3bde2c8 | ||
|
|
9125a4c451 | ||
|
|
bed47a4ab4 | ||
|
|
2de887c2ff | ||
|
|
fdf2c1b0d0 | ||
|
|
7f78b9bf56 | ||
|
|
d6f53b2582 | ||
|
|
848110bc33 | ||
|
|
eb4cdc5026 | ||
|
|
3d673c1f02 | ||
|
|
a48b4c4f8d | ||
|
|
ba7fdb580d | ||
|
|
9e5ff89ef3 | ||
|
|
0d5e4b40d0 | ||
|
|
142b9e667d | ||
|
|
f3b76d958d | ||
|
|
87d6df5204 | ||
|
|
c7193fa6fe | ||
|
|
645c24289e | ||
|
|
e52a5be16e | ||
|
|
7e37b61a05 | ||
|
|
cbd353fbb8 | ||
|
|
4c274223cf | ||
|
|
65e4e9f428 | ||
|
|
e6820ed169 | ||
|
|
c3cb0f2371 | ||
|
|
31f1ceea9f | ||
|
|
94afe54741 | ||
|
|
080f161c37 | ||
|
|
5ce35e3e60 | ||
|
|
6d0edcf58a | ||
|
|
7033836e01 | ||
|
|
b7409d98ff | ||
|
|
b6d1bb1fa7 | ||
|
|
4558a7d8d0 | ||
|
|
22c2625ace | ||
|
|
4de8ba489d | ||
|
|
65ae92859c | ||
|
|
d355270c2d | ||
|
|
ced7cc6d60 | ||
|
|
d54cc14ca2 | ||
|
|
98a57f4fac | ||
|
|
40ca71b10b | ||
|
|
e7e58cdd71 | ||
|
|
1dcf9de34c | ||
|
|
fcb1d8dc72 | ||
|
|
5fa7e1c31b | ||
|
|
6e3c258edb | ||
|
|
6be5421c8a | ||
|
|
76655ce2bb | ||
|
|
3e1738dcec | ||
|
|
ec8dec74a6 | ||
|
|
838d25890b | ||
|
|
4a6d3a5104 | ||
|
|
b688cdbc40 | ||
|
|
09de918198 | ||
|
|
3e2bb85f58 | ||
|
|
22d89c5984 | ||
|
|
88193a369f | ||
|
|
cdb99e7638 | ||
|
|
99e145da48 | ||
|
|
b30b695ff0 | ||
|
|
998c039fd9 | ||
|
|
5ffac8adbf | ||
|
|
80b8ea95bb | ||
|
|
68a7ce3745 | ||
|
|
bb68753bd2 | ||
|
|
dab47610ed | ||
|
|
e96e8c62be | ||
|
|
fa088f8baa | ||
|
|
48b6726cf4 | ||
|
|
bf42be12de | ||
|
|
4cfa3e4047 | ||
|
|
ac25dc03a8 | ||
|
|
680c35a845 | ||
|
|
26288eeeb4 | ||
|
|
3a69ab8934 | ||
|
|
cd3ed1959e | ||
|
|
eb72a83e5f | ||
|
|
85ab6d160b | ||
|
|
b769c7781e | ||
|
|
7324673bd1 | ||
|
|
4cfa715092 | ||
|
|
b4aade1e4c | ||
|
|
a81dcd7955 | ||
|
|
fae40cf380 | ||
|
|
28149e73e3 | ||
|
|
8b81d6e416 | ||
|
|
fbf0bf1fb7 | ||
|
|
9d6392fda9 | ||
|
|
23ce3a9042 | ||
|
|
33946e188c | ||
|
|
477495c648 | ||
|
|
16f7268729 | ||
|
|
a4a0ba670d | ||
|
|
e98083af15 | ||
|
|
513ade9b95 | ||
|
|
1624afe1ba | ||
|
|
0eb6056ea6 | ||
|
|
2602505885 | ||
|
|
82f3f0f741 | ||
|
|
02f8099aa7 | ||
|
|
43ff33cd79 | ||
|
|
2d1ace1dbc | ||
|
|
8d806d538b | ||
|
|
3fe0344246 | ||
|
|
c688d95cb8 | ||
|
|
282c58040b | ||
|
|
c18ea61994 | ||
|
|
5171846d72 | ||
|
|
206b37e5de | ||
|
|
f7526c6c4b | ||
|
|
f827ad8625 | ||
|
|
93a1f4853b | ||
|
|
2cce0ce238 | ||
|
|
cb5fc54b5e | ||
|
|
50e47c4173 | ||
|
|
b3afc108cf | ||
|
|
b66e7b1713 | ||
|
|
73753f1337 | ||
|
|
7195d4e8f1 | ||
|
|
89881adece | ||
|
|
f80c4a309e | ||
|
|
e1bbbe5614 | ||
|
|
71ecf8c143 | ||
|
|
5a2015ee67 | ||
|
|
0721615345 | ||
|
|
2862178a6f | ||
|
|
162b895e1b | ||
|
|
bbf15778b8 | ||
|
|
d6450599d6 | ||
|
|
8bad04a020 | ||
|
|
409c8ff47d | ||
|
|
59e85dcffc | ||
|
|
2c774bfe75 | ||
|
|
2e40152ff2 | ||
|
|
8ab03fa90f | ||
|
|
07e2b2b828 | ||
|
|
08175f5ebc | ||
|
|
2e15006dc0 | ||
|
|
b24fa87de6 | ||
|
|
a4143f8788 | ||
|
|
2fb754cd54 | ||
|
|
bcbab34543 | ||
|
|
475dd5760a | ||
|
|
8f2a369588 | ||
|
|
19b8615363 | ||
|
|
564f972aef | ||
|
|
86a2bf1961 | ||
|
|
70a1236626 | ||
|
|
7201865554 | ||
|
|
a4298df776 | ||
|
|
aa11f57b57 | ||
|
|
a4f3fa8997 | ||
|
|
9f860e319a | ||
|
|
29abc5a69e | ||
|
|
0f919ab5f3 | ||
|
|
eb0103deb5 | ||
|
|
5b7d783979 | ||
|
|
32e5eb6681 | ||
|
|
213d02c4e5 | ||
|
|
6997971884 | ||
|
|
11eccfc033 | ||
|
|
f949f96df1 | ||
|
|
1d215998b2 | ||
|
|
492d76e71d | ||
|
|
1cc68f745a | ||
|
|
4d8c0c79d6 | ||
|
|
a7f48c86e2 | ||
|
|
35e84f15d4 | ||
|
|
d513cf8f60 | ||
|
|
efdc1769e6 | ||
|
|
e1c697a746 | ||
|
|
393c9ab108 | ||
|
|
efa5222c66 | ||
|
|
f068196272 | ||
|
|
8317d8707e | ||
|
|
ed9aeec591 | ||
|
|
0c1c826410 | ||
|
|
c63a3acf93 | ||
|
|
b37fcf3593 | ||
|
|
6e486e9bcf | ||
|
|
076cecb6cd | ||
|
|
42006ec5f1 | ||
|
|
db7044850a | ||
|
|
5ee7cfb854 | ||
|
|
93f05306e7 | ||
|
|
8e21f0f363 | ||
|
|
b2f7f533f7 | ||
|
|
2271fc9894 | ||
|
|
a64a33e65a | ||
|
|
3a415fb04c | ||
|
|
0c7722ce7e | ||
|
|
86a283b9bc | ||
|
|
0fb4ba7907 | ||
|
|
f274c9cade | ||
|
|
4882f04945 | ||
|
|
a8a2b3e8f3 | ||
|
|
900949ab56 | ||
|
|
9f30615a91 | ||
|
|
a964e0479b | ||
|
|
6d7ac5d67b | ||
|
|
470b0d3d34 | ||
|
|
bb38653654 | ||
|
|
fb678877d7 | ||
|
|
64cc38f0eb | ||
|
|
1a21d2fe9d | ||
|
|
095995f09c | ||
|
|
851daff66f | ||
|
|
1b7261a393 | ||
|
|
1c41f8ebd2 | ||
|
|
59b1b4c7b9 | ||
|
|
0955058fbe | ||
|
|
12b9071f49 | ||
|
|
357461b034 | ||
|
|
4a0e7d56bd | ||
|
|
da4a7ea80a | ||
|
|
fcfa9d004a | ||
|
|
349f9ae302 | ||
|
|
3a5e55b229 | ||
|
|
1f44822510 | ||
|
|
6df3febada | ||
|
|
5fde1b3e05 | ||
|
|
fbf104bf4d | ||
|
|
dab04c221d | ||
|
|
251eb4f38f | ||
|
|
424e6a750c | ||
|
|
4594ac1c2c | ||
|
|
d904aceb2c | ||
|
|
a890724b40 | ||
|
|
31bdb87c8f | ||
|
|
b04148b754 | ||
|
|
f36c511c2f | ||
|
|
39bc45ce67 | ||
|
|
3d78b558bc | ||
|
|
54d38ac057 | ||
|
|
7a211b9136 | ||
|
|
6847dac5c2 | ||
|
|
a3e9a7417d | ||
|
|
25d6912217 | ||
|
|
1c238f1948 | ||
|
|
287d21f300 | ||
|
|
a6c6ac2191 | ||
|
|
d6fbc30cd5 | ||
|
|
9d82d19d07 | ||
|
|
006a2cce83 | ||
|
|
8f68a07476 | ||
|
|
555d447180 | ||
|
|
41a1c6bb02 | ||
|
|
6fb7120158 | ||
|
|
9f7eb4a935 | ||
|
|
5ee83fce70 | ||
|
|
e69345b9fe | ||
|
|
1c11c864d5 | ||
|
|
58d05dfca2 | ||
|
|
7d71abaa05 | ||
|
|
6b3b6f3384 | ||
|
|
0fe25f68f9 | ||
|
|
3017636c05 | ||
|
|
23acca48ff | ||
|
|
648e4c68e4 | ||
|
|
9eae940ebd | ||
|
|
0175a4fce0 | ||
|
|
aba4a877db | ||
|
|
031d91f813 | ||
|
|
f1fdce78be | ||
|
|
b119613a8a | ||
|
|
567badc7af | ||
|
|
b62f094874 | ||
|
|
28c0691b5f | ||
|
|
2d0e11283d | ||
|
|
f1825c54a7 | ||
|
|
cf1abfe38c |
@@ -6,6 +6,8 @@ ivl
|
||||
dep
|
||||
configure
|
||||
Makefile
|
||||
verilog
|
||||
gverilog
|
||||
config.status
|
||||
config.log
|
||||
config.cache
|
||||
|
||||
+5
-2
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: LineInfo.h,v 1.3 1999/02/15 02:06:15 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: LineInfo.h,v 1.4 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <cstdio>
|
||||
@@ -50,6 +50,9 @@ class LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.4 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/02/15 02:06:15 steve
|
||||
* Elaborate gate ranges.
|
||||
*
|
||||
|
||||
+73
-25
@@ -18,12 +18,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.11 1999/08/07 20:05:51 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.36 2000/02/05 06:40:35 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
VERSION = 0.2PRE
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -33,45 +33,77 @@ VPATH = $(srcdir)
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
mandir = @mandir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
STRIP = @STRIP@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CXXFLAGS = @CXXFLAGS@ -I$(srcdir)
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: ivl
|
||||
cd vvm ; make all
|
||||
cd ivlpp ; make all
|
||||
all: ivl verilog gverilog
|
||||
cd vpi ; $(MAKE) all
|
||||
cd vvm ; $(MAKE) all
|
||||
cd ivlpp ; $(MAKE) all
|
||||
|
||||
clean:
|
||||
rm *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc
|
||||
cd vvm ; make clean
|
||||
cd ivlpp ; make clean
|
||||
rm -f *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc verilog
|
||||
cd vpi ; $(MAKE) clean
|
||||
cd vvm ; $(MAKE) clean
|
||||
cd ivlpp ; $(MAKE) clean
|
||||
|
||||
distclean: clean
|
||||
rm -f vpi/Makefile
|
||||
rm -f vvm/Makefile
|
||||
rm -f ivlpp/Makefile
|
||||
rm -f config.status config.cache config.log
|
||||
rm -f Makefile
|
||||
|
||||
TT = t-null.o t-verilog.o t-vvm.o t-xnf.o
|
||||
FF = nobufz.o propinit.o sigfold.o xnfio.o xnfsyn.o
|
||||
FF = nobufz.o nodangle.o propinit.o synth.o xnfio.o xnfsyn.o
|
||||
|
||||
O = main.o cprop.o design_dump.o elaborate.o emit.o eval.o functor.o \
|
||||
lexor.o mangle.o netlist.o parse.o parse_misc.o pform.o pform_dump.o \
|
||||
verinum.o verireal.o target.o targets.o Module.o PExpr.o PGate.o \
|
||||
O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
||||
elab_net.o emit.o eval.o eval_tree.o expr_synth.o functor.o \
|
||||
lexor.o lexor_keyword.o mangle.o netlist.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
set_width.o \
|
||||
verinum.o verireal.o target.o targets.o Module.o PDelays.o PExpr.o PGate.o \
|
||||
PTask.o PFunction.o PWire.o Statement.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
# Make the actual verilog program from the script template. This
|
||||
# simply invloves editing the substitution strings in the script into
|
||||
# the configured copy.
|
||||
tmp1 = bindir
|
||||
tmp2 = libdir
|
||||
tmp3 = includedir
|
||||
tmp4 = CXX
|
||||
verilog: $(srcdir)/verilog.sh
|
||||
sed -e 's;@$(tmp1)@;@bindir@;' \
|
||||
-e 's;@$(tmp2)@;@libdir@;' \
|
||||
-e 's;@$(tmp3)@;@includedir@;' \
|
||||
-e 's;@dllib@;@DLLIB@;' \
|
||||
-e 's;@$(tmp4)@;@CXX@;' < $< > $@
|
||||
|
||||
ivl: $O
|
||||
$(CXX) $(CXXFLAGS) -o ivl $O
|
||||
|
||||
gverilog: gverilog.c
|
||||
$(CC) $(CPPFLAGS) -o gverilog -DLIBDIR='"@libdir@"' -DINCDIR='"@includedir@"' gverilog.c
|
||||
|
||||
%.o dep/%.d: %.cc
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CXX) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
|
||||
@@ -79,25 +111,41 @@ lexor.o dep/lexor.d: lexor.cc parse.h
|
||||
|
||||
parse.o dep/parse.d: parse.cc
|
||||
|
||||
parse.h parse.cc: parse.y
|
||||
bison --verbose -t -p VL -d parse.y -o parse.cc
|
||||
parse.h parse.cc: $(srcdir)/parse.y
|
||||
bison --verbose -t -p VL -d $(srcdir)/parse.y -o parse.cc
|
||||
mv parse.cc.h parse.h
|
||||
|
||||
lexor.cc: lexor.lex
|
||||
flex -PVL -s -olexor.cc lexor.lex
|
||||
lexor.cc: $(srcdir)/lexor.lex
|
||||
flex -PVL -s -olexor.cc $(srcdir)/lexor.lex
|
||||
|
||||
install: all installdirs $(bindir)/ivl
|
||||
cd vvm ; make install
|
||||
cd ivlpp ; make install
|
||||
install: all installdirs $(bindir)/verilog $(bindir)/gverilog $(libdir)/ivl/ivl $(mandir)/man1/verilog.1
|
||||
cd vpi ; $(MAKE) install
|
||||
cd vvm ; $(MAKE) install
|
||||
cd ivlpp ; $(MAKE) install
|
||||
|
||||
$(bindir)/ivl: ivl
|
||||
$(INSTALL_PROGRAM) ./ivl $(bindir)/ivl
|
||||
$(bindir)/verilog: ./verilog
|
||||
$(INSTALL_SCRIPT) ./verilog $(bindir)/verilog
|
||||
|
||||
$(bindir)/gverilog: ./gverilog
|
||||
$(INSTALL_PROGRAM) ./gverilog $(bindir)/gverilog
|
||||
|
||||
$(libdir)/ivl/ivl: ./ivl
|
||||
$(INSTALL_PROGRAM) ./ivl $(libdir)/ivl/ivl
|
||||
$(STRIP) $(libdir)/ivl/ivl
|
||||
|
||||
$(mandir)/man1/verilog.1: $(srcdir)/verilog.1
|
||||
$(INSTALL_DATA) $(srcdir)/verilog.1 $(mandir)/man1/verilog.1
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(bindir)
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(libdir)/ivl $(mandir)/man1
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/ivl
|
||||
rm -f $(libdir)/ivl/ivl
|
||||
rm -f $(bindir)/verilog
|
||||
rm -f $(mandir)/man1/verilog.1
|
||||
cd vpi ; $(MAKE) uninstall
|
||||
cd vvm ; $(MAKE) uninstall
|
||||
cd ivlpp ; $(MAKE) uninstall
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,22 +16,38 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Module.cc,v 1.6 1999/08/04 02:13:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Module.cc,v 1.10 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "Module.h"
|
||||
# include "PGate.h"
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
Module::Module(const string&name, const svector<Module::port_t*>*pp)
|
||||
: name_(name)
|
||||
{
|
||||
if (pp) {
|
||||
// Save the list of ports, then scan the list to make
|
||||
// the implicit wires. Add those wires to the wire map.
|
||||
ports_ = *pp;
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
port_t*cur = ports_[idx];
|
||||
for (unsigned jdx = 0 ; jdx < cur->wires.count() ; jdx += 1)
|
||||
add_wire(cur->wires[jdx]);
|
||||
if (cur == 0)
|
||||
continue;
|
||||
|
||||
// The port can actually be a list of wires, to
|
||||
// remember to scan the set. Also note the case
|
||||
// where a wire may be connected to multiple
|
||||
// ports, and reuse the link if that happens.
|
||||
for (unsigned jdx = 0; jdx < cur->wires.count(); jdx += 1) {
|
||||
PWire*tmp = add_wire(cur->wires[jdx]);
|
||||
if (tmp != cur->wires[jdx]) {
|
||||
delete cur->wires[jdx];
|
||||
cur->wires[jdx] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,9 +67,14 @@ void Module::add_function(const string &name, PFunction *func)
|
||||
funcs_[name] = func;
|
||||
}
|
||||
|
||||
void Module::add_wire(PWire*wire)
|
||||
PWire* Module::add_wire(PWire*wire)
|
||||
{
|
||||
wires_.push_back(wire);
|
||||
PWire*&ep = wires_[wire->name()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
void Module::add_behavior(PProcess*b)
|
||||
@@ -83,13 +104,22 @@ unsigned Module::find_port(const string&name) const
|
||||
}
|
||||
|
||||
|
||||
PWire* Module::get_wire(const string&name)
|
||||
PWire* Module::get_wire(const string&name) const
|
||||
{
|
||||
for (list<PWire*>::iterator cur = wires_.begin()
|
||||
; cur != wires_.end()
|
||||
map<string,PWire*>::const_iterator obj = wires_.find(name);
|
||||
if (obj == wires_.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
PGate* Module::get_gate(const string&name)
|
||||
{
|
||||
for (list<PGate*>::iterator cur = gates_.begin()
|
||||
; cur != gates_.end()
|
||||
; cur ++ ) {
|
||||
|
||||
if ((*cur)->name() == name)
|
||||
if ((*cur)->get_name() == name)
|
||||
return *cur;
|
||||
}
|
||||
|
||||
@@ -99,6 +129,18 @@ PWire* Module::get_wire(const string&name)
|
||||
|
||||
/*
|
||||
* $Log: Module.cc,v $
|
||||
* Revision 1.10 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.8 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.7 1999/09/17 02:06:25 steve
|
||||
* Handle unconnected module ports.
|
||||
*
|
||||
* Revision 1.6 1999/08/04 02:13:02 steve
|
||||
* Elaborate module ports that are concatenations of
|
||||
* module signals.
|
||||
|
||||
@@ -18,13 +18,14 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Module.h,v 1.8 1999/08/04 02:13:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Module.h,v 1.14 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include "svector.h"
|
||||
# include "named.h"
|
||||
# include <string>
|
||||
class PExpr;
|
||||
class PGate;
|
||||
@@ -33,6 +34,7 @@ class PFunction;
|
||||
class PWire;
|
||||
class PProcess;
|
||||
class Design;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
* A module is a named container and scope. A module holds a bunch of
|
||||
@@ -64,10 +66,23 @@ class Module {
|
||||
into this map. */
|
||||
map<string,PExpr*>parameters;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
but rather refer to parameters in the order they
|
||||
appear in the instantiated module. Therefore a
|
||||
list of names in module-order is needed to pass from
|
||||
a parameter-index to its name. */
|
||||
list<string> param_names;
|
||||
|
||||
const string&get_name() const { return name_; }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
void add_wire(PWire*wire);
|
||||
|
||||
// The add_wire method adds a wire by name, but only if the
|
||||
// wire name doesn't already exist. Either way, the result is
|
||||
// the existing wire or the pointer passed in.
|
||||
PWire* add_wire(PWire*wire);
|
||||
|
||||
void add_behavior(PProcess*behave);
|
||||
void add_task(const string&name, PTask*def);
|
||||
void add_function(const string&name, PFunction*def);
|
||||
@@ -78,20 +93,23 @@ class Module {
|
||||
|
||||
// Find a wire by name. This is used for connecting gates to
|
||||
// existing wires, etc.
|
||||
PWire* get_wire(const string&name);
|
||||
PWire* get_wire(const string&name) const;
|
||||
PGate* get_gate(const string&name);
|
||||
|
||||
const list<PWire*>& get_wires() const { return wires_; }
|
||||
const map<string,PWire*>& get_wires() const { return wires_; }
|
||||
const list<PGate*>& get_gates() const { return gates_; }
|
||||
const list<PProcess*>& get_behaviors() const { return behaviors_; }
|
||||
|
||||
void dump(ostream&out) const;
|
||||
bool elaborate(Design*, const string&path) const;
|
||||
bool elaborate(Design*, NetScope*scope,
|
||||
named<PExpr*>*parms, unsigned nparms,
|
||||
svector<PExpr*>*overrides_) const;
|
||||
|
||||
private:
|
||||
const string name_;
|
||||
|
||||
svector<port_t*> ports_;
|
||||
list<PWire*> wires_;
|
||||
map<string,PWire*> wires_;
|
||||
list<PGate*> gates_;
|
||||
list<PProcess*> behaviors_;
|
||||
map<string,PTask*> tasks_;
|
||||
@@ -105,6 +123,25 @@ class Module {
|
||||
|
||||
/*
|
||||
* $Log: Module.h,v $
|
||||
* Revision 1.14 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.13 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.12 2000/01/09 05:50:48 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.11 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.10 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.9 1999/08/23 16:48:39 steve
|
||||
* Parameter overrides support from Peter Monta
|
||||
* AND and XOR support wide expressions.
|
||||
*
|
||||
* Revision 1.8 1999/08/04 02:13:02 steve
|
||||
* Elaborate module ports that are concatenations of
|
||||
* module signals.
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PDelays.cc,v 1.2 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PDelays.h"
|
||||
# include "PExpr.h"
|
||||
# include "verinum.h"
|
||||
|
||||
PDelays::PDelays()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
|
||||
delay_[idx] = 0;
|
||||
}
|
||||
|
||||
PDelays::~PDelays()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
|
||||
delete delay_[idx];
|
||||
}
|
||||
|
||||
void PDelays::set_delay(PExpr*del)
|
||||
{
|
||||
assert(del);
|
||||
assert(delay_[0] == 0);
|
||||
delay_[0] = del;
|
||||
}
|
||||
|
||||
|
||||
void PDelays::set_delays(const svector<PExpr*>*del)
|
||||
{
|
||||
assert(del);
|
||||
assert(del->count() <= 3);
|
||||
for (unsigned idx = 0 ; idx < del->count() ; idx += 1)
|
||||
delay_[idx] = (*del)[idx];
|
||||
}
|
||||
|
||||
void PDelays::eval_delays(Design*des, const string&path,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const
|
||||
{
|
||||
verinum*dv;
|
||||
|
||||
if (delay_[0]) {
|
||||
dv = delay_[0]->eval_const(des, path);
|
||||
assert(dv);
|
||||
rise_time = dv->as_ulong();
|
||||
delete dv;
|
||||
|
||||
if (delay_[1]) {
|
||||
dv = delay_[1]->eval_const(des, path);
|
||||
assert(dv);
|
||||
fall_time = dv->as_ulong();
|
||||
delete dv;
|
||||
|
||||
if (delay_[2]) {
|
||||
dv = delay_[2]->eval_const(des, path);
|
||||
assert(dv);
|
||||
decay_time = dv->as_ulong();
|
||||
delete dv;
|
||||
} else {
|
||||
if (rise_time < fall_time)
|
||||
decay_time = rise_time;
|
||||
else
|
||||
decay_time = fall_time;
|
||||
}
|
||||
} else {
|
||||
assert(delay_[2] == 0);
|
||||
fall_time = rise_time;
|
||||
decay_time = rise_time;
|
||||
}
|
||||
} else {
|
||||
rise_time = 0;
|
||||
fall_time = 0;
|
||||
decay_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef __PDelays_H
|
||||
#define __PDelays_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PDelays.h,v 1.2 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include <string>
|
||||
class Design;
|
||||
class PExpr;
|
||||
class ostream;
|
||||
|
||||
/*
|
||||
* Various PForm objects can carry delays. These delays include rise,
|
||||
* fall and decay times. This class arranges to carry the triplet.
|
||||
*/
|
||||
class PDelays {
|
||||
|
||||
public:
|
||||
PDelays();
|
||||
~PDelays();
|
||||
|
||||
void set_delay(PExpr*);
|
||||
void set_delays(const svector<PExpr*>*del);
|
||||
|
||||
void eval_delays(Design*des, const string&path,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const;
|
||||
|
||||
void dump_delays(ostream&out) const;
|
||||
|
||||
private:
|
||||
PExpr* delay_[3];
|
||||
|
||||
private: // not implemented
|
||||
PDelays(const PDelays&);
|
||||
PDelays& operator= (const PDelays&);
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&o, const PDelays&);
|
||||
|
||||
/*
|
||||
* $Log: PDelays.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-1999 Stephen Williams <[email protected]>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PExpr.cc,v 1.7 1999/07/22 02:05:20 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PExpr.cc,v 1.13 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
@@ -38,14 +38,40 @@ bool PExpr::is_constant(Module*) const
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_net(Design*des, const string&path, unsigned,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
unsigned long) const
|
||||
{
|
||||
cerr << get_line() << ": error: Unable to elaborate `"
|
||||
<< *this << "' as gates." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, const string&path) const
|
||||
{
|
||||
cerr << get_line() << ": error: expression not valid in assign l-value: "
|
||||
<< *this << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PEBinary::is_constant(Module*mod) const
|
||||
{
|
||||
return left_->is_constant(mod) && right_->is_constant(mod);
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const string &n, const svector<PExpr *> &parms)
|
||||
: name_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::~PECallFunction()
|
||||
{
|
||||
}
|
||||
|
||||
bool PEConcat::is_constant(Module *mod) const
|
||||
{
|
||||
bool constant = repeat_->is_constant(mod);
|
||||
bool constant = repeat_? repeat_->is_constant(mod) : true;
|
||||
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
|
||||
constant = constant && parms_[i]->is_constant(mod);
|
||||
}
|
||||
@@ -102,6 +128,26 @@ bool PETernary::is_constant(Module*) const
|
||||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.13 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.12 1999/12/31 17:38:37 steve
|
||||
* Standardize some of the error messages.
|
||||
*
|
||||
* Revision 1.11 1999/10/31 04:11:27 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
* and instance number.
|
||||
*
|
||||
* Revision 1.10 1999/09/25 02:57:29 steve
|
||||
* Parse system function calls.
|
||||
*
|
||||
* Revision 1.9 1999/09/16 04:18:15 steve
|
||||
* elaborate concatenation repeats.
|
||||
*
|
||||
* Revision 1.8 1999/09/15 04:17:52 steve
|
||||
* separate assign lval elaboration for error checking.
|
||||
*
|
||||
* Revision 1.7 1999/07/22 02:05:20 steve
|
||||
* is_constant method for PEConcat.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PExpr_H
|
||||
#define __PExpr_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2000 Stephen Williams <[email protected]>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PExpr.h,v 1.17 1999/08/01 21:18:55 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PExpr.h,v 1.29 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -47,12 +47,22 @@ class PExpr : public LineInfo {
|
||||
virtual ~PExpr();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned long rise =0,
|
||||
unsigned long fall =0,
|
||||
unsigned long decay =0) const;
|
||||
|
||||
// Procedural elaboration of the expression.
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
|
||||
// This method elaborate the expression as gates, for use in a
|
||||
// continuous assign or other wholly structural context.
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
|
||||
|
||||
// This attempts to evaluate a constant expression, and return
|
||||
// a verinum as a result. If the expression cannot be
|
||||
// evaluated, return 0.
|
||||
@@ -68,6 +78,7 @@ class PExpr : public LineInfo {
|
||||
// identifiers and any other module specific interpretations
|
||||
// of expresions.
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
};
|
||||
|
||||
ostream& operator << (ostream&, const PExpr&);
|
||||
@@ -80,10 +91,12 @@ class PEConcat : public PExpr {
|
||||
~PEConcat();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned long rise =0,
|
||||
unsigned long fall =0,
|
||||
unsigned long decay =0) const;
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
@@ -116,11 +129,19 @@ class PEIdent : public PExpr {
|
||||
: text_(s), msb_(0), lsb_(0), idx_(0) { }
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Identifiers are allowed (with restrictions) is assign l-values.
|
||||
virtual NetNet* elaborate_lnet(Design*des, const string&path) const;
|
||||
|
||||
// Structural r-values are OK.
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned long rise =0,
|
||||
unsigned long fall =0,
|
||||
unsigned long decay =0) const;
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
@@ -138,6 +159,12 @@ class PEIdent : public PExpr {
|
||||
// If this is a reference to a memory, this is the index
|
||||
// expression.
|
||||
PExpr*idx_;
|
||||
|
||||
NetNet* elaborate_net_ram_(Design*des, const string&path,
|
||||
NetMemory*mem, unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
};
|
||||
|
||||
class PENumber : public PExpr {
|
||||
@@ -151,9 +178,10 @@ class PENumber : public PExpr {
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned long rise =0,
|
||||
unsigned long fall =0,
|
||||
unsigned long decay =0) const;
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
virtual verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
@@ -188,9 +216,10 @@ class PEUnary : public PExpr {
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned long rise =0,
|
||||
unsigned long fall =0,
|
||||
unsigned long decay =0) const;
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
|
||||
private:
|
||||
@@ -208,9 +237,10 @@ class PEBinary : public PExpr {
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned long rise =0,
|
||||
unsigned long fall =0,
|
||||
unsigned long decay =0) const;
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
virtual verinum* eval_const(const Design*des, const string&path) const;
|
||||
|
||||
@@ -218,6 +248,37 @@ class PEBinary : public PExpr {
|
||||
char op_;
|
||||
PExpr*left_;
|
||||
PExpr*right_;
|
||||
|
||||
NetNet* elaborate_net_add_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_bit_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_cmp_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_log_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_mul_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_shift_(Design*des, const string&path,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -234,6 +295,7 @@ class PETernary : public PExpr {
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, const string&path,
|
||||
unsigned width,
|
||||
unsigned long rise =0,
|
||||
unsigned long fall =0,
|
||||
unsigned long decay =0) const;
|
||||
@@ -246,22 +308,65 @@ class PETernary : public PExpr {
|
||||
PExpr*fal_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This class represents a parsed call to a function.
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const string &n, const svector<PExpr *> &parms)
|
||||
: name_(n), parms_(parms) {}
|
||||
~PECallFunction() {}
|
||||
public:
|
||||
explicit PECallFunction(const string &n, const svector<PExpr *> &parms);
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, const string&path) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
string name_;
|
||||
svector<PExpr *> parms_;
|
||||
|
||||
NetESFunc* elaborate_sfunc_(Design*des, const string&path) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.29 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.28 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.27 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.26 1999/12/16 03:46:39 steve
|
||||
* Structural logical or.
|
||||
*
|
||||
* Revision 1.25 1999/11/21 00:13:08 steve
|
||||
* Support memories in continuous assignments.
|
||||
*
|
||||
* Revision 1.24 1999/11/14 20:24:28 steve
|
||||
* Add support for the LPM_CLSHIFT device.
|
||||
*
|
||||
* Revision 1.23 1999/11/05 21:45:19 steve
|
||||
* Fix NetConst being set to zero width, and clean
|
||||
* up elaborate_set_cmp_ for NetEBinary.
|
||||
*
|
||||
* Revision 1.22 1999/10/31 20:08:24 steve
|
||||
* Include subtraction in LPM_ADD_SUB device.
|
||||
*
|
||||
* Revision 1.21 1999/10/31 04:11:27 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
* and instance number.
|
||||
*
|
||||
* Revision 1.20 1999/09/25 02:57:29 steve
|
||||
* Parse system function calls.
|
||||
*
|
||||
* Revision 1.19 1999/09/15 04:17:52 steve
|
||||
* separate assign lval elaboration for error checking.
|
||||
*
|
||||
* Revision 1.18 1999/08/31 22:38:29 steve
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
* Revision 1.17 1999/08/01 21:18:55 steve
|
||||
* elaborate rise/fall/decay for continuous assign.
|
||||
*
|
||||
|
||||
+39
-1
@@ -1,10 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PFunction.cc,v 1.3 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include "PTask.h"
|
||||
|
||||
PFunction::PFunction(svector<PWire*>*p, Statement*s)
|
||||
: ports_(p), statement_(s)
|
||||
: out_(0), ports_(p), statement_(s)
|
||||
{
|
||||
}
|
||||
|
||||
PFunction::~PFunction()
|
||||
{
|
||||
}
|
||||
|
||||
void PFunction::set_output(PWire*o)
|
||||
{
|
||||
assert(out_ == 0);
|
||||
out_ = o;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PFunction.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PGate.cc,v 1.3 1999/08/01 21:18:55 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PGate.cc,v 1.7 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PGate.h"
|
||||
@@ -30,14 +30,7 @@ PGate::PGate(const string&name,
|
||||
const svector<PExpr*>*del)
|
||||
: name_(name), pins_(pins)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
|
||||
delay_[idx] = 0;
|
||||
|
||||
if (del) {
|
||||
assert(del->count() <= 3);
|
||||
for (unsigned idx = 0 ; idx < del->count() ; idx += 1)
|
||||
delay_[idx] = (*del)[idx];
|
||||
}
|
||||
if (del) delay_.set_delays(del);
|
||||
}
|
||||
|
||||
PGate::PGate(const string&name,
|
||||
@@ -45,23 +38,16 @@ PGate::PGate(const string&name,
|
||||
PExpr*del)
|
||||
: name_(name), pins_(pins)
|
||||
{
|
||||
delay_[0] = del;
|
||||
delay_[1] = 0;
|
||||
delay_[2] = 0;
|
||||
if (del) delay_.set_delay(del);
|
||||
}
|
||||
|
||||
PGate::PGate(const string&name, svector<PExpr*>*pins)
|
||||
: name_(name), pins_(pins)
|
||||
{
|
||||
delay_[0] = 0;
|
||||
delay_[1] = 0;
|
||||
delay_[2] = 0;
|
||||
}
|
||||
|
||||
PGate::~PGate()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
|
||||
delete delay_[idx];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -77,41 +63,7 @@ void PGate::eval_delays(Design*des, const string&path,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const
|
||||
{
|
||||
verinum*dv;
|
||||
|
||||
if (delay_[0]) {
|
||||
dv = delay_[0]->eval_const(des, path);
|
||||
assert(dv);
|
||||
rise_time = dv->as_ulong();
|
||||
delete dv;
|
||||
|
||||
if (delay_[1]) {
|
||||
dv = delay_[1]->eval_const(des, path);
|
||||
assert(dv);
|
||||
fall_time = dv->as_ulong();
|
||||
delete dv;
|
||||
|
||||
if (delay_[2]) {
|
||||
dv = delay_[2]->eval_const(des, path);
|
||||
assert(dv);
|
||||
decay_time = dv->as_ulong();
|
||||
delete dv;
|
||||
} else {
|
||||
if (rise_time < fall_time)
|
||||
decay_time = rise_time;
|
||||
else
|
||||
decay_time = fall_time;
|
||||
}
|
||||
} else {
|
||||
assert(delay_[2] == 0);
|
||||
fall_time = rise_time;
|
||||
decay_time = rise_time;
|
||||
}
|
||||
} else {
|
||||
rise_time = 0;
|
||||
fall_time = 0;
|
||||
decay_time = 0;
|
||||
}
|
||||
delay_.eval_delays(des, path, rise_time, fall_time, decay_time);
|
||||
}
|
||||
|
||||
PGAssign::PGAssign(svector<PExpr*>*pins)
|
||||
@@ -158,8 +110,56 @@ void PGBuiltin::set_range(PExpr*msb, PExpr*lsb)
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
PGModule::PGModule(const string&type, const string&name, svector<PExpr*>*pins)
|
||||
: PGate(name, pins), type_(type), overrides_(0), pins_(0),
|
||||
npins_(0), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PGModule::PGModule(const string&type, const string&name,
|
||||
named<PExpr*>*pins, unsigned npins)
|
||||
: PGate(name, 0), type_(type), overrides_(0), pins_(pins),
|
||||
npins_(npins), parms_(0), nparms_(0), msb_(0), lsb_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void PGModule::set_parameters(svector<PExpr*>*o)
|
||||
{
|
||||
assert(overrides_ == 0);
|
||||
overrides_ = o;
|
||||
}
|
||||
|
||||
void PGModule::set_parameters(named<PExpr*>*pa, unsigned npa)
|
||||
{
|
||||
assert(parms_ == 0);
|
||||
assert(overrides_ == 0);
|
||||
parms_ = pa;
|
||||
nparms_ = npa;
|
||||
}
|
||||
|
||||
void PGModule::set_range(PExpr*msb, PExpr*lsb)
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
|
||||
msb_ = msb;
|
||||
lsb_ = lsb;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PGate.cc,v $
|
||||
* Revision 1.7 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 2000/02/18 05:15:02 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.5 1999/09/14 01:50:35 steve
|
||||
* Handle gates without delays.
|
||||
*
|
||||
* Revision 1.4 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
* Revision 1.3 1999/08/01 21:18:55 steve
|
||||
* elaborate rise/fall/decay for continuous assign.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PGate_H
|
||||
#define __PGate_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,12 +18,16 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PGate.h,v 1.8 1999/08/01 21:18:55 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PGate.h,v 1.14 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include "named.h"
|
||||
# include "LineInfo.h"
|
||||
# include "PDelays.h"
|
||||
# include <map>
|
||||
# include <string>
|
||||
class PExpr;
|
||||
class PUdp;
|
||||
class Design;
|
||||
@@ -61,6 +65,8 @@ class PGate : public LineInfo {
|
||||
unsigned pin_count() const { return pins_? pins_->count() : 0; }
|
||||
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
|
||||
map<string,string> attributes;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*des, const string&path) const;
|
||||
|
||||
@@ -72,7 +78,7 @@ class PGate : public LineInfo {
|
||||
|
||||
private:
|
||||
const string name_;
|
||||
PExpr* delay_[3];
|
||||
PDelays delay_;
|
||||
svector<PExpr*>*pins_;
|
||||
|
||||
private: // not implemented
|
||||
@@ -150,34 +156,65 @@ class PGModule : public PGate {
|
||||
// If the binding of ports is by position, this constructor
|
||||
// builds everything all at once.
|
||||
explicit PGModule(const string&type, const string&name,
|
||||
svector<PExpr*>*pins)
|
||||
: PGate(name, pins), type_(type), pins_(0), npins_(0) { }
|
||||
svector<PExpr*>*pins);
|
||||
|
||||
// If the binding of ports is by name, this constructor takes
|
||||
// the bindings and stores them for later elaboration.
|
||||
struct bind_t {
|
||||
string name;
|
||||
PExpr* parm;
|
||||
};
|
||||
explicit PGModule(const string&type, const string&name,
|
||||
bind_t*pins, unsigned npins)
|
||||
: PGate(name, 0), type_(type), pins_(pins), npins_(npins) { }
|
||||
named<PExpr*>*pins, unsigned npins);
|
||||
|
||||
|
||||
// Parameter overrides can come as an ordered list, or a set
|
||||
// of named expressions.
|
||||
void set_parameters(svector<PExpr*>*o);
|
||||
void set_parameters(named<PExpr*>*pa, unsigned npa);
|
||||
|
||||
// Modules can be instantiated in ranges. The parser uses this
|
||||
// method to pass the range to the pform.
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*, const string&path) const;
|
||||
|
||||
private:
|
||||
string type_;
|
||||
bind_t*pins_;
|
||||
svector<PExpr*>*overrides_;
|
||||
named<PExpr*>*pins_;
|
||||
unsigned npins_;
|
||||
|
||||
// These members support parameter override by name
|
||||
named<PExpr*>*parms_;
|
||||
unsigned nparms_;
|
||||
|
||||
// Arrays of modules are give if these are set.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
void elaborate_mod_(Design*, Module*mod, const string&path) const;
|
||||
void elaborate_udp_(Design*, PUdp *udp, const string&path) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PGate.h,v $
|
||||
* Revision 1.14 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.13 2000/02/18 05:15:02 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.12 2000/01/09 05:50:48 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.11 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.10 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
* Revision 1.9 1999/08/23 16:48:39 steve
|
||||
* Parameter overrides support from Peter Monta
|
||||
* AND and XOR support wide expressions.
|
||||
*
|
||||
* Revision 1.8 1999/08/01 21:18:55 steve
|
||||
* elaborate rise/fall/decay for continuous assign.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PTask.cc,v 1.2 1999/07/24 02:11:19 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PTask.cc,v 1.3 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PTask.h"
|
||||
@@ -33,6 +33,9 @@ PTask::~PTask()
|
||||
|
||||
/*
|
||||
* $Log: PTask.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/07/24 02:11:19 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PTask_H
|
||||
#define __PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PTask.h,v 1.3 1999/07/31 19:14:47 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PTask.h,v 1.7 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
@@ -38,7 +38,9 @@ class PTask : public LineInfo {
|
||||
explicit PTask(svector<PWire*>*p, Statement*s);
|
||||
~PTask();
|
||||
|
||||
virtual void elaborate(Design*des, const string&path) const;
|
||||
void elaborate_1(Design*des, const string&path) const;
|
||||
void elaborate_2(Design*des, const string&path) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
@@ -50,21 +52,48 @@ class PTask : public LineInfo {
|
||||
PTask& operator=(const PTask&);
|
||||
};
|
||||
|
||||
/*
|
||||
* The function is similar to a task (in this context) but there is a
|
||||
* single output port and a set of input ports. The output port is the
|
||||
* function return value.
|
||||
*/
|
||||
class PFunction : public LineInfo {
|
||||
public:
|
||||
explicit PFunction(svector<PWire *> *p, Statement *s);
|
||||
|
||||
public:
|
||||
explicit PFunction(svector<PWire *>*p, Statement *s);
|
||||
~PFunction();
|
||||
|
||||
//virtual void elaborate(Design *des, const string &path) const {}
|
||||
void set_output(PWire*);
|
||||
|
||||
/* Functions are elaborated in 2 passes. */
|
||||
void elaborate_1(Design *des, const string &path) const;
|
||||
void elaborate_2(Design *des, const string &path) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
PWire*out_;
|
||||
svector<PWire *> *ports_;
|
||||
Statement *statement_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.7 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/09/30 21:28:34 steve
|
||||
* Handle mutual reference of tasks by elaborating
|
||||
* task definitions in two passes, like functions.
|
||||
*
|
||||
* Revision 1.5 1999/09/01 20:46:19 steve
|
||||
* Handle recursive functions and arbitrary function
|
||||
* references to other functions, properly pass
|
||||
* function parameters and save function results.
|
||||
*
|
||||
* Revision 1.4 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
* Revision 1.3 1999/07/31 19:14:47 steve
|
||||
* Add functions up to elaboration (Ed Carter)
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PUdp_H
|
||||
#define __PUdp_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PUdp.h,v 1.3 1999/06/15 03:44:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PUdp.h,v 1.4 2000/02/23 02:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <map>
|
||||
@@ -82,6 +82,9 @@ class PUdp {
|
||||
|
||||
/*
|
||||
* $Log: PUdp.h,v $
|
||||
* Revision 1.4 2000/02/23 02:56:53 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PWire.cc,v 1.1 1999/06/17 05:34:42 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PWire.cc,v 1.3 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PWire.h"
|
||||
@@ -41,6 +41,10 @@ bool PWire::set_wire_type(NetNet::Type t)
|
||||
case NetNet::IMPLICIT:
|
||||
type_ = t;
|
||||
return true;
|
||||
case NetNet::IMPLICIT_REG:
|
||||
if (t == NetNet::REG) { type_ = t; return true; }
|
||||
if (t == NetNet::INTEGER) {type_ = t; return true; }
|
||||
return false;
|
||||
case NetNet::REG:
|
||||
if (t == NetNet::REG) return true;
|
||||
if (t == NetNet::INTEGER) {type_ = t; return true; }
|
||||
@@ -96,6 +100,12 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
|
||||
/*
|
||||
* $Log: PWire.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/09/10 05:02:09 steve
|
||||
* Handle integers at task parameters.
|
||||
*
|
||||
* Revision 1.1 1999/06/17 05:34:42 steve
|
||||
* Clean up interface of the PWire class,
|
||||
* Properly match wire ranges.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PWire_H
|
||||
#define __PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: PWire.h,v 1.5 1999/06/17 05:34:42 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PWire.h,v 1.7 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -58,7 +58,7 @@ class PWire : public LineInfo {
|
||||
// Write myself to the specified stream.
|
||||
void dump(ostream&out) const;
|
||||
|
||||
void elaborate(Design*, const string&path) const;
|
||||
void elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
string name_;
|
||||
@@ -82,6 +82,12 @@ class PWire : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PWire.h,v $
|
||||
* Revision 1.7 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.5 1999/06/17 05:34:42 steve
|
||||
* Clean up interface of the PWire class,
|
||||
* Properly match wire ranges.
|
||||
|
||||
+143
-84
@@ -1,53 +1,101 @@
|
||||
THE ICARUS VERILOG COMPILATION SYSTEM
|
||||
July 7, 1999
|
||||
September 18, 1999
|
||||
|
||||
|
||||
1.0 What is ICARUS Verilog(IVL)?
|
||||
1.0 What is ICARUS Verilog?
|
||||
|
||||
Icarus Verilog is intended to compile ALL of the Verilog HDL as described
|
||||
in the IEEE-1364 standard. Of course, it's not quite there yet. It does
|
||||
currently handle a mix of structural and behavioral constructs.
|
||||
currently handle a mix of structural and behavioral constructs. For a
|
||||
view of the current state of Icarus Verilog, see its home page at
|
||||
<http://www.icarus.com/eda/verilog>.
|
||||
|
||||
IVL is not aimed at being a simulator in the traditional sense, but a
|
||||
compiler that generates code employed by back-end tools. These back-
|
||||
end tools currently include a simulator written in C++ called VVM
|
||||
and an XNF (Xilinx Netlist Format) generator. See "vvm.txt" and
|
||||
"xnf.txt" for further details on these back-end processors.
|
||||
"xnf.txt" for further details on these back-end processors. In the
|
||||
future, backends are expected for EDIF/LPM, structural Verilog, etc.
|
||||
|
||||
2.0 How IVL Works
|
||||
2.0 Building/Installing IVL From Source
|
||||
|
||||
If you are starting from source, the build process is designed to be
|
||||
as simple as practical. Someone basically familiar with the target
|
||||
system and C/C++ compilation should be able to build the source
|
||||
distribution with little effort. Some actual programming skills are
|
||||
not required, but helpful in case of problems.
|
||||
|
||||
2.1 Compile Time Prerequisites
|
||||
|
||||
You need the following software to compile Icarus Verilog from source
|
||||
on a UNIX-like system:
|
||||
|
||||
- GNU Make
|
||||
The Makefiles use some GNU extensions to, so a basic POSIX
|
||||
make will not work. Linux systems typically come with a
|
||||
satisfactory make.
|
||||
|
||||
- ISO C++ Compiler
|
||||
The ivl program is written in C++ and makes use of templates
|
||||
and some of the standard C++ library. egcs compilers with
|
||||
the associated libstdc++ are known to work.
|
||||
|
||||
- bison
|
||||
|
||||
2.2 Compilation
|
||||
|
||||
Unpack the tar-ball and cd into the verilog-######### directory
|
||||
(presumably that is how you got to this README) and compile the source
|
||||
with the commands:
|
||||
|
||||
./configure
|
||||
make
|
||||
|
||||
2.3 Installation
|
||||
|
||||
Now install the files in an appropriate place. (The makefiles by
|
||||
default install in /usr/local unless you specify a different prefix
|
||||
with the --prefix=<path> flag to the configure command.) Do this as
|
||||
root.
|
||||
|
||||
make install
|
||||
|
||||
3.0 How IVL Works
|
||||
|
||||
This tool includes a parser which reads in Verilog (plus extensions)
|
||||
and generates an internal netlist. The netlist is passed to various
|
||||
processing steps that transform the design to more optimal/practical
|
||||
forms, then passed to a code generator for final output. The
|
||||
forms, then is passed to a code generator for final output. The
|
||||
processing steps and the code generator are selected by command line
|
||||
switches.
|
||||
|
||||
2.1 Preprocessing
|
||||
3.1 Preprocessing
|
||||
|
||||
There is a separate program, ivlpp, that does the preprocessing. This
|
||||
program implements the `include and `define directives producing
|
||||
output that is equivalent but without the directives. See
|
||||
ivlpp/ivlpp.txt for details.
|
||||
output that is equivalent but without the directives. The output is a
|
||||
single file with line number directives, so that the actual compiler
|
||||
only sees a single input file. See ivlpp/ivlpp.txt for details.
|
||||
|
||||
2.2 Parse
|
||||
3.2 Parse
|
||||
|
||||
The verilog compiler starts by parsing the verilog source file. The
|
||||
output of the parse in a list of Module objects in PFORM. The pform
|
||||
(see pform.h) is mostly a direct reflection of the compilation
|
||||
unit. There may be dangling references, and it is not yet clear which
|
||||
step. There may be dangling references, and it is not yet clear which
|
||||
module is the root.
|
||||
|
||||
One can see a human readable version of the final PFORM by using the
|
||||
``-P <path>'' flag to the compiler. This will cause ivl to dump the
|
||||
PFORM into the file named <path>.
|
||||
|
||||
2.3 Elaboration
|
||||
3.3 Elaboration
|
||||
|
||||
This phase takes the pform and generates a netlist. The driver selects
|
||||
(by user request or lucky guess) the root module to elaborate,
|
||||
resolves references and expands the instantiations to form the design
|
||||
netlist. (See netlist.txt.)
|
||||
netlist. (See netlist.txt.) Final semantic checks are performed during
|
||||
elaboration, and some simple optimizations are performed.
|
||||
|
||||
The elaborate() function performs the elaboration.
|
||||
|
||||
@@ -56,7 +104,7 @@ optimized netlist by using the ``-N <path>'' flag to the compiler. If
|
||||
elaboration succeeds, the final netlist (i.e. after optimizations but
|
||||
before code generation) will be dumped into the file named <path>.
|
||||
|
||||
2.4 Optimization
|
||||
3.4 Optimization
|
||||
|
||||
This is actually a collection of processing steps that perform
|
||||
optimizations that do not depend on the target technology. Examples of
|
||||
@@ -69,7 +117,7 @@ some useful transformations would be,
|
||||
The actual functions performed are specified on the command line by
|
||||
the -F flags (See below).
|
||||
|
||||
2.5 Code Generation
|
||||
3.5 Code Generation
|
||||
|
||||
This step takes the design netlist and uses it to drive the code
|
||||
generator. (See target.h.) This may require transforming the
|
||||
@@ -82,25 +130,14 @@ to generate actual output.
|
||||
The target code generator to used is given by the -t flag on the
|
||||
command line.
|
||||
|
||||
3.0 Building/Installing IVL
|
||||
4.0 Running Verilog
|
||||
|
||||
Unpack the tar-ball and cd into the verilog-######### directory.
|
||||
The preferred way to invoke the compiler with the verilog(1)
|
||||
command. This program invokes the preprocessor (ivlpp) and the
|
||||
compiler (ivl) with the proper command line options to get the job
|
||||
done in a friendly way. See the verilog(1) man page for usage details.
|
||||
|
||||
./configure
|
||||
make
|
||||
cd vvm
|
||||
make
|
||||
|
||||
Now install the files in an appropriate place. (The makefiles by
|
||||
default install in /usr/local unless you specify a different prefix
|
||||
with the --prefix=<path> flag to the configure command.) Do this as
|
||||
root.
|
||||
|
||||
make install
|
||||
cd vvm
|
||||
make install
|
||||
|
||||
4.0 Running IVL
|
||||
4.1 Running IVL Directly
|
||||
|
||||
The ivl command is the compiler driver, that invokes the parser,
|
||||
optimization functions and the code generator.
|
||||
@@ -129,6 +166,17 @@ Usage: ivl <options>... file
|
||||
target specific information to the target back-end, or
|
||||
options/parameters to optimization functions, if any are defined.
|
||||
|
||||
-m <module>
|
||||
Cause a named VPI module to be included in the module
|
||||
list. This parameter appends the named module to the end of
|
||||
the VPI_MODULE_LIST. This is an ordered list of modules to be
|
||||
loaded into the simulation at runtime.
|
||||
|
||||
This list can also be set with -fVPI_MODULE_LIST=<list> which
|
||||
sets the list completely. Then, -m after this will append
|
||||
module names to the list sp specified. The default list
|
||||
includes "system".
|
||||
|
||||
-N <file>
|
||||
Dump the elaborated netlist to the named file. The netlist is
|
||||
the folly elaborated netlist, after all the function modules
|
||||
@@ -208,78 +256,80 @@ endmodule
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
Insure that "ivl" is on your search path, and the library
|
||||
libvvm.a is available.
|
||||
Insure that "verilog" is on your search path, and the vpi library
|
||||
is available.
|
||||
|
||||
For csh -
|
||||
|
||||
setenv PATH /usr/local/bin:$PATH
|
||||
setenv LD_LIBRARY_PATH /usr/local/lib:$LD_LIBRARY_PATH
|
||||
setenv PATH /usr/local/bin:$PATH
|
||||
setenv VPI_MODULE_PATH /usr/local/lib/ivl
|
||||
|
||||
ivl -t vvm -o hello.cc hello.vl
|
||||
g++ hello.cc -o hello -lvvm
|
||||
verilog hello.vl
|
||||
|
||||
(The above presumes that /usr/local/include and /usr/local/lib are
|
||||
part of the compiler search path, which is usually the case for egcs.)
|
||||
part of the compiler search path, which is usually the case for gcc.)
|
||||
|
||||
To run the program
|
||||
|
||||
./hello
|
||||
./hello
|
||||
|
||||
|
||||
5.0 Unsupported Constructs
|
||||
|
||||
IVL is in development - as such it still only supports a (growing) subset
|
||||
of verilog. Below is a description of some of the currently unsupported
|
||||
verilog features.
|
||||
|
||||
- The "?" operator. Example: count = val ? 1 : 0;
|
||||
|
||||
- Ranges within parameter definitions:
|
||||
Example: parameter [15:0] seed = 16'ha3;
|
||||
|
||||
[Note: IEEE Std: 1364-1995 does not allow the syntax.]
|
||||
|
||||
- The "&&" operator:
|
||||
Example: if (a && 0) do = 1;
|
||||
|
||||
- The "===" operator: Example: if( a === b) do = 1;
|
||||
|
||||
- The ">=" operator: Example: if ( a >= 0) do = 1;
|
||||
|
||||
- The ">" operator: Example: if ( a > 0) do = 1;
|
||||
|
||||
- The "<=" operator: Example: if ( a <= 0) do = 1;
|
||||
|
||||
- The "<<" shift operator: Example: a = 8'b0000_0010 << 1;
|
||||
verilog features. This list is not exhaustive, and does not account
|
||||
for errors in the compiler. See the Icarus Verilog web page for the
|
||||
current state of support for Verilog.
|
||||
|
||||
- Min/Typ/Max expressions: Example: a = (1 : 6 : 14);
|
||||
|
||||
- Expansion of a string into a larger variable:
|
||||
Example: reg [0:15] b; b = "b";
|
||||
|
||||
- Function declarations/calls.
|
||||
|
||||
- Non-scalar memories, i.e. other than registers.
|
||||
Example: reg [1:0] b [2:0];
|
||||
|
||||
- Delay list. Example: sample #(9,99) sample1(a,b);
|
||||
|
||||
- Bit ranges within IF. Example: if (a[2:3]) do = 1;
|
||||
|
||||
- Assignment timing delay: Example: a = #1 0; #1 a = #2 ~a;
|
||||
|
||||
- Bit Ranges within $write, $display.
|
||||
|
||||
- `timescale directive
|
||||
|
||||
- Specify blocks
|
||||
- force/release/assign/deassign procedural assignments not
|
||||
supported.
|
||||
|
||||
- Named port parameters.
|
||||
Example: module foo(.x(r[0])) ; reg r[7:0]; endmodule
|
||||
- block disable not supported, i.e.:
|
||||
|
||||
begin : foo
|
||||
[...]
|
||||
disable foo; // sorry
|
||||
[...]
|
||||
end
|
||||
|
||||
- fork/join is not supported in vvm runtime
|
||||
|
||||
- Functions in structural contexts are not supported.
|
||||
|
||||
assign foo = user_function(a,b); // sorry
|
||||
always @(a or b) foo = user_function(a,b); // OK
|
||||
|
||||
- multiplicative operators (*, /, %) are not supported in
|
||||
general. They do work if the compiler can evaluate them at compile
|
||||
time.
|
||||
|
||||
assign foo = a * b; // sorry
|
||||
always @(a or b) foo = a * b; // sorry
|
||||
|
||||
- event data type is not supported.
|
||||
|
||||
- real data type not supported.
|
||||
|
||||
- system functions are not supported. (User defined functions are
|
||||
supported, and system tasks are supported.)
|
||||
|
||||
assign foo = $some_function(a,b); // sorry
|
||||
always @(a or b) foo = $some_function(a,b); // sorry
|
||||
|
||||
- non-constant delay expressions, i.e.:
|
||||
|
||||
reg [7:0] del;
|
||||
always #(reg) $display($time,,"del = %d", del); // sorry
|
||||
|
||||
- drive strengths are parsed, bug ignored.
|
||||
|
||||
Specify blocks are parsed but ignored in general.
|
||||
|
||||
Note that binding to a port by name does work from the outside.
|
||||
i.e. ``foo foogate(.x(n[0]))'' is OK.
|
||||
|
||||
6.0 CREDITS
|
||||
|
||||
@@ -288,14 +338,23 @@ Williams. The proper notices are in the head of each file. However,
|
||||
I have received aid in the form of fixes, Verilog guidance, and
|
||||
especially testing from many people, including (in alphabetical order):
|
||||
|
||||
Eric Aardoom <[email protected]>
|
||||
Stephan I. Boettcher <[email protected]>
|
||||
Ed Carter <[email protected]>
|
||||
Larry Doolittle <[email protected]>
|
||||
Guy Hutchison <[email protected]>
|
||||
Ales Hvezda <[email protected]>
|
||||
Yasuhisa Kato <[email protected]>
|
||||
James Lee <[email protected]>
|
||||
Jason Schonberg <schon@mips.com>
|
||||
Peter Monta <[email protected].com>
|
||||
Daniel H. Nelsen <[email protected]>
|
||||
Stefan Petersen <[email protected]>
|
||||
Jason Schonberg <[email protected]>
|
||||
Stuart Sutherland <[email protected]>
|
||||
Stephen Tell <[email protected]>
|
||||
Stefan Theide <[email protected]>
|
||||
Steve Wilson <[email protected]>
|
||||
|
||||
and others. Testers in particular include a larger community of people
|
||||
interested in a GPL Verilog for Linux.
|
||||
interested in a GPL Verilog for Linux. Special thanks to Steve Wilson
|
||||
for collecting and organizing the test suite code for all those testers.
|
||||
|
||||
+44
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Statement.cc,v 1.12 1999/07/12 00:59:36 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Statement.cc,v 1.17 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "Statement.h"
|
||||
@@ -27,20 +27,30 @@ Statement::~Statement()
|
||||
{
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval, PExpr*ex)
|
||||
: event_(0), lval_(lval), rval_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex)
|
||||
: lval_(lval), delay_(de), rval_(ex)
|
||||
: event_(0), lval_(lval), rval_(ex)
|
||||
{
|
||||
if (de) delay_.set_delay(de);
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex)
|
||||
: event_(ev), lval_(lval), rval_(ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign_::~PAssign_()
|
||||
{
|
||||
delete lval_;
|
||||
delete delay_;
|
||||
delete rval_;
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval, PExpr*ex)
|
||||
: PAssign_(lval, 0, ex)
|
||||
: PAssign_(lval, ex)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,12 +59,22 @@ PAssign::PAssign(PExpr*lval, PExpr*d, PExpr*ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign::PAssign(PExpr*lval, PEventStatement*d, PExpr*ex)
|
||||
: PAssign_(lval, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssign::~PAssign()
|
||||
{
|
||||
}
|
||||
|
||||
PAssignNB::PAssignNB(PExpr*lval, PExpr*ex)
|
||||
: PAssign_(lval, 0, ex)
|
||||
: PAssign_(lval, ex)
|
||||
{
|
||||
}
|
||||
|
||||
PAssignNB::PAssignNB(PExpr*lval, PExpr*d, PExpr*ex)
|
||||
: PAssign_(lval, d, ex)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -88,8 +108,8 @@ PCallTask::PCallTask(const string&n, const svector<PExpr*>&p)
|
||||
{
|
||||
}
|
||||
|
||||
PCase::PCase(PExpr*ex, svector<PCase::Item*>*l)
|
||||
: expr_(ex), items_(l)
|
||||
PCase::PCase(NetCase::TYPE t, PExpr*ex, svector<PCase::Item*>*l)
|
||||
: type_(t), expr_(ex), items_(l)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -143,6 +163,21 @@ PWhile::~PWhile()
|
||||
|
||||
/*
|
||||
* $Log: Statement.cc,v $
|
||||
* Revision 1.17 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.16 1999/09/29 18:36:02 steve
|
||||
* Full case support
|
||||
*
|
||||
* Revision 1.15 1999/09/22 02:00:48 steve
|
||||
* assignment with blocking event delay.
|
||||
*
|
||||
* Revision 1.14 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
* Revision 1.13 1999/09/02 01:59:27 steve
|
||||
* Parse non-blocking assignment delays.
|
||||
*
|
||||
* Revision 1.12 1999/07/12 00:59:36 steve
|
||||
* procedural blocking assignment delays.
|
||||
*
|
||||
|
||||
+38
-6
@@ -1,7 +1,7 @@
|
||||
#ifndef __Statement_H
|
||||
#define __Statement_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,16 +18,18 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Statement.h,v 1.15 1999/07/12 00:59:36 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Statement.h,v 1.21 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
# include "svector.h"
|
||||
# include "PDelays.h"
|
||||
# include "PExpr.h"
|
||||
# include "LineInfo.h"
|
||||
class PExpr;
|
||||
class Statement;
|
||||
class PEventStatement;
|
||||
|
||||
/*
|
||||
* The PProcess is the root of a behavioral process. Each process gets
|
||||
@@ -77,11 +79,12 @@ class Statement : public LineInfo {
|
||||
*/
|
||||
class PAssign_ : public Statement {
|
||||
public:
|
||||
explicit PAssign_(PExpr*lval, PExpr*ex);
|
||||
explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
explicit PAssign_(PExpr*lval, PEventStatement*de, PExpr*ex);
|
||||
virtual ~PAssign_() =0;
|
||||
|
||||
const PExpr* lval() const { return lval_; }
|
||||
const PExpr* delay() const { return delay_; }
|
||||
const PExpr* rval() const { return rval_; }
|
||||
|
||||
protected:
|
||||
@@ -89,9 +92,11 @@ class PAssign_ : public Statement {
|
||||
unsigned&lsb, unsigned&msb,
|
||||
NetExpr*&mux) const;
|
||||
|
||||
PDelays delay_;
|
||||
PEventStatement*event_;
|
||||
|
||||
private:
|
||||
PExpr* lval_;
|
||||
PExpr* delay_;
|
||||
PExpr* rval_;
|
||||
};
|
||||
|
||||
@@ -100,6 +105,7 @@ class PAssign : public PAssign_ {
|
||||
public:
|
||||
explicit PAssign(PExpr*lval, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
explicit PAssign(PExpr*lval, PEventStatement*de, PExpr*ex);
|
||||
~PAssign();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
@@ -114,12 +120,15 @@ class PAssignNB : public PAssign_ {
|
||||
|
||||
public:
|
||||
explicit PAssignNB(PExpr*lval, PExpr*ex);
|
||||
explicit PAssignNB(PExpr*lval, PExpr*de, PExpr*ex);
|
||||
~PAssignNB();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
|
||||
private:
|
||||
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
|
||||
Design*des, const string&path) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -191,13 +200,14 @@ class PCase : public Statement {
|
||||
Statement*stat;
|
||||
};
|
||||
|
||||
PCase(PExpr*ex, svector<Item*>*);
|
||||
PCase(NetCase::TYPE, PExpr*ex, svector<Item*>*);
|
||||
~PCase();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
NetCase::TYPE type_;
|
||||
PExpr*expr_;
|
||||
|
||||
svector<Item*>*items_;
|
||||
@@ -256,6 +266,10 @@ class PEventStatement : public Statement {
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, const string&path) const;
|
||||
|
||||
// This method is used to elaborate, but attach a previously
|
||||
// elaborated statement to the event.
|
||||
NetProc* elaborate_st(Design*des, const string&path, NetProc*st) const;
|
||||
|
||||
private:
|
||||
svector<PEEvent*>expr_;
|
||||
Statement*statement_;
|
||||
@@ -333,6 +347,24 @@ class PWhile : public Statement {
|
||||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.21 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.20 1999/09/29 18:36:02 steve
|
||||
* Full case support
|
||||
*
|
||||
* Revision 1.19 1999/09/22 02:00:48 steve
|
||||
* assignment with blocking event delay.
|
||||
*
|
||||
* Revision 1.18 1999/09/15 01:55:06 steve
|
||||
* Elaborate non-blocking assignment to memories.
|
||||
*
|
||||
* Revision 1.17 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
* Revision 1.16 1999/09/02 01:59:27 steve
|
||||
* Parse non-blocking assignment delays.
|
||||
*
|
||||
* Revision 1.15 1999/07/12 00:59:36 steve
|
||||
* procedural blocking assignment delays.
|
||||
*
|
||||
|
||||
+6
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef __compiler_H
|
||||
#define __compiler_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: compiler.h,v 1.1 1999/06/06 20:42:48 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: compiler.h,v 1.2 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -35,6 +35,9 @@
|
||||
|
||||
/*
|
||||
* $Log: compiler.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/06/06 20:42:48 steve
|
||||
* Make compiler width a compile time constant.
|
||||
*
|
||||
|
||||
+912
@@ -0,0 +1,912 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Written by Per Bothner <[email protected]>.
|
||||
# The master version of this file is at the FSF in /home/gd/gnu/lib.
|
||||
#
|
||||
# This script attempts to guess a canonical system name similar to
|
||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||
# exits with 0. Otherwise, it exits with 1.
|
||||
#
|
||||
# The plan is that this can be called by configure scripts if you
|
||||
# don't specify an explicit system type (host/target name).
|
||||
#
|
||||
# Only a few systems have been added to this list; please add others
|
||||
# (but try to keep the structure clean).
|
||||
#
|
||||
|
||||
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
|
||||
# ([email protected] 8/24/94.)
|
||||
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
|
||||
PATH=$PATH:/.attbin ; export PATH
|
||||
fi
|
||||
|
||||
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
|
||||
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
|
||||
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
|
||||
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
|
||||
|
||||
trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
|
||||
|
||||
# Note: order is significant - the case branches are not exclusive.
|
||||
|
||||
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
alpha:OSF1:*:*)
|
||||
if test $UNAME_RELEASE = "V4.0"; then
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
||||
fi
|
||||
# A Vn.n version is a released version.
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
cat <<EOF >dummy.s
|
||||
.globl main
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,0,\$26,0
|
||||
.prologue 0
|
||||
.long 0x47e03d80 # implver $0
|
||||
lda \$2,259
|
||||
.long 0x47e20c21 # amask $2,$1
|
||||
srl \$1,8,\$2
|
||||
sll \$2,2,\$2
|
||||
sll \$0,3,\$0
|
||||
addl \$1,\$0,\$0
|
||||
addl \$2,\$0,\$0
|
||||
ret \$31,(\$26),1
|
||||
.end main
|
||||
EOF
|
||||
${CC-cc} dummy.s -o dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy
|
||||
case "$?" in
|
||||
7)
|
||||
UNAME_MACHINE="alpha"
|
||||
;;
|
||||
15)
|
||||
UNAME_MACHINE="alphaev5"
|
||||
;;
|
||||
14)
|
||||
UNAME_MACHINE="alphaev56"
|
||||
;;
|
||||
10)
|
||||
UNAME_MACHINE="alphapca56"
|
||||
;;
|
||||
16)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
rm -f dummy.s dummy
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
|
||||
exit 0 ;;
|
||||
21064:Windows_NT:50:3)
|
||||
echo alpha-dec-winnt3.5
|
||||
exit 0 ;;
|
||||
Amiga*:UNIX_System_V:4.0:*)
|
||||
echo m68k-cbm-sysv4
|
||||
exit 0;;
|
||||
amiga:NetBSD:*:*)
|
||||
echo m68k-cbm-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
amiga:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
arc64:OpenBSD:*:*)
|
||||
echo mips64el-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
arc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hkmips:OpenBSD:*:*)
|
||||
echo mips-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
pmax:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sgi:OpenBSD:*:*)
|
||||
echo mips-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
wgrisc:OpenBSD:*:*)
|
||||
echo mipsel-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
|
||||
echo arm-acorn-riscix${UNAME_RELEASE}
|
||||
exit 0;;
|
||||
arm32:NetBSD:*:*)
|
||||
echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
SR2?01:HI-UX/MPP:*:*)
|
||||
echo hppa1.1-hitachi-hiuxmpp
|
||||
exit 0;;
|
||||
Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
|
||||
# [email protected] (Earle F. Ake) contributed MIS and NILE.
|
||||
if test "`(/bin/universe) 2>/dev/null`" = att ; then
|
||||
echo pyramid-pyramid-sysv3
|
||||
else
|
||||
echo pyramid-pyramid-bsd
|
||||
fi
|
||||
exit 0 ;;
|
||||
NILE:*:*:dcosx)
|
||||
echo pyramid-pyramid-svr4
|
||||
exit 0 ;;
|
||||
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
|
||||
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
i86pc:SunOS:5.*:*)
|
||||
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
sun4*:SunOS:6*:*)
|
||||
# According to config.sub, this is the proper way to canonicalize
|
||||
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
|
||||
# it's likely to be more like Solaris than SunOS4.
|
||||
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
sun4*:SunOS:*:*)
|
||||
case "`/usr/bin/arch -k`" in
|
||||
Series*|S4*)
|
||||
UNAME_RELEASE=`uname -v`
|
||||
;;
|
||||
esac
|
||||
# Japanese Language versions have a version number like `4.1.3-JL'.
|
||||
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
|
||||
exit 0 ;;
|
||||
sun3*:SunOS:*:*)
|
||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun*:*:4.2BSD:*)
|
||||
UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
|
||||
case "`/bin/arch`" in
|
||||
sun3)
|
||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||
;;
|
||||
sun4)
|
||||
echo sparc-sun-sunos${UNAME_RELEASE}
|
||||
;;
|
||||
esac
|
||||
exit 0 ;;
|
||||
aushp:SunOS:*:*)
|
||||
echo sparc-auspex-sunos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:NetBSD:*:*)
|
||||
echo m68k-atari-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
atari*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3*:NetBSD:*:*)
|
||||
echo m68k-sun-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
sun3*:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mac68k:NetBSD:*:*)
|
||||
echo m68k-apple-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mac68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvme68k:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mvme88k:OpenBSD:*:*)
|
||||
echo m88k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
powerpc:machten:*:*)
|
||||
echo powerpc-apple-machten${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
RISC*:Mach:*:*)
|
||||
echo mips-dec-mach_bsd4.3
|
||||
exit 0 ;;
|
||||
RISC*:ULTRIX:*:*)
|
||||
echo mips-dec-ultrix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
VAX*:ULTRIX*:*:*)
|
||||
echo vax-dec-ultrix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
2020:CLIX:*:*)
|
||||
echo clipper-intergraph-clix${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mips:*:*:UMIPS | mips:*:*:RISCos)
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
int main (argc, argv) int argc; char **argv; {
|
||||
#if defined (host_mips) && defined (MIPSEB)
|
||||
#if defined (SYSTYPE_SYSV)
|
||||
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#if defined (SYSTYPE_SVR4)
|
||||
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
|
||||
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
exit (-1);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy \
|
||||
&& ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
|
||||
&& rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
echo mips-mips-riscos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
Night_Hawk:Power_UNIX:*:*)
|
||||
echo powerpc-harris-powerunix
|
||||
exit 0 ;;
|
||||
m88k:CX/UX:7*:*)
|
||||
echo m88k-harris-cxux7
|
||||
exit 0 ;;
|
||||
m88k:*:4*:R4*)
|
||||
echo m88k-motorola-sysv4
|
||||
exit 0 ;;
|
||||
m88k:*:3*:R3*)
|
||||
echo m88k-motorola-sysv3
|
||||
exit 0 ;;
|
||||
AViiON:dgux:*:*)
|
||||
# DG/UX returns AViiON for all architectures
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
|
||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
|
||||
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
|
||||
echo m88k-dg-dgux${UNAME_RELEASE}
|
||||
else
|
||||
echo m88k-dg-dguxbcs${UNAME_RELEASE}
|
||||
fi
|
||||
else echo i586-dg-dgux${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
|
||||
echo m88k-dolphin-sysv3
|
||||
exit 0 ;;
|
||||
M88*:*:R3*:*)
|
||||
# Delta 88k system running SVR3
|
||||
echo m88k-motorola-sysv3
|
||||
exit 0 ;;
|
||||
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
|
||||
echo m88k-tektronix-sysv3
|
||||
exit 0 ;;
|
||||
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
|
||||
echo m68k-tektronix-bsd
|
||||
exit 0 ;;
|
||||
*:IRIX*:*:*)
|
||||
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
|
||||
exit 0 ;;
|
||||
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
|
||||
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
|
||||
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
|
||||
i?86:AIX:*:*)
|
||||
echo i386-ibm-aix
|
||||
exit 0 ;;
|
||||
*:AIX:2:3)
|
||||
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
#include <sys/systemcfg.h>
|
||||
|
||||
main()
|
||||
{
|
||||
if (!__power_pc())
|
||||
exit(1);
|
||||
puts("powerpc-ibm-aix3.2.5");
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
echo rs6000-ibm-aix3.2.5
|
||||
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
|
||||
echo rs6000-ibm-aix3.2.4
|
||||
else
|
||||
echo rs6000-ibm-aix3.2
|
||||
fi
|
||||
exit 0 ;;
|
||||
*:AIX:*:4)
|
||||
if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
|
||||
IBM_ARCH=rs6000
|
||||
else
|
||||
IBM_ARCH=powerpc
|
||||
fi
|
||||
if [ -x /usr/bin/oslevel ] ; then
|
||||
IBM_REV=`/usr/bin/oslevel`
|
||||
else
|
||||
IBM_REV=4.${UNAME_RELEASE}
|
||||
fi
|
||||
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
|
||||
exit 0 ;;
|
||||
*:AIX:*:*)
|
||||
echo rs6000-ibm-aix
|
||||
exit 0 ;;
|
||||
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
|
||||
echo romp-ibm-bsd4.4
|
||||
exit 0 ;;
|
||||
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
|
||||
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
|
||||
exit 0 ;; # report: romp-ibm BSD 4.3
|
||||
*:BOSX:*:*)
|
||||
echo rs6000-bull-bosx
|
||||
exit 0 ;;
|
||||
DPX/2?00:B.O.S.:*:*)
|
||||
echo m68k-bull-sysv3
|
||||
exit 0 ;;
|
||||
9000/[34]??:4.3bsd:1.*:*)
|
||||
echo m68k-hp-bsd
|
||||
exit 0 ;;
|
||||
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
|
||||
echo m68k-hp-bsd4.4
|
||||
exit 0 ;;
|
||||
9000/[3478]??:HP-UX:*:*)
|
||||
case "${UNAME_MACHINE}" in
|
||||
9000/31? ) HP_ARCH=m68000 ;;
|
||||
9000/[34]?? ) HP_ARCH=m68k ;;
|
||||
9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
|
||||
9000/8?? ) HP_ARCH=hppa1.0 ;;
|
||||
esac
|
||||
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
|
||||
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
||||
exit 0 ;;
|
||||
3050*:HI-UX:*:*)
|
||||
sed 's/^ //' << EOF >dummy.c
|
||||
#include <unistd.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
long cpu = sysconf (_SC_CPU_VERSION);
|
||||
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
|
||||
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
|
||||
results, however. */
|
||||
if (CPU_IS_PA_RISC (cpu))
|
||||
{
|
||||
switch (cpu)
|
||||
{
|
||||
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
|
||||
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
|
||||
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
|
||||
default: puts ("hppa-hitachi-hiuxwe2"); break;
|
||||
}
|
||||
}
|
||||
else if (CPU_IS_HP_MC68K (cpu))
|
||||
puts ("m68k-hitachi-hiuxwe2");
|
||||
else puts ("unknown-hitachi-hiuxwe2");
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
echo unknown-hitachi-hiuxwe2
|
||||
exit 0 ;;
|
||||
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
|
||||
echo hppa1.1-hp-bsd
|
||||
exit 0 ;;
|
||||
9000/8??:4.3bsd:*:*)
|
||||
echo hppa1.0-hp-bsd
|
||||
exit 0 ;;
|
||||
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
|
||||
echo hppa1.1-hp-osf
|
||||
exit 0 ;;
|
||||
hp8??:OSF1:*:*)
|
||||
echo hppa1.0-hp-osf
|
||||
exit 0 ;;
|
||||
i?86:OSF1:*:*)
|
||||
if [ -x /usr/sbin/sysversion ] ; then
|
||||
echo ${UNAME_MACHINE}-unknown-osf1mk
|
||||
else
|
||||
echo ${UNAME_MACHINE}-unknown-osf1
|
||||
fi
|
||||
exit 0 ;;
|
||||
parisc*:Lites*:*:*)
|
||||
echo hppa1.1-hp-lites
|
||||
exit 0 ;;
|
||||
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
|
||||
echo c1-convex-bsd
|
||||
exit 0 ;;
|
||||
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
|
||||
if getsysinfo -f scalar_acc
|
||||
then echo c32-convex-bsd
|
||||
else echo c2-convex-bsd
|
||||
fi
|
||||
exit 0 ;;
|
||||
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
|
||||
echo c34-convex-bsd
|
||||
exit 0 ;;
|
||||
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
|
||||
echo c38-convex-bsd
|
||||
exit 0 ;;
|
||||
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
|
||||
echo c4-convex-bsd
|
||||
exit 0 ;;
|
||||
CRAY*X-MP:*:*:*)
|
||||
echo xmp-cray-unicos
|
||||
exit 0 ;;
|
||||
CRAY*Y-MP:*:*:*)
|
||||
echo ymp-cray-unicos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
CRAY*[A-Z]90:*:*:*)
|
||||
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
|
||||
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
|
||||
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
|
||||
exit 0 ;;
|
||||
CRAY*TS:*:*:*)
|
||||
echo t90-cray-unicos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
CRAY-2:*:*:*)
|
||||
echo cray2-cray-unicos
|
||||
exit 0 ;;
|
||||
F300:UNIX_System_V:*:*)
|
||||
FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit 0 ;;
|
||||
F301:UNIX_System_V:*:*)
|
||||
echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
|
||||
exit 0 ;;
|
||||
hp3[0-9][05]:NetBSD:*:*)
|
||||
echo m68k-hp-netbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
hp300:OpenBSD:*:*)
|
||||
echo m68k-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
i?86:BSD/386:*:* | *:BSD/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:FreeBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
|
||||
exit 0 ;;
|
||||
*:NetBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
*:OpenBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
exit 0 ;;
|
||||
i*:CYGWIN*:*)
|
||||
echo i386-pc-cygwin32
|
||||
exit 0 ;;
|
||||
i*:MINGW*:*)
|
||||
echo i386-pc-mingw32
|
||||
exit 0 ;;
|
||||
p*:CYGWIN*:*)
|
||||
echo powerpcle-unknown-cygwin32
|
||||
exit 0 ;;
|
||||
prep*:SunOS:5.*:*)
|
||||
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit 0 ;;
|
||||
*:GNU:*:*)
|
||||
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
||||
exit 0 ;;
|
||||
*:Linux:*:*)
|
||||
# The BFD linker knows what the default object file format is, so
|
||||
# first see if it will tell us.
|
||||
ld_help_string=`ld --help 2>&1`
|
||||
ld_supported_emulations=`echo $ld_help_string \
|
||||
| sed -ne '/supported emulations:/!d
|
||||
s/[ ][ ]*/ /g
|
||||
s/.*supported emulations: *//
|
||||
s/ .*//
|
||||
p'`
|
||||
case "$ld_supported_emulations" in
|
||||
i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
|
||||
i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
|
||||
sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
|
||||
elf32ppc)
|
||||
# Determine Lib Version
|
||||
cat >dummy.c <<EOF
|
||||
#include <features.h>
|
||||
#if defined(__GLIBC__)
|
||||
extern char __libc_version[];
|
||||
extern char __libc_release[];
|
||||
#endif
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#if defined(__GLIBC__)
|
||||
printf("%s %s\n", __libc_version, __libc_release);
|
||||
#else
|
||||
printf("unkown\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
LIBC=""
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy | grep 1\.99 > /dev/null
|
||||
if test "$?" = 0 ; then
|
||||
LIBC="libc1"
|
||||
fi
|
||||
fi
|
||||
rm -f dummy.c dummy
|
||||
echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
|
||||
esac
|
||||
|
||||
if test "${UNAME_MACHINE}" = "alpha" ; then
|
||||
sed 's/^ //' <<EOF >dummy.s
|
||||
.globl main
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,0,\$26,0
|
||||
.prologue 0
|
||||
.long 0x47e03d80 # implver $0
|
||||
lda \$2,259
|
||||
.long 0x47e20c21 # amask $2,$1
|
||||
srl \$1,8,\$2
|
||||
sll \$2,2,\$2
|
||||
sll \$0,3,\$0
|
||||
addl \$1,\$0,\$0
|
||||
addl \$2,\$0,\$0
|
||||
ret \$31,(\$26),1
|
||||
.end main
|
||||
EOF
|
||||
LIBC=""
|
||||
${CC-cc} dummy.s -o dummy 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
./dummy
|
||||
case "$?" in
|
||||
7)
|
||||
UNAME_MACHINE="alpha"
|
||||
;;
|
||||
15)
|
||||
UNAME_MACHINE="alphaev5"
|
||||
;;
|
||||
14)
|
||||
UNAME_MACHINE="alphaev56"
|
||||
;;
|
||||
10)
|
||||
UNAME_MACHINE="alphapca56"
|
||||
;;
|
||||
16)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
esac
|
||||
|
||||
objdump --private-headers dummy | \
|
||||
grep ld.so.1 > /dev/null
|
||||
if test "$?" = 0 ; then
|
||||
LIBC="libc1"
|
||||
fi
|
||||
fi
|
||||
rm -f dummy.s dummy
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
|
||||
elif test "${UNAME_MACHINE}" = "mips" ; then
|
||||
cat >dummy.c <<EOF
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#ifdef __MIPSEB__
|
||||
printf ("%s-unknown-linux-gnu\n", argv[1]);
|
||||
#endif
|
||||
#ifdef __MIPSEL__
|
||||
printf ("%sel-unknown-linux-gnu\n", argv[1]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
else
|
||||
# Either a pre-BFD a.out linker (linux-gnuoldld)
|
||||
# or one that does not give us useful --help.
|
||||
# GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
|
||||
# If ld does not provide *any* "supported emulations:"
|
||||
# that means it is gnuoldld.
|
||||
echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
|
||||
test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
|
||||
|
||||
case "${UNAME_MACHINE}" in
|
||||
i?86)
|
||||
VENDOR=pc;
|
||||
;;
|
||||
*)
|
||||
VENDOR=unknown;
|
||||
;;
|
||||
esac
|
||||
# Determine whether the default compiler is a.out or elf
|
||||
cat >dummy.c <<EOF
|
||||
#include <features.h>
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
#ifdef __ELF__
|
||||
# ifdef __GLIBC__
|
||||
# if __GLIBC__ >= 2
|
||||
printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
|
||||
# else
|
||||
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
|
||||
# endif
|
||||
# else
|
||||
printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
|
||||
# endif
|
||||
#else
|
||||
printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
fi ;;
|
||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
|
||||
# are messed up and put the nodename in both sysname and nodename.
|
||||
i?86:DYNIX/ptx:4*:*)
|
||||
echo i386-sequent-sysv4
|
||||
exit 0 ;;
|
||||
i?86:UNIX_SV:4.2MP:2.*)
|
||||
# Unixware is an offshoot of SVR4, but it has its own version
|
||||
# number series starting with 2...
|
||||
# I am not positive that other SVR4 systems won't match this,
|
||||
# I just have to hope. -- rms.
|
||||
# Use sysv4.2uw... so that sysv4* matches it.
|
||||
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
|
||||
exit 0 ;;
|
||||
i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
|
||||
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
|
||||
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
i?86:*:3.2:*)
|
||||
if test -f /usr/options/cb.name; then
|
||||
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
|
||||
echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
|
||||
elif /bin/uname -X 2>/dev/null >/dev/null ; then
|
||||
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
|
||||
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
|
||||
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
|
||||
&& UNAME_MACHINE=i586
|
||||
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
|
||||
else
|
||||
echo ${UNAME_MACHINE}-pc-sysv32
|
||||
fi
|
||||
exit 0 ;;
|
||||
pc:*:*:*)
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i386.
|
||||
echo i386-pc-msdosdjgpp
|
||||
exit 0 ;;
|
||||
Intel:Mach:3*:*)
|
||||
echo i386-pc-mach3
|
||||
exit 0 ;;
|
||||
paragon:*:*:*)
|
||||
echo i860-intel-osf1
|
||||
exit 0 ;;
|
||||
i860:*:4.*:*) # i860-SVR4
|
||||
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
|
||||
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
|
||||
else # Add other i860-SVR4 vendors below as they are discovered.
|
||||
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
|
||||
fi
|
||||
exit 0 ;;
|
||||
mini*:CTIX:SYS*5:*)
|
||||
# "miniframe"
|
||||
echo m68010-convergent-sysv
|
||||
exit 0 ;;
|
||||
M68*:*:R3V[567]*:*)
|
||||
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
|
||||
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
|
||||
OS_REL=''
|
||||
test -r /etc/.relid \
|
||||
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& echo i486-ncr-sysv4.3${OS_REL} && exit 0
|
||||
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||
&& echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
|
||||
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& echo i486-ncr-sysv4 && exit 0 ;;
|
||||
m68*:LynxOS:2.*:*)
|
||||
echo m68k-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
mc68030:UNIX_System_V:4.*:*)
|
||||
echo m68k-atari-sysv4
|
||||
exit 0 ;;
|
||||
i?86:LynxOS:2.*:*)
|
||||
echo i386-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
TSUNAMI:LynxOS:2.*:*)
|
||||
echo sparc-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
|
||||
echo rs6000-unknown-lynxos${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
SM[BE]S:UNIX_SV:*:*)
|
||||
echo mips-dde-sysv${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
RM*:SINIX-*:*:*)
|
||||
echo mips-sni-sysv4
|
||||
exit 0 ;;
|
||||
*:SINIX-*:*:*)
|
||||
if uname -p 2>/dev/null >/dev/null ; then
|
||||
UNAME_MACHINE=`(uname -p) 2>/dev/null`
|
||||
echo ${UNAME_MACHINE}-sni-sysv4
|
||||
else
|
||||
echo ns32k-sni-sysv
|
||||
fi
|
||||
exit 0 ;;
|
||||
PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
|
||||
# says <[email protected]>
|
||||
echo i586-unisys-sysv4
|
||||
exit 0 ;;
|
||||
*:UNIX_System_V:4*:FTX*)
|
||||
# From Gerald Hewes <[email protected]>.
|
||||
# How about differentiating between stratus architectures? -djm
|
||||
echo hppa1.1-stratus-sysv4
|
||||
exit 0 ;;
|
||||
*:*:*:FTX*)
|
||||
# From [email protected].
|
||||
echo i860-stratus-sysv4
|
||||
exit 0 ;;
|
||||
mc68*:A/UX:*:*)
|
||||
echo m68k-apple-aux${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
news*:NEWS-OS:*:6*)
|
||||
echo mips-sony-newsos6
|
||||
exit 0 ;;
|
||||
R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
|
||||
if [ -d /usr/nec ]; then
|
||||
echo mips-nec-sysv${UNAME_RELEASE}
|
||||
else
|
||||
echo mips-unknown-sysv${UNAME_RELEASE}
|
||||
fi
|
||||
exit 0 ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
|
||||
|
||||
cat >dummy.c <<EOF
|
||||
#ifdef _SEQUENT_
|
||||
# include <sys/types.h>
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
main ()
|
||||
{
|
||||
#if defined (sony)
|
||||
#if defined (MIPSEB)
|
||||
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
|
||||
I don't know.... */
|
||||
printf ("mips-sony-bsd\n"); exit (0);
|
||||
#else
|
||||
#include <sys/param.h>
|
||||
printf ("m68k-sony-newsos%s\n",
|
||||
#ifdef NEWSOS4
|
||||
"4"
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__arm) && defined (__acorn) && defined (__unix)
|
||||
printf ("arm-acorn-riscix"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (hp300) && !defined (hpux)
|
||||
printf ("m68k-hp-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (NeXT)
|
||||
#if !defined (__ARCHITECTURE__)
|
||||
#define __ARCHITECTURE__ "m68k"
|
||||
#endif
|
||||
int version;
|
||||
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
|
||||
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (MULTIMAX) || defined (n16)
|
||||
#if defined (UMAXV)
|
||||
printf ("ns32k-encore-sysv\n"); exit (0);
|
||||
#else
|
||||
#if defined (CMU)
|
||||
printf ("ns32k-encore-mach\n"); exit (0);
|
||||
#else
|
||||
printf ("ns32k-encore-bsd\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__386BSD__)
|
||||
printf ("i386-pc-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (sequent)
|
||||
#if defined (i386)
|
||||
printf ("i386-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#if defined (ns32000)
|
||||
printf ("ns32k-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (_SEQUENT_)
|
||||
struct utsname un;
|
||||
|
||||
uname(&un);
|
||||
|
||||
if (strncmp(un.version, "V2", 2) == 0) {
|
||||
printf ("i386-sequent-ptx2\n"); exit (0);
|
||||
}
|
||||
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
|
||||
printf ("i386-sequent-ptx1\n"); exit (0);
|
||||
}
|
||||
printf ("i386-sequent-ptx\n"); exit (0);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (vax)
|
||||
#if !defined (ultrix)
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
#else
|
||||
printf ("vax-dec-ultrix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (alliant) && defined (i860)
|
||||
printf ("i860-alliant-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
exit (1);
|
||||
}
|
||||
EOF
|
||||
|
||||
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
|
||||
rm -f dummy.c dummy
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
|
||||
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
|
||||
|
||||
# Convex versions that predate uname can use getsysinfo(1)
|
||||
|
||||
if [ -x /usr/convex/getsysinfo ]
|
||||
then
|
||||
case `getsysinfo -f cpu_type` in
|
||||
c1*)
|
||||
echo c1-convex-bsd
|
||||
exit 0 ;;
|
||||
c2*)
|
||||
if getsysinfo -f scalar_acc
|
||||
then echo c32-convex-bsd
|
||||
else echo c2-convex-bsd
|
||||
fi
|
||||
exit 0 ;;
|
||||
c34*)
|
||||
echo c34-convex-bsd
|
||||
exit 0 ;;
|
||||
c38*)
|
||||
echo c38-convex-bsd
|
||||
exit 0 ;;
|
||||
c4*)
|
||||
echo c4-convex-bsd
|
||||
exit 0 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#echo '(Unable to guess system type)' 1>&2
|
||||
|
||||
exit 1
|
||||
+1178
File diff suppressed because it is too large
Load Diff
+45
-1
@@ -4,6 +4,50 @@ AC_INIT(netlist.h)
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_CHECK_TOOL(STRIP, strip, true)
|
||||
AC_CHECK_HEADERS(getopt.h)
|
||||
AC_PROG_INSTALL
|
||||
AC_CHECK_LIB(dl,main,[DLLIB=-ldl])
|
||||
AC_SUBST(DLLIB)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile vvm/Makefile)
|
||||
#######################
|
||||
## test for underscores
|
||||
#######################
|
||||
|
||||
AC_MSG_CHECKING("for leading and/or trailing underscores")
|
||||
cat << EOF > underscore.c
|
||||
void underscore(void){}
|
||||
EOF
|
||||
$CC -c underscore.c > /dev/null 2>&1
|
||||
|
||||
CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
|
||||
output=`nm underscore.o|grep underscore_ 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_TRAILING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_TU)
|
||||
fi
|
||||
|
||||
if test "$CC_LEADING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WLU)
|
||||
fi
|
||||
if test "$CC_TRAILING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WTU)
|
||||
fi
|
||||
|
||||
rm underscore.c underscore.o
|
||||
|
||||
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
|
||||
|
||||
#######################
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,13 +16,53 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: cprop.cc,v 1.2 1998/12/02 04:37:13 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: cprop.cc,v 1.7 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "functor.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* This local function returns true if all the the possible drivers of
|
||||
* this link are constant. It will also return true if there are no
|
||||
* drivers at all.
|
||||
*/
|
||||
static bool all_drivers_constant(const NetObj::Link&lnk)
|
||||
{
|
||||
for (const NetObj::Link*cur = lnk.next_link()
|
||||
; *cur != lnk ; cur = cur->next_link()) {
|
||||
|
||||
if (cur->get_dir() == NetObj::Link::INPUT)
|
||||
continue;
|
||||
if (cur->get_dir() == NetObj::Link::PASSIVE)
|
||||
continue;
|
||||
if (! dynamic_cast<const NetConst*>(cur->get_obj()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the value of the constant driving this link,
|
||||
* or Vz if there is no constant. The results of this function are
|
||||
* only meaningful if all_drivers_constant(lnk) == true.
|
||||
*/
|
||||
static verinum::V driven_value(const NetObj::Link&lnk)
|
||||
{
|
||||
for (const NetObj::Link*cur = lnk.next_link()
|
||||
; *cur != lnk ; cur = cur->next_link()) {
|
||||
|
||||
const NetConst*obj;
|
||||
if (obj = dynamic_cast<const NetConst*>(cur->get_obj()))
|
||||
return obj->value(cur->get_pin());
|
||||
}
|
||||
|
||||
return verinum::Vz;
|
||||
}
|
||||
|
||||
/*
|
||||
* The cprop function below invokes constant propogation where
|
||||
* possible. The elaboration generates NetConst objects. I can remove
|
||||
@@ -30,142 +70,249 @@
|
||||
* may even be able to replace nets with a new constant.
|
||||
*/
|
||||
|
||||
static bool is_a_const_node(const NetNode*obj)
|
||||
struct cprop_functor : public functor_t {
|
||||
|
||||
unsigned count;
|
||||
|
||||
virtual void lpm_add_sub(Design*des, NetAddSub*obj);
|
||||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||
};
|
||||
|
||||
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
{
|
||||
return dynamic_cast<const NetConst*>(obj);
|
||||
// For now, only additions are handled.
|
||||
if (obj->attribute("LPM_Direction") != "ADD")
|
||||
return;
|
||||
|
||||
// If the low bit on the A side is 0, then eliminate it from
|
||||
// the adder, and pass the B side directly to the
|
||||
// result. Don't reduce the adder smaller then a 1-bit
|
||||
// adder. These will be eliminated later.
|
||||
while ((obj->width() > 1)
|
||||
&& all_drivers_constant(obj->pin_DataA(0))
|
||||
&& (driven_value(obj->pin_DataA(0)) == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// Now do the same thing on the B side.
|
||||
while ((obj->width() > 1)
|
||||
&& all_drivers_constant(obj->pin_DataB(0))
|
||||
&& (driven_value(obj->pin_DataB(0)) == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataA(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// If the adder is only 1 bit wide, then replace it with the
|
||||
// simple logic gate.
|
||||
if (obj->width() == 1) {
|
||||
NetLogic*tmp;
|
||||
if (obj->pin_Cout().is_linked()) {
|
||||
tmp = new NetLogic(des->local_symbol(obj->name()), 3,
|
||||
NetLogic::AND);
|
||||
connect(tmp->pin(0), obj->pin_Cout());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
des->add_node(tmp);
|
||||
}
|
||||
tmp = new NetLogic(obj->name(), 3, NetLogic::XOR);
|
||||
connect(tmp->pin(0), obj->pin_Result(0));
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static bool const_into_xnor(Design*des, NetConst*obj,
|
||||
NetLogic*log, unsigned pin)
|
||||
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||
{
|
||||
assert(pin > 0);
|
||||
|
||||
/* if this is the last input pin of the XNOR device, then
|
||||
the device is simply buffering the constant value. */
|
||||
if (log->pin_count() == 2) {
|
||||
cerr << "cprop: delete gate " << log->name() <<
|
||||
" and propogate " << obj->value() << "." << endl;
|
||||
|
||||
assert(pin == 1);
|
||||
connect(log->pin(0), log->pin(1));
|
||||
|
||||
delete log;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If this is a constant 0, then replace the gate with one
|
||||
1-pin smaller. Skip this pin. */
|
||||
if (obj->value() == verinum::V0) {
|
||||
cerr << "cprop: disconnect pin " << pin << " from gate "
|
||||
<< log->name() << "." << endl;
|
||||
|
||||
NetLogic*tmp = new NetLogic(log->name(),
|
||||
log->pin_count()-1,
|
||||
NetLogic::XNOR);
|
||||
connect(log->pin(0), tmp->pin(0));
|
||||
unsigned idx, jdx;
|
||||
for (idx = 1, jdx = 1 ; idx < log->pin_count() ; idx += 1) {
|
||||
if (idx == pin) continue;
|
||||
connect(log->pin(idx), tmp->pin(jdx));
|
||||
jdx += 1;
|
||||
// Look for and count unlinked FF outputs. Note that if the
|
||||
// Data and Q pins are connected together, they can be removed
|
||||
// from the circuit.
|
||||
unsigned unlinked_count = 0;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (connected(obj->pin_Data(idx), obj->pin_Q(idx))) {
|
||||
obj->pin_Data(idx).unlink();
|
||||
obj->pin_Q(idx).unlink();
|
||||
}
|
||||
|
||||
delete log;
|
||||
des->add_node(tmp);
|
||||
return true;
|
||||
if (! obj->pin_Q(idx).is_linked())
|
||||
unlinked_count += 1;
|
||||
}
|
||||
|
||||
/* If this is a constant 1, then replace the gate with an XOR
|
||||
that is 1-pin smaller. Removing the constant 1 causes the
|
||||
sense of the output to change. */
|
||||
if (obj->value() == verinum::V1) {
|
||||
cerr << "cprop: disconnect pin " << pin << " from gate "
|
||||
<< log->name() << "." << endl;
|
||||
|
||||
NetLogic*tmp = new NetLogic(log->name(),
|
||||
log->pin_count()-1,
|
||||
NetLogic::XOR);
|
||||
connect(log->pin(0), tmp->pin(0));
|
||||
unsigned idx, jdx;
|
||||
for (idx = 1, jdx = 1 ; idx < log->pin_count() ; idx += 1) {
|
||||
if (idx == pin) continue;
|
||||
connect(log->pin(idx), tmp->pin(jdx));
|
||||
jdx += 1;
|
||||
}
|
||||
|
||||
delete log;
|
||||
des->add_node(tmp);
|
||||
return true;
|
||||
// If the entire FF is unlinked, remove the whole thing.
|
||||
if (unlinked_count == obj->width()) {
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this is a constant X or Z, then the gate is certain to
|
||||
generate an X. Replace the gate with a constant X. This may
|
||||
cause other signals all over to become dangling. */
|
||||
if ((obj->value() == verinum::Vx) || (obj->value() == verinum::Vz)) {
|
||||
cerr << "cprop: replace gate " << log->name() << " with "
|
||||
"a constant X." << endl;
|
||||
// If some of the FFs are unconnected, make a new FF array
|
||||
// that does not include the useless FF devices.
|
||||
if (unlinked_count > 0) {
|
||||
NetFF*tmp = new NetFF(obj->name(), obj->width()-unlinked_count);
|
||||
connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
connect(tmp->pin_Enable(), obj->pin_Enable());
|
||||
connect(tmp->pin_Aload(), obj->pin_Aload());
|
||||
connect(tmp->pin_Aset(), obj->pin_Aset());
|
||||
connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
connect(tmp->pin_Sload(), obj->pin_Sload());
|
||||
connect(tmp->pin_Sset(), obj->pin_Sset());
|
||||
connect(tmp->pin_Sclr(), obj->pin_Sclr());
|
||||
|
||||
NetConst*tmp = new NetConst(log->name(), verinum::Vx);
|
||||
connect(log->pin(0), tmp->pin(0));
|
||||
delete log;
|
||||
unsigned tidx = 0;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
if (obj->pin_Q(idx).is_linked()) {
|
||||
connect(tmp->pin_Data(tidx), obj->pin_Data(idx));
|
||||
connect(tmp->pin_Q(tidx), obj->pin_Q(idx));
|
||||
tidx += 1;
|
||||
}
|
||||
|
||||
assert(tidx == obj->width() - unlinked_count);
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
return true;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void look_for_core_logic(Design*des, NetConst*obj)
|
||||
void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
{
|
||||
NetObj*cur = obj;
|
||||
unsigned pin = 0;
|
||||
for (obj->pin(0).next_link(cur, pin)
|
||||
; cur != obj
|
||||
; cur->pin(pin).next_link(cur, pin)) {
|
||||
switch (obj->type()) {
|
||||
|
||||
NetLogic*log = dynamic_cast<NetLogic*>(cur);
|
||||
if (log == 0)
|
||||
continue;
|
||||
|
||||
bool flag = false;
|
||||
switch (log->type()) {
|
||||
case NetLogic::XNOR:
|
||||
flag = const_into_xnor(des, obj, log, pin);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case NetLogic::AND:
|
||||
// If there is one zero input to an AND gate, we know
|
||||
// the resulting output is going to be zero and can
|
||||
// elininate the gate.
|
||||
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
|
||||
if (! all_drivers_constant(obj->pin(idx)))
|
||||
continue;
|
||||
if (driven_value(obj->pin(idx)) == verinum::V0) {
|
||||
connect(obj->pin(0), obj->pin(idx));
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the optimization test tells me that a link was
|
||||
deleted, restart the scan. */
|
||||
if (flag) obj->pin(0).next_link(cur, pin);
|
||||
// There are no zero constant drivers. If there are any
|
||||
// non-constant drivers, give up.
|
||||
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
|
||||
if (! all_drivers_constant(obj->pin(idx)))
|
||||
return;
|
||||
}
|
||||
|
||||
// If there are any non-1 values (Vx or Vz) then the
|
||||
// result is Vx.
|
||||
for (unsigned idx = 1 ; idx < obj->pin_count() ; idx += 1) {
|
||||
if (driven_value(obj->pin(idx)) != verinum::V1) {
|
||||
connect(obj->pin(0), obj->pin(idx));
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// What's left? The inputs are all 1's, return the first
|
||||
// input as the output value and remove the gate.
|
||||
connect(obj->pin(0), obj->pin(1));
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function looks to see if the constant is connected to nothing
|
||||
* This functor looks to see if the constant is connected to nothing
|
||||
* but signals. If that is the case, delete the dangling constant and
|
||||
* the now useless signals.
|
||||
* the now useless signals. This functor is applied after the regular
|
||||
* functor to clean up dangling constants that might be left behind.
|
||||
*/
|
||||
static void dangling_const(Design*des, NetConst*obj)
|
||||
struct cprop_dc_functor : public functor_t {
|
||||
|
||||
virtual void lpm_const(Design*des, NetConst*obj);
|
||||
};
|
||||
|
||||
void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
{
|
||||
// If there are any links that take input, abort this
|
||||
// operation.
|
||||
if (count_inputs(obj->pin(0)) > 0)
|
||||
return;
|
||||
// If there are any links that take input, the constant is
|
||||
// used structurally somewhere.
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1)
|
||||
if (count_inputs(obj->pin(idx)) > 0)
|
||||
return;
|
||||
|
||||
// Look for signals that have NetESignal nodes attached to
|
||||
// them. If I find any, this this constant is used by a
|
||||
// behavioral expression somewhere.
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
|
||||
NetObj*cur;
|
||||
unsigned pin;
|
||||
obj->pin(idx).next_link(cur, pin);
|
||||
while (cur != obj) {
|
||||
NetNet*tmp = dynamic_cast<NetNet*>(cur);
|
||||
if (tmp && tmp->get_eref() > 0)
|
||||
return;
|
||||
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no other drivers, delete all the signals that
|
||||
// are also dangling.
|
||||
if (count_outputs(obj->pin(0)) == 1) {
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
|
||||
if (count_outputs(obj->pin(idx)) != 1)
|
||||
continue;
|
||||
|
||||
NetObj*cur;
|
||||
unsigned pin;
|
||||
obj->pin(0).next_link(cur, pin);
|
||||
obj->pin(idx).next_link(cur, pin);
|
||||
while (cur != obj) {
|
||||
cerr << "cprop: delete dangling signal " << cur->name() <<
|
||||
"." << endl;
|
||||
delete cur;
|
||||
obj->pin(0).next_link(cur, pin);
|
||||
NetNet*tmp = dynamic_cast<NetNet*>(cur);
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
assert(tmp->get_eref() == 0);
|
||||
cerr << "cprop: delete dangling signal " <<
|
||||
tmp->name() << "." << endl;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,20 +320,38 @@ static void dangling_const(Design*des, NetConst*obj)
|
||||
delete obj;
|
||||
}
|
||||
|
||||
|
||||
void cprop(Design*des)
|
||||
{
|
||||
des->clear_node_marks();
|
||||
while (NetNode*obj = des->find_node(&is_a_const_node)) {
|
||||
NetConst*cur = dynamic_cast<NetConst*>(obj);
|
||||
look_for_core_logic(des, cur);
|
||||
cur->set_mark();
|
||||
dangling_const(des, cur);
|
||||
}
|
||||
// Continually propogate constants until a scan finds nothing
|
||||
// to do.
|
||||
cprop_functor prop;
|
||||
do {
|
||||
prop.count = 0;
|
||||
des->functor(&prop);
|
||||
} while (prop.count > 0);
|
||||
|
||||
cprop_dc_functor dc;
|
||||
des->functor(&dc);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.7 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 2000/01/02 17:56:42 steve
|
||||
* Do not delete constants that input to exressions.
|
||||
*
|
||||
* Revision 1.5 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.4 1999/12/17 06:18:15 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.3 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.2 1998/12/02 04:37:13 steve
|
||||
* Add the nobufz function to eliminate bufz objects,
|
||||
* Object links are marked with direction,
|
||||
|
||||
+338
-42
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: design_dump.cc,v 1.34 1999/08/01 16:34:50 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: design_dump.cc,v 1.67 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -49,6 +49,8 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
pin_count() << "]";
|
||||
if (local_flag_)
|
||||
o << " (local)";
|
||||
if (scope_)
|
||||
o << " scope=" << scope_->name();
|
||||
o << " #(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ") init=";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
@@ -84,7 +86,9 @@ void NetNode::dump_node(ostream&o, unsigned ind) const
|
||||
void NetObj::dump_node_pins(ostream&o, unsigned ind) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
o << setw(ind) << "" << idx;
|
||||
o << setw(ind) << "" << idx << " " << pin(idx).get_name()
|
||||
<< "<" << pin(idx).get_inst() << ">";
|
||||
|
||||
switch (pin(idx).get_dir()) {
|
||||
case Link::PASSIVE:
|
||||
o << " p";
|
||||
@@ -121,35 +125,90 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
|
||||
}
|
||||
}
|
||||
|
||||
void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
|
||||
name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCompare::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_COMPARE (NetCompare): " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetMult::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetMux::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Multiplexer (NetMux): " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetAssign::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Procedural assign: " << *rval_ << endl;
|
||||
o << setw(ind) << "" << "Procedural assign (NetAssign): " << name();
|
||||
if (bmux())
|
||||
o << "[" << *bmux() << "]";
|
||||
o << " = " << *rval() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetAssignNB::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
if (bmux_)
|
||||
o << setw(ind) << "" << "Procedural NB assign: " << name()
|
||||
<< "[" << *bmux_ << "] <= " << *rval_ << endl;
|
||||
if (bmux())
|
||||
o << setw(ind) << "" << "Procedural NB assign (NetAssignNB): "
|
||||
<< name() << "[" << *bmux() << "] <= " << *rval() << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "Procedural NB assign: " << name()
|
||||
<< " <= " << *rval_ << endl;
|
||||
o << setw(ind) << "" << "Procedural NB assign (NetAssignNB): "
|
||||
<< name() << " <= " << *rval() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetBUFZ::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "BUFZ: " << name() << endl;
|
||||
o << setw(ind) << "" << "NetBUFZ: " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "case compare === : " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant " << value_ << ": " << name() << endl;
|
||||
o << setw(ind) << "" << "constant ";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
o << value_[idx-1];
|
||||
o << ": " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetFF::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetLogic::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "logic: ";
|
||||
@@ -193,6 +252,14 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
|
||||
<< name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "task " << name_ << ";" << endl;
|
||||
@@ -273,6 +340,12 @@ void NetUDP::dump_comb_(ostream&o, unsigned ind) const
|
||||
o << " #(" << rise_time() << "," << fall_time() << "," << decay_time() <<
|
||||
") " << name() << endl;
|
||||
|
||||
for (CM_::const_iterator ent = cm_.begin()
|
||||
; ent != cm_.end() ; ent++) {
|
||||
o << setw(ind+6) << "" << (*ent).first << " --> " <<
|
||||
(*ent).second << endl;
|
||||
}
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -327,28 +400,35 @@ void NetAssign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
|
||||
const NetNet*sig;
|
||||
unsigned msb, lsb;
|
||||
find_lval_range(sig, msb, lsb);
|
||||
o << sig->name() << "[" << msb;
|
||||
if (pin_count() > 1)
|
||||
o << ":" << lsb;
|
||||
o << "] = ";
|
||||
|
||||
rval_->dump(o);
|
||||
o << ";" << endl;
|
||||
if (bmux()) {
|
||||
o << name() << "[" << *bmux() << "] = ";
|
||||
if (rise_time())
|
||||
o << "#" << rise_time() << " ";
|
||||
o << *rval() << ";" << endl;
|
||||
|
||||
} else {
|
||||
o << name() << " = ";
|
||||
if (rise_time())
|
||||
o << "#" << rise_time() << " ";
|
||||
o << *rval() << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
|
||||
if (bmux_) {
|
||||
o << name() << "[" << *bmux_ << "] <= " << *rval_ << ";" <<
|
||||
endl;
|
||||
if (bmux()) {
|
||||
o << name() << "[" << *bmux() << "] <= ";
|
||||
if (rise_time())
|
||||
o << "#" << rise_time() << " ";
|
||||
o << *rval() << ";" << endl;
|
||||
|
||||
} else {
|
||||
o << name() << " <= " << *rval_ << ";" << endl;
|
||||
o << name() << " <= ";
|
||||
if (rise_time())
|
||||
o << "#" << rise_time() << " ";
|
||||
o << *rval() << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,10 +437,18 @@ void NetAssignMem::dump(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "";
|
||||
o << "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "";
|
||||
o << mem_->name() << "[";
|
||||
index_->dump(o);
|
||||
o << "] = ";
|
||||
rval_->dump(o);
|
||||
o << memory()->name() << "[" << index()->name() << "] = ";
|
||||
rval()->dump(o);
|
||||
o << ";" << endl;
|
||||
}
|
||||
|
||||
void NetAssignMemNB::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
o << "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "";
|
||||
o << memory()->name() << "[" << index()->name() << "] <= ";
|
||||
rval()->dump(o);
|
||||
o << ";" << endl;
|
||||
}
|
||||
|
||||
@@ -382,7 +470,17 @@ void NetBlock::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetCase::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "case (" << *expr_ << ")" << endl;
|
||||
switch (type_) {
|
||||
case EQ:
|
||||
o << setw(ind) << "" << "case (" << *expr_ << ")" << endl;
|
||||
break;
|
||||
case EQX:
|
||||
o << setw(ind) << "" << "casex (" << *expr_ << ")" << endl;
|
||||
break;
|
||||
case EQZ:
|
||||
o << setw(ind) << "" << "casez (" << *expr_ << ")" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
o << setw(ind+2) << "";
|
||||
@@ -423,6 +521,15 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "function " << name_ << endl;
|
||||
if (statement_)
|
||||
statement_->dump(o, ind+2);
|
||||
else
|
||||
o << setw(ind+2) << "" << "// NO STATEMENT" << endl;
|
||||
}
|
||||
|
||||
void NetPDelay::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "#" << delay_;
|
||||
@@ -479,6 +586,23 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
void NetScope::dump(ostream&o) const
|
||||
{
|
||||
o << name();
|
||||
switch (type_) {
|
||||
case BEGIN_END:
|
||||
o << " sequential block";
|
||||
break;
|
||||
case FORK_JOIN:
|
||||
o << " parallel block";
|
||||
break;
|
||||
case MODULE:
|
||||
o << " module";
|
||||
break;
|
||||
}
|
||||
o << endl;
|
||||
}
|
||||
|
||||
void NetSTask::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << name_;
|
||||
@@ -558,9 +682,15 @@ void NetEBinary::dump(ostream&o) const
|
||||
case 'o':
|
||||
o << "||";
|
||||
break;
|
||||
case 'O':
|
||||
o << "~|";
|
||||
break;
|
||||
case 'r':
|
||||
o << ">>";
|
||||
break;
|
||||
case 'X':
|
||||
o << "~^";
|
||||
break;
|
||||
}
|
||||
o << "(";
|
||||
right_->dump(o);
|
||||
@@ -569,9 +699,20 @@ void NetEBinary::dump(ostream&o) const
|
||||
|
||||
void NetEConcat::dump(ostream&o) const
|
||||
{
|
||||
o << "{" << *parms_[0];
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1)
|
||||
o << ", " << *parms_[idx];
|
||||
if (repeat_ != 1)
|
||||
o << repeat_;
|
||||
|
||||
if (parms_[0])
|
||||
o << "{" << *parms_[0];
|
||||
else
|
||||
o << "{";
|
||||
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
if (parms_[idx])
|
||||
o << ", " << *parms_[idx];
|
||||
else
|
||||
o << ", ";
|
||||
}
|
||||
o << "}";
|
||||
}
|
||||
|
||||
@@ -588,6 +729,11 @@ void NetEIdent::dump(ostream&o) const
|
||||
o << name_;
|
||||
}
|
||||
|
||||
void NetEScope::dump(ostream&o) const
|
||||
{
|
||||
o << "<scope=" << scope_->name() << ">";
|
||||
}
|
||||
|
||||
void NetESignal::dump(ostream&o) const
|
||||
{
|
||||
o << name();
|
||||
@@ -604,32 +750,58 @@ void NetESubSignal::dump(ostream&o) const
|
||||
void NetEMemory::dump(ostream&o) const
|
||||
{
|
||||
o << mem_->name() << "[";
|
||||
idx_->dump(o);
|
||||
if (idx_) idx_->dump(o);
|
||||
o << "]";
|
||||
}
|
||||
|
||||
void NetESignal::dump_node(ostream&o, unsigned ind) const
|
||||
void NetEParam::dump(ostream&o) const
|
||||
{
|
||||
o << setw(ind) << "" << "Expression Node: " << name() << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
o << "<" << path_ << "." << name_ << ">";
|
||||
}
|
||||
|
||||
void NetETernary::dump(ostream&o) const
|
||||
{
|
||||
o << "(" << *cond_ << ")? (" << *true_val_ << ") : (" <<
|
||||
false_val_ << ")";
|
||||
o << "(" << *cond_ << ") ? (" << *true_val_ << ") : (" <<
|
||||
*false_val_ << ")";
|
||||
}
|
||||
|
||||
void NetEUFunc::dump(ostream&o) const
|
||||
{
|
||||
o << name() << "(";
|
||||
assert(parms_.count() > 0);
|
||||
parms_[0]->dump(o);
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
o << ", ";
|
||||
parms_[idx]->dump(o);
|
||||
}
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetEUnary::dump(ostream&o) const
|
||||
{
|
||||
o << op_ << "(";
|
||||
switch (op_) {
|
||||
case 'N':
|
||||
o << "~|";
|
||||
break;
|
||||
default:
|
||||
o << op_;
|
||||
break;
|
||||
}
|
||||
o << "(";
|
||||
expr_->dump(o);
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void Design::dump(ostream&o) const
|
||||
{
|
||||
o << "SCOPES:" << endl;
|
||||
{
|
||||
map<string,NetScope*>::const_iterator pp;
|
||||
for (pp = scopes_.begin()
|
||||
; pp != scopes_.end() ; pp ++)
|
||||
(*pp).second -> dump(o);
|
||||
}
|
||||
|
||||
o << "ELABORATED PARAMETERS:" << endl;
|
||||
{
|
||||
map<string,NetExpr*>::const_iterator pp;
|
||||
@@ -660,6 +832,15 @@ void Design::dump(ostream&o) const
|
||||
}
|
||||
}
|
||||
|
||||
o << "ELABORATED FUNCTION DEFINITIONS:" << endl;
|
||||
{
|
||||
map<string,NetFuncDef*>::const_iterator pp;
|
||||
for (pp = funcs_.begin()
|
||||
; pp != funcs_.end() ; pp ++) {
|
||||
(*pp).second->dump(o, 0);
|
||||
}
|
||||
}
|
||||
|
||||
o << "ELABORATED TASK DEFINITIONS:" << endl;
|
||||
{
|
||||
map<string,NetTaskDef*>::const_iterator pp;
|
||||
@@ -690,6 +871,121 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.67 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.66 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.65 2000/01/10 01:35:23 steve
|
||||
* Elaborate parameters afer binding of overrides.
|
||||
*
|
||||
* Revision 1.64 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.63 1999/12/12 06:03:14 steve
|
||||
* Allow memories without indices in expressions.
|
||||
*
|
||||
* Revision 1.62 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.61 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
*
|
||||
* Revision 1.60 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.59 1999/11/24 04:01:58 steve
|
||||
* Detect and list scope names.
|
||||
*
|
||||
* Revision 1.58 1999/11/21 00:13:08 steve
|
||||
* Support memories in continuous assignments.
|
||||
*
|
||||
* Revision 1.57 1999/11/14 23:43:45 steve
|
||||
* Support combinatorial comparators.
|
||||
*
|
||||
* Revision 1.56 1999/11/14 20:24:28 steve
|
||||
* Add support for the LPM_CLSHIFT device.
|
||||
*
|
||||
* Revision 1.55 1999/11/04 03:53:26 steve
|
||||
* Patch to synthesize unary ~ and the ternary operator.
|
||||
* Thanks to Larry Doolittle <[email protected]>.
|
||||
*
|
||||
* Add the LPM_MUX device, and integrate it with the
|
||||
* ternary synthesis from Larry. Replace the lpm_mux
|
||||
* generator in t-xnf.cc to use XNF EQU devices to
|
||||
* put muxs into function units.
|
||||
*
|
||||
* Rewrite elaborate_net for the PETernary class to
|
||||
* also use the LPM_MUX device.
|
||||
*
|
||||
* Revision 1.54 1999/11/04 01:12:41 steve
|
||||
* Elaborate combinational UDP devices.
|
||||
*
|
||||
* Revision 1.53 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.52 1999/10/31 20:08:24 steve
|
||||
* Include subtraction in LPM_ADD_SUB device.
|
||||
*
|
||||
* Revision 1.51 1999/10/31 04:11:27 steve
|
||||
* Add to netlist links pin name and instance number,
|
||||
* and arrange in vvm for pin connections by name
|
||||
* and instance number.
|
||||
*
|
||||
* Revision 1.50 1999/10/10 01:59:54 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
* Revision 1.49 1999/10/08 02:00:35 steve
|
||||
* Fix dump of sase statements.
|
||||
*
|
||||
* Revision 1.48 1999/10/07 05:25:33 steve
|
||||
* Add non-const bit select in l-value of assignment.
|
||||
*
|
||||
* Revision 1.47 1999/10/06 05:06:16 steve
|
||||
* Move the rvalue into NetAssign_ common code.
|
||||
*
|
||||
* Revision 1.46 1999/10/05 06:19:46 steve
|
||||
* Add support for reduction NOR.
|
||||
*
|
||||
* Revision 1.45 1999/09/30 02:43:01 steve
|
||||
* Elaborate ~^ and ~| operators.
|
||||
*
|
||||
* Revision 1.44 1999/09/29 18:36:03 steve
|
||||
* Full case support
|
||||
*
|
||||
* Revision 1.43 1999/09/21 00:13:40 steve
|
||||
* Support parameters that reference other paramters.
|
||||
*
|
||||
* Revision 1.42 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.41 1999/09/19 01:06:36 steve
|
||||
* dump the repeat count, if applicable.
|
||||
*
|
||||
* Revision 1.40 1999/09/15 01:55:06 steve
|
||||
* Elaborate non-blocking assignment to memories.
|
||||
*
|
||||
* Revision 1.39 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
* Revision 1.38 1999/09/03 04:28:38 steve
|
||||
* elaborate the binary plus operator.
|
||||
*
|
||||
* Revision 1.37 1999/09/01 20:46:19 steve
|
||||
* Handle recursive functions and arbitrary function
|
||||
* references to other functions, properly pass
|
||||
* function parameters and save function results.
|
||||
*
|
||||
* Revision 1.36 1999/08/31 22:38:29 steve
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
* Revision 1.35 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
* Revision 1.34 1999/08/01 16:34:50 steve
|
||||
* Parse and elaborate rise/fall/decay times
|
||||
* for gates, and handle the rules for partial
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@picturel.com)
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,23 +16,26 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: vvm_monitor.cc,v 1.1 1998/11/09 23:44:11 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: dup_expr.cc,v 1.2 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
# include "netlist.h"
|
||||
# include <cassert>
|
||||
|
||||
|
||||
vvm_monitor_t::vvm_monitor_t(const string&n)
|
||||
: name_(n)
|
||||
NetEScope* NetEScope::dup_expr() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: vvm_monitor.cc,v $
|
||||
* Revision 1.1 1998/11/09 23:44:11 steve
|
||||
* Add vvm library.
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
*/
|
||||
|
||||
+431
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_expr.cc,v 1.16 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include "pform.h"
|
||||
# include "netlist.h"
|
||||
|
||||
/*
|
||||
* Elaborate binary expressions. This involves elaborating the left
|
||||
* and right sides, and creating one of a variety of different NetExpr
|
||||
* types.
|
||||
*/
|
||||
NetExpr* PEBinary::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
bool flag;
|
||||
NetExpr*lp = left_->elaborate_expr(des, path);
|
||||
NetExpr*rp = right_->elaborate_expr(des, path);
|
||||
if ((lp == 0) || (rp == 0)) {
|
||||
delete lp;
|
||||
delete rp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If either expression can be evaluated ahead of time, then
|
||||
do so. This can prove helpful later. */
|
||||
{ NetExpr*tmp;
|
||||
tmp = lp->eval_tree();
|
||||
if (tmp) {
|
||||
delete lp;
|
||||
lp = tmp;
|
||||
}
|
||||
tmp = rp->eval_tree();
|
||||
if (tmp) {
|
||||
delete rp;
|
||||
rp = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetEBinary*tmp;
|
||||
switch (op_) {
|
||||
default:
|
||||
tmp = new NetEBinary(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'o':
|
||||
tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '*':
|
||||
tmp = new NetEBMult(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
case 'r':
|
||||
tmp = new NetEBShift(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '^':
|
||||
case '&':
|
||||
case '|':
|
||||
case 'O':
|
||||
case 'X':
|
||||
tmp = new NetEBBits(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '+':
|
||||
case '-':
|
||||
tmp = new NetEBAdd(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case 'e': /* == */
|
||||
case 'E': /* === */
|
||||
case 'n': /* != */
|
||||
case 'N': /* !== */
|
||||
case 'L': /* <= */
|
||||
case 'G': /* >= */
|
||||
case '<':
|
||||
case '>':
|
||||
tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
flag = tmp->set_width(1);
|
||||
if (flag == false) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
"expression bit width of comparison != 1." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESFunc* PECallFunction::elaborate_sfunc_(Design*des, const string&path) const
|
||||
{
|
||||
cerr << get_line() << ": sorry: system functions not supported."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
if (name_[0] == '$')
|
||||
return elaborate_sfunc_(des, path);
|
||||
|
||||
string myname = path+"."+name_;
|
||||
NetFuncDef*def = des->find_function(path, name_);
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": error: No function " << name_ <<
|
||||
" in this context (" << path << ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(def);
|
||||
svector<NetExpr*> parms (parms_.count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
|
||||
NetExpr*tmp = parms_[idx]->elaborate_expr(des, myname);
|
||||
parms[idx] = tmp;
|
||||
}
|
||||
|
||||
/* Look for the return value signal for the called function in
|
||||
the context of the function definition, not my context. */
|
||||
NetNet*res = des->find_signal(def->name(), name_);
|
||||
if (res == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to locate "
|
||||
"function return value for " << name_ << " in " <<
|
||||
def->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(res);
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
assert(eres);
|
||||
NetEUFunc*func = new NetEUFunc(def, eres, parms);
|
||||
return func;
|
||||
}
|
||||
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
unsigned repeat = 1;
|
||||
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
if (repeat_) {
|
||||
verinum*vrep = repeat_->eval_const(des, path);
|
||||
if (vrep == 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = vrep->as_ulong();
|
||||
delete vrep;
|
||||
}
|
||||
|
||||
/* Make the empty concat expression. */
|
||||
NetEConcat*tmp = new NetEConcat(parms_.count(), repeat);
|
||||
tmp->set_line(*this);
|
||||
|
||||
/* Elaborate all the parameters and attach them to the concat node. */
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
assert(parms_[idx]);
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, path);
|
||||
if (ex == 0) continue;
|
||||
ex->set_line(*parms_[idx]);
|
||||
tmp->set(idx, ex);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
// System identifiers show up in the netlist as identifiers.
|
||||
if (text_[0] == '$')
|
||||
return new NetEIdent(text_, 64);
|
||||
|
||||
string name = path+"."+text_;
|
||||
|
||||
// If the identifier name is a parameter name, then return
|
||||
// a reference to the parameter expression.
|
||||
if (const NetExpr*ex = des->find_parameter(path, text_)) {
|
||||
NetExpr*tmp;
|
||||
if (dynamic_cast<const NetExpr*>(ex))
|
||||
tmp = ex->dup_expr();
|
||||
else
|
||||
tmp = new NetEParam(des, path, text_);
|
||||
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (NetNet*net = des->find_signal(path, text_)) {
|
||||
|
||||
// If this is a part select of a signal, then make a new
|
||||
// temporary signal that is connected to just the
|
||||
// selected bits.
|
||||
if (lsb_) {
|
||||
assert(msb_);
|
||||
verinum*lsn = lsb_->eval_const(des, path);
|
||||
verinum*msn = msb_->eval_const(des, path);
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_line() << ": error: "
|
||||
"Part select expresions must be "
|
||||
"constant expressions." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsn);
|
||||
assert(msn);
|
||||
unsigned long lsv = lsn->as_ulong();
|
||||
unsigned long msv = msn->as_ulong();
|
||||
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
|
||||
assert(wid <= net->pin_count());
|
||||
assert(net->sb_to_idx(msv) >= net->sb_to_idx(lsv));
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetTmp*tsig = new NetTmp(tname, wid);
|
||||
|
||||
// Connect the pins from the lsb up to the msb.
|
||||
unsigned off = net->sb_to_idx(lsv);
|
||||
for (unsigned idx = 0 ; idx < wid ; idx += 1)
|
||||
connect(tsig->pin(idx), net->pin(idx+off));
|
||||
|
||||
NetESignal*tmp = new NetESignal(tsig);
|
||||
tmp->set_line(*this);
|
||||
|
||||
des->add_signal(tsig);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// If the bit select is constant, then treat it similar
|
||||
// to the part select, so that I save the effort of
|
||||
// making a mux part in the netlist.
|
||||
verinum*msn;
|
||||
if (msb_ && (msn = msb_->eval_const(des, path))) {
|
||||
assert(idx_ == 0);
|
||||
unsigned long msv = msn->as_ulong();
|
||||
|
||||
string tname = des->local_symbol(path);
|
||||
NetTmp*tsig = new NetTmp(tname);
|
||||
connect(tsig->pin(0), net->pin(msv));
|
||||
NetESignal*tmp = new NetESignal(tsig);
|
||||
tmp->set_line(*this);
|
||||
|
||||
des->add_signal(tsig);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
assert(idx_ == 0);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
// device to mux the bit in the net.
|
||||
if (msb_) {
|
||||
NetExpr*ex = msb_->elaborate_expr(des, path);
|
||||
NetESubSignal*ss = new NetESubSignal(node, ex);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
// All else fails, return the signal itself as the
|
||||
// expression.
|
||||
assert(msb_ == 0);
|
||||
return node;
|
||||
}
|
||||
|
||||
// If the identifier names a memory, then this is a
|
||||
// memory reference and I must generate a NetEMemory
|
||||
// object to handle it.
|
||||
if (NetMemory*mem = des->find_memory(path, text_)) {
|
||||
if (msb_ == 0) {
|
||||
NetEMemory*node = new NetEMemory(mem);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
#if 0
|
||||
cerr << get_line() << ": error: Memory ``" << name <<
|
||||
"'' referenced without an index expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
assert(msb_ != 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_ == 0);
|
||||
NetExpr*i = msb_->elaborate_expr(des, path);
|
||||
if (msb_ && i == 0) {
|
||||
cerr << get_line() << ": error: Unable to exaborate "
|
||||
"index expression `" << *msb_ << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEMemory*node = new NetEMemory(mem, i);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
// Finally, if this is a scope name, then return that.
|
||||
if (NetScope*nsc = des->find_scope(text_)) {
|
||||
NetEScope*tmp = new NetEScope(nsc);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// I cannot interpret this identifier. Error message.
|
||||
cerr << get_line() << ": error: Unable to bind wire/reg/memory "
|
||||
"`" << path << "." << text_ << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the Ternary operator. I know that the expressions were
|
||||
* parsed so I can presume that they exist, and call elaboration
|
||||
* methods. If any elaboration fails, then give up and return 0.
|
||||
*/
|
||||
NetExpr*PETernary::elaborate_expr(Design*des, const string&path) const
|
||||
{
|
||||
assert(expr_);
|
||||
assert(tru_);
|
||||
assert(fal_);
|
||||
|
||||
NetExpr*con = expr_->elaborate_expr(des, path);
|
||||
if (con == 0)
|
||||
return 0;
|
||||
|
||||
NetExpr*tru = tru_->elaborate_expr(des, path);
|
||||
if (tru == 0) {
|
||||
delete con;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*fal = fal_->elaborate_expr(des, path);
|
||||
if (fal == 0) {
|
||||
delete con;
|
||||
delete tru;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetETernary*res = new NetETernary(con, tru, fal);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.16 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.15 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.14 2000/01/01 06:18:00 steve
|
||||
* Handle synthesis of concatenation.
|
||||
*
|
||||
* Revision 1.13 1999/12/12 06:03:14 steve
|
||||
* Allow memories without indices in expressions.
|
||||
*
|
||||
* Revision 1.12 1999/11/30 04:54:01 steve
|
||||
* Match scope names as last resort.
|
||||
*
|
||||
* Revision 1.11 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
*
|
||||
* Revision 1.10 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.9 1999/11/21 17:35:37 steve
|
||||
* Memory name lookup handles scopes.
|
||||
*
|
||||
* Revision 1.8 1999/11/10 02:52:24 steve
|
||||
* Create the vpiMemory handle type.
|
||||
*
|
||||
* Revision 1.7 1999/10/18 00:02:21 steve
|
||||
* Catch unindexed memory reference.
|
||||
*
|
||||
* Revision 1.6 1999/09/30 02:43:02 steve
|
||||
* Elaborate ~^ and ~| operators.
|
||||
*
|
||||
* Revision 1.5 1999/09/30 00:48:49 steve
|
||||
* Cope with errors during ternary operator elaboration.
|
||||
*
|
||||
* Revision 1.4 1999/09/29 22:57:10 steve
|
||||
* Move code to elab_expr.cc
|
||||
*
|
||||
* Revision 1.3 1999/09/25 02:57:30 steve
|
||||
* Parse system function calls.
|
||||
*
|
||||
* Revision 1.2 1999/09/21 00:13:40 steve
|
||||
* Support parameters that reference other paramters.
|
||||
*
|
||||
* Revision 1.1 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
*/
|
||||
|
||||
+1424
File diff suppressed because it is too large
Load Diff
+750
-812
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: emit.cc,v 1.18 1999/07/17 19:50:59 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: emit.cc,v 1.33 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -45,6 +45,11 @@ void NetUDP::emit_node(ostream&o, struct target_t*tgt) const
|
||||
tgt->udp(o, this);
|
||||
}
|
||||
|
||||
void NetAddSub::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_add_sub(o, this);
|
||||
}
|
||||
|
||||
void NetAssign::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_assign(o, this);
|
||||
@@ -55,11 +60,46 @@ void NetAssignNB::emit_node(ostream&o, struct target_t*tgt) const
|
||||
tgt->net_assign_nb(o, this);
|
||||
}
|
||||
|
||||
void NetCaseCmp::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_case_cmp(o, this);
|
||||
}
|
||||
|
||||
void NetCLShift::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_clshift(o, this);
|
||||
}
|
||||
|
||||
void NetCompare::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_compare(o, this);
|
||||
}
|
||||
|
||||
void NetConst::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_const(o, this);
|
||||
}
|
||||
|
||||
void NetFF::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ff(o, this);
|
||||
}
|
||||
|
||||
void NetMult::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_mult(o, this);
|
||||
}
|
||||
|
||||
void NetMux::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_mux(o, this);
|
||||
}
|
||||
|
||||
void NetRamDq::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ram_dq(o, this);
|
||||
}
|
||||
|
||||
void NetNEvent::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_event(o, this);
|
||||
@@ -70,54 +110,68 @@ void NetBUFZ::emit_node(ostream&o, struct target_t*tgt) const
|
||||
tgt->bufz(o, this);
|
||||
}
|
||||
|
||||
void NetProcTop::emit(ostream&o, struct target_t*tgt) const
|
||||
bool NetProcTop::emit(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->process(o, this);
|
||||
return tgt->process(o, this);
|
||||
}
|
||||
|
||||
void NetProc::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetProc::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
cerr << "EMIT: Proc type? " << typeid(*this).name() << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetAssign::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetAssign::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetAssignNB::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetAssignNB::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign_nb(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetAssignMem::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetAssignMem::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign_mem(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetBlock::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetAssignMemNB::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_block(o, this);
|
||||
tgt->proc_assign_mem_nb(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetCase::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetBlock::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_block(o, this);
|
||||
}
|
||||
|
||||
bool NetCase::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_case(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetCondit::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetCondit::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_condit(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetForever::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetForever::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_forever(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetPDelay::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetPDelay::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_delay(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetPDelay::emit_proc_recurse(ostream&o, struct target_t*tgt) const
|
||||
@@ -125,9 +179,10 @@ void NetPDelay::emit_proc_recurse(ostream&o, struct target_t*tgt) const
|
||||
if (statement_) statement_->emit_proc(o, tgt);
|
||||
}
|
||||
|
||||
void NetPEvent::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetPEvent::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_event(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetPEvent::emit_proc_recurse(ostream&o, struct target_t*tgt) const
|
||||
@@ -135,24 +190,28 @@ void NetPEvent::emit_proc_recurse(ostream&o, struct target_t*tgt) const
|
||||
if (statement_) statement_->emit_proc(o, tgt);
|
||||
}
|
||||
|
||||
void NetRepeat::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetRepeat::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_repeat(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetSTask::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetSTask::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_stask(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetUTask::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetUTask::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_utask(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetWhile::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
bool NetWhile::emit_proc(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_while(o, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetBlock::emit_recurse(ostream&o, struct target_t*tgt) const
|
||||
@@ -196,10 +255,18 @@ void NetWhile::emit_proc_recurse(ostream&o, struct target_t*tgt) const
|
||||
proc_->emit_proc(o, tgt);
|
||||
}
|
||||
|
||||
void Design::emit(ostream&o, struct target_t*tgt) const
|
||||
bool Design::emit(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
bool rc = true;
|
||||
tgt->start_design(o, this);
|
||||
|
||||
// enumerate the scopes
|
||||
{ map<string,NetScope*>::const_iterator sc;
|
||||
for (sc = scopes_.begin() ; sc != scopes_.end() ; sc++) {
|
||||
tgt->scope(o, (*sc).second);
|
||||
}
|
||||
}
|
||||
|
||||
// emit signals
|
||||
if (signals_) {
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
@@ -229,6 +296,14 @@ void Design::emit(ostream&o, struct target_t*tgt) const
|
||||
}
|
||||
|
||||
|
||||
// emit function definitions
|
||||
{
|
||||
map<string,NetFuncDef*>::const_iterator ta;
|
||||
for (ta = funcs_.begin() ; ta != funcs_.end() ; ta ++) {
|
||||
tgt->func_def(o, (*ta).second);
|
||||
}
|
||||
}
|
||||
|
||||
// emit task definitions
|
||||
{
|
||||
map<string,NetTaskDef*>::const_iterator ta;
|
||||
@@ -239,9 +314,10 @@ void Design::emit(ostream&o, struct target_t*tgt) const
|
||||
|
||||
// emit the processes
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
idx->emit(o, tgt);
|
||||
rc = rc && idx->emit(o, tgt);
|
||||
|
||||
tgt->end_design(o, this);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void NetEBinary::expr_scan(struct expr_scan_t*tgt) const
|
||||
@@ -269,16 +345,27 @@ void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_memory(this);
|
||||
}
|
||||
|
||||
void NetEParam::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
cerr << get_line() << ":internal error: unexpected NetEParam."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void NetEScope::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_scope(this);
|
||||
}
|
||||
|
||||
void NetEUFunc::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_ufunc(this);
|
||||
}
|
||||
|
||||
void NetESignal::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_signal(this);
|
||||
}
|
||||
|
||||
void NetESignal::emit_node(ostream&o, struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_esignal(o, this);
|
||||
}
|
||||
|
||||
void NetESubSignal::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_subsignal(this);
|
||||
@@ -294,20 +381,76 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_unary(this);
|
||||
}
|
||||
|
||||
void emit(ostream&o, const Design*des, const char*type)
|
||||
bool emit(ostream&o, const Design*des, const char*type)
|
||||
{
|
||||
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
|
||||
const struct target*tgt = target_table[idx];
|
||||
if (tgt->name == type) {
|
||||
des->emit(o, tgt->meth);
|
||||
return;
|
||||
}
|
||||
if (tgt->name == type)
|
||||
return des->emit(o, tgt->meth);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.33 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.32 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.31 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
*
|
||||
* Revision 1.30 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.29 1999/11/21 00:13:08 steve
|
||||
* Support memories in continuous assignments.
|
||||
*
|
||||
* Revision 1.28 1999/11/14 23:43:45 steve
|
||||
* Support combinatorial comparators.
|
||||
*
|
||||
* Revision 1.27 1999/11/14 20:24:28 steve
|
||||
* Add support for the LPM_CLSHIFT device.
|
||||
*
|
||||
* Revision 1.26 1999/11/04 03:53:26 steve
|
||||
* Patch to synthesize unary ~ and the ternary operator.
|
||||
* Thanks to Larry Doolittle <[email protected]>.
|
||||
*
|
||||
* Add the LPM_MUX device, and integrate it with the
|
||||
* ternary synthesis from Larry. Replace the lpm_mux
|
||||
* generator in t-xnf.cc to use XNF EQU devices to
|
||||
* put muxs into function units.
|
||||
*
|
||||
* Rewrite elaborate_net for the PETernary class to
|
||||
* also use the LPM_MUX device.
|
||||
*
|
||||
* Revision 1.25 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.24 1999/10/10 01:59:54 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
* Revision 1.23 1999/09/22 16:57:23 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
*
|
||||
* Revision 1.22 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.21 1999/09/15 01:55:06 steve
|
||||
* Elaborate non-blocking assignment to memories.
|
||||
*
|
||||
* Revision 1.20 1999/09/03 04:28:38 steve
|
||||
* elaborate the binary plus operator.
|
||||
*
|
||||
* Revision 1.19 1999/08/31 22:38:29 steve
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
* Revision 1.18 1999/07/17 19:50:59 steve
|
||||
* netlist support for ternary operator.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: eval.cc,v 1.5 1999/08/06 04:05:28 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval.cc,v 1.13 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PExpr.h"
|
||||
@@ -41,12 +41,46 @@ verinum* PEBinary::eval_const(const Design*des, const string&path) const
|
||||
verinum*res;
|
||||
|
||||
switch (op_) {
|
||||
case '+': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv+rv, l->len());
|
||||
break;
|
||||
}
|
||||
case '-': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv-rv, l->len());
|
||||
break;
|
||||
}
|
||||
case '*': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv * rv, l->len());
|
||||
break;
|
||||
}
|
||||
case '/': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv / rv, l->len());
|
||||
break;
|
||||
}
|
||||
case '%': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv % rv, l->len());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
delete l;
|
||||
delete r;
|
||||
@@ -56,11 +90,25 @@ verinum* PEBinary::eval_const(const Design*des, const string&path) const
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate an identifier as a constant expression. This is only
|
||||
* possible if the identifier is that of a parameter.
|
||||
*/
|
||||
verinum* PEIdent::eval_const(const Design*des, const string&path) const
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
const NetExpr*expr = des->find_parameter(path, text_);
|
||||
if (expr == 0) return 0;
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
assert(msb_ == 0);
|
||||
|
||||
if (dynamic_cast<const NetEParam*>(expr)) {
|
||||
cerr << get_line() << ": sorry: I cannot evaluate ``" <<
|
||||
text_ << "'' in this context." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
|
||||
assert(eval);
|
||||
return new verinum(eval->value());
|
||||
@@ -71,14 +119,54 @@ verinum* PENumber::eval_const(const Design*, const string&) const
|
||||
return new verinum(value());
|
||||
}
|
||||
|
||||
verinum* PETernary::eval_const(const Design*, const string&) const
|
||||
verinum* PETernary::eval_const(const Design*des, const string&path) const
|
||||
{
|
||||
assert(0);
|
||||
verinum*test = expr_->eval_const(des, path);
|
||||
if (test == 0)
|
||||
return 0;
|
||||
|
||||
verinum::V bit = test->get(0);
|
||||
delete test;
|
||||
switch (bit) {
|
||||
case verinum::V0:
|
||||
return fal_->eval_const(des, path);
|
||||
case verinum::V1:
|
||||
return tru_->eval_const(des, path);
|
||||
default:
|
||||
return 0;
|
||||
// XXXX It is possible to handle this case if both fal_
|
||||
// and tru_ are constant. Someday...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.13 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.12 1999/11/30 04:48:17 steve
|
||||
* Handle evaluation of ternary during elaboration.
|
||||
*
|
||||
* Revision 1.11 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
*
|
||||
* Revision 1.10 1999/11/21 20:03:24 steve
|
||||
* Handle multiply in constant expressions.
|
||||
*
|
||||
* Revision 1.9 1999/10/08 17:48:09 steve
|
||||
* Support + in constant expressions.
|
||||
*
|
||||
* Revision 1.8 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
* Revision 1.7 1999/09/18 01:52:48 steve
|
||||
* Remove spurious message.
|
||||
*
|
||||
* Revision 1.6 1999/09/16 04:18:15 steve
|
||||
* elaborate concatenation repeats.
|
||||
*
|
||||
* Revision 1.5 1999/08/06 04:05:28 steve
|
||||
* Handle scope of parameters.
|
||||
*
|
||||
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval_tree.cc,v 1.8 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
NetExpr* NetExpr::eval_tree()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some of the derived classes can be evaluated by the compiler, this
|
||||
* method provides the common aid of evaluating the parameter
|
||||
* expressions.
|
||||
*/
|
||||
void NetEBinary::eval_sub_tree_()
|
||||
{
|
||||
NetExpr*tmp = left_->eval_tree();
|
||||
if (tmp) {
|
||||
delete left_;
|
||||
left_ = tmp;
|
||||
}
|
||||
tmp = right_->eval_tree();
|
||||
if (tmp){
|
||||
delete right_;
|
||||
right_ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetEConst* NetEBAdd::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
verinum val;
|
||||
switch (op_) {
|
||||
case '+':
|
||||
val = lval + rval;
|
||||
break;
|
||||
case '-':
|
||||
val = lval - rval;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new NetEConst(val);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
if (lv.len() < rv.len())
|
||||
return 0;
|
||||
|
||||
verinum result(verinum::V1, 1);
|
||||
for (unsigned idx = 0 ; idx < lv.len(); idx += 1) {
|
||||
if (lv[idx] != rv[idx])
|
||||
result = verinum::V0;
|
||||
}
|
||||
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_()
|
||||
{
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
verinum rv = r->value();
|
||||
|
||||
/* 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 result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEBComp::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
switch (op_) {
|
||||
case 'e':
|
||||
return eval_eqeq_();
|
||||
|
||||
case 'L':
|
||||
return eval_leeq_();
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NetEConst* NetEBLogic::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBMult::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate the shift operator if possible. For this to work, both
|
||||
* operands must be constant.
|
||||
*/
|
||||
NetEConst* NetEBShift::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
NetEConst*re = dynamic_cast<NetEConst*>(right_);
|
||||
if (re == 0)
|
||||
return 0;
|
||||
|
||||
NetEConst*le = dynamic_cast<NetEConst*>(left_);
|
||||
if (le == 0)
|
||||
return 0;
|
||||
|
||||
NetEConst*res;
|
||||
|
||||
verinum rv = re->value();
|
||||
verinum lv = le->value();
|
||||
if (rv.is_defined()) {
|
||||
|
||||
unsigned wid = expr_width();
|
||||
unsigned shift = rv.as_ulong();
|
||||
|
||||
verinum nv (verinum::V0, wid);
|
||||
|
||||
if (op() == 'r')
|
||||
for (unsigned idx = 0 ; idx < (wid-shift) ; idx += 1)
|
||||
nv.set(idx, lv[idx+shift]);
|
||||
|
||||
else
|
||||
for (unsigned idx = 0 ; idx < (wid-shift) ; idx += 1)
|
||||
nv.set(idx+shift, lv[idx]);
|
||||
|
||||
res = new NetEConst(nv);
|
||||
|
||||
} else {
|
||||
verinum nv (verinum::Vx, expr_width());
|
||||
res = new NetEConst(nv);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetEConcat::eval_tree()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
|
||||
// Parameter not here? This is an error, but presumably
|
||||
// already caught and we are here just to catch more.
|
||||
if (parms_[idx] == 0)
|
||||
continue;
|
||||
|
||||
// If this parameter is already a constant, all is well
|
||||
// so go on.
|
||||
if (dynamic_cast<NetEConst*>(parms_[idx]))
|
||||
continue;
|
||||
|
||||
// Finally, try to evaluate the parameter expression
|
||||
// that is here. If I succeed, reset the parameter to
|
||||
// the evaluated value.
|
||||
assert(parms_[idx]);
|
||||
NetExpr*expr = parms_[idx]->eval_tree();
|
||||
if (expr) {
|
||||
delete parms_[idx];
|
||||
parms_[idx] = expr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned gap = expr_width() / repeat_;
|
||||
verinum val (verinum::Vx, repeat_ * gap);
|
||||
|
||||
|
||||
// build up the result from least significant to most.
|
||||
|
||||
unsigned cur = 0;
|
||||
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
|
||||
NetEConst*expr = dynamic_cast<NetEConst*>(parms_[idx-1]);
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
verinum tmp = expr->value();
|
||||
for (unsigned bit = 0 ; bit < tmp.len() ; bit += 1, cur += 1)
|
||||
for (unsigned rep = 0 ; rep < repeat_ ; rep += 1)
|
||||
val.set(rep*gap+cur, tmp[bit]);
|
||||
}
|
||||
|
||||
NetEConst*res = new NetEConst(val);
|
||||
res->set_width(val.len());
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetEParam::eval_tree()
|
||||
{
|
||||
if (des_ == 0)
|
||||
return 0;
|
||||
|
||||
const NetExpr*expr = des_->find_parameter(path_, name_);
|
||||
assert(expr);
|
||||
|
||||
NetExpr*nexpr = expr->dup_expr();
|
||||
assert(nexpr);
|
||||
|
||||
// If the parameter that I refer to is already evaluated, then
|
||||
// return the constant value.
|
||||
if (dynamic_cast<NetEConst*>(nexpr))
|
||||
return nexpr;
|
||||
|
||||
// Try to evaluate the expression. If I cannot, then the
|
||||
// expression is not a constant expression and I fail here.
|
||||
NetExpr*res = nexpr->eval_tree();
|
||||
if (res == 0) {
|
||||
delete nexpr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The result can be saved as the value of the parameter for
|
||||
// future reference, and return a copy to the caller.
|
||||
des_->set_parameter(path_+"."+name_, res);
|
||||
return res->dup_expr();
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.8 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.7 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.6 1999/10/22 23:57:53 steve
|
||||
* do the <= in bits, not numbers.
|
||||
*
|
||||
* Revision 1.5 1999/10/10 23:29:37 steve
|
||||
* Support evaluating + operator at compile time.
|
||||
*
|
||||
* Revision 1.4 1999/09/23 03:56:57 steve
|
||||
* Support shift operators.
|
||||
*
|
||||
* Revision 1.3 1999/09/23 00:21:54 steve
|
||||
* Move set_width methods into a single file,
|
||||
* Add the NetEBLogic class for logic expressions,
|
||||
* Fix error setting with of && in if statements.
|
||||
*
|
||||
* Revision 1.2 1999/09/21 00:13:40 steve
|
||||
* Support parameters that reference other paramters.
|
||||
*
|
||||
* Revision 1.1 1999/09/20 02:21:10 steve
|
||||
* Elaborate parameters in phases.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here we have the canonical "Hello, World" program written in Verilog.
|
||||
* We simply print to the program output a simple message. This example
|
||||
* demonstrates the process of compiling and executing a program with
|
||||
* Icarus Verilog.
|
||||
*
|
||||
* Compile this program with the command:
|
||||
*
|
||||
* verilog hello.vl
|
||||
*
|
||||
* After churning for a little while, the program will create the output
|
||||
* file "hello" which is compiled, linked and ready to run. Run this
|
||||
* program like so:
|
||||
*
|
||||
* ./hello
|
||||
*
|
||||
* and the program will print the message to its output. Easy!
|
||||
*/
|
||||
|
||||
module main();
|
||||
|
||||
initial
|
||||
begin
|
||||
$display("Hello, World");
|
||||
$finish ;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* IVL should generate an AND gate, and should make an OBUF and two
|
||||
* IBUF objects, along with the PAD objects.
|
||||
*
|
||||
* To compile this for XNF, try a command like this:
|
||||
*
|
||||
* verilog -X -fpart=XC4010XLPQ160 -fncf=outff.ncf outff.v
|
||||
*
|
||||
* That command causes an outff.xnf and outff.ncf file to be created.
|
||||
* Next, make the outff.ngd file with the command:
|
||||
*
|
||||
* xnf2ngd -l xilinxun -u outff.xnf outff.ngo
|
||||
* ngdbuild outff.ngo outff.ngd
|
||||
*
|
||||
* Finally, map the file to fully render it in the target part. The
|
||||
* par command is the step that actually optimizes the design and tries
|
||||
* to meet timing constraints.
|
||||
*
|
||||
* map -o map.ncd outff.ngd
|
||||
* par -w map.ncd outff.ncd
|
||||
*
|
||||
* At this point, you can use the FPGA Editor to edit the outff.ncd
|
||||
* file to see that the AND gate is in a CLB and the IOB for pin 150
|
||||
* has its flip-flop in use, and that gbuf is a global buffer.
|
||||
*/
|
||||
|
||||
module main;
|
||||
|
||||
wire clk, iclk;
|
||||
wire i0, i1;
|
||||
wire out;
|
||||
reg o0;
|
||||
|
||||
// This simple logic gate get turned into a function unit.
|
||||
// The par program will map this into a CLB F or G unit.
|
||||
and (out, i0, i1);
|
||||
|
||||
// This creates a global clock buffer. Notice how I attach an
|
||||
// attribute to the named gate to force it to be mapped to the
|
||||
// desired XNF device. This device will not be pulled into the
|
||||
// IOB associated with iclk because of the attribute.
|
||||
buf gbuf(clk, iclk);
|
||||
$attribute(gbuf, "XNF-LCA", "GCLK:O,I");
|
||||
|
||||
// This is mapped to a DFF. Since o0 is connected to a PAD, it
|
||||
// is turned into a OUTFF so that it get placed into an IOB.
|
||||
always @(posedge clk) o0 = out;
|
||||
|
||||
// These attribute commands assign pins to the listed wires.
|
||||
// This can be done to wires and registers, as internally both
|
||||
// are treated as named signals.
|
||||
$attribute(o0, "PAD", "o150");
|
||||
$attribute(i0, "PAD", "i152");
|
||||
$attribute(i1, "PAD", "i153");
|
||||
$attribute(iclk,"PAD", "i154");
|
||||
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example program simulates a 16x1 ram, and is used as an
|
||||
* example for using VCD output and waveform viewers.
|
||||
*
|
||||
* Like any other Verilog simulation, compile this program with the
|
||||
* command:
|
||||
*
|
||||
* verilog show_vcd.vl
|
||||
*
|
||||
* This will generate the show_vcd command in the current directory.
|
||||
* When you run the command, you will see the output from all the
|
||||
* calls to $display, but also there will be a dump file ``show_vcd.vcd''.
|
||||
* The name of this file is set by the statement:
|
||||
*
|
||||
* $dumpfile("show_vcd.vcd");
|
||||
*
|
||||
* in the main module. The output file uses the standard VCD file format
|
||||
* so can be viewed using off-the-shelf waveform viewers. The remaining
|
||||
* steps describe how to use GTKWave to view the file. If you are using
|
||||
* a different viewer, see the documentation for that tool.
|
||||
*
|
||||
* To view the output generated by running show_vcd, start the GTKWave
|
||||
* viewer with the command:
|
||||
*
|
||||
* wave show_vcd.vcd
|
||||
*
|
||||
* The GTKWave program will display its main window, and show in a small
|
||||
* status box (upper left corner) that it succeeded in loading the dump
|
||||
* file. However, there are no waveforms displayed yet. Select signals to
|
||||
* add to the waveform display using the menu selection:
|
||||
*
|
||||
* "Search --> Signal Search Tree"
|
||||
*
|
||||
* This will bring up a dialog box that shows in directory tree format
|
||||
* the signals of the program. Select the signals you wish to view, and
|
||||
* click one of the buttons on the bottom of the dialog box to display
|
||||
* the selected signals in the waveform window. Click "Exit" on the box
|
||||
* to get rid of it.
|
||||
*
|
||||
* The magic that makes all this work is contained in the $dumpfile and
|
||||
* $dumpvars system tasks. The $dumpfile task tells the simulation where
|
||||
* to write the VCD output. This task must be called once before the
|
||||
* $dumpvars task is called.
|
||||
*
|
||||
* The $dumpvars task tells the simulation what variables to write to
|
||||
* the VCD output. The first parameter is how far to descend while
|
||||
* scanning a scope, and the remaining paramters are signals or scope
|
||||
* names to include in the dump. If a scope name is given, all the
|
||||
* signals within the scope are dumped. If a wire or register name is
|
||||
* given, that signal is included.
|
||||
*/
|
||||
|
||||
module ram16x1 (q, d, a, we, wclk);
|
||||
output q;
|
||||
input d;
|
||||
input [3:0] a;
|
||||
input we;
|
||||
input wclk;
|
||||
|
||||
reg mem[15:0];
|
||||
|
||||
assign q = mem[a];
|
||||
always @(posedge wclk) if (we) mem[a] = d;
|
||||
|
||||
endmodule /* ram16x1 */
|
||||
|
||||
module main;
|
||||
wire q;
|
||||
reg d;
|
||||
reg [3:0] a;
|
||||
reg we, wclk;
|
||||
|
||||
ram16x1 r1 (q, d, a, we, wclk);
|
||||
|
||||
initial begin
|
||||
$dumpfile("show_vcd.vcd");
|
||||
$dumpvars(1, main.r1);
|
||||
wclk = 0;
|
||||
we = 1;
|
||||
for (a = 0 ; a < 4'hf ; a = a + 1) begin
|
||||
d = a[0];
|
||||
#1 wclk = 1;
|
||||
#1 wclk = 0;
|
||||
$display("r1[%x] == %b", a, q);
|
||||
end
|
||||
|
||||
for (a = 0 ; a < 4'hf ; a = a + 1)
|
||||
#1 if (q !== a[0]) begin
|
||||
$display("FAILED -- mem[%h] !== %b", a, a[0]);
|
||||
$finish;
|
||||
end
|
||||
|
||||
$display("PASSED");
|
||||
end
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* $Id: sqrt.vl,v 1.1 1999/12/05 21:08:56 steve Exp $"
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module approximates the square root of an unsigned 32bit
|
||||
* number. The algorithm works by doing a bit-wise binary search.
|
||||
* Starting from the most significant bit, the accumulated value
|
||||
* tries to put a 1 in the bit position. If that makes the square
|
||||
* to big for the input, the bit is left zero, otherwise it is set
|
||||
* in the result. This continues for each bit, decreasing in
|
||||
* significance, until all the bits are calculated or all the
|
||||
* remaining bits are zero.
|
||||
*
|
||||
* Since the result is an integer, this function really calculates
|
||||
* value of the expression:
|
||||
*
|
||||
* x = floor(sqrt(y))
|
||||
*
|
||||
* where sqrt(y) is the exact square root of y and floor(N) is the
|
||||
* largest integer <= N.
|
||||
*
|
||||
* For 32bit numbers, this will never run more then 16 iterations,
|
||||
* which amounts to 16 clocks.
|
||||
*/
|
||||
|
||||
module sqrt32(clk, rdy, reset, x, .y(acc));
|
||||
input clk;
|
||||
output rdy;
|
||||
input reset;
|
||||
|
||||
input [31:0] x;
|
||||
output [15:0] acc;
|
||||
|
||||
|
||||
// acc holds the accumulated result, and acc2 is the accumulated
|
||||
// square of the accumulated result.
|
||||
reg [15:0] acc;
|
||||
reg [31:0] acc2;
|
||||
|
||||
// Keep track of which bit I'm working on.
|
||||
reg [4:0] bitl;
|
||||
wire [15:0] bit = 1 << bitl;
|
||||
wire [31:0] bit2 = 1 << (bitl << 1);
|
||||
|
||||
// The output is ready when the bitl counter underflows.
|
||||
wire rdy = bitl[4];
|
||||
|
||||
// guess holds the potential next values for acc, and guess2 holds
|
||||
// the square of that guess. The guess2 calculation is a little bit
|
||||
// subtle. The idea is that:
|
||||
//
|
||||
// guess2 = (acc + bit) * (acc + bit)
|
||||
// = (acc * acc) + 2*acc*bit + bit*bit
|
||||
// = acc2 + 2*acc*bit + bit2
|
||||
// = acc2 + 2 * (acc<<bitl) + bit
|
||||
//
|
||||
// This works out using shifts because bit and bit2 are known to
|
||||
// have only a single bit in them.
|
||||
wire [15:0] guess = acc | bit;
|
||||
wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1);
|
||||
|
||||
task clear;
|
||||
begin
|
||||
acc = 0;
|
||||
acc2 = 0;
|
||||
bitl = 15;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial clear;
|
||||
|
||||
always @(reset or posedge clk)
|
||||
if (reset)
|
||||
clear;
|
||||
else begin
|
||||
if (guess2 <= x) begin
|
||||
acc <= guess;
|
||||
acc2 <= guess2;
|
||||
end
|
||||
bitl <= bitl - 1;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module main;
|
||||
|
||||
reg clk, reset;
|
||||
reg [31:0] value;
|
||||
wire [15:0] result;
|
||||
wire rdy;
|
||||
|
||||
sqrt32 root(.clk(clk), .rdy(rdy), .reset(reset), .x(value), .y(result));
|
||||
|
||||
always #5 clk = ~clk;
|
||||
|
||||
always @(posedge rdy) begin
|
||||
$display("sqrt(%d) --> %d", value, result);
|
||||
$finish;
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
reset = 1;
|
||||
$monitor($time,,"%m = %b", root.acc, root.acc);
|
||||
#100 value = 63;
|
||||
reset = 0;
|
||||
end
|
||||
endmodule /* main */
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example demonstrates Icarus Verilog's ability to synthesize
|
||||
* efficient adders for Xilinx 4000 series FPGAs. The synthesis and
|
||||
* code generation makes an adder and translates that into XOR gates
|
||||
* and fast carry chain hardware.
|
||||
*
|
||||
* To compile this for XNF, try a command like this:
|
||||
*
|
||||
* verilog -X -fpart=XC4010XLPQ160 -fncf=xnf_add.ncf xnf_add.v
|
||||
*
|
||||
* That command causes an xnf_add.xnf and xnf_add.ncf file to be created.
|
||||
* Next, make the xnf_add.ngd file with the command:
|
||||
*
|
||||
* xnf2ngd -l xilinxun -u xnf_add.xnf xnf_add.ngo
|
||||
* ngdbuild xnf_add.ngo xnf_add.ngd
|
||||
*
|
||||
* Finally, map the file to fully render it in the target part. The
|
||||
* par command is the step that actually optimizes the design and tries
|
||||
* to meet timing constraints.
|
||||
*
|
||||
* map -o map.ncd xnf_add.ngd
|
||||
* par -w map.ncd xnf_add.ncd
|
||||
*
|
||||
* At this point, you can use the FPGA Editor to edit the xnf_add.ncd
|
||||
* file to see the carry chains made up to support the adder.
|
||||
*/
|
||||
|
||||
module main;
|
||||
|
||||
wire [3:0] a, b;
|
||||
wire [3:0] out;
|
||||
wire carry;
|
||||
|
||||
wire a0, a1, a2, a3, b0, b1, b2, b3;
|
||||
wire out0, out1, out2, out3;
|
||||
|
||||
// This creates the actual adder. Note that we also create a link
|
||||
// to the carry output. The principle adder is 4 bits wide, so two
|
||||
// IOBs are used to to the actual addition. PAR will place them in
|
||||
// order along carry lines. An extra carry cell from below a[0] is
|
||||
// used in FORCE-0 mode to load the bottom carry node.
|
||||
//
|
||||
// The carry signal from the top CY device is used to drive the
|
||||
// main.carry wire shown here. It is managed in this case by using
|
||||
// an ADD-FG-CI CY device for the top pair and using the CLB above
|
||||
// the carry chain, with its CY in EXAMINE-CI mode, to put the carry
|
||||
// out through its G function unit.
|
||||
|
||||
assign {carry, out} = a + b;
|
||||
|
||||
|
||||
// These attribute commands assign pins to the listed wires.
|
||||
// This can be done to wires and registers, as internally both
|
||||
// are treated as named signals. It doesn't work (yet) on vectors,
|
||||
// though, so break out the vectors with scaler assignments.
|
||||
|
||||
assign a[0] = a0;
|
||||
assign a[1] = a1;
|
||||
assign a[2] = a2;
|
||||
assign a[3] = a3;
|
||||
$attribute(a0, "PAD", "i150");
|
||||
$attribute(a1, "PAD", "i152");
|
||||
$attribute(a2, "PAD", "i153");
|
||||
$attribute(a3, "PAD", "i154");
|
||||
assign b[0] = b0;
|
||||
assign b[1] = b1;
|
||||
assign b[2] = b2;
|
||||
assign b[3] = b3;
|
||||
$attribute(b0, "PAD", "i155");
|
||||
$attribute(b1, "PAD", "i156");
|
||||
$attribute(b2, "PAD", "i157");
|
||||
$attribute(b3, "PAD", "i158");
|
||||
assign out0 = out[0];
|
||||
assign out1 = out[1];
|
||||
assign out2 = out[2];
|
||||
assign out3 = out[3];
|
||||
$attribute(out0, "PAD", "o71");
|
||||
$attribute(out1, "PAD", "o72");
|
||||
$attribute(out2, "PAD", "o73");
|
||||
$attribute(out3, "PAD", "o74");
|
||||
$attribute(carry, "PAD", "o75");
|
||||
|
||||
endmodule /* main */
|
||||
+282
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: expr_synth.cc,v 1.10 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_line() << ": internal error: cannot synthesize expression: "
|
||||
<< *this << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make an LPM_ADD_SUB device from addition operators.
|
||||
*/
|
||||
NetNet* NetEBAdd::synthesize(Design*des)
|
||||
{
|
||||
assert((op()=='+') || (op()=='-'));
|
||||
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
unsigned width=lsig->pin_count();
|
||||
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width);
|
||||
|
||||
string oname = des->local_symbol(path);
|
||||
NetAddSub *adder = new NetAddSub(oname, width);
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1) {
|
||||
connect(lsig->pin(idx), adder->pin_DataA(idx));
|
||||
connect(rsig->pin(idx), adder->pin_DataB(idx));
|
||||
connect(osig->pin(idx), adder->pin_Result(idx));
|
||||
}
|
||||
des->add_node(adder);
|
||||
des->add_signal(osig);
|
||||
|
||||
switch (op()) {
|
||||
case '+':
|
||||
adder->attribute("LPM_Direction", "ADD");
|
||||
break;
|
||||
case '-':
|
||||
adder->attribute("LPM_Direction", "SUB");
|
||||
break;
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* The bitwise logic operators are turned into discrete gates pretty
|
||||
* easily. Synthesize the left and right sub-expressions to get
|
||||
* signals, then just connect a single gate to each bit of the vector
|
||||
* of the expression.
|
||||
*/
|
||||
NetNet* NetEBBits::synthesize(Design*des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
assert(lsig->pin_count() == rsig->pin_count());
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, lsig->pin_count());
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
string oname = des->local_symbol(path);
|
||||
NetLogic*gate;
|
||||
|
||||
switch (op()) {
|
||||
case '&':
|
||||
gate = new NetLogic(oname, 3, NetLogic::AND);
|
||||
break;
|
||||
case '|':
|
||||
gate = new NetLogic(oname, 3, NetLogic::OR);
|
||||
break;
|
||||
case '^':
|
||||
gate = new NetLogic(oname, 3, NetLogic::XOR);
|
||||
break;
|
||||
case 'O':
|
||||
gate = new NetLogic(oname, 3, NetLogic::NOR);
|
||||
break;
|
||||
case 'X':
|
||||
gate = new NetLogic(oname, 3, NetLogic::XNOR);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
connect(osig->pin(idx), gate->pin(0));
|
||||
connect(lsig->pin(idx), gate->pin(1));
|
||||
connect(rsig->pin(idx), gate->pin(2));
|
||||
|
||||
des->add_node(gate);
|
||||
}
|
||||
|
||||
des->add_signal(osig);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConcat::synthesize(Design*des)
|
||||
{
|
||||
assert(repeat_ == 1);
|
||||
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, expr_width());
|
||||
osig->local_flag(true);
|
||||
|
||||
unsigned obit = 0;
|
||||
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*tmp = parms_[idx-1]->synthesize(des);
|
||||
|
||||
for (unsigned bit = 0 ; bit < tmp->pin_count() ; bit += 1) {
|
||||
connect(osig->pin(obit), tmp->pin(bit));
|
||||
obit += 1;
|
||||
}
|
||||
|
||||
if (tmp->local_flag())
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
des->add_signal(osig);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEConst::synthesize(Design*des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
unsigned width=expr_width();
|
||||
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
NetConst*con = new NetConst(des->local_symbol(path), value());
|
||||
for (unsigned idx = 0 ; idx < width; idx += 1)
|
||||
connect(osig->pin(idx), con->pin(idx));
|
||||
|
||||
des->add_node(con);
|
||||
des->add_signal(osig);
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* The bitwise unary logic operator (there is only one) is turned
|
||||
* into discrete gates just as easily as the binary ones above.
|
||||
*/
|
||||
NetNet* NetEUBits::synthesize(Design*des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, isig->pin_count());
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1) {
|
||||
string oname = des->local_symbol(path);
|
||||
NetLogic*gate;
|
||||
|
||||
switch (op()) {
|
||||
case '~':
|
||||
gate = new NetLogic(oname, 2, NetLogic::NOT);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
connect(osig->pin(idx), gate->pin(0));
|
||||
connect(isig->pin(idx), gate->pin(1));
|
||||
|
||||
des->add_node(gate);
|
||||
}
|
||||
des->add_signal(osig);
|
||||
return osig;
|
||||
}
|
||||
|
||||
|
||||
NetNet* NetETernary::synthesize(Design *des)
|
||||
{
|
||||
string path = des->local_symbol("SYNTH");
|
||||
NetNet*csig = cond_->synthesize(des);
|
||||
NetNet*tsig = true_val_->synthesize(des);
|
||||
NetNet*fsig = false_val_->synthesize(des);
|
||||
|
||||
assert(csig->pin_count() == 1);
|
||||
assert(tsig->pin_count() == fsig->pin_count());
|
||||
unsigned width=tsig->pin_count();
|
||||
NetNet*osig = new NetNet(0, path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
|
||||
string oname = des->local_symbol(path);
|
||||
NetMux *mux = new NetMux(oname, width, 2, 1);
|
||||
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));
|
||||
connect(osig->pin(idx), mux->pin_Result(idx));
|
||||
}
|
||||
des->add_node(mux);
|
||||
connect(csig->pin(0), mux->pin_Sel(0));
|
||||
des->add_signal(osig);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetESignal::synthesize(Design*des)
|
||||
{
|
||||
return net_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.10 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/01 06:18:00 steve
|
||||
* Handle synthesis of concatenation.
|
||||
*
|
||||
* Revision 1.8 1999/12/17 06:18:15 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.7 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.6 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
*
|
||||
* Revision 1.5 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.4 1999/11/19 03:00:59 steve
|
||||
* Whoops, created a signal with a duplicate name.
|
||||
*
|
||||
* Revision 1.3 1999/11/05 04:40:40 steve
|
||||
* Patch to synthesize LPM_ADD_SUB from expressions,
|
||||
* Thanks to Larry Doolittle. Also handle constants
|
||||
* in expressions.
|
||||
*
|
||||
* Synthesize adders in XNF, based on a patch from
|
||||
* Larry. Accept synthesis of constants from Larry
|
||||
* as is.
|
||||
*
|
||||
* Revision 1.2 1999/11/04 03:53:26 steve
|
||||
* Patch to synthesize unary ~ and the ternary operator.
|
||||
* Thanks to Larry Doolittle <[email protected]>.
|
||||
*
|
||||
* Add the LPM_MUX device, and integrate it with the
|
||||
* ternary synthesis from Larry. Replace the lpm_mux
|
||||
* generator in t-xnf.cc to use XNF EQU devices to
|
||||
* put muxs into function units.
|
||||
*
|
||||
* Rewrite elaborate_net for the PETernary class to
|
||||
* also use the LPM_MUX device.
|
||||
*
|
||||
* Revision 1.1 1999/11/02 04:55:34 steve
|
||||
* Add the synthesize method to NetExpr to handle
|
||||
* synthesis of expressions, and use that method
|
||||
* to improve r-value handling of LPM_FF synthesis.
|
||||
*
|
||||
* Modify the XNF target to handle LPM_FF objects.
|
||||
*
|
||||
*/
|
||||
|
||||
+161
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.cc,v 1.2 1999/07/18 05:52:46 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: functor.cc,v 1.12 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "functor.h"
|
||||
@@ -35,14 +35,35 @@ void functor_t::process(class Design*, class NetProcTop*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_add_sub(class Design*, class NetAddSub*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_const(class Design*, class NetConst*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_ff(class Design*, class NetFF*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_logic(class Design*, class NetLogic*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_mult(class Design*, class NetMult*)
|
||||
{
|
||||
}
|
||||
|
||||
void Design::functor(functor_t*fun)
|
||||
{
|
||||
// apply to signals
|
||||
if (signals_) {
|
||||
NetNet*cur = signals_->sig_next_;
|
||||
do {
|
||||
NetNet*tmp = cur->sig_next_;
|
||||
fun->signal(this, cur);
|
||||
cur = cur->sig_next_;
|
||||
cur = tmp;
|
||||
} while (cur != signals_->sig_next_);
|
||||
}
|
||||
|
||||
@@ -53,10 +74,146 @@ void Design::functor(functor_t*fun)
|
||||
procs_idx_ = idx->next_;
|
||||
fun->process(this, idx);
|
||||
}
|
||||
|
||||
// apply to nodes
|
||||
if (nodes_) {
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
do {
|
||||
NetNode*tmp = cur->node_next_;
|
||||
cur->functor_node(this, fun);
|
||||
cur = tmp;
|
||||
} while (nodes_ && cur != nodes_->node_next_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NetNode::functor_node(Design*, functor_t*)
|
||||
{
|
||||
}
|
||||
|
||||
void NetAddSub::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_add_sub(des, this);
|
||||
}
|
||||
|
||||
void NetConst::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_const(des, this);
|
||||
}
|
||||
|
||||
void NetFF::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_ff(des, this);
|
||||
}
|
||||
|
||||
void NetLogic::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_logic(des, this);
|
||||
}
|
||||
|
||||
void NetMult::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_mult(des, this);
|
||||
}
|
||||
|
||||
proc_match_t::~proc_match_t()
|
||||
{
|
||||
}
|
||||
|
||||
int NetProc::match_proc(proc_match_t*that)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int proc_match_t::assign(NetAssign*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetAssign::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->assign(this);
|
||||
}
|
||||
|
||||
int proc_match_t::assign_mem(NetAssignMem*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetAssignMem::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->assign_mem(this);
|
||||
}
|
||||
|
||||
int proc_match_t::block(NetBlock*)
|
||||
{
|
||||
cerr << "default (failing) match for block" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetBlock::match_proc(proc_match_t*that)
|
||||
{
|
||||
cerr << "NetBlock::match_proc" << endl;
|
||||
return that->block(this);
|
||||
}
|
||||
|
||||
int proc_match_t::condit(NetCondit*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetCondit::match_proc(proc_match_t*that)
|
||||
{
|
||||
cerr << "NetCondit::match_proc" << endl;
|
||||
return that->condit(this);
|
||||
}
|
||||
|
||||
int proc_match_t::pevent(NetPEvent*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetPEvent::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->pevent(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.12 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.11 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.10 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.9 2000/01/02 17:57:20 steve
|
||||
* Handle nodes running out during node scan.
|
||||
*
|
||||
* Revision 1.8 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.7 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.6 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.5 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
* Revision 1.4 1999/11/18 03:52:19 steve
|
||||
* Turn NetTmp objects into normal local NetNet objects,
|
||||
* and add the nodangle functor to clean up the local
|
||||
* symbols generated by elaboration and other steps.
|
||||
*
|
||||
* Revision 1.3 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.2 1999/07/18 05:52:46 steve
|
||||
* xnfsyn generates DFF objects for XNF output, and
|
||||
* properly rewrites the Design netlist in the process.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __functor_H
|
||||
#define __functor_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: functor.h,v 1.1 1999/07/17 22:01:13 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: functor.h,v 1.9 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -42,10 +42,61 @@ struct functor_t {
|
||||
/* This method is called for each process in the design. */
|
||||
virtual void process(class Design*des, class NetProcTop*);
|
||||
|
||||
/* This method is called for each structural adder. */
|
||||
virtual void lpm_add_sub(class Design*des, class NetAddSub*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_const(class Design*des, class NetConst*);
|
||||
|
||||
/* This method is called for each FF in the design. */
|
||||
virtual void lpm_ff(class Design*des, class NetFF*);
|
||||
|
||||
/* Handle LPM combinational logic devices. */
|
||||
virtual void lpm_logic(class Design*des, class NetLogic*);
|
||||
|
||||
/* This method is called for each multiplier. */
|
||||
virtual void lpm_mult(class Design*des, class NetMult*);
|
||||
};
|
||||
|
||||
struct proc_match_t {
|
||||
virtual ~proc_match_t();
|
||||
|
||||
virtual int assign(class NetAssign*);
|
||||
virtual int assign_mem(class NetAssignMem*);
|
||||
virtual int condit(class NetCondit*);
|
||||
virtual int pevent(class NetPEvent*);
|
||||
virtual int block(class NetBlock*);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.9 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.8 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.7 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.6 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.5 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.4 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.3 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
* Revision 1.2 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.1 1999/07/17 22:01:13 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
*
|
||||
|
||||
+419
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* gverilog.c - A driver for verilog compiler ivl
|
||||
* Copyright (C) 1999 Stefan Petersen ([email protected])
|
||||
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifndef LIBDIR
|
||||
# define LIBDIR "/usr/local/lib"
|
||||
#endif
|
||||
#ifndef INCLUDEDIR
|
||||
# define INCLUDEDIR "/usr/local/include"
|
||||
#endif
|
||||
|
||||
const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
|
||||
#ifndef PATHLEN
|
||||
# define PATHLEN 100
|
||||
#endif
|
||||
|
||||
#define P_IF_SET(var) var.set ? var.name : ""
|
||||
|
||||
/* Div compiler settings */
|
||||
struct compset {
|
||||
char compsw[5];
|
||||
char name[PATHLEN];
|
||||
int set;
|
||||
};
|
||||
|
||||
/* cpp include path */
|
||||
struct compset cppincpath = {"-I", INCLUDEDIR, 1};
|
||||
|
||||
/* cpp library path */
|
||||
struct compset cpplibpath ={"-L", LIBDIR, 1};
|
||||
|
||||
/* VPI module path */
|
||||
struct compset VPImodpath = {"-f", LIBDIR "/ivl", 1};
|
||||
|
||||
/* ivl include path */
|
||||
struct compset ivlppincpath = {"-I", "", 0};
|
||||
|
||||
/* ivl defines */
|
||||
struct compset ivlppdefines = {"-D", "", 0};
|
||||
|
||||
/* ivl target setup */
|
||||
/* Compilation target, default vvm */
|
||||
typedef enum {VVM, XNF, NULLT, OTHER} targettype;
|
||||
struct target {
|
||||
targettype target;
|
||||
struct compset targetinfo;
|
||||
};
|
||||
struct target target = {VVM, {"-t", "vvm", 0}};
|
||||
|
||||
|
||||
/* functors setup */
|
||||
struct compset functors = {"-F","", 0};
|
||||
|
||||
/* output file */
|
||||
struct compset outputfile = {"-o", "", 0};
|
||||
|
||||
/* topmodule name */
|
||||
struct compset topmodule = {"-s", "", 0};
|
||||
|
||||
/* verilog files */
|
||||
char verilogfiles[PATHLEN] = "";
|
||||
|
||||
|
||||
/* Temp files for storage */
|
||||
char tmpPPfile[50];
|
||||
char tmpCCfile[50];
|
||||
|
||||
/* Compilation flag info */
|
||||
struct compileinfo {
|
||||
int pform;
|
||||
int execute;
|
||||
int elabnetlist;
|
||||
int debug;
|
||||
};
|
||||
struct compileinfo compileinfo = {0, 0, 0, 0};
|
||||
|
||||
|
||||
void sorry(char optelem)
|
||||
{
|
||||
printf("Sorry, switch -%c not implemented yet!\n", optelem);
|
||||
}
|
||||
|
||||
|
||||
void strchk(char *str, unsigned int maxlen)
|
||||
{
|
||||
if (strlen(str) >= maxlen)
|
||||
fprintf(stderr, "Warning! Following path too long, truncating it!\n%s\n",
|
||||
str);
|
||||
}
|
||||
|
||||
|
||||
targettype resolvtarget(char *target)
|
||||
{
|
||||
if (strcmp(target, "vvm") == 0) {
|
||||
return VVM;
|
||||
} else if (strcmp(target, "xnf") == 0) {
|
||||
sprintf(functors.name, "%ssynth %snodangle %sxnfio",
|
||||
functors.compsw, functors.compsw, functors.compsw);
|
||||
functors.set = 1;
|
||||
return XNF;
|
||||
} else if (strcmp(target, "null") == 0) {
|
||||
return NULLT;
|
||||
} else {
|
||||
return OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void error_exit(void)
|
||||
{
|
||||
fprintf(stderr, "verilog [-Dmacro[=defn]] [-Iincludepath] [-X] \n");
|
||||
fprintf(stderr, "[-x] [-o outputfilename] [-s topmodule] sourcefile[s]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void create_outputfilename(char *input, char *output)
|
||||
{
|
||||
char *dotpos, *spacepos;
|
||||
|
||||
if ((dotpos = strrchr(input, (int)'.')) == NULL) {
|
||||
dotpos = input + strlen(input);
|
||||
}
|
||||
|
||||
if ((spacepos = strrchr(input, (int)' ')) == NULL) {
|
||||
spacepos = input;
|
||||
}
|
||||
|
||||
output = strncpy(output, spacepos, dotpos-spacepos);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void preprocess(void)
|
||||
{
|
||||
char *argument;
|
||||
|
||||
argument = (char *)malloc(256);
|
||||
|
||||
sprintf(argument, LIBDIR "/ivl/ivlpp %s %s -L -o%s %s",
|
||||
P_IF_SET(ivlppdefines),
|
||||
P_IF_SET(ivlppincpath),
|
||||
tmpPPfile,
|
||||
verilogfiles);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Executing command : \n%s\n", argument);
|
||||
} else {
|
||||
if (system(argument)) {
|
||||
fprintf(stderr, "Preprocessing failed. Terminating compilation\n");
|
||||
unlink(tmpPPfile);
|
||||
free(argument);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
free(argument);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void compile(void)
|
||||
{
|
||||
char *argument;
|
||||
|
||||
argument = (char *)malloc(256);
|
||||
|
||||
/* VPI_MODULE_PATH should be better integrated. */
|
||||
/* HACK */
|
||||
sprintf(argument, LIBDIR "/ivl/ivl %s %s %s %sVPI_MODULE_PATH=%s -o %s %s",
|
||||
P_IF_SET(topmodule),
|
||||
target.targetinfo.compsw, target.targetinfo.name,
|
||||
VPImodpath.compsw, VPImodpath.name,
|
||||
/* compileinfo.pform ? "-P whatever_pform" : "",
|
||||
compileinfo.elabnetlist ? "-E whatever_netlist" : "", */
|
||||
tmpCCfile,
|
||||
tmpPPfile);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Executing command : \n%s\n", argument);
|
||||
printf("Removing file %s\n", tmpPPfile);
|
||||
} else {
|
||||
if (system(argument)) {
|
||||
fprintf(stderr, "Compilation failed. Terminating compilation\n");
|
||||
unlink(tmpCCfile);
|
||||
free(argument);
|
||||
exit(1);
|
||||
}
|
||||
unlink(tmpPPfile);
|
||||
}
|
||||
|
||||
free(argument);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void postprocess(void)
|
||||
{
|
||||
char *argument;
|
||||
|
||||
/* Hopefully not filling stack with large array */
|
||||
argument = malloc(256);
|
||||
|
||||
switch (target.target) {
|
||||
case VVM: /* Compile C++ source */
|
||||
|
||||
sprintf(argument, "g++ -rdynamic %s%s %s%s %s -o %s -lvvm -ldl",
|
||||
cppincpath.compsw, cppincpath.name, /* Include dir */
|
||||
cpplibpath.compsw, cpplibpath.name, /* Library dir */
|
||||
tmpCCfile,
|
||||
outputfile.name);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Executing command :\n%s\n", argument);
|
||||
} else {
|
||||
if (system(argument)) {
|
||||
fprintf(stderr, "g++ compilation failed. Terminating compilation\n");
|
||||
unlink(tmpCCfile);
|
||||
free(argument);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
unlink(tmpCCfile);
|
||||
break;
|
||||
case XNF: /* Just move file as is */
|
||||
sprintf(outputfile.name, "%s.xnf", outputfile.name);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Moving file %s to %s\n", tmpCCfile, outputfile.name);
|
||||
} else {
|
||||
if (rename(tmpCCfile, outputfile.name) == -1) {
|
||||
perror("Failed moving file. gverilog:postprocess\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NULLT: /* Remove file we accidently created */
|
||||
unlink(tmpCCfile);
|
||||
break;
|
||||
case OTHER: /* Just move file as is */
|
||||
sprintf(outputfile.name, "%s.%s", outputfile.name, target.targetinfo.name);
|
||||
|
||||
strchk(argument, 255);
|
||||
|
||||
if (compileinfo.debug) {
|
||||
printf("Moving file %s to %s\n", tmpCCfile, outputfile.name);
|
||||
} else {
|
||||
if (rename(tmpCCfile, outputfile.name) == -1) {
|
||||
perror("Failed moving file. gverilog:postprocess\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Illegal target. This should never happen.\n");
|
||||
error_exit();
|
||||
}
|
||||
|
||||
if (compileinfo.execute) {
|
||||
if (compileinfo.debug) {
|
||||
printf("Executing command :\n%s\n", outputfile.name);
|
||||
} else {
|
||||
system(outputfile.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(argument);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char optstring[] = "D:I:Xxf:o:s:t:EPvd";
|
||||
int optelem = 0;
|
||||
|
||||
|
||||
while ((optelem = getopt(argc, argv, optstring)) != EOF) {
|
||||
|
||||
switch ((char)optelem) {
|
||||
case 'D': /* defines */
|
||||
sprintf(ivlppdefines.name, "%s %s%s", ivlppdefines.name,
|
||||
ivlppdefines.compsw, optarg);
|
||||
ivlppdefines.set =1;
|
||||
break;
|
||||
case 'I': /* includepath */
|
||||
sprintf(ivlppincpath.name, "%s %s %s", ivlppincpath.name,
|
||||
ivlppincpath.compsw, optarg);
|
||||
ivlppincpath.set = 1;
|
||||
strchk(ivlppincpath.name, PATHLEN);
|
||||
break;
|
||||
case 'X': /* xnf target */
|
||||
if (target.targetinfo.set)
|
||||
fprintf(stderr, "Target already set to %s\n", target.targetinfo.name);
|
||||
else {
|
||||
sprintf(target.targetinfo.name,"%s xnf", target.targetinfo.compsw);
|
||||
target.targetinfo.set = 1;
|
||||
target.target = XNF;
|
||||
}
|
||||
break;
|
||||
case 'x': /* execute */
|
||||
compileinfo.execute = 1;
|
||||
break;
|
||||
case 'f': /* flags? */
|
||||
sorry((char)optelem);
|
||||
break;
|
||||
case 'o': /* output file */
|
||||
if (outputfile.set)
|
||||
fprintf(stderr, "Output filename already set to %s\n",
|
||||
outputfile.name);
|
||||
else {
|
||||
sprintf(outputfile.name, "%s", optarg);
|
||||
outputfile.set = 1;
|
||||
}
|
||||
break;
|
||||
case 's': /* top module */
|
||||
if (topmodule.set)
|
||||
fprintf(stderr, "Topmodule name already set to %s\n", topmodule.name);
|
||||
else {
|
||||
sprintf(topmodule.name, "%s %s", topmodule.compsw, optarg);
|
||||
topmodule.set = 1 ;
|
||||
}
|
||||
break;
|
||||
case 't': /* code target */
|
||||
if (target.targetinfo.set)
|
||||
fprintf(stderr, "Target already set to %s\n", target.targetinfo.name);
|
||||
else {
|
||||
sprintf(target.targetinfo.name, "%s", optarg);
|
||||
target.targetinfo.set = 1;
|
||||
target.target = resolvtarget(target.targetinfo.name);
|
||||
}
|
||||
break;
|
||||
case 'E': /* elaborated netlist */
|
||||
compileinfo.elabnetlist = 1;
|
||||
break;
|
||||
case 'P': /* dump pform */
|
||||
compileinfo.pform = 1;
|
||||
break;
|
||||
case 'v':
|
||||
printf("gverilog version %s\n", VERSION);
|
||||
system("ivlpp -v");
|
||||
printf("*****\n");
|
||||
system("ivl -v");
|
||||
printf("*****\n");
|
||||
system("g++ -v");
|
||||
return(0);
|
||||
case 'd':
|
||||
compileinfo.debug = 1;
|
||||
break;
|
||||
case '?':
|
||||
fprintf(stderr, "Not defined commandswitch %s\n", argv[optind]);
|
||||
error_exit();
|
||||
default:
|
||||
fprintf(stderr, "Not handled commandswitch %s\n", argv[optind]);
|
||||
error_exit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (optind == argc){
|
||||
fprintf(stderr, "Missing infile(s)\n");
|
||||
error_exit();
|
||||
}
|
||||
|
||||
/* Resolve temporary file storage */
|
||||
sprintf(tmpPPfile, "ivl%d.pp", (int)getpid());
|
||||
sprintf(tmpCCfile, "ivl%d.cc", (int)getpid());
|
||||
|
||||
/* Build list of verilog files */
|
||||
for(; optind != argc; optind++) {
|
||||
sprintf(verilogfiles, "%s %s", verilogfiles, argv[optind]);
|
||||
}
|
||||
strchk(verilogfiles , PATHLEN);
|
||||
|
||||
/* Determine output filename if not explicitly set */
|
||||
if (!outputfile.set) {
|
||||
create_outputfilename(verilogfiles, outputfile.name);
|
||||
}
|
||||
|
||||
|
||||
preprocess();
|
||||
|
||||
compile();
|
||||
|
||||
postprocess();
|
||||
|
||||
return(0);
|
||||
}
|
||||
+6
-6
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.5 1999/07/30 00:42:33 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.7 2000/01/01 20:57:51 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -60,16 +60,16 @@ lexor.c: lexor.lex
|
||||
parse.h parse.c: parse.y
|
||||
bison --verbose -t -d parse.y -o parse.c
|
||||
|
||||
install: all installdirs $(bindir)/ivlpp
|
||||
install: all installdirs $(libdir)/ivl/ivlpp
|
||||
|
||||
$(bindir)/ivlpp: ivlpp
|
||||
$(INSTALL_PROGRAM) ./ivlpp $(bindir)/ivlpp
|
||||
$(libdir)/ivl/ivlpp: ivlpp
|
||||
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(includedir) $(bindir)
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/ivlpp
|
||||
rm -f $(libdir)/ivl/ivlpp
|
||||
|
||||
lexor.o: lexor.c parse.h globals.h
|
||||
main.o: main.c globals.h
|
||||
|
||||
+5
-2
@@ -19,12 +19,12 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: globals.h,v 1.1 1999/07/03 20:03:47 steve Exp $"
|
||||
#ident "$Id: globals.h,v 1.2 1999/09/05 22:33:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
extern void reset_lexor(FILE*out, const char*ipath);
|
||||
extern void reset_lexor(FILE*out, char*paths[]);
|
||||
extern void define_macro(const char*name, const char*value);
|
||||
|
||||
/* These variables contain the include directories to be searched when
|
||||
@@ -40,6 +40,9 @@ extern int yyparse();
|
||||
|
||||
/*
|
||||
* $Log: globals.h,v $
|
||||
* Revision 1.2 1999/09/05 22:33:18 steve
|
||||
* Take multiple source files on the command line.
|
||||
*
|
||||
* Revision 1.1 1999/07/03 20:03:47 steve
|
||||
* Add include path and line directives.
|
||||
*
|
||||
|
||||
+67
-12
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: lexor.lex,v 1.11 1999/07/25 00:03:13 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.14 1999/10/08 17:27:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
@@ -60,6 +60,7 @@ struct include_stack_t {
|
||||
struct include_stack_t*next;
|
||||
};
|
||||
|
||||
static struct include_stack_t*file_queue = 0;
|
||||
static struct include_stack_t*istack = 0;
|
||||
static struct include_stack_t*standby = 0;
|
||||
|
||||
@@ -114,7 +115,7 @@ W [ \t\b\f]+
|
||||
that follows it. when the directive ends, the do_include function
|
||||
performs the include operation. */
|
||||
|
||||
^`include { BEGIN(PPINCLUDE); }
|
||||
^{W}?`include { BEGIN(PPINCLUDE); }
|
||||
|
||||
<PPINCLUDE>\"[^\"]*\" { include_filename(); }
|
||||
|
||||
@@ -128,7 +129,7 @@ W [ \t\b\f]+
|
||||
directive and the name, go into PPDEFINE mode and prepare to
|
||||
collect the defined value. */
|
||||
|
||||
^`define{W}[a-zA-Z][a-zA-Z0-9_]*{W}? { BEGIN(PPDEFINE); def_start(); }
|
||||
`define{W}[a-zA-Z][a-zA-Z0-9_]*{W}? { BEGIN(PPDEFINE); def_start(); }
|
||||
|
||||
<PPDEFINE>.*\n {
|
||||
do_define();
|
||||
@@ -137,7 +138,7 @@ W [ \t\b\f]+
|
||||
BEGIN(0);
|
||||
}
|
||||
|
||||
^`undef{W}[a-zA-Z][a-zA-Z0-9_]*{W}?.* { def_undefine(); }
|
||||
`undef{W}[a-zA-Z][a-zA-Z0-9_]*{W}?.* { def_undefine(); }
|
||||
|
||||
|
||||
/* Detect conditional compilation directives, and parse them. If I
|
||||
@@ -466,15 +467,22 @@ static void do_include()
|
||||
yy_switch_to_buffer(yy_new_buffer(istack->file, YY_BUF_SIZE));
|
||||
|
||||
if (line_direct_flag && istack->path)
|
||||
fprintf(yyout, "#line \"%s\" %u\n", istack->path, istack->lineno);
|
||||
fprintf(yyout, "\n#line \"%s\" %u\n",
|
||||
istack->path, istack->lineno);
|
||||
}
|
||||
|
||||
/*
|
||||
* The lexical analyzer calls this function when the current file
|
||||
* ends. Here I pop the include stack and resume the previous file. If
|
||||
* there is no previous file, then the main input is ended.
|
||||
*/
|
||||
static int yywrap()
|
||||
{
|
||||
int line_mask_flag = 0;
|
||||
struct include_stack_t*isp = istack;
|
||||
istack = isp->next;
|
||||
|
||||
/* Delete the current input buffers, and free the cell. */
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
if (isp->file) {
|
||||
fclose(isp->file);
|
||||
@@ -492,13 +500,42 @@ static int yywrap()
|
||||
}
|
||||
free(isp);
|
||||
|
||||
if (istack == 0)
|
||||
return 1;
|
||||
/* If I am out if include stack, the main input is
|
||||
done. Look for another file to process in the input
|
||||
queue. If none are there, give up. Otherwise, open the file
|
||||
and continue parsing. */
|
||||
if (istack == 0) {
|
||||
if (file_queue == 0)
|
||||
return 1;
|
||||
|
||||
istack = file_queue;
|
||||
file_queue = file_queue->next;
|
||||
istack->next = 0;
|
||||
istack->lineno = 0;
|
||||
|
||||
istack->file = fopen(istack->path, "r");
|
||||
if (istack->file == 0) {
|
||||
perror(istack->path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (line_direct_flag)
|
||||
fprintf(yyout, "\n#line \"%s\" 0\n", istack->path);
|
||||
|
||||
yyrestart(isp->file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Otherwise, resume the input buffer that is the new stack
|
||||
top. If I need to print a line directive, do so. */
|
||||
|
||||
yy_switch_to_buffer(istack->yybs);
|
||||
|
||||
if (line_direct_flag && istack->path && !line_mask_flag)
|
||||
fprintf(yyout, "#line \"%s\" %u\n", istack->path, istack->lineno);
|
||||
fprintf(yyout, "\n#line \"%s\" %u\n",
|
||||
istack->path, istack->lineno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -507,14 +544,16 @@ static int yywrap()
|
||||
* opened, and the lexor is initialized. The include stack is cleared
|
||||
* and ready to go.
|
||||
*/
|
||||
void reset_lexor(FILE*out, const char*path)
|
||||
void reset_lexor(FILE*out, char*paths[])
|
||||
{
|
||||
unsigned idx;
|
||||
struct include_stack_t*tail = 0;
|
||||
struct include_stack_t*isp = malloc(sizeof(struct include_stack_t));
|
||||
isp->path = strdup(path);
|
||||
isp->file = fopen(path, "r");
|
||||
isp->path = strdup(paths[0]);
|
||||
isp->file = fopen(paths[0], "r");
|
||||
isp->str = 0;
|
||||
if (isp->file == 0) {
|
||||
perror(path);
|
||||
perror(paths[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -525,4 +564,20 @@ void reset_lexor(FILE*out, const char*path)
|
||||
assert(istack == 0);
|
||||
istack = isp;
|
||||
isp->next = 0;
|
||||
|
||||
/* Now build up a queue of all the remaining file names, so
|
||||
that yywrap can pull them when needed. */
|
||||
file_queue = 0;
|
||||
for (idx = 1 ; paths[idx] ; idx += 1) {
|
||||
isp = malloc(sizeof(struct include_stack_t));
|
||||
isp->path = strdup(paths[idx]);
|
||||
isp->str = 0;
|
||||
isp->next = 0;
|
||||
if (tail)
|
||||
tail->next = isp;
|
||||
else
|
||||
file_queue = isp;
|
||||
|
||||
tail = isp;
|
||||
}
|
||||
}
|
||||
|
||||
+17
-3
@@ -17,7 +17,7 @@ const char COPYRIGHT[] =
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: main.c,v 1.2 1999/07/03 20:03:47 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.4 1999/11/29 17:02:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
const char NOTICE[] =
|
||||
@@ -42,6 +42,9 @@ const char VERSION[] = "$Name: $ $State: Exp $";
|
||||
# include <malloc.h>
|
||||
# include <unistd.h>
|
||||
# include <string.h>
|
||||
#if defined(HAVE_GETOPT_H)
|
||||
# include <getopt.h>
|
||||
#endif
|
||||
# include "globals.h"
|
||||
|
||||
char**include_dir = 0;
|
||||
@@ -109,7 +112,7 @@ int main(int argc, char*argv[])
|
||||
flag_errors += 1;
|
||||
|
||||
if (flag_errors) {
|
||||
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>\n"
|
||||
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>...\n"
|
||||
" -D<def> - Predefine a value.\n"
|
||||
" -I<dir> - Add an include file search directory\n"
|
||||
" -L - Emit line number directives\n"
|
||||
@@ -129,12 +132,23 @@ int main(int argc, char*argv[])
|
||||
out = stdout;
|
||||
}
|
||||
|
||||
reset_lexor(out, argv[optind]);
|
||||
if (argv[optind] == 0) {
|
||||
fprintf(stderr, "%s: No input files given.\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
reset_lexor(out, argv+optind);
|
||||
return yyparse();
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.4 1999/11/29 17:02:21 steve
|
||||
* include getopt if present.
|
||||
*
|
||||
* Revision 1.3 1999/09/05 22:33:18 steve
|
||||
* Take multiple source files on the command line.
|
||||
*
|
||||
* Revision 1.2 1999/07/03 20:03:47 steve
|
||||
* Add include path and line directives.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: lexor.lex,v 1.33 1999/07/17 18:25:38 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.42 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
//# define YYSTYPE lexval
|
||||
@@ -40,8 +40,9 @@ extern YYLTYPE yylloc;
|
||||
|
||||
static void reset_lexor();
|
||||
static void line_directive();
|
||||
static void line_directive2();
|
||||
|
||||
static int check_identifier(const char*name);
|
||||
extern int check_identifier(const char*str, int len);
|
||||
static verinum*make_sized_binary(const char*txt);
|
||||
static verinum*make_sized_dec(const char*txt);
|
||||
static verinum*make_unsized_dec(const char*txt);
|
||||
@@ -66,6 +67,7 @@ W [ \t\b\f\r]+
|
||||
%%
|
||||
|
||||
^"#line"[ ]+\"[^\"]*\"[ ]+[0-9]+.* { line_directive(); }
|
||||
^"`line"[ ]+[0-9]+[ ]+\"[^\"]*\".* { line_directive2(); }
|
||||
|
||||
[ \t\b\f\r] { ; }
|
||||
\n { yylloc.first_line += 1; }
|
||||
@@ -95,6 +97,7 @@ W [ \t\b\f\r]+
|
||||
"~^" { return K_NXOR; }
|
||||
"^~" { return K_NXOR; }
|
||||
"~&" { return K_NAND; }
|
||||
"->" { return K_TRIGGER; }
|
||||
|
||||
|
||||
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
|
||||
@@ -128,7 +131,7 @@ W [ \t\b\f\r]+
|
||||
<UDPTABLE>[pPnN01\?\*\-] { return yytext[0]; }
|
||||
|
||||
[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
int rc = check_identifier(yytext);
|
||||
int rc = check_identifier(yytext, yyleng);
|
||||
if (rc == IDENTIFIER)
|
||||
yylval.text = strdup(yytext);
|
||||
else
|
||||
@@ -150,30 +153,33 @@ W [ \t\b\f\r]+
|
||||
yylval.text = strdup(yytext);
|
||||
return SYSTEM_IDENTIFIER; }
|
||||
|
||||
\.[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
yylval.text = strdup(yytext+1);
|
||||
\.{W}?[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
char*cp = yytext+1;
|
||||
while (! (isalpha(*cp) || (*cp == '_')))
|
||||
cp += 1;
|
||||
yylval.text = strdup(cp);
|
||||
return PORTNAME; }
|
||||
|
||||
[0-9][0-9_]*[ \t]*\'d[ \t]*[0-9][0-9_]* {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[dD][ \t]*[0-9][0-9_]* {
|
||||
yylval.number = make_sized_dec(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[bB][ \t]*[0-1xzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ {
|
||||
yylval.number = make_sized_binary(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[oO][ \t]*[0-7xzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ {
|
||||
yylval.number = make_sized_octal(yytext);
|
||||
return NUMBER; }
|
||||
[0-9][0-9_]*[ \t]*\'[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ {
|
||||
[0-9][0-9_]*[ \t]*\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ {
|
||||
yylval.number = make_sized_hex(yytext);
|
||||
return NUMBER; }
|
||||
|
||||
\'d[ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return NUMBER; }
|
||||
\'[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return NUMBER; }
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
return NUMBER; }
|
||||
\'[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
return NUMBER; }
|
||||
\'[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
return NUMBER; }
|
||||
|
||||
[0-9][0-9_]* {
|
||||
@@ -193,6 +199,7 @@ W [ \t\b\f\r]+
|
||||
}
|
||||
|
||||
yylval.number = new verinum(bits, nbits, false);
|
||||
yylval.number->has_sign(true);
|
||||
delete[]bits;
|
||||
return NUMBER; }
|
||||
|
||||
@@ -305,136 +312,28 @@ void lex_end_table()
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
|
||||
static const struct { const char*name; int code; } key_table[] = {
|
||||
{ "always", K_always },
|
||||
{ "and", K_and },
|
||||
{ "assign", K_assign },
|
||||
{ "begin", K_begin },
|
||||
{ "buf", K_buf },
|
||||
{ "bufif0", K_bufif0 },
|
||||
{ "bufif1", K_bufif1 },
|
||||
{ "case", K_case },
|
||||
{ "casex", K_casex },
|
||||
{ "casez", K_casez },
|
||||
{ "cmos", K_cmos },
|
||||
{ "deassign", K_deassign },
|
||||
{ "default", K_default },
|
||||
{ "defparam", K_defparam },
|
||||
{ "disable", K_disable },
|
||||
{ "edge", K_edge },
|
||||
{ "else", K_else },
|
||||
{ "end", K_end },
|
||||
{ "endcase", K_endcase },
|
||||
{ "endfunction", K_endfunction },
|
||||
{ "endmodule", K_endmodule },
|
||||
{ "endprimitive", K_endprimitive },
|
||||
{ "endspecify", K_endspecify },
|
||||
{ "endtable", K_endtable },
|
||||
{ "endtask", K_endtask },
|
||||
{ "event", K_event },
|
||||
{ "for", K_for },
|
||||
{ "force", K_force },
|
||||
{ "forever", K_forever },
|
||||
{ "fork", K_fork },
|
||||
{ "function", K_function },
|
||||
{ "highz0", K_highz0 },
|
||||
{ "highz1", K_highz1 },
|
||||
{ "if", K_if },
|
||||
{ "initial", K_initial },
|
||||
{ "inout", K_inout },
|
||||
{ "input", K_input },
|
||||
{ "integer", K_integer },
|
||||
{ "join", K_join },
|
||||
{ "large", K_large },
|
||||
{ "macromodule", K_macromodule },
|
||||
{ "medium", K_medium },
|
||||
{ "module", K_module },
|
||||
{ "nand", K_nand },
|
||||
{ "negedge", K_negedge },
|
||||
{ "nmos", K_nmos },
|
||||
{ "nor", K_nor },
|
||||
{ "not", K_not },
|
||||
{ "notif0", K_notif0 },
|
||||
{ "notif1", K_notif1 },
|
||||
{ "or", K_or },
|
||||
{ "output", K_output },
|
||||
{ "parameter", K_parameter },
|
||||
{ "pmos", K_pmos },
|
||||
{ "posedge", K_posedge },
|
||||
{ "primitive", K_primitive },
|
||||
{ "pull0", K_pull0 },
|
||||
{ "pull1", K_pull1 },
|
||||
{ "pulldown", K_pulldown },
|
||||
{ "pullup", K_pullup },
|
||||
{ "rcmos", K_rcmos },
|
||||
{ "reg", K_reg },
|
||||
{ "release", K_release },
|
||||
{ "repeat", K_repeat },
|
||||
{ "rnmos", K_rnmos },
|
||||
{ "rpmos", K_rpmos },
|
||||
{ "rtran", K_rtran },
|
||||
{ "rtranif0", K_rtranif0 },
|
||||
{ "rtranif1", K_rtranif1 },
|
||||
{ "scalered", K_scalered },
|
||||
{ "small", K_small },
|
||||
{ "specify", K_specify },
|
||||
{ "specparam", K_specparam },
|
||||
{ "strong0", K_strong0 },
|
||||
{ "strong1", K_strong1 },
|
||||
{ "supply0", K_supply0 },
|
||||
{ "supply1", K_supply1 },
|
||||
{ "table", K_table },
|
||||
{ "task", K_task },
|
||||
{ "time", K_time },
|
||||
{ "tran", K_tran },
|
||||
{ "tranif0", K_tranif0 },
|
||||
{ "tranif1", K_tranif1 },
|
||||
{ "tri", K_tri },
|
||||
{ "tri0", K_tri0 },
|
||||
{ "tri1", K_tri1 },
|
||||
{ "triand", K_triand },
|
||||
{ "trior", K_trior },
|
||||
{ "trireg", K_trireg },
|
||||
{ "vectored", K_vectored },
|
||||
{ "wait", K_wait },
|
||||
{ "wand", K_wand },
|
||||
{ "weak0", K_weak0 },
|
||||
{ "weak1", K_weak1 },
|
||||
{ "while", K_while },
|
||||
{ "wire", K_wire },
|
||||
{ "wor", K_wor },
|
||||
{ "xnor", K_xnor },
|
||||
{ "xor", K_xor },
|
||||
{ 0, IDENTIFIER }
|
||||
};
|
||||
|
||||
static int check_identifier(const char*name)
|
||||
{
|
||||
for (unsigned idx = 0 ; key_table[idx].name ; idx += 1)
|
||||
if (strcmp(key_table[idx].name, name) == 0)
|
||||
return key_table[idx].code;
|
||||
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
{
|
||||
assert(tolower(*ptr) == 'b');
|
||||
bool sign_flag = false;
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
|
||||
if (tolower(ptr[0]) == 's') {
|
||||
ptr += 1;
|
||||
sign_flag = true;
|
||||
}
|
||||
assert(tolower(*ptr) == 'b');
|
||||
ptr += 1;
|
||||
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
|
||||
unsigned idx = 0;
|
||||
const char*eptr = ptr + strlen(ptr) - 1;
|
||||
while ((eptr > ptr) && (idx < size)) {
|
||||
|
||||
if (*eptr == '_') {
|
||||
eptr -= 1;
|
||||
continue;
|
||||
}
|
||||
while ((eptr >= ptr) && (idx < size)) {
|
||||
|
||||
switch (*eptr) {
|
||||
case '_':
|
||||
break;
|
||||
case '0':
|
||||
bits[idx++] = verinum::V0;
|
||||
break;
|
||||
@@ -456,7 +355,7 @@ static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
// Zero-extend binary number, except that z or x is extended
|
||||
// if it is the highest supplied digit.
|
||||
while (idx < size) {
|
||||
switch (ptr[1]) {
|
||||
switch (ptr[0]) {
|
||||
case '0':
|
||||
case '1':
|
||||
bits[idx++] = verinum::V0;
|
||||
@@ -472,7 +371,10 @@ static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
}
|
||||
}
|
||||
|
||||
return new verinum(bits, size, fixed);
|
||||
verinum*out = new verinum(bits, size, fixed);
|
||||
delete[]bits;
|
||||
out->has_sign(sign_flag);
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_binary(const char*txt)
|
||||
@@ -483,16 +385,21 @@ static verinum*make_sized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
assert(tolower(*ptr) == 'b');
|
||||
|
||||
return make_binary_with_size(size, true, ptr);
|
||||
}
|
||||
|
||||
static verinum*make_unsized_binary(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'b');
|
||||
while (*ptr && ((*ptr == 'b') || (*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
@@ -527,70 +434,120 @@ static verinum*make_unsized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_octal(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
char*ptr;
|
||||
|
||||
unsigned size = strtoul(txt,&ptr,10);
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'o');
|
||||
|
||||
/* We know from the size number how bit to make the verinom
|
||||
array, so make it now. */
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
|
||||
/* skip white space between size and the base token. */
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
|
||||
unsigned idx = 0;
|
||||
/* Find the end of the digits. ptr already points to the start. */
|
||||
char*eptr = ptr + strlen(ptr);
|
||||
|
||||
while ((eptr > ptr) && (idx < (size-3))) {
|
||||
switch (*eptr) {
|
||||
/* From the last digit and forward, build up the number, least
|
||||
significant bit first. This loop will not get the last few
|
||||
bits if the size is not a multiple of 3. */
|
||||
unsigned idx = 0;
|
||||
while ((eptr > ptr) && ((idx/3) < (size/3))) switch (*--eptr) {
|
||||
|
||||
case 'x': case 'X':
|
||||
bits[idx++] = verinum::Vx;
|
||||
bits[idx++] = verinum::Vx;
|
||||
bits[idx++] = verinum::Vx;
|
||||
break;
|
||||
|
||||
case 'z': case 'Z': case '?':
|
||||
bits[idx++] = verinum::Vz;
|
||||
bits[idx++] = verinum::Vz;
|
||||
bits[idx++] = verinum::Vz;
|
||||
break;
|
||||
|
||||
default: {
|
||||
unsigned val = *eptr - '0';
|
||||
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
|
||||
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
|
||||
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((eptr > ptr) && (idx < size)) switch (*--eptr) {
|
||||
|
||||
case 'x': case 'X':
|
||||
for ( ; idx < size ; idx += 1)
|
||||
bits[idx] = verinum::Vx;
|
||||
break;
|
||||
|
||||
case 'z': case 'Z': case '?':
|
||||
for ( ; idx < size ; idx += 1)
|
||||
bits[idx] = verinum::Vz;
|
||||
break;
|
||||
|
||||
default: {
|
||||
unsigned val = *eptr - '0';
|
||||
for ( ; idx < size ; idx += 1) {
|
||||
bits[idx] = (val&1)? verinum::V1 : verinum::V0;
|
||||
val >>= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
eptr -= 1;
|
||||
} else {
|
||||
|
||||
// zero extend octal numbers
|
||||
while (idx < size) switch (ptr[1]) {
|
||||
case 'x': case 'X':
|
||||
bits[idx++] = verinum::Vx;
|
||||
break;
|
||||
case 'z': case 'Z': case '?':
|
||||
bits[idx++] = verinum::Vz;
|
||||
break;
|
||||
default:
|
||||
bits[idx++] = verinum::V0;
|
||||
}
|
||||
}
|
||||
|
||||
// zero extend octal numbers
|
||||
while (idx < size) switch (ptr[1]) {
|
||||
case 'x': case 'X':
|
||||
bits[idx++] = verinum::Vx;
|
||||
break;
|
||||
case 'z': case 'Z': case '?':
|
||||
bits[idx++] = verinum::Vz;
|
||||
break;
|
||||
default:
|
||||
bits[idx++] = verinum::V0;
|
||||
}
|
||||
|
||||
return new verinum(bits, size, true);
|
||||
verinum*out = new verinum(bits, size, true);
|
||||
delete[]bits;
|
||||
out->has_sign(sign_flag);
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_unsized_octal(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
assert(tolower(*ptr) == 'o');
|
||||
ptr += 1;
|
||||
|
||||
@@ -632,11 +589,15 @@ static verinum*make_unsized_octal(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_hex(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
char*ptr;
|
||||
unsigned size = strtoul(txt,&ptr,10);
|
||||
|
||||
@@ -645,6 +606,12 @@ static verinum*make_sized_hex(const char*txt)
|
||||
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
assert(tolower(*ptr) == 'h');
|
||||
|
||||
ptr += 1;
|
||||
@@ -711,14 +678,23 @@ static verinum*make_sized_hex(const char*txt)
|
||||
bits[idx++] = verinum::V0;
|
||||
}
|
||||
|
||||
return new verinum(bits, size, true);
|
||||
verinum*out = new verinum(bits, size, true);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_unsized_hex(const char*txt)
|
||||
{
|
||||
bool sign_flag = false;
|
||||
const char*ptr = txt;
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
sign_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'h');
|
||||
|
||||
ptr += 1;
|
||||
@@ -771,7 +747,10 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
return new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -780,6 +759,11 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
*/
|
||||
static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
{
|
||||
bool signed_flag = false;
|
||||
if (tolower(*ptr) == 's') {
|
||||
signed_flag = true;
|
||||
ptr += 1;
|
||||
}
|
||||
assert(tolower(*ptr) == 'd');
|
||||
|
||||
ptr += 1;
|
||||
@@ -803,7 +787,10 @@ static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
value /= 2;
|
||||
}
|
||||
|
||||
return new verinum(bits, size, fixed);
|
||||
verinum*out = new verinum(bits, size, fixed);
|
||||
out->has_sign(signed_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
}
|
||||
|
||||
static verinum*make_sized_dec(const char*txt)
|
||||
@@ -816,7 +803,6 @@ static verinum*make_sized_dec(const char*txt)
|
||||
|
||||
assert(*ptr == '\'');
|
||||
ptr += 1;
|
||||
assert(tolower(*ptr) == 'd');
|
||||
|
||||
return make_dec_with_size(size, true, ptr);
|
||||
}
|
||||
@@ -857,6 +843,31 @@ static void line_directive()
|
||||
yylloc.first_line = strtoul(qt2,0,0);
|
||||
}
|
||||
|
||||
static void line_directive2()
|
||||
{
|
||||
assert(strncmp(yytext,"`line",5) == 0);
|
||||
char*cp = yytext + strlen("`line");
|
||||
cp += strspn(cp, " ");
|
||||
yylloc.first_line = strtoul(cp,&cp,10);
|
||||
|
||||
cp += strspn(cp, " ");
|
||||
if (*cp == 0) return;
|
||||
|
||||
char*qt1 = strchr(yytext, '"');
|
||||
assert(qt1);
|
||||
qt1 += 1;
|
||||
|
||||
char*qt2 = strchr(qt1, '"');
|
||||
assert(qt2);
|
||||
|
||||
char*buf = new char[qt2-qt1+1];
|
||||
strncpy(buf, qt1, qt2-qt1);
|
||||
buf[qt2-qt1] = 0;
|
||||
|
||||
delete[]yylloc.text;
|
||||
yylloc.text = buf;
|
||||
}
|
||||
|
||||
static void reset_lexor()
|
||||
{
|
||||
yyrestart(vl_input);
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/* C code produced by gperf version 2.7 */
|
||||
/* Command-line: gperf -o -i 1 -C -k 1-3,$ -L C -H keyword_hash -N check_identifier -tT lexor_keyword.gperf > lexor_keyword.cc */
|
||||
|
||||
#include "parse_misc.h"
|
||||
#include "parse.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define TOTAL_KEYWORDS 99
|
||||
#define MIN_WORD_LENGTH 2
|
||||
#define MAX_WORD_LENGTH 12
|
||||
#define MIN_HASH_VALUE 7
|
||||
#define MAX_HASH_VALUE 239
|
||||
/* maximum key range = 233, duplicates = 0 */
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline
|
||||
#endif
|
||||
static unsigned int
|
||||
keyword_hash (const char *str, int len)
|
||||
{
|
||||
static const unsigned char asso_values[] =
|
||||
{
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 126, 66,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 31, 11, 81,
|
||||
1, 1, 81, 26, 11, 51, 11, 21, 81, 81,
|
||||
1, 46, 16, 240, 1, 1, 6, 11, 36, 46,
|
||||
21, 16, 6, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
|
||||
240, 240, 240, 240, 240, 240
|
||||
};
|
||||
int hval = len;
|
||||
|
||||
hval += asso_values[(unsigned char)str[len - 1]];
|
||||
hval += asso_values[(unsigned char)str[0]];
|
||||
hval += asso_values[(unsigned char)str[1]];
|
||||
|
||||
if (len > 2)
|
||||
hval += asso_values[(unsigned char)str[2]];
|
||||
|
||||
return hval ;
|
||||
}
|
||||
|
||||
int
|
||||
check_identifier (const char *str, int len)
|
||||
{
|
||||
static const struct { const char *name; int tokenType; } wordlist[] =
|
||||
{
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{"end", K_end},
|
||||
{""}, {""}, {""},
|
||||
{"endcase", K_endcase},
|
||||
{"endtable", K_endtable},
|
||||
{"endmodule", K_endmodule},
|
||||
{"rtran", K_rtran},
|
||||
{"endfunction", K_endfunction},
|
||||
{"endprimitive", K_endprimitive},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""},
|
||||
{"endspecify", K_endspecify},
|
||||
{"repeat", K_repeat},
|
||||
{"endtask", K_endtask},
|
||||
{""},
|
||||
{"edge", K_edge},
|
||||
{""}, {""},
|
||||
{"negedge", K_negedge},
|
||||
{"and", K_and},
|
||||
{"nand", K_nand},
|
||||
{""},
|
||||
{"assign", K_assign},
|
||||
{"specify", K_specify},
|
||||
{"deassign", K_deassign},
|
||||
{"tran", K_tran},
|
||||
{"begin", K_begin},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"event", K_event},
|
||||
{"or", K_or},
|
||||
{""},
|
||||
{"nor", K_nor},
|
||||
{""},
|
||||
{"table", K_table},
|
||||
{""}, {""},
|
||||
{"reg", K_reg},
|
||||
{"parameter", K_parameter},
|
||||
{""}, {""},
|
||||
{"disable", K_disable},
|
||||
{"not", K_not},
|
||||
{"task", K_task},
|
||||
{"trior", K_trior},
|
||||
{"triand", K_triand},
|
||||
{"integer", K_integer},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"posedge", K_posedge},
|
||||
{"xor", K_xor},
|
||||
{"xnor", K_xnor},
|
||||
{""},
|
||||
{"output", K_output},
|
||||
{""}, {""},
|
||||
{"primitive", K_primitive},
|
||||
{"input", K_input},
|
||||
{""},
|
||||
{"strong1", K_strong1},
|
||||
{"rtranif1", K_rtranif1},
|
||||
{"wand", K_wand},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"else", K_else},
|
||||
{"rnmos", K_rnmos},
|
||||
{"trireg", K_trireg},
|
||||
{"release", K_release},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"default", K_default},
|
||||
{"wor", K_wor},
|
||||
{""}, {""}, {""},
|
||||
{"supply1", K_supply1},
|
||||
{"function", K_function},
|
||||
{"wire", K_wire},
|
||||
{"rpmos", K_rpmos},
|
||||
{""}, {""}, {""},
|
||||
{"specparam", K_specparam},
|
||||
{"inout", K_inout},
|
||||
{""},
|
||||
{"tranif1", K_tranif1},
|
||||
{"tri", K_tri},
|
||||
{"join", K_join},
|
||||
{"while", K_while},
|
||||
{""}, {""},
|
||||
{"pulldown", K_pulldown},
|
||||
{"case", K_case},
|
||||
{"large", K_large},
|
||||
{""}, {""},
|
||||
{"scalered", K_scalered},
|
||||
{""},
|
||||
{"casez", K_casez},
|
||||
{"notif1", K_notif1},
|
||||
{""},
|
||||
{"vectored", K_vectored},
|
||||
{"tri1", K_tri1},
|
||||
{""},
|
||||
{"pullup", K_pullup},
|
||||
{""},
|
||||
{"for", K_for},
|
||||
{"nmos", K_nmos},
|
||||
{"force", K_force},
|
||||
{"module", K_module},
|
||||
{"forever", K_forever},
|
||||
{""},
|
||||
{"wait", K_wait},
|
||||
{"casex", K_casex},
|
||||
{""},
|
||||
{"strong0", K_strong0},
|
||||
{"rtranif0", K_rtranif0},
|
||||
{"time", K_time},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"pmos", K_pmos},
|
||||
{"weak1", K_weak1},
|
||||
{""}, {""}, {""},
|
||||
{"fork", K_fork},
|
||||
{""}, {""}, {""}, {""}, {""}, {""},
|
||||
{"highz1", K_highz1},
|
||||
{"supply0", K_supply0},
|
||||
{""}, {""}, {""},
|
||||
{"always", K_always},
|
||||
{""}, {""}, {""},
|
||||
{"rcmos", K_rcmos},
|
||||
{"medium", K_medium},
|
||||
{"tranif0", K_tranif0},
|
||||
{"defparam", K_defparam},
|
||||
{""}, {""},
|
||||
{"bufif1", K_bufif1},
|
||||
{""}, {""}, {""},
|
||||
{"pull1", K_pull1},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
{"notif0", K_notif0},
|
||||
{""},
|
||||
{"buf", K_buf},
|
||||
{"tri0", K_tri0},
|
||||
{""}, {""},
|
||||
{"initial", K_initial},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{"small", K_small},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
{"macromodule", K_macromodule},
|
||||
{""}, {""}, {""},
|
||||
{"weak0", K_weak0},
|
||||
{""}, {""}, {""},
|
||||
{"cmos", K_cmos},
|
||||
{""},
|
||||
{"if", K_if},
|
||||
{""}, {""}, {""}, {""},
|
||||
{"highz0", K_highz0},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
{"bufif0", K_bufif0},
|
||||
{""}, {""}, {""},
|
||||
{"pull0", K_pull0}
|
||||
};
|
||||
|
||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||
{
|
||||
int key = keyword_hash (str, len);
|
||||
|
||||
if (key <= MAX_HASH_VALUE && key >= 0)
|
||||
{
|
||||
const char *s = wordlist[key].name;
|
||||
|
||||
if (*str == *s && !strcmp (str + 1, s + 1))
|
||||
return wordlist[key].tokenType;
|
||||
}
|
||||
}
|
||||
return IDENTIFIER;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
%{
|
||||
/* Command-line: gperf -o -i 1 -C -k 1-3,$ -L C -H keyword_hash -N check_identifier -tT lexor_keyword.gperf */
|
||||
|
||||
#include "parse_misc.h"
|
||||
#include "parse.h"
|
||||
#include <string.h>
|
||||
|
||||
%}
|
||||
struct Keywords {
|
||||
char *name;
|
||||
int tokenType;
|
||||
} Keywords;
|
||||
%%
|
||||
always, K_always
|
||||
and, K_and
|
||||
assign, K_assign
|
||||
begin, K_begin
|
||||
buf, K_buf
|
||||
bufif0, K_bufif0
|
||||
bufif1, K_bufif1
|
||||
case, K_case
|
||||
casex, K_casex
|
||||
casez, K_casez
|
||||
cmos, K_cmos
|
||||
deassign, K_deassign
|
||||
default, K_default
|
||||
defparam, K_defparam
|
||||
disable, K_disable
|
||||
edge, K_edge
|
||||
else, K_else
|
||||
end, K_end
|
||||
endcase, K_endcase
|
||||
endfunction, K_endfunction
|
||||
endmodule, K_endmodule
|
||||
endprimitive, K_endprimitive
|
||||
endspecify, K_endspecify
|
||||
endtable, K_endtable
|
||||
endtask, K_endtask
|
||||
event, K_event
|
||||
for, K_for
|
||||
force, K_force
|
||||
forever, K_forever
|
||||
fork, K_fork
|
||||
function, K_function
|
||||
highz0, K_highz0
|
||||
highz1, K_highz1
|
||||
if, K_if
|
||||
initial, K_initial
|
||||
inout, K_inout
|
||||
input, K_input
|
||||
integer, K_integer
|
||||
join, K_join
|
||||
large, K_large
|
||||
macromodule, K_macromodule
|
||||
medium, K_medium
|
||||
module, K_module
|
||||
nand, K_nand
|
||||
negedge, K_negedge
|
||||
nmos, K_nmos
|
||||
nor, K_nor
|
||||
not, K_not
|
||||
notif0, K_notif0
|
||||
notif1, K_notif1
|
||||
or, K_or
|
||||
output, K_output
|
||||
parameter, K_parameter
|
||||
pmos, K_pmos
|
||||
posedge, K_posedge
|
||||
primitive, K_primitive
|
||||
pull0, K_pull0
|
||||
pull1, K_pull1
|
||||
pulldown, K_pulldown
|
||||
pullup, K_pullup
|
||||
rcmos, K_rcmos
|
||||
reg, K_reg
|
||||
release, K_release
|
||||
repeat, K_repeat
|
||||
rnmos, K_rnmos
|
||||
rpmos, K_rpmos
|
||||
rtran, K_rtran
|
||||
rtranif0, K_rtranif0
|
||||
rtranif1, K_rtranif1
|
||||
scalered, K_scalered
|
||||
small, K_small
|
||||
specify, K_specify
|
||||
specparam, K_specparam
|
||||
strong0, K_strong0
|
||||
strong1, K_strong1
|
||||
supply0, K_supply0
|
||||
supply1, K_supply1
|
||||
table, K_table
|
||||
task, K_task
|
||||
time, K_time
|
||||
tran, K_tran
|
||||
tranif0, K_tranif0
|
||||
tranif1, K_tranif1
|
||||
tri, K_tri
|
||||
tri0, K_tri0
|
||||
tri1, K_tri1
|
||||
triand, K_triand
|
||||
trior, K_trior
|
||||
trireg, K_trireg
|
||||
vectored, K_vectored
|
||||
wait, K_wait
|
||||
wand, K_wand
|
||||
weak0, K_weak0
|
||||
weak1, K_weak1
|
||||
while, K_while
|
||||
wire, K_wire
|
||||
wor, K_wor
|
||||
xnor, K_xnor
|
||||
xor, K_xor
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
WHAT IS LPM
|
||||
|
||||
LPM (Library of Paramaterized Modules) is EIS-IS standard 103-A. It is
|
||||
a standard library of abstract devices that are designed to be close
|
||||
enough to the target hardware to be easily translated, yet abstract
|
||||
enough to support a variety of target technologies without excessive
|
||||
constraints. Icarus Verilog uses LPM internally to represent idealized
|
||||
hardware, especially when doing target neutral synthesis.
|
||||
|
||||
In general, the user does not even see the LPM that Icarus Verilog
|
||||
generates, because the LPM devices are translated into technology
|
||||
specific devices by the final code generator or target specific
|
||||
optimizers.
|
||||
|
||||
INTERNAL USES OF LPM
|
||||
|
||||
Internally, Icarus Verilog uses LPM devices to represent the design in
|
||||
abstract, especially when synthesizing such functions as addition,
|
||||
flip-flops, etc. The ``synth'' functor generates LPM modules when
|
||||
interpreting procedural constructs. The functor generates the LPM
|
||||
objects needed to replace a behavioral description, and uses
|
||||
attributes to tag the devices with LPM properties.
|
||||
|
||||
Code generators need to understand the supported LPM devices so that
|
||||
they can translate the devices into technology specific devices.
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-1999 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1998-2000 Stephen Williams ([email protected])";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -18,8 +18,8 @@ const char COPYRIGHT[] =
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: main.cc,v 1.22 1999/08/03 04:14:49 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: main.cc,v 1.29 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
const char NOTICE[] =
|
||||
@@ -44,6 +44,9 @@ const char NOTICE[] =
|
||||
# include <queue>
|
||||
# include <map>
|
||||
# include <unistd.h>
|
||||
#if defined(HAVE_GETOPT_H)
|
||||
# include <getopt.h>
|
||||
#endif
|
||||
# include "pform.h"
|
||||
# include "netlist.h"
|
||||
# include "target.h"
|
||||
@@ -75,12 +78,12 @@ static void parm_to_flagmap(const string&flag)
|
||||
extern Design* elaborate(const map<string,Module*>&modules,
|
||||
const map<string,PUdp*>&primitives,
|
||||
const string&root);
|
||||
extern void emit(ostream&o, const Design*, const char*);
|
||||
|
||||
extern void cprop(Design*des);
|
||||
extern void propinit(Design*des);
|
||||
extern void sigfold(Design*des);
|
||||
extern void synth(Design*des);
|
||||
extern void nobufz(Design*des);
|
||||
extern void nodangle(Design*des);
|
||||
extern void xnfio(Design*des);
|
||||
extern void xnfsyn(Design*des);
|
||||
|
||||
@@ -91,8 +94,9 @@ static struct net_func_map {
|
||||
} func_table[] = {
|
||||
{ "cprop", &cprop },
|
||||
{ "nobufz", &nobufz },
|
||||
{ "propinit", &propinit },
|
||||
{ "sigfold", &sigfold },
|
||||
{ "nodangle",&nodangle },
|
||||
{ "propinit",&propinit },
|
||||
{ "synth", &synth },
|
||||
{ "xnfio", &xnfio },
|
||||
{ "xnfsyn", &xnfsyn },
|
||||
{ 0, 0 }
|
||||
@@ -118,7 +122,9 @@ int main(int argc, char*argv[])
|
||||
unsigned flag_errors = 0;
|
||||
queue<net_func> net_func_queue;
|
||||
|
||||
while ((opt = getopt(argc, argv, "F:f:hN:o:P:s:t:v")) != EOF) switch (opt) {
|
||||
flags["VPI_MODULE_LIST"] = "system";
|
||||
|
||||
while ((opt = getopt(argc, argv, "F:f:hm:N:o:P:s:t:v")) != EOF) switch (opt) {
|
||||
case 'F': {
|
||||
net_func tmp = name_to_net_func(optarg);
|
||||
if (tmp == 0) {
|
||||
@@ -136,6 +142,9 @@ int main(int argc, char*argv[])
|
||||
case 'h':
|
||||
help_flag = true;
|
||||
break;
|
||||
case 'm':
|
||||
flags["VPI_MODULE_LIST"] = flags["VPI_MODULE_LIST"]+","+optarg;
|
||||
break;
|
||||
case 'N':
|
||||
net_path = optarg;
|
||||
break;
|
||||
@@ -252,6 +261,7 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
|
||||
|
||||
bool emit_rc;
|
||||
if (out_path) {
|
||||
ofstream out;
|
||||
out.open(out_path);
|
||||
@@ -261,10 +271,15 @@ int main(int argc, char*argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
emit(out, des, target);
|
||||
emit_rc = emit(out, des, target);
|
||||
|
||||
} else {
|
||||
emit(cout, des, target);
|
||||
emit_rc = emit(cout, des, target);
|
||||
}
|
||||
|
||||
if (!emit_rc) {
|
||||
cerr << "internal error: Code generation had errors." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -272,6 +287,31 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.29 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.28 2000/01/13 05:11:25 steve
|
||||
* Support for multiple VPI modules.
|
||||
*
|
||||
* Revision 1.27 1999/12/30 17:37:14 steve
|
||||
* Remove the now useless sigfold functor.
|
||||
*
|
||||
* Revision 1.26 1999/11/29 17:02:21 steve
|
||||
* include getopt if present.
|
||||
*
|
||||
* Revision 1.25 1999/11/18 03:52:19 steve
|
||||
* Turn NetTmp objects into normal local NetNet objects,
|
||||
* and add the nodangle functor to clean up the local
|
||||
* symbols generated by elaboration and other steps.
|
||||
*
|
||||
* Revision 1.24 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.23 1999/09/22 16:57:23 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
*
|
||||
* Revision 1.22 1999/08/03 04:14:49 steve
|
||||
* Parse into pform arbitrarily complex module
|
||||
* port declarations.
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: mangle.cc,v 1.2 1999/02/15 05:52:50 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: mangle.cc,v 1.3 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -63,6 +63,9 @@ string mangle(const string&str)
|
||||
|
||||
/*
|
||||
* $Log: mangle.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/02/15 05:52:50 steve
|
||||
* Mangle that handles device instance numbers.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef __named_H
|
||||
#define __named_H
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: named.h,v 1.2 2000/02/23 02:56:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
|
||||
/*
|
||||
* There are lots of places where names are attached to objects. This
|
||||
* simple template expresses the lot.
|
||||
*/
|
||||
|
||||
template <class T> struct named {
|
||||
string name;
|
||||
T parm;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: named.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+1865
-402
File diff suppressed because it is too large
Load Diff
+79
-11
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: netlist.txt,v 1.3 1999/07/24 02:11:20 steve Exp $"
|
||||
#ident "$Id: netlist.txt,v 1.7 1999/11/28 23:42:02 steve Exp $"
|
||||
|
||||
|
||||
Note that the netlist.h header contains detailed descriptions of how
|
||||
@@ -53,14 +53,39 @@ in the vector.
|
||||
Node and net pins can be connected together via the connect
|
||||
function. Connections are transitive (A==B and B==c means A==C) so
|
||||
connections accumulate on a link as items are connected to it. The
|
||||
descructors for nets and nodes automatically arrange for pins to be
|
||||
destructors for nets and nodes automatically arrange for pins to be
|
||||
disconnected when the item is deleted, so that the netlist can be
|
||||
changed during processing.
|
||||
|
||||
STRUCTURAL LINKS
|
||||
|
||||
The NetNode and NetNet classes contain arrays of Link objects, one
|
||||
object per pin. Each pin is a single bit. The Link objects link
|
||||
circularly to all the NetNode and NetNet objects' links that are
|
||||
connected together in the design. This way, code that examines a node
|
||||
of the design can discover what is connected to each pin.
|
||||
|
||||
See the NetObj::Link class definition for a description of the link
|
||||
methods.
|
||||
|
||||
Currently, a link has 3 possible direction properties:
|
||||
|
||||
PASSIVE -- These pins are sampled by the object that holds the
|
||||
pin based on some external event. These are used,
|
||||
for example, by NetESignal objects that read a
|
||||
point for a procedural expression.
|
||||
|
||||
INPUT -- These pins potentially react to the setting of its
|
||||
input.
|
||||
|
||||
OUTPUT -- These pins potentially drive the node. (They may be
|
||||
three-state.)
|
||||
|
||||
|
||||
BEHAVIORAL ITEMS: NetProcTop, NetProc and derived classes
|
||||
|
||||
Behavioral items are not in general linked to the netlist. Instead,
|
||||
they represent elabrated behavioral statements. The type of the object
|
||||
they represent elaborated behavioral statements. The type of the object
|
||||
implies what the behavior of the statement does. For example, a
|
||||
NetCondit object represents an ``if'' statement, and carries a
|
||||
condition expression and up to two alternative sub-statements.
|
||||
@@ -89,6 +114,35 @@ and a NetProc. The NetAssign_ node has pins that represent the l-value
|
||||
of the statement, and carries behavioral expressions that represent
|
||||
the r-value of the assignment.
|
||||
|
||||
MEMORIES
|
||||
|
||||
The netlist form includes the NetMemory type to hold the content of a
|
||||
memory. Instances of this type represent the declaration of a memory,
|
||||
and occur once for each memory. References to the memory are managed
|
||||
by the NetEMemory and NetAssignMem_ classes.
|
||||
|
||||
An instance of the NetEMemory class is created whenever a procedural
|
||||
expression references a memory element. The operand is the index to
|
||||
use to address (and read) the memory.
|
||||
|
||||
An instance of the NetAssignMem_ class is created when there is a
|
||||
procedural assignment to the memory. The NetAssignMem_ object
|
||||
represents the l-value reference (a write) to the memory. As with the
|
||||
NetEMemory class, this is a procedural reference only.
|
||||
|
||||
When a memory reference appears in structural context (i.e. continuous
|
||||
assignments) elaboration creates a NetRamDq. This is a LPM_RAM_DQ
|
||||
device. Elaboration leaves the write control and data input pins
|
||||
unconnected for now, because memories cannot appear is l-values of
|
||||
continuous assignments. However, the synthesis functor may connect
|
||||
signals to the write control lines to get a fully operational RAM.
|
||||
|
||||
By the time elaboration completes, there may be many NetAssignMem_,
|
||||
NetEMemory and NetRamDq objects referencing the same NetMemory
|
||||
object. Each represents a port into the memory. It is up to the
|
||||
synthesis steps (and the target code) to figure out what to do with
|
||||
these ports.
|
||||
|
||||
EXPRESSIONS
|
||||
|
||||
Expressions are represented as a tree of NetExpr nodes. The NetExpr
|
||||
@@ -105,7 +159,7 @@ structurally as events are like devices that trigger behavioral
|
||||
statements.
|
||||
|
||||
However, typical expressions the behavioral description are
|
||||
represented as a tree of NetExpr nodes. The derived clas of the node
|
||||
represented as a tree of NetExpr nodes. The derived class of the node
|
||||
encodes what kind of operator the node represents.
|
||||
|
||||
EXPRESSION BIT WIDTH
|
||||
@@ -150,17 +204,14 @@ INTERACTION OF EXPRESSIONS AND STRUCTURE: NetESignal
|
||||
The NetAssign_ class described above is the means for processes to
|
||||
manipulate the net, but values are read from the net by NetESignal
|
||||
objects. These objects are class NetExpr because they can appear in
|
||||
expressions (and have width) but are also class NetNode because they
|
||||
connect to and receive signals from the structural aspects of the
|
||||
design.
|
||||
expressions (and have width). They are not NetNode object, but hold
|
||||
pointers to a NetNet object, which is used to retrieve values with the
|
||||
expression is evaluated.
|
||||
|
||||
The pins of a NetESignal object are passive. The values at the pin are
|
||||
only sampled when the process evaluates the expression that includes
|
||||
the NetESignal object.
|
||||
|
||||
HIERARCHY IN NETLISTS
|
||||
|
||||
The obvious hierarchical structure of verilog is the module. The
|
||||
The obvious hierarchical structure of Verilog is the module. The
|
||||
Verilog program may contain any number of instantiations of modules in
|
||||
order to form an hierarchical design. However, the elaboration of the
|
||||
design into a netlist erases module boundaries. Modules are expanded
|
||||
@@ -189,6 +240,23 @@ some task calls. C++ programmers recognize this as inlining a task.)
|
||||
|
||||
|
||||
$Log: netlist.txt,v $
|
||||
Revision 1.7 1999/11/28 23:42:02 steve
|
||||
NetESignal object no longer need to be NetNode
|
||||
objects. Let them keep a pointer to NetNet objects.
|
||||
|
||||
Revision 1.6 1999/11/21 00:13:09 steve
|
||||
Support memories in continuous assignments.
|
||||
|
||||
Revision 1.5 1999/11/02 04:55:34 steve
|
||||
Add the synthesize method to NetExpr to handle
|
||||
synthesis of expressions, and use that method
|
||||
to improve r-value handling of LPM_FF synthesis.
|
||||
|
||||
Modify the XNF target to handle LPM_FF objects.
|
||||
|
||||
Revision 1.4 1999/09/29 00:03:27 steve
|
||||
Spelling fixes from Larry.
|
||||
|
||||
Revision 1.3 1999/07/24 02:11:20 steve
|
||||
Elaborate task input ports.
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef __netmisc_H
|
||||
#define __netmisc_H
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: netmisc.h,v 1.3 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
/*
|
||||
* This funciton transforms an expression by padding the high bits
|
||||
* with V0 until the expression has the desired width. This may mean
|
||||
* not transforming the expression at all, if it is already wide
|
||||
* enough.
|
||||
*/
|
||||
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid);
|
||||
extern NetNet*pad_to_width(Design*des, const string&p, NetNet*n, unsigned w);
|
||||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.3 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.1 1999/09/29 00:42:51 steve
|
||||
* Allow expanding of additive operators.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: nobufz.cc,v 1.1 1998/12/02 04:37:13 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: nobufz.cc,v 1.2 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/* NOBUFZ Function
|
||||
@@ -61,6 +61,9 @@ void nobufz(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: nobufz.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1998/12/02 04:37:13 steve
|
||||
* Add the nobufz function to eliminate bufz objects,
|
||||
* Object links are marked with direction,
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: nodangle.cc,v 1.3 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This functor scans the design looking for dangling objects and
|
||||
* excess local signals. These deletions are not necessarily required
|
||||
* for proper functioning of anything, but they can clean up the
|
||||
* appearance of design files that are generated.
|
||||
*/
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
|
||||
class nodangle_f : public functor_t {
|
||||
public:
|
||||
void signal(Design*des, NetNet*sig);
|
||||
};
|
||||
|
||||
|
||||
void nodangle_f::signal(Design*des, NetNet*sig)
|
||||
{
|
||||
if (! sig->local_flag())
|
||||
return;
|
||||
if (sig->get_eref() > 0)
|
||||
return;
|
||||
|
||||
/* Check to see if there is some significant signal connected
|
||||
to every pin of this signal. */
|
||||
unsigned significant_flags = 0;
|
||||
for (unsigned idx = 0 ; idx < sig->pin_count() ; idx += 1) {
|
||||
NetObj::Link&lnk = sig->pin(idx);
|
||||
for (NetObj::Link*cur = lnk.next_link()
|
||||
; cur != &lnk ; cur = cur->next_link()) {
|
||||
NetNet*cursig = dynamic_cast<NetNet*>(cur->get_obj());
|
||||
if (cursig == 0)
|
||||
continue;
|
||||
if (cursig->local_flag())
|
||||
continue;
|
||||
significant_flags += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If every pin is connected to another significant signal,
|
||||
then I can delete this one. */
|
||||
if (significant_flags == sig->pin_count())
|
||||
delete sig;
|
||||
}
|
||||
|
||||
void nodangle(Design*des)
|
||||
{
|
||||
nodangle_f fun;
|
||||
des->functor(&fun);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: nodangle.cc,v $
|
||||
* Revision 1.3 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/11/28 23:42:02 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
*
|
||||
* Revision 1.1 1999/11/18 03:52:20 steve
|
||||
* Turn NetTmp objects into normal local NetNet objects,
|
||||
* and add the nodangle functor to clean up the local
|
||||
* symbols generated by elaboration and other steps.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pad_to_width.cc,v 1.4 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
/*
|
||||
* This funciton transforms an expression by padding the high bits
|
||||
* with V0 until the expression has the desired width. This may mean
|
||||
* not transforming the expression at all, if it is already wide
|
||||
* enough.
|
||||
*/
|
||||
NetExpr*pad_to_width(NetExpr*expr, unsigned wid)
|
||||
{
|
||||
if (wid > expr->expr_width()) {
|
||||
verinum pad(verinum::V0, wid - expr->expr_width());
|
||||
NetEConst*co = new NetEConst(pad);
|
||||
co->set_line(*expr);
|
||||
NetEConcat*cc = new NetEConcat(2);
|
||||
cc->set_line(*expr);
|
||||
cc->set(0, co);
|
||||
cc->set(1, expr);
|
||||
cc->set_width(wid);
|
||||
expr = cc;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
NetNet*pad_to_width(Design*des, const string&path, NetNet*net, unsigned wid)
|
||||
{
|
||||
if (net->pin_count() >= wid)
|
||||
return net;
|
||||
|
||||
verinum pad(verinum::V0, wid - net->pin_count());
|
||||
NetConst*con = new NetConst(des->local_symbol(path), pad);
|
||||
des->add_node(con);
|
||||
|
||||
NetNet*tmp = new NetNet(0, des->local_symbol(path), NetNet::WIRE, wid);
|
||||
tmp->local_flag(true);
|
||||
des->add_signal(tmp);
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
connect(tmp->pin(idx), net->pin(idx));
|
||||
for (unsigned idx = net->pin_count() ; idx < wid ; idx += 1)
|
||||
connect(tmp->pin(idx), con->pin(idx-net->pin_count()));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: pad_to_width.cc,v $
|
||||
* Revision 1.4 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 2000/02/16 03:58:27 steve
|
||||
* Fix up width matching in structural bitwise operators.
|
||||
*
|
||||
* Revision 1.2 2000/01/01 06:17:25 steve
|
||||
* Propogate line number information when expanding expressions.
|
||||
*
|
||||
* Revision 1.1 1999/09/29 00:42:51 steve
|
||||
* Allow expanding of additive operators.
|
||||
*
|
||||
*/
|
||||
|
||||
+10
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: parse_misc.cc,v 1.2 1998/11/07 17:05:05 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse_misc.cc,v 1.4 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "parse_misc.h"
|
||||
@@ -48,7 +48,7 @@ void yywarn(const YYLTYPE&loc, const char*msg)
|
||||
if (loc.text)
|
||||
cerr << loc.text << ":";
|
||||
|
||||
cerr << loc.first_line << ": warning -- " << msg << endl;
|
||||
cerr << loc.first_line << ": warning: " << msg << endl;
|
||||
}
|
||||
|
||||
int VLwrap()
|
||||
@@ -58,6 +58,12 @@ int VLwrap()
|
||||
|
||||
/*
|
||||
* $Log: parse_misc.cc,v $
|
||||
* Revision 1.4 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/09/29 21:15:31 steve
|
||||
* Standardize formatting of warning messages.
|
||||
*
|
||||
* Revision 1.2 1998/11/07 17:05:05 steve
|
||||
* Handle procedural conditional, and some
|
||||
* of the conditional expressions.
|
||||
|
||||
+6
-3
@@ -1,7 +1,7 @@
|
||||
#ifndef __parse_misc_H
|
||||
#define __parse_misc_H
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: parse_misc.h,v 1.3 1999/07/10 01:03:18 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse_misc.h,v 1.4 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -53,6 +53,9 @@ extern unsigned error_count, warn_count;
|
||||
|
||||
/*
|
||||
* $Log: parse_misc.h,v $
|
||||
* Revision 1.4 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/07/10 01:03:18 steve
|
||||
* remove string from lexical phase.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: pform.cc,v 1.37 1999/08/03 04:14:49 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pform.cc,v 1.54 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "compiler.h"
|
||||
@@ -42,7 +42,9 @@ static Module*pform_cur_module = 0;
|
||||
/*
|
||||
* The scope stack and the following functions handle the processing
|
||||
* of scope. As I enter a scope, the push function is called, and as I
|
||||
* leave a scope the opo function is called.
|
||||
* leave a scope the pop function is called.
|
||||
*
|
||||
* The top module is not included in the scope list.
|
||||
*/
|
||||
struct scope_name_t {
|
||||
string name;
|
||||
@@ -97,6 +99,15 @@ static unsigned long evaluate_delay(PExpr*delay)
|
||||
void pform_startmodule(const string&name, svector<Module::port_t*>*ports)
|
||||
{
|
||||
assert( pform_cur_module == 0 );
|
||||
|
||||
/* The parser parses ``module foo()'' as having one
|
||||
unconnected port, but it is really a module with no
|
||||
ports. Fix it up here. */
|
||||
if (ports && (ports->count() == 1) && ((*ports)[0] == 0)) {
|
||||
delete ports;
|
||||
ports = 0;
|
||||
}
|
||||
|
||||
pform_cur_module = new Module(name, ports);
|
||||
delete ports;
|
||||
}
|
||||
@@ -292,11 +303,15 @@ void pform_makegates(PGBuiltin::Type type,
|
||||
|
||||
/*
|
||||
* A module is different from a gate in that there are different
|
||||
* constraints, and sometimes different syntax.
|
||||
* constraints, and sometimes different syntax. The X_modgate
|
||||
* functions handle the instantaions of modules (and UDP objects) by
|
||||
* making PGModule objects.
|
||||
*/
|
||||
static void pform_make_modgate(const string&type,
|
||||
const string&name,
|
||||
struct parmvalue_t*overrides,
|
||||
svector<PExpr*>*wires,
|
||||
PExpr*msb, PExpr*lsb,
|
||||
const string&fn, unsigned ln)
|
||||
{
|
||||
if (name == "") {
|
||||
@@ -306,15 +321,35 @@ static void pform_make_modgate(const string&type,
|
||||
return;
|
||||
}
|
||||
|
||||
PGate*cur = new PGModule(type, name, wires);
|
||||
PGModule*cur = new PGModule(type, name, wires);
|
||||
cur->set_file(fn);
|
||||
cur->set_lineno(ln);
|
||||
cur->set_range(msb,lsb);
|
||||
|
||||
if (overrides && overrides->by_name) {
|
||||
unsigned cnt = overrides->by_name->count();
|
||||
named<PExpr*>*byname = new named<PExpr*>[cnt];
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
portname_t*curp = (*overrides->by_name)[idx];
|
||||
byname[idx].name = curp->name;
|
||||
byname[idx].parm = curp->parm;
|
||||
}
|
||||
|
||||
cur->set_parameters(byname, cnt);
|
||||
|
||||
} else if (overrides && overrides->by_order) {
|
||||
cur->set_parameters(overrides->by_order);
|
||||
}
|
||||
|
||||
pform_cur_module->add_gate(cur);
|
||||
}
|
||||
|
||||
static void pform_make_modgate(const string&type,
|
||||
const string&name,
|
||||
struct parmvalue_t*overrides,
|
||||
svector<portname_t*>*bind,
|
||||
PExpr*msb, PExpr*lsb,
|
||||
const string&fn, unsigned ln)
|
||||
{
|
||||
if (name == "") {
|
||||
@@ -325,35 +360,70 @@ static void pform_make_modgate(const string&type,
|
||||
}
|
||||
|
||||
unsigned npins = bind->count();
|
||||
PGModule::bind_t*pins = new PGModule::bind_t[npins];
|
||||
named<PExpr*>*pins = new named<PExpr*>[npins];
|
||||
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
|
||||
portname_t*curp = (*bind)[idx];
|
||||
pins[idx].name = curp->name;
|
||||
pins[idx].parm = curp->parm;
|
||||
}
|
||||
|
||||
PGate*cur = new PGModule(type, name, pins, npins);
|
||||
PGModule*cur = new PGModule(type, name, pins, npins);
|
||||
cur->set_file(fn);
|
||||
cur->set_lineno(ln);
|
||||
cur->set_range(msb,lsb);
|
||||
|
||||
if (overrides && overrides->by_name) {
|
||||
unsigned cnt = overrides->by_name->count();
|
||||
named<PExpr*>*byname = new named<PExpr*>[cnt];
|
||||
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
portname_t*curp = (*overrides->by_name)[idx];
|
||||
byname[idx].name = curp->name;
|
||||
byname[idx].parm = curp->parm;
|
||||
}
|
||||
|
||||
cur->set_parameters(byname, cnt);
|
||||
|
||||
} else if (overrides && overrides->by_order) {
|
||||
|
||||
cur->set_parameters(overrides->by_order);
|
||||
}
|
||||
|
||||
pform_cur_module->add_gate(cur);
|
||||
}
|
||||
|
||||
void pform_make_modgates(const string&type, svector<lgate>*gates)
|
||||
void pform_make_modgates(const string&type,
|
||||
struct parmvalue_t*overrides,
|
||||
svector<lgate>*gates)
|
||||
{
|
||||
if (overrides && overrides->by_order)
|
||||
for (unsigned idx = 0 ; idx < overrides->by_order->count() ; idx += 1)
|
||||
if (! pform_expression_is_constant((*overrides->by_order)[idx])) {
|
||||
VLerror("error: Parameter override expression"
|
||||
" must be constant.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < gates->count() ; idx += 1) {
|
||||
lgate cur = (*gates)[idx];
|
||||
|
||||
if (cur.parms_by_name) {
|
||||
pform_make_modgate(type, cur.name, cur.parms_by_name,
|
||||
pform_make_modgate(type, cur.name, overrides,
|
||||
cur.parms_by_name,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.file, cur.lineno);
|
||||
|
||||
} else if (cur.parms) {
|
||||
pform_make_modgate(type, cur.name, cur.parms, cur.file,
|
||||
cur.lineno);
|
||||
pform_make_modgate(type, cur.name, overrides,
|
||||
cur.parms,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.file, cur.lineno);
|
||||
} else {
|
||||
svector<PExpr*>*wires = new svector<PExpr*>(0);
|
||||
pform_make_modgate(type, cur.name, wires, cur.file,
|
||||
cur.lineno);
|
||||
pform_make_modgate(type, cur.name, overrides,
|
||||
wires,
|
||||
cur.range[0], cur.range[1],
|
||||
cur.file, cur.lineno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,6 +448,60 @@ PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
return cur;
|
||||
}
|
||||
|
||||
void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
svector<PExpr*>*del,
|
||||
const string& text,
|
||||
unsigned lineno)
|
||||
{
|
||||
PGAssign*tmp;
|
||||
for (unsigned idx = 0 ; idx < alist->count()/2 ; idx += 1) {
|
||||
tmp = pform_make_pgassign((*alist)[2*idx],
|
||||
(*alist)[2*idx+1], del);
|
||||
tmp->set_file(text);
|
||||
tmp->set_lineno(lineno);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this function makes the initial assignment to a register as given
|
||||
* in the source. It handles the case where a reg variable is assigned
|
||||
* where it it declared:
|
||||
*
|
||||
* reg foo = <expr>;
|
||||
*
|
||||
* This is equivilent to the combination of statements:
|
||||
*
|
||||
* reg foo;
|
||||
* initital foo = <expr>;
|
||||
*
|
||||
* and that is how it is parsed. This syntax is not part of the
|
||||
* IEEE1364-1994 standard, but is approved by OVI as enhancement
|
||||
* BTF-B14.
|
||||
*/
|
||||
void pform_make_reginit(const struct vlltype&li,
|
||||
const string&name, PExpr*expr)
|
||||
{
|
||||
const string sname = scoped_name(name);
|
||||
PWire*cur = pform_cur_module->get_wire(sname);
|
||||
if (cur == 0) {
|
||||
VLerror(li, "internal error: reginit to non-register?");
|
||||
delete expr;
|
||||
return;
|
||||
}
|
||||
|
||||
PEIdent*lval = new PEIdent(sname);
|
||||
lval->set_file(li.text);
|
||||
lval->set_lineno(li.first_line);
|
||||
PAssign*ass = new PAssign(lval, expr);
|
||||
ass->set_file(li.text);
|
||||
ass->set_lineno(li.first_line);
|
||||
PProcess*top = new PProcess(PProcess::PR_INITIAL, ass);
|
||||
top->set_file(li.text);
|
||||
top->set_lineno(li.first_line);
|
||||
|
||||
pform_cur_module->add_behavior(top);
|
||||
}
|
||||
|
||||
void pform_makewire(const vlltype&li, const string&nm,
|
||||
NetNet::Type type)
|
||||
{
|
||||
@@ -387,7 +511,7 @@ void pform_makewire(const vlltype&li, const string&nm,
|
||||
if (cur->get_wire_type() != NetNet::IMPLICIT) {
|
||||
strstream msg;
|
||||
msg << name << " previously defined at " <<
|
||||
cur->get_line() << ".";
|
||||
cur->get_line() << "." << ends;
|
||||
VLerror(msg.str());
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
@@ -465,8 +589,11 @@ void pform_set_port_type(const string&name, NetNet::PortType pt)
|
||||
*/
|
||||
svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
const svector<PExpr*>*range,
|
||||
const list<string>*names)
|
||||
const list<string>*names,
|
||||
const string& file,
|
||||
unsigned lineno)
|
||||
{
|
||||
assert(names);
|
||||
svector<PWire*>*res = new svector<PWire*>(0);
|
||||
for (list<string>::const_iterator cur = names->begin()
|
||||
; cur != names->end() ; cur ++ ) {
|
||||
@@ -480,6 +607,8 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt);
|
||||
curw->set_file(file);
|
||||
curw->set_lineno(lineno);
|
||||
pform_cur_module->add_wire(curw);
|
||||
}
|
||||
|
||||
@@ -500,16 +629,37 @@ void pform_set_task(const string&name, PTask*task)
|
||||
pform_cur_module->add_task(name, task);
|
||||
}
|
||||
|
||||
void pform_set_function(const string&name, PFunction *func)
|
||||
/*
|
||||
* This function is called to fill out the definition of the function
|
||||
* with the trappings that are discovered after the basic function
|
||||
* name is parsed.
|
||||
*/
|
||||
void pform_set_function(const string&name, svector<PExpr*>*ra, PFunction *func)
|
||||
{
|
||||
PWire*out = new PWire(name+"."+name, NetNet::REG, NetNet::POUTPUT);
|
||||
if (ra) {
|
||||
assert(ra->count() == 2);
|
||||
out->set_range((*ra)[0], (*ra)[1]);
|
||||
delete ra;
|
||||
}
|
||||
pform_cur_module->add_wire(out);
|
||||
func->set_output(out);
|
||||
pform_cur_module->add_function(name, func);
|
||||
}
|
||||
|
||||
void pform_set_attrib(const string&name, const string&key, const string&value)
|
||||
{
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
assert(cur);
|
||||
cur->attributes[key] = value;
|
||||
if (PWire*cur = pform_cur_module->get_wire(name)) {
|
||||
cur->attributes[key] = value;
|
||||
|
||||
} else if (PGate*cur = pform_cur_module->get_gate(name)) {
|
||||
cur->attributes[key] = value;
|
||||
|
||||
} else {
|
||||
VLerror("Unable to match name for setting attribute.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -536,21 +686,26 @@ void pform_set_reg_idx(const string&name, PExpr*l, PExpr*r)
|
||||
{
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur == 0) {
|
||||
VLerror("name is not a valid net.");
|
||||
VLerror(" error: name is not a valid net.");
|
||||
return;
|
||||
}
|
||||
|
||||
cur->set_memory_idx(l, r);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function attaches a range to a given name. The function is
|
||||
* only called by the parser within the scope of the net declaration,
|
||||
* and the name that I receive only has the tail component.
|
||||
*/
|
||||
static void pform_set_net_range(const string&name, const svector<PExpr*>*range)
|
||||
{
|
||||
assert(range);
|
||||
assert(range->count() == 2);
|
||||
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = pform_cur_module->get_wire(scoped_name(name));
|
||||
if (cur == 0) {
|
||||
VLerror("name is not a valid net.");
|
||||
VLerror(" error: name is not a valid net.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -573,6 +728,7 @@ void pform_set_net_range(list<string>*names, const svector<PExpr*>*range)
|
||||
void pform_set_parameter(const string&name, PExpr*expr)
|
||||
{
|
||||
pform_cur_module->parameters[name] = expr;
|
||||
pform_cur_module->param_names.push_back(name);
|
||||
}
|
||||
|
||||
void pform_set_port_type(list<string>*names, NetNet::PortType pt)
|
||||
@@ -584,12 +740,18 @@ void pform_set_port_type(list<string>*names, NetNet::PortType pt)
|
||||
}
|
||||
}
|
||||
|
||||
static void pform_set_reg_integer(const string&name)
|
||||
static void pform_set_reg_integer(const string&nm)
|
||||
{
|
||||
string name = scoped_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::INTEGER, NetNet::NOT_A_PORT);
|
||||
pform_cur_module->add_wire(cur);
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::INTEGER);
|
||||
assert(rc);
|
||||
}
|
||||
assert(cur);
|
||||
bool rc = cur->set_wire_type(NetNet::INTEGER);
|
||||
assert(rc);
|
||||
|
||||
cur->set_range(new PENumber(new verinum(INTEGER_WIDTH-1, INTEGER_WIDTH)),
|
||||
new PENumber(new verinum(0UL, INTEGER_WIDTH)));
|
||||
@@ -634,7 +796,10 @@ int pform_parse(const char*path, map<string,Module*>&modules,
|
||||
map<string,PUdp*>&prim)
|
||||
{
|
||||
vl_file = path;
|
||||
vl_input = fopen(path, "r");
|
||||
if (strcmp(path, "-") == 0)
|
||||
vl_input = stdin;
|
||||
else
|
||||
vl_input = fopen(path, "r");
|
||||
if (vl_input == 0) {
|
||||
cerr << "Unable to open " <<vl_file << "." << endl;
|
||||
return 11;
|
||||
@@ -655,158 +820,60 @@ int pform_parse(const char*path, map<string,Module*>&modules,
|
||||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.54 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.53 2000/02/18 05:15:03 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.52 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.51 2000/01/02 01:59:28 steve
|
||||
* Forgot to handle no overrides at all.
|
||||
*
|
||||
* Revision 1.50 2000/01/01 23:47:58 steve
|
||||
* Fix module parameter override syntax.
|
||||
*
|
||||
* Revision 1.49 1999/12/30 19:06:14 steve
|
||||
* Support reg initial assignment syntax.
|
||||
*
|
||||
* Revision 1.48 1999/12/11 05:45:41 steve
|
||||
* Fix support for attaching attributes to primitive gates.
|
||||
*
|
||||
* Revision 1.47 1999/11/23 01:04:57 steve
|
||||
* A file name of - means standard input.
|
||||
*
|
||||
* Revision 1.46 1999/09/30 01:22:37 steve
|
||||
* Handle declaration of integers (including scope) in functions.
|
||||
*
|
||||
* Revision 1.45 1999/09/21 00:58:33 steve
|
||||
* Get scope right when setting the net range.
|
||||
*
|
||||
* Revision 1.44 1999/09/17 02:06:26 steve
|
||||
* Handle unconnected module ports.
|
||||
*
|
||||
* Revision 1.43 1999/09/15 01:55:06 steve
|
||||
* Elaborate non-blocking assignment to memories.
|
||||
*
|
||||
* Revision 1.42 1999/09/10 05:02:09 steve
|
||||
* Handle integers at task parameters.
|
||||
*
|
||||
* Revision 1.41 1999/08/31 22:38:29 steve
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
* Revision 1.40 1999/08/27 15:08:37 steve
|
||||
* continuous assignment lists.
|
||||
*
|
||||
* Revision 1.39 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
* Revision 1.38 1999/08/23 16:48:39 steve
|
||||
* Parameter overrides support from Peter Monta
|
||||
* AND and XOR support wide expressions.
|
||||
*
|
||||
* Revision 1.37 1999/08/03 04:14:49 steve
|
||||
* Parse into pform arbitrarily complex module
|
||||
* port declarations.
|
||||
*
|
||||
* Revision 1.36 1999/08/01 16:34:50 steve
|
||||
* Parse and elaborate rise/fall/decay times
|
||||
* for gates, and handle the rules for partial
|
||||
* lists of times.
|
||||
*
|
||||
* Revision 1.35 1999/07/31 19:15:21 steve
|
||||
* misspelled comment.
|
||||
*
|
||||
* Revision 1.34 1999/07/31 19:14:47 steve
|
||||
* Add functions up to elaboration (Ed Carter)
|
||||
*
|
||||
* Revision 1.33 1999/07/24 02:11:20 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.32 1999/07/10 01:03:18 steve
|
||||
* remove string from lexical phase.
|
||||
*
|
||||
* Revision 1.31 1999/07/03 02:12:52 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
* Revision 1.30 1999/06/24 04:24:18 steve
|
||||
* Handle expression widths for EEE and NEE operators,
|
||||
* add named blocks and scope handling,
|
||||
* add registers declared in named blocks.
|
||||
*
|
||||
* Revision 1.29 1999/06/21 01:02:16 steve
|
||||
* Fix merging of UDP port type in decls.
|
||||
*
|
||||
* Revision 1.28 1999/06/17 05:34:42 steve
|
||||
* Clean up interface of the PWire class,
|
||||
* Properly match wire ranges.
|
||||
*
|
||||
* Revision 1.27 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
* Revision 1.26 1999/06/13 23:51:16 steve
|
||||
* l-value part select for procedural assignments.
|
||||
*
|
||||
* Revision 1.25 1999/06/12 20:35:27 steve
|
||||
* parse more verilog.
|
||||
*
|
||||
* Revision 1.24 1999/06/12 03:42:17 steve
|
||||
* Assert state of bit range expressions.
|
||||
*
|
||||
* Revision 1.23 1999/06/06 20:45:39 steve
|
||||
* Add parse and elaboration of non-blocking assignments,
|
||||
* Replace list<PCase::Item*> with an svector version,
|
||||
* Add integer support.
|
||||
*
|
||||
* Revision 1.22 1999/06/02 15:38:46 steve
|
||||
* Line information with nets.
|
||||
*
|
||||
* Revision 1.21 1999/05/31 15:45:59 steve
|
||||
* makegates infinite loop fixed.
|
||||
*
|
||||
* Revision 1.20 1999/05/29 02:36:17 steve
|
||||
* module parameter bind by name.
|
||||
*
|
||||
* Revision 1.19 1999/05/20 04:31:45 steve
|
||||
* Much expression parsing work,
|
||||
* mark continuous assigns with source line info,
|
||||
* replace some assertion failures with Sorry messages.
|
||||
*
|
||||
* Revision 1.18 1999/05/16 05:08:42 steve
|
||||
* Redo constant expression detection to happen
|
||||
* after parsing.
|
||||
*
|
||||
* Parse more operators and expressions.
|
||||
*
|
||||
* Revision 1.17 1999/05/10 00:16:58 steve
|
||||
* Parse and elaborate the concatenate operator
|
||||
* in structural contexts, Replace vector<PExpr*>
|
||||
* and list<PExpr*> with svector<PExpr*>, evaluate
|
||||
* constant expressions with parameters, handle
|
||||
* memories as lvalues.
|
||||
*
|
||||
* Parse task declarations, integer types.
|
||||
*
|
||||
* Revision 1.16 1999/05/08 20:19:20 steve
|
||||
* Parse more things.
|
||||
*
|
||||
* Revision 1.15 1999/05/07 04:26:49 steve
|
||||
* Parse more complex continuous assign lvalues.
|
||||
*
|
||||
* Revision 1.14 1999/05/06 04:37:17 steve
|
||||
* Get rid of list<lgate> types.
|
||||
*
|
||||
* Revision 1.13 1999/05/06 04:09:28 steve
|
||||
* Parse more constant expressions.
|
||||
*
|
||||
* Revision 1.12 1999/05/02 23:25:32 steve
|
||||
* Enforce module instance names.
|
||||
*
|
||||
* Revision 1.11 1999/04/19 01:59:37 steve
|
||||
* Add memories to the parse and elaboration phases.
|
||||
*
|
||||
* Revision 1.10 1999/02/21 17:01:57 steve
|
||||
* Add support for module parameters.
|
||||
*
|
||||
* Revision 1.9 1999/02/15 02:06:15 steve
|
||||
* Elaborate gate ranges.
|
||||
*
|
||||
* Revision 1.8 1999/01/25 05:45:56 steve
|
||||
* Add the LineInfo class to carry the source file
|
||||
* location of things. PGate, Statement and PProcess.
|
||||
*
|
||||
* elaborate handles module parameter mismatches,
|
||||
* missing or incorrect lvalues for procedural
|
||||
* assignment, and errors are propogated to the
|
||||
* top of the elaboration call tree.
|
||||
*
|
||||
* Attach line numbers to processes, gates and
|
||||
* assignment statements.
|
||||
*
|
||||
* Revision 1.7 1998/12/09 04:02:47 steve
|
||||
* Support the include directive.
|
||||
*
|
||||
* Revision 1.6 1998/12/01 00:42:14 steve
|
||||
* Elaborate UDP devices,
|
||||
* Support UDP type attributes, and
|
||||
* pass those attributes to nodes that
|
||||
* are instantiated by elaboration,
|
||||
* Put modules into a map instead of
|
||||
* a simple list.
|
||||
*
|
||||
* Revision 1.5 1998/11/25 02:35:53 steve
|
||||
* Parse UDP primitives all the way to pform.
|
||||
*
|
||||
* Revision 1.4 1998/11/23 00:20:23 steve
|
||||
* NetAssign handles lvalues as pin links
|
||||
* instead of a signal pointer,
|
||||
* Wire attributes added,
|
||||
* Ability to parse UDP descriptions added,
|
||||
* XNF generates EXT records for signals with
|
||||
* the PAD attribute.
|
||||
*
|
||||
* Revision 1.3 1998/11/11 00:01:51 steve
|
||||
* Check net ranges in declarations.
|
||||
*
|
||||
* Revision 1.2 1998/11/07 17:05:06 steve
|
||||
* Handle procedural conditional, and some
|
||||
* of the conditional expressions.
|
||||
*
|
||||
* Elaborate signals and identifiers differently,
|
||||
* allowing the netlist to hold signal information.
|
||||
*
|
||||
* Revision 1.1 1998/11/03 23:29:03 steve
|
||||
* Introduce verilog to CVS.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __pform_H
|
||||
#define __pform_H
|
||||
/*
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,11 +18,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: pform.h,v 1.27 1999/08/03 04:14:49 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pform.h,v 1.35 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "named.h"
|
||||
# include "Module.h"
|
||||
# include "Statement.h"
|
||||
# include "PGate.h"
|
||||
@@ -65,9 +66,12 @@ struct vlltype;
|
||||
|
||||
/* This is information about port name information for named port
|
||||
connections. */
|
||||
struct portname_t {
|
||||
string name;
|
||||
PExpr*parm;
|
||||
|
||||
typedef struct named<PExpr*> portname_t;
|
||||
|
||||
struct parmvalue_t {
|
||||
svector<PExpr*>*by_order;
|
||||
svector<portname_t*>*by_name;
|
||||
};
|
||||
|
||||
/* The lgate is gate instantiation information. */
|
||||
@@ -116,12 +120,14 @@ extern void pform_makewire(const struct vlltype&li, const string&name,
|
||||
NetNet::Type type = NetNet::IMPLICIT);
|
||||
extern void pform_makewire(const struct vlltype&li, const list<string>*names,
|
||||
NetNet::Type type);
|
||||
extern void pform_make_reginit(const struct vlltype&li,
|
||||
const string&name, PExpr*expr);
|
||||
extern void pform_set_port_type(list<string>*names, NetNet::PortType);
|
||||
extern void pform_set_net_range(list<string>*names, const svector<PExpr*>*);
|
||||
extern void pform_set_reg_idx(const string&name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_integer(list<string>*names);
|
||||
extern void pform_set_task(const string&, PTask*);
|
||||
extern void pform_set_function(const string&, PFunction*);
|
||||
extern void pform_set_function(const string&, svector<PExpr*>*, PFunction*);
|
||||
extern void pform_set_attrib(const string&name, const string&key,
|
||||
const string&value);
|
||||
extern void pform_set_type_attrib(const string&name, const string&key,
|
||||
@@ -141,18 +147,25 @@ extern void pform_makegates(PGBuiltin::Type type,
|
||||
svector<PExpr*>*delay,
|
||||
svector<lgate>*gates);
|
||||
|
||||
extern void pform_make_modgates(const string&type, svector<lgate>*gates);
|
||||
extern void pform_make_modgates(const string&type,
|
||||
struct parmvalue_t*overrides,
|
||||
svector<lgate>*gates);
|
||||
|
||||
/* Make a continuous assignment node, with optional bit- or part- select. */
|
||||
extern PGAssign* pform_make_pgassign(PExpr*lval, PExpr*rval,
|
||||
svector<PExpr*>*delays);
|
||||
|
||||
extern void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
svector<PExpr*>*del,
|
||||
const string& text,
|
||||
unsigned lineno);
|
||||
|
||||
/* Given a port type and a list of names, make a list of wires that
|
||||
can be used as task port information. */
|
||||
extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
const svector<PExpr*>*range,
|
||||
const list<string>*names);
|
||||
const list<string>*names,
|
||||
const string& file,
|
||||
unsigned lineno);
|
||||
|
||||
|
||||
/*
|
||||
@@ -167,6 +180,31 @@ extern void pform_dump(ostream&out, Module*mod);
|
||||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.35 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.34 2000/01/10 22:16:24 steve
|
||||
* minor type syntax fix for stubborn C++ compilers.
|
||||
*
|
||||
* Revision 1.33 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.32 1999/12/30 19:06:14 steve
|
||||
* Support reg initial assignment syntax.
|
||||
*
|
||||
* Revision 1.31 1999/09/10 05:02:09 steve
|
||||
* Handle integers at task parameters.
|
||||
*
|
||||
* Revision 1.30 1999/08/27 15:08:37 steve
|
||||
* continuous assignment lists.
|
||||
*
|
||||
* Revision 1.29 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
* Revision 1.28 1999/08/23 16:48:39 steve
|
||||
* Parameter overrides support from Peter Monta
|
||||
* AND and XOR support wide expressions.
|
||||
*
|
||||
* Revision 1.27 1999/08/03 04:14:49 steve
|
||||
* Parse into pform arbitrarily complex module
|
||||
* port declarations.
|
||||
|
||||
+155
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: pform_dump.cc,v 1.34 1999/08/03 04:49:13 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: pform_dump.cc,v 1.49 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -37,6 +37,12 @@ ostream& operator << (ostream&out, const PExpr&obj)
|
||||
return out;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&o, const PDelays&d)
|
||||
{
|
||||
d.dump_delays(o);
|
||||
return o;
|
||||
}
|
||||
|
||||
void PExpr::dump(ostream&out) const
|
||||
{
|
||||
out << typeid(*this).name();
|
||||
@@ -65,7 +71,7 @@ void PECallFunction::dump(ostream &out) const
|
||||
{
|
||||
out << name_ << "(";
|
||||
parms_[0]->dump(out);
|
||||
for (unsigned idx = 0; idx < parms_.count(); ++idx) {
|
||||
for (unsigned idx = 1; idx < parms_.count(); ++idx) {
|
||||
out << ", ";
|
||||
parms_[idx]->dump(out);
|
||||
}
|
||||
@@ -126,6 +132,9 @@ void PEBinary::dump(ostream&out) const
|
||||
{
|
||||
out << "(" << *left_ << ")";
|
||||
switch (op_) {
|
||||
case 'a':
|
||||
out << "&&";
|
||||
break;
|
||||
case 'e':
|
||||
out << "==";
|
||||
break;
|
||||
@@ -209,7 +218,7 @@ void PGate::dump_pins(ostream&out) const
|
||||
}
|
||||
}
|
||||
|
||||
void PGate::dump_delays(ostream&out) const
|
||||
void PDelays::dump_delays(ostream&out) const
|
||||
{
|
||||
if (delay_[0] && delay_[1] && delay_[2])
|
||||
out << "#(" << *delay_[0] << "," << *delay_[1] << "," <<
|
||||
@@ -221,10 +230,15 @@ void PGate::dump_delays(ostream&out) const
|
||||
|
||||
}
|
||||
|
||||
void PGate::dump_delays(ostream&out) const
|
||||
{
|
||||
delay_.dump_delays(out);
|
||||
}
|
||||
|
||||
void PGate::dump(ostream&out) const
|
||||
{
|
||||
out << " " << typeid(*this).name() << " ";
|
||||
dump_delays(out);
|
||||
delay_.dump_delays(out);
|
||||
out << " " << get_name() << "(";
|
||||
dump_pins(out);
|
||||
out << ");" << endl;
|
||||
@@ -268,12 +282,52 @@ void PGBuiltin::dump(ostream&out) const
|
||||
|
||||
void PGModule::dump(ostream&out) const
|
||||
{
|
||||
out << " " << type_ << " " << get_name() << "(";
|
||||
out << " " << type_ << " ";
|
||||
|
||||
// If parameters are overridden by order, dump them.
|
||||
if (overrides_) {
|
||||
assert(parms_ == 0);
|
||||
out << "#(";
|
||||
out << *((*overrides_)[0]);
|
||||
for (unsigned idx = 1 ; idx < overrides_->count() ; idx += 1) {
|
||||
out << "," << *((*overrides_)[idx]);
|
||||
}
|
||||
out << ") ";
|
||||
}
|
||||
|
||||
// If parameters are overridden by name, dump them.
|
||||
if (parms_) {
|
||||
assert(overrides_ == 0);
|
||||
out << "#(";
|
||||
out << "." << parms_[0].name << "(" << *parms_[0].parm << ")";
|
||||
for (unsigned idx = 1 ; idx < nparms_ ; idx += 1) {
|
||||
out << ", ." << parms_[idx].name << "(" <<
|
||||
*parms_[idx].parm << ")";
|
||||
}
|
||||
out << ") ";
|
||||
}
|
||||
|
||||
out << get_name();
|
||||
|
||||
// If the module is arrayed, print the index expressions.
|
||||
if (msb_ || lsb_) {
|
||||
out << "[";
|
||||
if (msb_) out << *msb_;
|
||||
out << ":";
|
||||
if (lsb_) out << *lsb_;
|
||||
out << "]";
|
||||
}
|
||||
|
||||
out << "(";
|
||||
if (pins_) {
|
||||
out << "." << pins_[0].name << "(" << *pins_[0].parm << ")";
|
||||
out << "." << pins_[0].name << "(";
|
||||
if (pins_[0].parm) out << *pins_[0].parm;
|
||||
out << ")";
|
||||
for (unsigned idx = 1 ; idx < npins_ ; idx += 1) {
|
||||
out << ", ." << pins_[idx].name << "(" <<
|
||||
*pins_[idx].parm << ")";
|
||||
out << ", ." << pins_[idx].name << "(";
|
||||
if (pins_[idx].parm)
|
||||
out << *pins_[idx].parm;
|
||||
out << ")";
|
||||
}
|
||||
} else {
|
||||
dump_pins(out);
|
||||
@@ -294,18 +348,14 @@ void Statement::dump(ostream&out, unsigned ind) const
|
||||
void PAssign::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "";
|
||||
out << *lval() << " = ";
|
||||
if (delay()) out << "#" << *delay() << " ";
|
||||
out << *rval() << ";";
|
||||
out << *lval() << " = " << delay_ << " " << *rval() << ";";
|
||||
out << " /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void PAssignNB::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "";
|
||||
out << *lval() << " <= ";
|
||||
if (delay()) out << "#" << *delay() << " ";
|
||||
out << *rval() << ";";
|
||||
out << *lval() << " <= " << delay_ << " " << *rval() << ";";
|
||||
out << " /* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
@@ -317,7 +367,10 @@ void PBlock::dump(ostream&out, unsigned ind) const
|
||||
out << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {
|
||||
list_[idx]->dump(out, ind+2);
|
||||
if (list_[idx])
|
||||
list_[idx]->dump(out, ind+2);
|
||||
else
|
||||
out << setw(ind+2) << "" << "/* NOOP */ ;" << endl;
|
||||
}
|
||||
|
||||
out << setw(ind) << "" << "end" << endl;
|
||||
@@ -345,8 +398,19 @@ void PCallTask::dump(ostream&out, unsigned ind) const
|
||||
|
||||
void PCase::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "case (" << *expr_ << ") /* " <<
|
||||
get_line() << " */" << endl;
|
||||
out << setw(ind) << "";
|
||||
switch (type_) {
|
||||
case NetCase::EQ:
|
||||
out << "case";
|
||||
break;
|
||||
case NetCase::EQX:
|
||||
out << "casex";
|
||||
break;
|
||||
case NetCase::EQZ:
|
||||
out << "casez";
|
||||
break;
|
||||
}
|
||||
out << " (" << *expr_ << ") /* " << get_line() << " */" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
||||
PCase::Item*cur = (*items_)[idx];
|
||||
@@ -377,7 +441,10 @@ void PCase::dump(ostream&out, unsigned ind) const
|
||||
void PCondit::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "if (" << *expr_ << ")" << endl;
|
||||
if_->dump(out, ind+3);
|
||||
if (if_)
|
||||
if_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind) << ";" << endl;
|
||||
if (else_) {
|
||||
out << setw(ind) << "" << "else" << endl;
|
||||
else_->dump(out, ind+3);
|
||||
@@ -430,13 +497,17 @@ void PForStatement::dump(ostream&out, unsigned ind) const
|
||||
|
||||
void PFunction::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "output " << out_->name() << ";" << endl;
|
||||
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
||||
out << setw(ind) << "";
|
||||
out << "input ";
|
||||
out << (*ports_)[idx]->name() << ";" << endl;
|
||||
}
|
||||
|
||||
statement_->dump(out, ind);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind);
|
||||
else
|
||||
out << setw(ind) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PRepeat::dump(ostream&out, unsigned ind) const
|
||||
@@ -464,7 +535,10 @@ void PTask::dump(ostream&out, unsigned ind) const
|
||||
out << (*ports_)[idx]->name() << ";" << endl;
|
||||
}
|
||||
|
||||
statement_->dump(out, ind);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind);
|
||||
else
|
||||
out << setw(ind) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -496,6 +570,12 @@ void Module::dump(ostream&out) const
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
port_t*cur = ports_[idx];
|
||||
|
||||
if (cur == 0) {
|
||||
out << " unconnected" << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cur->wires[0]->get_port_type()) {
|
||||
case NetNet::PINPUT:
|
||||
out << " input ." << cur->name << "(";
|
||||
@@ -522,16 +602,19 @@ void Module::dump(ostream&out) const
|
||||
typedef map<string,PExpr*>::const_iterator parm_iter_t;
|
||||
for (parm_iter_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
out << " parameter " << (*cur).first << " = " <<
|
||||
*(*cur).second << ";" << endl;
|
||||
out << " parameter " << (*cur).first << " = ";
|
||||
if ((*cur).second)
|
||||
out << *(*cur).second << ";" << endl;
|
||||
else
|
||||
out << "/* ERROR */;" << endl;
|
||||
}
|
||||
|
||||
// Iterate through and display all the wires.
|
||||
for (list<PWire*>::const_iterator wire = wires_.begin()
|
||||
for (map<string,PWire*>::const_iterator wire = wires_.begin()
|
||||
; wire != wires_.end()
|
||||
; wire ++ ) {
|
||||
|
||||
(*wire)->dump(out);
|
||||
(*wire).second->dump(out);
|
||||
}
|
||||
|
||||
// Dump the task definitions.
|
||||
@@ -619,6 +702,52 @@ void PUdp::dump(ostream&out) const
|
||||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.49 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.48 2000/02/18 05:15:03 steve
|
||||
* Catch module instantiation arrays.
|
||||
*
|
||||
* Revision 1.47 2000/01/09 20:37:57 steve
|
||||
* Careful with wires connected to multiple ports.
|
||||
*
|
||||
* Revision 1.46 2000/01/09 05:50:49 steve
|
||||
* Support named parameter override lists.
|
||||
*
|
||||
* Revision 1.45 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
* Revision 1.44 1999/09/30 02:43:02 steve
|
||||
* Elaborate ~^ and ~| operators.
|
||||
*
|
||||
* Revision 1.43 1999/09/30 00:48:50 steve
|
||||
* Cope with errors during ternary operator elaboration.
|
||||
*
|
||||
* Revision 1.42 1999/09/29 21:15:58 steve
|
||||
* Handle some mor missing names.
|
||||
*
|
||||
* Revision 1.41 1999/09/29 20:23:53 steve
|
||||
* Handle empty named ports in the dump.
|
||||
*
|
||||
* Revision 1.40 1999/09/29 18:36:04 steve
|
||||
* Full case support
|
||||
*
|
||||
* Revision 1.39 1999/09/17 02:06:26 steve
|
||||
* Handle unconnected module ports.
|
||||
*
|
||||
* Revision 1.38 1999/09/08 02:24:39 steve
|
||||
* Empty conditionals (pmonta@imedia.com)
|
||||
*
|
||||
* Revision 1.37 1999/09/04 19:11:46 steve
|
||||
* Add support for delayed non-blocking assignments.
|
||||
*
|
||||
* Revision 1.36 1999/08/25 22:22:41 steve
|
||||
* elaborate some aspects of functions.
|
||||
*
|
||||
* Revision 1.35 1999/08/23 16:48:39 steve
|
||||
* Parameter overrides support from Peter Monta
|
||||
* AND and XOR support wide expressions.
|
||||
*
|
||||
* Revision 1.34 1999/08/03 04:49:13 steve
|
||||
* Proper port type names.
|
||||
*
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: propinit.cc,v 1.1 1998/12/20 02:05:41 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: propinit.cc,v 1.2 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -81,6 +81,9 @@ void propinit(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: propinit.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1998/12/20 02:05:41 steve
|
||||
* Function to calculate wire initial value.
|
||||
*
|
||||
|
||||
+307
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: set_width.cc,v 1.9 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file contains set_width methods for the various NetExpr
|
||||
* classes. The set_width method is used by elaboration to ask the
|
||||
* expression to resize itself. If the expression can't, then the
|
||||
* set_width method will return false and the caller will arrange for
|
||||
* whatever is needed to deal with the size mismatch.
|
||||
*/
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include <typeinfo>
|
||||
|
||||
|
||||
bool NetExpr::set_width(unsigned w)
|
||||
{
|
||||
cerr << typeid(*this).name() << ": set_width(unsigned) "
|
||||
"not implemented." << endl;
|
||||
expr_width(w);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetEBinary::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
switch (op_) {
|
||||
|
||||
case 'l': // left shift (<<)
|
||||
case 'r': // right shift (>>)
|
||||
flag = left_->set_width(w);
|
||||
expr_width(w);
|
||||
break;
|
||||
|
||||
/* The default rule is that the operands of the binary
|
||||
operator might as well use the same width as the
|
||||
output from the binary operation. */
|
||||
default:
|
||||
expr_width(left_->expr_width() > right_->expr_width()
|
||||
? left_->expr_width() : right_->expr_width());
|
||||
cerr << "NetEBinary::set_width(): Using default for " <<
|
||||
op_ << "." << endl;
|
||||
flag = false;
|
||||
|
||||
case '%':
|
||||
case '/':
|
||||
flag = left_->set_width(w) && flag;
|
||||
flag = right_->set_width(w) && flag;
|
||||
expr_width(w);
|
||||
break;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* The bitwise logical operators have operands the same size as the
|
||||
* result. Anything else is a mess.
|
||||
*/
|
||||
bool NetEBAdd::set_width(unsigned w)
|
||||
{
|
||||
|
||||
unsigned wid = w;
|
||||
if (left_->expr_width() > wid)
|
||||
wid = left_->expr_width();
|
||||
if (right_->expr_width() > wid)
|
||||
wid = right_->expr_width();
|
||||
|
||||
left_->set_width(wid);
|
||||
right_->set_width(wid);
|
||||
|
||||
if (left_->expr_width() < wid) {
|
||||
NetExpr*tmp = pad_to_width(left_, wid);
|
||||
assert(tmp);
|
||||
left_ = tmp;
|
||||
}
|
||||
|
||||
if (right_->expr_width() < wid) {
|
||||
NetExpr*tmp = pad_to_width(right_, wid);
|
||||
assert(tmp);
|
||||
right_ = tmp;
|
||||
}
|
||||
|
||||
expr_width(wid);
|
||||
return wid == w;
|
||||
}
|
||||
|
||||
/*
|
||||
* The bitwise logical operators have operands the same size as the
|
||||
* result. Anything else is a mess.
|
||||
*/
|
||||
bool NetEBBits::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
flag = left_->set_width(w) && flag;
|
||||
flag = right_->set_width(w) && flag;
|
||||
if (flag)
|
||||
expr_width(w);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Comparison operators allow the subexpressions to have
|
||||
* their own natural width, but the comparison operator result has a
|
||||
* fixed width of 1.
|
||||
*/
|
||||
bool NetEBComp::set_width(unsigned w)
|
||||
{
|
||||
return (w == 1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* There is nothing we can do to the operands of a multiply to make it
|
||||
* confirm to the requested width. Force the context to pad or truncate.
|
||||
*/
|
||||
bool NetEBMult::set_width(unsigned w)
|
||||
{
|
||||
return w == expr_width();
|
||||
}
|
||||
|
||||
/*
|
||||
* The shift operator allows the shift amount to have its own
|
||||
* natural width. The width of the operator result is the width of the
|
||||
* left operand, the value that is to be shifted.
|
||||
*/
|
||||
bool NetEBShift::set_width(unsigned w)
|
||||
{
|
||||
bool flag;
|
||||
flag = left_->set_width(w);
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add up the widths from all the expressions that are concatenated
|
||||
* together. This is the width of the expression, tough luck if you
|
||||
* want it otherwise.
|
||||
*
|
||||
* If during the course of elaboration one of the sub-expressions is
|
||||
* broken, then don't count it in the width. This doesn't really
|
||||
* matter because the null expression is indication of an error and
|
||||
* the compiler will not go beyond elaboration.
|
||||
*/
|
||||
bool NetEConcat::set_width(unsigned w)
|
||||
{
|
||||
unsigned sum = 0;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||
if (parms_[idx] != 0)
|
||||
sum += parms_[idx]->expr_width();
|
||||
|
||||
sum *= repeat_;
|
||||
expr_width(sum);
|
||||
if (sum != w) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEConst::set_width(unsigned w)
|
||||
{
|
||||
if (w > value_.len()) {
|
||||
verinum tmp (verinum::V0, w);
|
||||
for (unsigned idx = 0 ; idx < value_.len() ; idx += 1)
|
||||
tmp.set(idx, value_[idx]);
|
||||
|
||||
value_ = tmp;
|
||||
|
||||
} else {
|
||||
verinum tmp (verinum::V0, w);
|
||||
for (unsigned idx = 0 ; idx < w ; idx += 1)
|
||||
tmp.set(idx, value_[idx]);
|
||||
|
||||
value_ = tmp;
|
||||
}
|
||||
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEMemory::set_width(unsigned w)
|
||||
{
|
||||
if (w != mem_->width())
|
||||
return false;
|
||||
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEParam::set_width(unsigned)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The signal should automatically pad with zeros to get to th desired
|
||||
* width. Do not allow signal bits to be truncated, however.
|
||||
*/
|
||||
bool NetESignal::set_width(unsigned w)
|
||||
{
|
||||
if (w != pin_count())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetESubSignal::set_width(unsigned w)
|
||||
{
|
||||
if (w != 1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetETernary::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
flag = flag && true_val_->set_width(w);
|
||||
flag = flag && false_val_->set_width(w);
|
||||
expr_width(true_val_->expr_width());
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXX FIX ME: For now, just take whatever the caller says as my
|
||||
* width. What I really need to do is note the width of the output
|
||||
* parameter of the function definition and take that into account.
|
||||
*/
|
||||
bool NetEUFunc::set_width(unsigned wid)
|
||||
{
|
||||
expr_width(wid);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEUnary::set_width(unsigned w)
|
||||
{
|
||||
bool flag = true;
|
||||
switch (op_) {
|
||||
case '~':
|
||||
case '-':
|
||||
flag = expr_->set_width(w);
|
||||
break;
|
||||
default:
|
||||
flag = expr_width() == w;
|
||||
break;
|
||||
}
|
||||
expr_width(w);
|
||||
return flag;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.9 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.8 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.7 2000/01/01 19:56:51 steve
|
||||
* Properly expand/shrink constants in expressions.
|
||||
*
|
||||
* Revision 1.6 1999/10/05 06:19:46 steve
|
||||
* Add support for reduction NOR.
|
||||
*
|
||||
* Revision 1.5 1999/10/05 04:02:10 steve
|
||||
* Relaxed width handling for <= assignment.
|
||||
*
|
||||
* Revision 1.4 1999/09/29 00:42:51 steve
|
||||
* Allow expanding of additive operators.
|
||||
*
|
||||
* Revision 1.3 1999/09/23 03:56:57 steve
|
||||
* Support shift operators.
|
||||
*
|
||||
* Revision 1.2 1999/09/23 02:27:50 steve
|
||||
* comparison parameter width is self determined.
|
||||
*
|
||||
* Revision 1.1 1999/09/23 00:21:55 steve
|
||||
* Move set_width methods into a single file,
|
||||
* Add the NetEBLogic class for logic expressions,
|
||||
* Fix error setting with of && in if statements.
|
||||
*
|
||||
*/
|
||||
|
||||
-168
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: sigfold.cc,v 1.2 1998/12/02 04:37:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
/*
|
||||
* Some targets require that a list of connections include exactly one
|
||||
* signal. This processing step deletes excess signals to meet that
|
||||
* requirement.
|
||||
*
|
||||
* If there is a ring that has more then one signal connected
|
||||
* together, the following heuristic is used to choose which signal to
|
||||
* keep:
|
||||
*
|
||||
* If the name of signal X is deeper in the design hierarchy then
|
||||
* signal Y, keep signal Y.
|
||||
*
|
||||
* Else, if X is a bus that is not as wide as Y, keep signal Y.
|
||||
*
|
||||
* The result of this should be that signals of enclosing modules will
|
||||
* be preferred over signals of instantiated modules, and bussed
|
||||
* signals (vectors) will be preferred over scaler signals.
|
||||
*
|
||||
* The presence of attributes modifies the folding process, by placing
|
||||
* restrictions on what is allowed.
|
||||
*
|
||||
* If two signals have an attribute key X, they can be folded
|
||||
* only if X has the same value for both signals.
|
||||
*
|
||||
* If signal A has attribute X and signal B does not, then
|
||||
* signals can be folded if B can take the attribute.
|
||||
*
|
||||
* All the pins in a vector have identical attributes.
|
||||
*/
|
||||
|
||||
static unsigned depth(const string&sym)
|
||||
{
|
||||
unsigned cnt = 0;
|
||||
for (unsigned idx = 0 ; idx < sym.length() ; idx += 1)
|
||||
if (sym[idx] == '.')
|
||||
cnt += 1;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static bool is_any_signal(const NetNet*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void clear_extra_signals(NetNet*net, unsigned npin)
|
||||
{
|
||||
const unsigned mydepth = depth(net->name());
|
||||
NetObj*cur = net;
|
||||
unsigned pin = npin;
|
||||
for (net->pin(pin).next_link(cur, pin) ; cur != net ; ) {
|
||||
|
||||
// sig is the node I am going to try to subsume.
|
||||
NetNet*sig = dynamic_cast<NetNet*>(cur);
|
||||
|
||||
// Skip the node if it isn't even a signal.
|
||||
if (sig == 0) {
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip the node if it has incompatible attributes.
|
||||
if (! net->has_compat_attributes(*sig)) {
|
||||
|
||||
// SPECIAL CASE!
|
||||
if (sig->has_compat_attributes(*net)) {
|
||||
net->pin(npin).unlink();
|
||||
return;
|
||||
}
|
||||
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip the node if it is higher up.
|
||||
if (depth(sig->name()) < mydepth) {
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip the node if it is a larger vector.
|
||||
if (sig->pin_count() > net->pin_count()) {
|
||||
cur->pin(pin).next_link(cur, pin);
|
||||
continue;
|
||||
}
|
||||
|
||||
// save the next link, ...
|
||||
NetObj*nxt;
|
||||
unsigned pnxt;
|
||||
cur->pin(pin).next_link(nxt, pnxt);
|
||||
|
||||
// disconnect the target signal, ...
|
||||
sig->pin(pin).unlink();
|
||||
|
||||
// And onward.
|
||||
cur = nxt;
|
||||
pin = pnxt;
|
||||
}
|
||||
}
|
||||
|
||||
static void delete_if_unconnected(NetNet*net)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
if (net->pin(idx).is_linked())
|
||||
return;
|
||||
|
||||
delete net;
|
||||
}
|
||||
|
||||
void sigfold(Design*des)
|
||||
{
|
||||
des->clear_signal_marks();
|
||||
while (NetNet*obj = des->find_signal(&is_any_signal)) {
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1)
|
||||
clear_extra_signals(obj, idx);
|
||||
obj->set_mark();
|
||||
}
|
||||
|
||||
// After the disconnect step, I may have signals that are not
|
||||
// connected to anything. Delete those.
|
||||
|
||||
des->clear_signal_marks();
|
||||
while (NetNet*obj = des->find_signal(&is_any_signal)) {
|
||||
obj->set_mark();
|
||||
delete_if_unconnected(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sigfold.cc,v $
|
||||
* Revision 1.2 1998/12/02 04:37:13 steve
|
||||
* Add the nobufz function to eliminate bufz objects,
|
||||
* Object links are marked with direction,
|
||||
* constant propagation is more careful will wide links,
|
||||
* Signal folding is aware of attributes, and
|
||||
* the XNF target can dump UDP objects based on LCA
|
||||
* attributes.
|
||||
*
|
||||
* Revision 1.1 1998/11/16 05:03:53 steve
|
||||
* Add the sigfold function that unlinks excess
|
||||
* signal nodes, and add the XNF target.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: sref.h,v 1.4 1999/08/05 04:58:17 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sref.h,v 1.5 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <assert.h>
|
||||
@@ -146,6 +146,9 @@ template <class T1, class T2> void sref_back<T1,T2>::desert_(sref<T1,T2>*item)
|
||||
|
||||
/*
|
||||
* $Log: sref.h,v $
|
||||
* Revision 1.5 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 1999/08/05 04:58:17 steve
|
||||
* Fix compile error with gcc 2.95
|
||||
*
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: svector.h,v 1.4 1999/06/15 03:44:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: svector.h,v 1.5 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <assert.h>
|
||||
@@ -97,6 +97,9 @@ template <class TYPE> class svector {
|
||||
|
||||
/*
|
||||
* $Log: svector.h,v $
|
||||
* Revision 1.5 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 1999/06/15 03:44:53 steve
|
||||
* Get rid of the STL vector template.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: synth.cc,v 1.6 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The synth function searches the behavioral description for
|
||||
* patterns that are known to represent LPM library components. This
|
||||
* is especially interesting for the sequential components such as
|
||||
* flip flops and latches. As threads are transformed into components,
|
||||
* the design is rewritten.
|
||||
*/
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
|
||||
/*
|
||||
* This transform recognizes the following patterns:
|
||||
*
|
||||
* always @(posedge CLK) Q = D
|
||||
* always @(negedge CLK) Q = D
|
||||
*
|
||||
* always @(posedge CLK) if (CE) Q = D;
|
||||
* always @(negedge CLK) if (CE) Q = D;
|
||||
*
|
||||
* These are memory assignments:
|
||||
*
|
||||
* always @(posedge CLK) M[a] = D
|
||||
* always @(negedge CLK) M[a] = D
|
||||
*
|
||||
* always @(posedge CLK) if (CE) M[a] = D;
|
||||
* always @(negedge CLK) if (CE) M[a] = D;
|
||||
*
|
||||
* The r-value of the assignments must be identifiers (i.e. wires or
|
||||
* registers) and the CE must be single-bit identifiers. The generated
|
||||
* device will be wide enough to accomodate Q and D.
|
||||
*/
|
||||
class match_dff : public proc_match_t {
|
||||
|
||||
public:
|
||||
match_dff(Design*d, NetProcTop*t)
|
||||
: des_(d), top_(t), pclk_(0), nclk_(0), con_(0), ce_(0),
|
||||
asn_(0), asm_(0), d_(0)
|
||||
{ }
|
||||
|
||||
~match_dff() { }
|
||||
|
||||
void make_it();
|
||||
|
||||
private:
|
||||
void make_dff_();
|
||||
void make_ram_();
|
||||
|
||||
virtual int assign(NetAssign*);
|
||||
virtual int assign_mem(NetAssignMem*);
|
||||
virtual int condit(NetCondit*);
|
||||
virtual int pevent(NetPEvent*);
|
||||
|
||||
Design*des_;
|
||||
NetProcTop*top_;
|
||||
NetPEvent*pclk_;
|
||||
NetNEvent*nclk_;
|
||||
|
||||
NetCondit *con_;
|
||||
NetNet*ce_;
|
||||
|
||||
NetAssign *asn_;
|
||||
NetAssignMem*asm_;
|
||||
|
||||
NetNet*d_;
|
||||
};
|
||||
|
||||
int match_dff::assign(NetAssign*as)
|
||||
{
|
||||
if (!pclk_)
|
||||
return 0;
|
||||
if (asn_ || asm_)
|
||||
return 0;
|
||||
|
||||
asn_ = as;
|
||||
d_ = asn_->rval()->synthesize(des_);
|
||||
if (d_ == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int match_dff::assign_mem(NetAssignMem*as)
|
||||
{
|
||||
if (!pclk_)
|
||||
return 0;
|
||||
if (asn_ || asm_)
|
||||
return 0;
|
||||
|
||||
asm_ = as;
|
||||
d_ = asm_->rval()->synthesize(des_);
|
||||
if (d_ == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int match_dff::condit(NetCondit*co)
|
||||
{
|
||||
if (!pclk_)
|
||||
return 0;
|
||||
if (con_ || asn_ || asm_)
|
||||
return 0;
|
||||
|
||||
con_ = co;
|
||||
if (con_->else_clause())
|
||||
return 0;
|
||||
ce_ = con_->expr()->synthesize(des_);
|
||||
if (ce_ == 0)
|
||||
return 0;
|
||||
|
||||
return con_->if_clause()->match_proc(this);
|
||||
}
|
||||
|
||||
int match_dff::pevent(NetPEvent*pe)
|
||||
{
|
||||
if (pclk_ || con_ || asn_ || asm_)
|
||||
return 0;
|
||||
|
||||
pclk_ = pe;
|
||||
|
||||
// ... there must be a single event source, ...
|
||||
svector<class NetNEvent*>*neb = pclk_->back_list();
|
||||
if (neb == 0)
|
||||
return 0;
|
||||
if (neb->count() != 1) {
|
||||
delete neb;
|
||||
return 0;
|
||||
}
|
||||
nclk_ = (*neb)[0];
|
||||
delete neb;
|
||||
return pclk_->statement()->match_proc(this);
|
||||
}
|
||||
|
||||
void match_dff::make_it()
|
||||
{
|
||||
if (asn_) {
|
||||
assert(asm_ == 0);
|
||||
make_dff_();
|
||||
} else {
|
||||
assert(asm_);
|
||||
make_ram_();
|
||||
}
|
||||
}
|
||||
|
||||
void match_dff::make_dff_()
|
||||
{
|
||||
NetFF*ff = new NetFF(asn_->name(), asn_->pin_count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < ff->width() ; idx += 1) {
|
||||
connect(ff->pin_Data(idx), d_->pin(idx));
|
||||
connect(ff->pin_Q(idx), asn_->pin(idx));
|
||||
}
|
||||
|
||||
connect(ff->pin_Clock(), nclk_->pin(0));
|
||||
if (ce_) connect(ff->pin_Enable(), ce_->pin(0));
|
||||
|
||||
ff->attribute("LPM_FFType", "DFF");
|
||||
if (nclk_->type() == NetNEvent::NEGEDGE)
|
||||
ff->attribute("Clock:LPM_Polarity", "INVERT");
|
||||
|
||||
des_->add_node(ff);
|
||||
}
|
||||
|
||||
void match_dff::make_ram_()
|
||||
{
|
||||
NetMemory*mem = asm_->memory();
|
||||
NetNet*adr = asm_->index();
|
||||
NetRamDq*ram = new NetRamDq(des_->local_symbol(mem->name()), mem,
|
||||
adr->pin_count());
|
||||
for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
|
||||
connect(adr->pin(idx), ram->pin_Address(idx));
|
||||
|
||||
for (unsigned idx = 0 ; idx < ram->width() ; idx += 1)
|
||||
connect(ram->pin_Data(idx), d_->pin(idx));
|
||||
|
||||
if (ce_)
|
||||
connect(ram->pin_WE(), ce_->pin(0));
|
||||
|
||||
assert(nclk_->type() == NetNEvent::POSEDGE);
|
||||
connect(ram->pin_InClock(), nclk_->pin(0));
|
||||
|
||||
ram->absorb_partners();
|
||||
des_->add_node(ram);
|
||||
}
|
||||
|
||||
class match_block : public proc_match_t {
|
||||
|
||||
public:
|
||||
match_block(Design*d, NetProcTop*t)
|
||||
: des_(d), top_(t)
|
||||
{ }
|
||||
|
||||
~match_block() { }
|
||||
|
||||
private:
|
||||
|
||||
Design*des_;
|
||||
NetProcTop*top_;
|
||||
};
|
||||
|
||||
class synth_f : public functor_t {
|
||||
|
||||
public:
|
||||
void process(class Design*, class NetProcTop*);
|
||||
|
||||
private:
|
||||
void proc_always_(class Design*);
|
||||
|
||||
NetProcTop*top_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Look at a process, and divide the problem into always and initial
|
||||
* threads.
|
||||
*/
|
||||
void synth_f::process(class Design*des, class NetProcTop*top)
|
||||
{
|
||||
switch (top->type()) {
|
||||
case NetProcTop::KALWAYS:
|
||||
top_ = top;
|
||||
proc_always_(des);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* An "always ..." statement has been found.
|
||||
*/
|
||||
void synth_f::proc_always_(class Design*des)
|
||||
{
|
||||
match_dff dff_pat(des, top_);
|
||||
if (top_->statement()->match_proc(&dff_pat)) {
|
||||
dff_pat.make_it();
|
||||
des->delete_process(top_);
|
||||
return;
|
||||
}
|
||||
|
||||
match_block block_pat(des, top_);
|
||||
if (top_->statement()->match_proc(&block_pat)) {
|
||||
cerr << "XXXX: recurse and return here" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void synth(Design*des)
|
||||
{
|
||||
synth_f synth_obj;
|
||||
des->functor(&synth_obj);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: synth.cc,v $
|
||||
* Revision 1.6 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.5 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.4 1999/12/05 02:24:09 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.3 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
* Revision 1.2 1999/11/02 04:55:34 steve
|
||||
* Add the synthesize method to NetExpr to handle
|
||||
* synthesis of expressions, and use that method
|
||||
* to improve r-value handling of LPM_FF synthesis.
|
||||
*
|
||||
* Modify the XNF target to handle LPM_FF objects.
|
||||
*
|
||||
* Revision 1.1 1999/11/01 02:07:41 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: t-null.cc,v 1.4 1999/07/03 02:12:52 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-null.cc,v 1.10 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -33,19 +33,43 @@ static class target_null_t : public target_t {
|
||||
void bufz(ostream&os, const NetBUFZ*) { }
|
||||
void memory(ostream&, const NetMemory*) { }
|
||||
void task_def(ostream&, const NetTaskDef*) { }
|
||||
void net_assign(ostream&os, const NetAssign*) { }
|
||||
void net_assign_nb(ostream&os, const NetAssignNB*) { }
|
||||
void net_const(ostream&, const NetConst*) { }
|
||||
void net_esignal(ostream&, const NetESignal*) { }
|
||||
void net_event(ostream&, const NetNEvent*) { }
|
||||
void proc_block(ostream&, const NetBlock*) { }
|
||||
bool proc_block(ostream&, const NetBlock*) { return true; }
|
||||
void proc_condit(ostream&, const NetCondit*) { }
|
||||
void proc_delay(ostream&, const NetPDelay*) { }
|
||||
void proc_event(ostream&, const NetPEvent*) { }
|
||||
void proc_forever(ostream&, const NetForever*) { }
|
||||
void proc_repeat(ostream&, const NetRepeat*) { }
|
||||
void proc_stask(ostream&, const NetSTask*) { }
|
||||
void proc_utask(ostream&os, const NetUTask*) { }
|
||||
|
||||
} target_null_obj;
|
||||
|
||||
extern const struct target tgt_null = { "null", &target_null_obj };
|
||||
/*
|
||||
* $Log: t-null.cc,v $
|
||||
* Revision 1.10 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/02/14 06:04:52 steve
|
||||
* Unary reduction operators do not set their operand width
|
||||
*
|
||||
* Revision 1.8 1999/10/05 03:26:37 steve
|
||||
* null target ignore assignment nodes.
|
||||
*
|
||||
* Revision 1.7 1999/09/30 21:27:29 steve
|
||||
* Ignore user task definitions.
|
||||
*
|
||||
* Revision 1.6 1999/09/22 16:57:24 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
*
|
||||
* Revision 1.5 1999/09/17 02:06:26 steve
|
||||
* Handle unconnected module ports.
|
||||
*
|
||||
* Revision 1.4 1999/07/03 02:12:52 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
|
||||
+12
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: t-verilog.cc,v 1.7 1999/08/01 16:34:50 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-verilog.cc,v 1.9 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -43,7 +43,7 @@ class target_verilog : public target_t {
|
||||
virtual void logic(ostream&os, const NetLogic*);
|
||||
virtual void bufz(ostream&os, const NetBUFZ*);
|
||||
virtual void start_process(ostream&os, const NetProcTop*);
|
||||
virtual void proc_block(ostream&os, const NetBlock*);
|
||||
virtual bool proc_block(ostream&os, const NetBlock*);
|
||||
virtual void proc_delay(ostream&os, const NetPDelay*);
|
||||
virtual void proc_event(ostream&os, const NetPEvent*);
|
||||
virtual void proc_stask(ostream&os, const NetSTask*);
|
||||
@@ -173,13 +173,14 @@ void target_verilog::emit_expr_(ostream&os, const NetExpr*expr)
|
||||
}
|
||||
}
|
||||
|
||||
void target_verilog::proc_block(ostream&os, const NetBlock*net)
|
||||
bool target_verilog::proc_block(ostream&os, const NetBlock*net)
|
||||
{
|
||||
os << setw(indent_) << "" << "begin" << endl;
|
||||
indent_ += 4;
|
||||
net->emit_recurse(os, this);
|
||||
indent_ -= 4;
|
||||
os << setw(indent_) << "" << "end" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void target_verilog::proc_delay(ostream&os, const NetPDelay*net)
|
||||
@@ -271,6 +272,12 @@ const struct target tgt_verilog = {
|
||||
|
||||
/*
|
||||
* $Log: t-verilog.cc,v $
|
||||
* Revision 1.9 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.8 1999/09/22 16:57:24 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
*
|
||||
* Revision 1.7 1999/08/01 16:34:50 steve
|
||||
* Parse and elaborate rise/fall/decay times
|
||||
* for gates, and handle the rules for partial
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: t-xnf.cc,v 1.7 1999/07/17 03:39:11 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: t-xnf.cc,v 1.23 2000/02/23 02:56:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
/* XNF BACKEND
|
||||
@@ -33,6 +33,12 @@
|
||||
* PART record. Valid types are defined by Xilinx or the
|
||||
* receiving tools.
|
||||
*
|
||||
* ncf=<path>
|
||||
* Specify the path to a NCF file. This is an OUTPUT file into
|
||||
* which the code generator will write netlist constraints that
|
||||
* relate to pin assignments, CLB placement, etc. If this flag is
|
||||
* not given, no NCF file will be written.
|
||||
*
|
||||
* WIRE ATTRIBUTES
|
||||
*
|
||||
* PAD = <io><n>
|
||||
@@ -63,26 +69,44 @@
|
||||
|
||||
# include "netlist.h"
|
||||
# include "target.h"
|
||||
# include <fstream>
|
||||
# include <strstream>
|
||||
|
||||
class target_xnf : public target_t {
|
||||
|
||||
public:
|
||||
void start_design(ostream&os, const Design*);
|
||||
void end_design(ostream&os, const Design*);
|
||||
void memory(ostream&os, const NetMemory*);
|
||||
void signal(ostream&os, const NetNet*);
|
||||
|
||||
void lpm_add_sub(ostream&os, const NetAddSub*);
|
||||
void lpm_ff(ostream&os, const NetFF*);
|
||||
void lpm_mux(ostream&os, const NetMux*);
|
||||
void lpm_ram_dq(ostream&os, const NetRamDq*);
|
||||
|
||||
void net_const(ostream&os, const NetConst*);
|
||||
void logic(ostream&os, const NetLogic*);
|
||||
void bufz(ostream&os, const NetBUFZ*);
|
||||
void udp(ostream&os, const NetUDP*);
|
||||
|
||||
private:
|
||||
static string mangle(const string&);
|
||||
static string choose_sig_name(const NetObj::Link*lnk);
|
||||
static void draw_pin(ostream&os, const string&name,
|
||||
const NetObj::Link&lnk);
|
||||
static void draw_sym_with_lcaname(ostream&os, string lca,
|
||||
const NetNode*net);
|
||||
static void draw_xor(ostream&os, const NetAddSub*, unsigned idx);
|
||||
enum adder_type {FORCE0, LOWER, DOUBLE, LOWER_W_CO, EXAMINE_CI };
|
||||
static void draw_carry(ostream&os, const NetAddSub*, unsigned idx,
|
||||
enum adder_type);
|
||||
|
||||
ofstream ncf_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function takes a signal name and mangles it into an equivilent
|
||||
* This function takes a signal name and mangles it into an equivalent
|
||||
* name that is suitable to the XNF format.
|
||||
*/
|
||||
string target_xnf::mangle(const string&name)
|
||||
@@ -101,6 +125,58 @@ string target_xnf::mangle(const string&name)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method takes a signal and pin number as a nexus. Scan the
|
||||
* nexus to decide which name to use if there are lots of attached
|
||||
* signals.
|
||||
*/
|
||||
string target_xnf::choose_sig_name(const NetObj::Link*lnk)
|
||||
{
|
||||
const NetNet*sig = dynamic_cast<const NetNet*>(lnk->get_obj());
|
||||
unsigned pin = lnk->get_pin();
|
||||
|
||||
for (const NetObj::Link*cur = lnk->next_link()
|
||||
; cur != lnk ; cur = cur->next_link()) {
|
||||
|
||||
const NetNet*cursig = dynamic_cast<const NetNet*>(cur->get_obj());
|
||||
if (cursig == 0)
|
||||
continue;
|
||||
|
||||
if (sig == 0) {
|
||||
sig = cursig;
|
||||
pin = cur->get_pin();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((cursig->pin_count() == 1) && (sig->pin_count() > 1))
|
||||
continue;
|
||||
|
||||
if ((cursig->pin_count() > 1) && (sig->pin_count() == 1)) {
|
||||
sig = cursig;
|
||||
pin = cur->get_pin();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cursig->local_flag() && !sig->local_flag())
|
||||
continue;
|
||||
|
||||
if (cursig->name() < sig->name())
|
||||
continue;
|
||||
|
||||
sig = cursig;
|
||||
pin = cur->get_pin();
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
ostrstream tmp;
|
||||
tmp << mangle(sig->name());
|
||||
if (sig->pin_count() > 1)
|
||||
tmp << "<" << pin << ">";
|
||||
tmp << ends;
|
||||
|
||||
return tmp.str();
|
||||
}
|
||||
|
||||
void target_xnf::draw_pin(ostream&os, const string&name,
|
||||
const NetObj::Link&lnk)
|
||||
{
|
||||
@@ -121,26 +197,11 @@ void target_xnf::draw_pin(ostream&os, const string&name,
|
||||
type = 'O';
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned cpin;
|
||||
const NetObj*cur;
|
||||
for (lnk.next_link(cur, cpin)
|
||||
; cur->pin(cpin) != lnk
|
||||
; cur->pin(cpin).next_link(cur, cpin)) {
|
||||
|
||||
const NetNet*sig = dynamic_cast<const NetNet*>(cur);
|
||||
if (sig) {
|
||||
os << " PIN, " << use_name << ", " << type << ", "
|
||||
<< mangle(sig->name());
|
||||
if (sig->pin_count() > 1)
|
||||
os << "<" << cpin << ">";
|
||||
|
||||
if (inv)
|
||||
os << ",,INV";
|
||||
|
||||
os << endl;
|
||||
}
|
||||
}
|
||||
os << " PIN, " << use_name << ", " << type << ", " <<
|
||||
choose_sig_name(&lnk);
|
||||
if (inv) os << ",,INV";
|
||||
os << endl;
|
||||
}
|
||||
|
||||
static string scrape_pin_name(string&list)
|
||||
@@ -166,22 +227,35 @@ void target_xnf::draw_sym_with_lcaname(ostream&os, string lca,
|
||||
os << "SYM, " << mangle(net->name()) << ", " << lcaname
|
||||
<< ", LIBVER=2.0.0" << endl;
|
||||
|
||||
for (idx = 0 ; idx < net->pin_count() ; idx += 1)
|
||||
draw_pin(os, scrape_pin_name(lca), net->pin(idx));
|
||||
for (idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
string usename = scrape_pin_name(lca);
|
||||
if (usename == "") continue;
|
||||
draw_pin(os, usename, net->pin(idx));
|
||||
}
|
||||
|
||||
os << "END" << endl;
|
||||
}
|
||||
|
||||
void target_xnf::start_design(ostream&os, const Design*des)
|
||||
{
|
||||
string ncfpath = des->get_flag("ncf");
|
||||
if (ncfpath != "")
|
||||
ncf_.open(ncfpath.c_str());
|
||||
|
||||
os << "LCANET,6" << endl;
|
||||
os << "PROG,verilog,0.0,\"Icarus Verilog\"" << endl;
|
||||
os << "PART," << des->get_flag("part") << endl;
|
||||
os << "PROG,verilog,0.2PRE,\"Icarus Verilog\"" << endl;
|
||||
ncf_ << "# Generated by Icarus Verilog 0.2PRE" << endl;
|
||||
|
||||
if (des->get_flag("part") != "") {
|
||||
os << "PART," << des->get_flag("part") << endl;
|
||||
ncf_ << "CONFIG PART=" << des->get_flag("part") << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void target_xnf::end_design(ostream&os, const Design*)
|
||||
{
|
||||
os << "EOF" << endl;
|
||||
ncf_.close();
|
||||
}
|
||||
|
||||
void scrape_pad_info(string str, char&dir, unsigned&num)
|
||||
@@ -223,6 +297,14 @@ void scrape_pad_info(string str, char&dir, unsigned&num)
|
||||
num = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memories are handled by the lpm_ram_dq method, so there is nothing
|
||||
* to do here.
|
||||
*/
|
||||
void target_xnf::memory(ostream&, const NetMemory*)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for signals that have attributes that are pertinent to XNF
|
||||
* files. The most obvious are those that have the PAD attribute.
|
||||
@@ -251,6 +333,287 @@ void target_xnf::signal(ostream&os, const NetNet*net)
|
||||
scrape_pad_info(pad, dir, num);
|
||||
os << "EXT, " << mangle(net->name()) << ", " << dir
|
||||
<< ", " << num << endl;
|
||||
|
||||
ncf_ << "# Assignment to pin " << num << " (DIR=" << dir <<
|
||||
") by $attribute(" << net->name() << ", \"PAD\", \"" <<
|
||||
pad << "\")" << endl;
|
||||
ncf_ << "NET " << mangle(net->name()) << " LOC=P" << num << ";"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void target_xnf::draw_xor(ostream &os, const NetAddSub*gate, unsigned idx)
|
||||
{
|
||||
string name = mangle(gate->name());
|
||||
string name_add = name;
|
||||
string name_cout = name + "/COUT";
|
||||
|
||||
// We only need to pick up the
|
||||
// carry if we are not the 0 bit. (We know it is 0).
|
||||
os << "SYM, " << name_add << "<" << (idx+0) << ">, XOR, "
|
||||
"LIBVER=2.0.0" << endl;
|
||||
draw_pin(os, "O", gate->pin_Result(idx));
|
||||
draw_pin(os, "I0", gate->pin_DataA(idx));
|
||||
draw_pin(os, "I1", gate->pin_DataB(idx));
|
||||
if (idx > 0) {
|
||||
os << " PIN, I2, I, " << name_cout << "<" <<
|
||||
idx << ">" << endl;
|
||||
}
|
||||
os << "END" << endl;
|
||||
}
|
||||
|
||||
void target_xnf::draw_carry(ostream &os, const NetAddSub*gate, unsigned idx,
|
||||
enum adder_type type)
|
||||
{
|
||||
string name = mangle(gate->name());
|
||||
|
||||
string name_cy4 = name + "/CY";
|
||||
string name_cym = name + "/CM";
|
||||
string name_cout = name + "/COUT";
|
||||
|
||||
os << "SYM, " << name_cy4 << "<" << idx << ">, CY4, "
|
||||
"LIBVER=2.0.0" << endl;
|
||||
|
||||
// Less significant bit addends, if any
|
||||
if ( type == LOWER || type == DOUBLE || type == LOWER_W_CO ) {
|
||||
draw_pin(os, "A0", gate->pin_DataA(idx));
|
||||
draw_pin(os, "B0", gate->pin_DataB(idx));
|
||||
}
|
||||
|
||||
// More significant bit addends, if any
|
||||
if ( type == DOUBLE ) {
|
||||
draw_pin(os, "A1", gate->pin_DataA(idx+1));
|
||||
draw_pin(os, "B1", gate->pin_DataB(idx+1));
|
||||
}
|
||||
|
||||
// All but FORCE0 cells have carry input
|
||||
if ( type != FORCE0 ) {
|
||||
os << " PIN, CIN, I, " << name_cout << "<" << idx << ">" << endl;
|
||||
}
|
||||
|
||||
// Connect the Cout0 to a signal so that I can connect
|
||||
// it to the adder.
|
||||
switch (type) {
|
||||
case LOWER:
|
||||
case DOUBLE:
|
||||
os << " PIN, COUT0, O, " << name_cout << "<" << (idx+1) <<
|
||||
">" << endl;
|
||||
break;
|
||||
case EXAMINE_CI:
|
||||
case LOWER_W_CO:
|
||||
draw_pin(os, "COUT0", gate->pin_Cout());
|
||||
break;
|
||||
}
|
||||
|
||||
// Connect the Cout, this will connect to the next Cin
|
||||
if ( type == FORCE0 || type == DOUBLE ) {
|
||||
unsigned int to = (type==FORCE0)?(0):(idx+2);
|
||||
os << " PIN, COUT, O, " << name_cout << "<" << to <<
|
||||
">" << endl;
|
||||
}
|
||||
|
||||
// These are the mode inputs from the CY_xx pseudo-device
|
||||
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
|
||||
os << " PIN, C" << cn << ", I, " << name << "/C"
|
||||
<< cn << "<" << (idx) << ">" << endl;
|
||||
}
|
||||
os << "END" << endl;
|
||||
|
||||
// On to the CY_xx pseudo-device itself
|
||||
os << "SYM, " << name_cym << "<" << (idx) << ">, ";
|
||||
switch (type) {
|
||||
case FORCE0:
|
||||
os << "CY4_37, CYMODE=FORCE-0" << endl;
|
||||
break;
|
||||
case LOWER:
|
||||
os << "CY4_01, CYMODE=ADD-F-CI" << endl;
|
||||
break;
|
||||
case LOWER_W_CO:
|
||||
os << "CY4_01, CYMODE=ADD-F-CI" << endl;
|
||||
break;
|
||||
case DOUBLE:
|
||||
os << "CY4_02, CYMODE=ADD-FG-CI" << endl;
|
||||
break;
|
||||
case EXAMINE_CI:
|
||||
os << "CY4_42, CYMODE-EXAMINE-CI" << endl;
|
||||
break;
|
||||
}
|
||||
for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
|
||||
os << " PIN, C" << cn << ", O, " << name << "/C"
|
||||
<< cn << "<" << (idx) << ">" << endl;
|
||||
}
|
||||
os << "END" << endl;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function makes an adder out of carry logic symbols. It makes
|
||||
* as many 2 bit adders as are possible, then the top bit is made into
|
||||
* a 1-bit adder (with carry in) in the F unit. The low carry is
|
||||
* initialized with the FORCE-0 configuration of a carry unit below
|
||||
* the 0 bit. This takes up the carry logic of the CLB below, but not
|
||||
* the G function.
|
||||
*
|
||||
* References:
|
||||
* XNF 6.1 Specification
|
||||
* Application note XAPP013
|
||||
* Xilinx Libraries Guide, Chapter 12
|
||||
*/
|
||||
void target_xnf::lpm_add_sub(ostream&os, const NetAddSub*gate)
|
||||
{
|
||||
unsigned width = gate->width();
|
||||
|
||||
/* Make the force-0 carry mode object to initialize the bottom
|
||||
bits of the carry chain. Label this with the width instead
|
||||
of the bit position so that symbols don't clash. */
|
||||
|
||||
draw_carry(os, gate, width+1, FORCE0);
|
||||
|
||||
|
||||
/* Now make the 2 bit adders that chain from the cin
|
||||
initializer and up. Save the tail bits for later. */
|
||||
for (unsigned idx = 0 ; idx < width-2 ; idx += 2)
|
||||
draw_carry(os, gate, idx, DOUBLE);
|
||||
|
||||
/* Always have one or two tail bits. The situation gets a
|
||||
little tricky if we want the carry output, so handle that
|
||||
here.
|
||||
|
||||
If the carry-out is connected, and there are an even number
|
||||
of data bits, we need to see the cout from the CLB. This is
|
||||
done by configuring the top CLB CY device as ADD-FG-CI (to
|
||||
activate cout) and create an extra CLB CY device on top of
|
||||
the carry chain configured EXAMINE-CI to put the carry into
|
||||
the G function block.
|
||||
|
||||
IF the carry-out is connected and there are an odd number
|
||||
of data bits, then the top CLB can be configured to carry
|
||||
the top bit in the F unit and deliver the carry out through
|
||||
the G unit.
|
||||
|
||||
If the carry-out is not connected, then configure this top
|
||||
CLB as ADD-F-CI. The draw_xor for the top bit will include
|
||||
the F carry if needed. */
|
||||
|
||||
if (gate->pin_Cout().is_linked()) {
|
||||
if (width%2 == 0) {
|
||||
draw_carry(os, gate, width-2, DOUBLE);
|
||||
draw_carry(os, gate, width, EXAMINE_CI);
|
||||
} else {
|
||||
draw_carry(os, gate, width-1, LOWER_W_CO);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (width%2 == 0)
|
||||
draw_carry(os, gate, width-2, LOWER);
|
||||
else
|
||||
draw_carry(os, gate, width-1, LOWER);
|
||||
}
|
||||
|
||||
/* Now draw all the single bit (plus carry in) adders from XOR
|
||||
gates. This puts the F and G units to use. */
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
draw_xor(os, gate, idx);
|
||||
|
||||
}
|
||||
|
||||
void target_xnf::lpm_ff(ostream&os, const NetFF*net)
|
||||
{
|
||||
string type = net->attribute("LPM_FFType");
|
||||
if (type == "") type = "DFF";
|
||||
|
||||
// XXXX For now, only support DFF
|
||||
assert(type == "DFF");
|
||||
|
||||
string lcaname = net->attribute("XNF-LCA");
|
||||
if (lcaname != "") {
|
||||
draw_sym_with_lcaname(os, lcaname, net);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(net->attribute("XNF-LCA") == "");
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
|
||||
|
||||
os << "SYM, " << mangle(net->name()) << "<" << idx
|
||||
<< ">, DFF, LIBVER=2.0.0" << endl;
|
||||
draw_pin(os, "Q", net->pin_Q(idx));
|
||||
draw_pin(os, "D", net->pin_Data(idx));
|
||||
|
||||
if (net->attribute("Clock:LPM_Polarity") == "INVERT")
|
||||
draw_pin(os, "~C", net->pin_Clock());
|
||||
else
|
||||
draw_pin(os, "C", net->pin_Clock());
|
||||
|
||||
if (count_outputs(net->pin_Enable()) > 0)
|
||||
draw_pin(os, "CE", net->pin_Enable());
|
||||
|
||||
os << "END" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate an LPM_MUX.
|
||||
*
|
||||
* XXXX NOTE: For now, this only supports combinational LPM_MUX
|
||||
* devices that have a single select input. These are typically
|
||||
* generated from ?: expressions.
|
||||
*/
|
||||
void target_xnf::lpm_mux(ostream&os, const NetMux*net)
|
||||
{
|
||||
assert(net->sel_width() == 1);
|
||||
assert(net->size() == 2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
|
||||
|
||||
os << "SYM, " << mangle(net->name()) << "<" << idx << ">,"
|
||||
<< " EQN, EQN=(I0 * I2) + (~I0 * I1)" << endl;
|
||||
|
||||
draw_pin(os, "I0", net->pin_Sel(0));
|
||||
draw_pin(os, "I1", net->pin_Data(idx,0));
|
||||
draw_pin(os, "I2", net->pin_Data(idx,1));
|
||||
draw_pin(os, "O", net->pin_Result(idx));
|
||||
|
||||
os << "END" << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void target_xnf::lpm_ram_dq(ostream&os, const NetRamDq*ram)
|
||||
{
|
||||
assert(ram->count_partners() == 1);
|
||||
|
||||
const NetMemory*mem = ram->mem();
|
||||
|
||||
for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) {
|
||||
os << "SYM, " << mangle(ram->name())
|
||||
<< "<" << idx << ">, RAMS" << endl;
|
||||
|
||||
draw_pin(os, "O", ram->pin_Q(idx));
|
||||
draw_pin(os, "D", ram->pin_Data(idx));
|
||||
draw_pin(os, "WE", ram->pin_WE());
|
||||
draw_pin(os, "WCLK", ram->pin_InClock());
|
||||
for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) {
|
||||
strstream tmp;
|
||||
tmp << "A" << adr << ends;
|
||||
draw_pin(os, tmp.str(), ram->pin_Address(adr));
|
||||
}
|
||||
|
||||
os << "END" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void target_xnf::net_const(ostream&os, const NetConst*c)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < c->pin_count() ; idx += 1) {
|
||||
verinum::V v=c->value(idx);
|
||||
assert(v==verinum::V0 || v==verinum::V1);
|
||||
const NetObj::Link& lnk = c->pin(idx);
|
||||
// Code parallels draw_pin above, some smart c++ guru should
|
||||
// find a way to make a method out of this.
|
||||
unsigned cpin;
|
||||
const NetObj*cur;
|
||||
|
||||
os << " PWR, " << v << ", " << choose_sig_name(&lnk) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -313,6 +676,21 @@ void target_xnf::logic(ostream&os, const NetLogic*net)
|
||||
os << "END" << endl;
|
||||
}
|
||||
|
||||
void target_xnf::bufz(ostream&os, const NetBUFZ*net)
|
||||
{
|
||||
static int warned_once=0;
|
||||
if (!warned_once) {
|
||||
cerr << "Warning: BUFZ object found for xnf output."
|
||||
" Try -Fnobufz." << endl;
|
||||
warned_once=1;
|
||||
}
|
||||
os << "SYM, " << mangle(net->name()) << ", BUF, LIBVER=2.0.0" << endl;
|
||||
assert(net->pin_count() == 2);
|
||||
draw_pin(os, "O", net->pin(0));
|
||||
draw_pin(os, "I", net->pin(1));
|
||||
os << "END" << endl;
|
||||
}
|
||||
|
||||
void target_xnf::udp(ostream&os, const NetUDP*net)
|
||||
{
|
||||
string lca = net->attribute("XNF-LCA");
|
||||
@@ -333,6 +711,75 @@ extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-xnf.cc,v $
|
||||
* Revision 1.23 2000/02/23 02:56:55 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.22 1999/12/17 03:38:46 steve
|
||||
* NetConst can now hold wide constants.
|
||||
*
|
||||
* Revision 1.21 1999/12/16 18:54:32 steve
|
||||
* Capture the carry out of carry-chain addition.
|
||||
*
|
||||
* Revision 1.20 1999/12/16 02:42:15 steve
|
||||
* Simulate carry output on adders.
|
||||
*
|
||||
* Revision 1.19 1999/12/05 19:30:43 steve
|
||||
* Generate XNF RAMS from synthesized memories.
|
||||
*
|
||||
* Revision 1.18 1999/11/19 03:02:25 steve
|
||||
* Detect flip-flops connected to opads and turn
|
||||
* them into OUTFF devices. Inprove support for
|
||||
* the XNF-LCA attribute in the process.
|
||||
*
|
||||
* Revision 1.17 1999/11/17 18:52:09 steve
|
||||
* Add algorithm for choosing nexus name from attached signals.
|
||||
*
|
||||
* Revision 1.16 1999/11/17 01:31:28 steve
|
||||
* Clean up warnings that add_sub got from Alliance
|
||||
*
|
||||
* Revision 1.15 1999/11/06 04:51:42 steve
|
||||
* Support writing some XNF things into an NCF file.
|
||||
*
|
||||
* Revision 1.14 1999/11/05 18:43:12 steve
|
||||
* fix syntax of EQN record.
|
||||
*
|
||||
* Revision 1.13 1999/11/05 07:10:45 steve
|
||||
* Include the obvious XOR gates in the adders.
|
||||
*
|
||||
* Revision 1.12 1999/11/05 04:40:40 steve
|
||||
* Patch to synthesize LPM_ADD_SUB from expressions,
|
||||
* Thanks to Larry Doolittle. Also handle constants
|
||||
* in expressions.
|
||||
*
|
||||
* Synthesize adders in XNF, based on a patch from
|
||||
* Larry. Accept synthesis of constants from Larry
|
||||
* as is.
|
||||
*
|
||||
* Revision 1.11 1999/11/04 03:53:26 steve
|
||||
* Patch to synthesize unary ~ and the ternary operator.
|
||||
* Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.
|
||||
*
|
||||
* Add the LPM_MUX device, and integrate it with the
|
||||
* ternary synthesis from Larry. Replace the lpm_mux
|
||||
* generator in t-xnf.cc to use XNF EQU devices to
|
||||
* put muxs into function units.
|
||||
*
|
||||
* Rewrite elaborate_net for the PETernary class to
|
||||
* also use the LPM_MUX device.
|
||||
*
|
||||
* Revision 1.10 1999/11/02 04:55:34 steve
|
||||
* Add the synthesize method to NetExpr to handle
|
||||
* synthesis of expressions, and use that method
|
||||
* to improve r-value handling of LPM_FF synthesis.
|
||||
*
|
||||
* Modify the XNF target to handle LPM_FF objects.
|
||||
*
|
||||
* Revision 1.9 1999/08/25 22:22:08 steve
|
||||
* handle bufz in XNF backend.
|
||||
*
|
||||
* Revision 1.8 1999/08/18 04:00:02 steve
|
||||
* Fixup spelling and some error messages. <LRDoolittle@lbl.gov>
|
||||
*
|
||||
* Revision 1.7 1999/07/17 03:39:11 steve
|
||||
* simplified process scan for targets.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 1998-2000 Stephen Williams <steve@icarus.com>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: target.cc,v 1.15 1999/07/17 19:51:00 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: target.cc,v 1.30 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -31,6 +31,10 @@ void target_t::start_design(ostream&os, const Design*)
|
||||
{
|
||||
}
|
||||
|
||||
void target_t::scope(ostream&, const NetScope*)
|
||||
{
|
||||
}
|
||||
|
||||
void target_t::signal(ostream&os, const NetNet*)
|
||||
{
|
||||
}
|
||||
@@ -41,6 +45,12 @@ void target_t::memory(ostream&os, const NetMemory*)
|
||||
"Unhandled memory." << endl;
|
||||
}
|
||||
|
||||
void target_t::func_def(ostream&os, const NetFuncDef*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled function definition." << endl;
|
||||
}
|
||||
|
||||
void target_t::task_def(ostream&os, const NetTaskDef*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -63,6 +73,48 @@ void target_t::udp(ostream&os, const NetUDP*)
|
||||
"Unhandled UDP." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_add_sub(ostream&, const NetAddSub*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetAddSub." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_clshift(ostream&, const NetCLShift*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetCLShift." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_compare(ostream&, const NetCompare*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetCompare." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_ff(ostream&, const NetFF*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetFF." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_mult(ostream&, const NetMult*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetMult." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_mux(ostream&, const NetMux*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetMux." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_ram_dq(ostream&, const NetRamDq*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetRamDq." << endl;
|
||||
}
|
||||
|
||||
void target_t::net_assign(ostream&os, const NetAssign*)
|
||||
{
|
||||
}
|
||||
@@ -73,27 +125,28 @@ void target_t::net_assign_nb(ostream&os, const NetAssignNB*)
|
||||
"Unhandled non-blocking assignment node." << endl;
|
||||
}
|
||||
|
||||
void target_t::net_case_cmp(ostream&os, const NetCaseCmp*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled case compare node." << endl;
|
||||
}
|
||||
|
||||
void target_t::net_const(ostream&os, const NetConst*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled CONSTANT node." << endl;
|
||||
}
|
||||
|
||||
void target_t::net_esignal(ostream&os, const NetESignal*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled Expression Signal node." << endl;
|
||||
}
|
||||
|
||||
void target_t::net_event(ostream&os, const NetNEvent*)
|
||||
void target_t::net_event(ostream&os, const NetNEvent*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled EVENT net node." << endl;
|
||||
net->dump_node(cerr, 4);
|
||||
}
|
||||
|
||||
void target_t::process(ostream&os, const NetProcTop*top)
|
||||
bool target_t::process(ostream&os, const NetProcTop*top)
|
||||
{
|
||||
top->statement()->emit_proc(os, this);
|
||||
return top->statement()->emit_proc(os, this);
|
||||
}
|
||||
|
||||
void target_t::proc_assign(ostream&os, const NetAssign*)
|
||||
@@ -114,10 +167,17 @@ void target_t::proc_assign_nb(ostream&os, const NetAssignNB*)
|
||||
"Unhandled non-blocking assignment." << endl;
|
||||
}
|
||||
|
||||
void target_t::proc_block(ostream&os, const NetBlock*)
|
||||
void target_t::proc_assign_mem_nb(ostream&os, const NetAssignMemNB*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled non-blocking memory assignment." << endl;
|
||||
}
|
||||
|
||||
bool target_t::proc_block(ostream&os, const NetBlock*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled proc_block." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::proc_case(ostream&os, const NetCase*cur)
|
||||
@@ -140,10 +200,11 @@ void target_t::proc_delay(ostream&os, const NetPDelay*)
|
||||
"Unhandled proc_delay." << endl;
|
||||
}
|
||||
|
||||
void target_t::proc_event(ostream&os, const NetPEvent*)
|
||||
void target_t::proc_event(ostream&os, const NetPEvent*net)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled proc_event." << endl;
|
||||
net->dump(cerr, 4);
|
||||
}
|
||||
|
||||
void target_t::proc_forever(ostream&os, const NetForever*)
|
||||
@@ -209,6 +270,12 @@ void expr_scan_t::expr_memory(const NetEMemory*)
|
||||
"unhandled expr_memory." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_scope(const NetEScope*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled expr_scope." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_signal(const NetESignal*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
@@ -227,6 +294,12 @@ void expr_scan_t::expr_ternary(const NetETernary*)
|
||||
"unhandled expr_ternary." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_ufunc(const NetEUFunc*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled function call." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_unary(const NetEUnary*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
@@ -241,6 +314,63 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.30 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.29 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.28 1999/11/28 23:42:03 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
*
|
||||
* Revision 1.27 1999/11/27 19:07:58 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.26 1999/11/21 00:13:09 steve
|
||||
* Support memories in continuous assignments.
|
||||
*
|
||||
* Revision 1.25 1999/11/14 23:43:45 steve
|
||||
* Support combinatorial comparators.
|
||||
*
|
||||
* Revision 1.24 1999/11/14 20:24:28 steve
|
||||
* Add support for the LPM_CLSHIFT device.
|
||||
*
|
||||
* Revision 1.23 1999/11/04 03:53:26 steve
|
||||
* Patch to synthesize unary ~ and the ternary operator.
|
||||
* Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.
|
||||
*
|
||||
* Add the LPM_MUX device, and integrate it with the
|
||||
* ternary synthesis from Larry. Replace the lpm_mux
|
||||
* generator in t-xnf.cc to use XNF EQU devices to
|
||||
* put muxs into function units.
|
||||
*
|
||||
* Rewrite elaborate_net for the PETernary class to
|
||||
* also use the LPM_MUX device.
|
||||
*
|
||||
* Revision 1.22 1999/11/01 02:07:41 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.21 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
* Revision 1.20 1999/09/22 16:57:24 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
*
|
||||
* Revision 1.19 1999/09/15 01:55:06 steve
|
||||
* Elaborate non-blocking assignment to memories.
|
||||
*
|
||||
* Revision 1.18 1999/09/03 04:28:38 steve
|
||||
* elaborate the binary plus operator.
|
||||
*
|
||||
* Revision 1.17 1999/08/31 22:38:29 steve
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
* Revision 1.16 1999/08/18 04:00:02 steve
|
||||
* Fixup spelling and some error messages. <LRDoolittle@lbl.gov>
|
||||
*
|
||||
* Revision 1.15 1999/07/17 19:51:00 steve
|
||||
* netlist support for ternary operator.
|
||||
*
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: target.h,v 1.15 1999/07/17 19:51:00 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: target.h,v 1.29 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -55,6 +55,10 @@ struct target_t {
|
||||
/* Start the design. */
|
||||
virtual void start_design(ostream&os, const Design*);
|
||||
|
||||
/* This is called once for each scope in the design, before
|
||||
anything else is called. */
|
||||
virtual void scope(ostream&os, const NetScope*);
|
||||
|
||||
/* Output a signal (called for each signal) */
|
||||
virtual void signal(ostream&os, const NetNet*);
|
||||
|
||||
@@ -63,6 +67,16 @@ struct target_t {
|
||||
|
||||
/* Output a defined task. */
|
||||
virtual void task_def(ostream&, const NetTaskDef*);
|
||||
virtual void func_def(ostream&, const NetFuncDef*);
|
||||
|
||||
/* LPM style components are handled here. */
|
||||
virtual void lpm_add_sub(ostream&os, const NetAddSub*);
|
||||
virtual void lpm_clshift(ostream&os, const NetCLShift*);
|
||||
virtual void lpm_compare(ostream&os, const NetCompare*);
|
||||
virtual void lpm_ff(ostream&os, const NetFF*);
|
||||
virtual void lpm_mult(ostream&os, const NetMult*);
|
||||
virtual void lpm_mux(ostream&os, const NetMux*);
|
||||
virtual void lpm_ram_dq(ostream&os, const NetRamDq*);
|
||||
|
||||
/* Output a gate (called for each gate) */
|
||||
virtual void logic(ostream&os, const NetLogic*);
|
||||
@@ -70,19 +84,20 @@ struct target_t {
|
||||
virtual void udp(ostream&os, const NetUDP*);
|
||||
virtual void net_assign(ostream&os, const NetAssign*);
|
||||
virtual void net_assign_nb(ostream&os, const NetAssignNB*);
|
||||
virtual void net_case_cmp(ostream&os, const NetCaseCmp*);
|
||||
virtual void net_const(ostream&os, const NetConst*);
|
||||
virtual void net_esignal(ostream&os, const NetESignal*);
|
||||
virtual void net_event(ostream&os, const NetNEvent*);
|
||||
|
||||
/* Output a process (called for each process). It is up to the
|
||||
target to recurse if desired. */
|
||||
virtual void process(ostream&os, const NetProcTop*);
|
||||
virtual bool process(ostream&os, const NetProcTop*);
|
||||
|
||||
/* Various kinds of process nodes are dispatched through these. */
|
||||
virtual void proc_assign(ostream&os, const NetAssign*);
|
||||
virtual void proc_assign_mem(ostream&os, const NetAssignMem*);
|
||||
virtual void proc_assign_nb(ostream&os, const NetAssignNB*);
|
||||
virtual void proc_block(ostream&os, const NetBlock*);
|
||||
virtual void proc_assign_mem_nb(ostream&os, const NetAssignMemNB*);
|
||||
virtual bool proc_block(ostream&os, const NetBlock*);
|
||||
virtual void proc_case(ostream&os, const NetCase*);
|
||||
virtual void proc_condit(ostream&os, const NetCondit*);
|
||||
virtual void proc_forever(ostream&os, const NetForever*);
|
||||
@@ -106,9 +121,11 @@ struct expr_scan_t {
|
||||
virtual void expr_concat(const NetEConcat*);
|
||||
virtual void expr_ident(const NetEIdent*);
|
||||
virtual void expr_memory(const NetEMemory*);
|
||||
virtual void expr_scope(const NetEScope*);
|
||||
virtual void expr_signal(const NetESignal*);
|
||||
virtual void expr_subsignal(const NetESubSignal*);
|
||||
virtual void expr_ternary(const NetETernary*);
|
||||
virtual void expr_ufunc(const NetEUFunc*);
|
||||
virtual void expr_unary(const NetEUnary*);
|
||||
virtual void expr_binary(const NetEBinary*);
|
||||
};
|
||||
@@ -117,7 +134,7 @@ struct expr_scan_t {
|
||||
/* The emit functions take a design and emit it to the output stream
|
||||
using the specified target. If the target is given by name, it is
|
||||
located in the target_table and used. */
|
||||
extern void emit(ostream&o, const Design*des, const char*type);
|
||||
extern bool emit(ostream&o, const Design*des, const char*type);
|
||||
|
||||
/* This function takes a fully qualified verilog name (which may have,
|
||||
for example, dots in it) and produces a mangled version that can be
|
||||
@@ -130,6 +147,60 @@ extern const struct target *target_table[];
|
||||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.29 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.28 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.27 1999/11/28 23:42:03 steve
|
||||
* NetESignal object no longer need to be NetNode
|
||||
* objects. Let them keep a pointer to NetNet objects.
|
||||
*
|
||||
* Revision 1.26 1999/11/27 19:07:58 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.25 1999/11/21 00:13:09 steve
|
||||
* Support memories in continuous assignments.
|
||||
*
|
||||
* Revision 1.24 1999/11/14 23:43:46 steve
|
||||
* Support combinatorial comparators.
|
||||
*
|
||||
* Revision 1.23 1999/11/14 20:24:28 steve
|
||||
* Add support for the LPM_CLSHIFT device.
|
||||
*
|
||||
* Revision 1.22 1999/11/04 03:53:26 steve
|
||||
* Patch to synthesize unary ~ and the ternary operator.
|
||||
* Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.
|
||||
*
|
||||
* Add the LPM_MUX device, and integrate it with the
|
||||
* ternary synthesis from Larry. Replace the lpm_mux
|
||||
* generator in t-xnf.cc to use XNF EQU devices to
|
||||
* put muxs into function units.
|
||||
*
|
||||
* Rewrite elaborate_net for the PETernary class to
|
||||
* also use the LPM_MUX device.
|
||||
*
|
||||
* Revision 1.21 1999/11/01 02:07:41 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.20 1999/10/10 01:59:55 steve
|
||||
* Structural case equals device.
|
||||
*
|
||||
* Revision 1.19 1999/09/22 16:57:24 steve
|
||||
* Catch parallel blocks in vvm emit.
|
||||
*
|
||||
* Revision 1.18 1999/09/15 01:55:06 steve
|
||||
* Elaborate non-blocking assignment to memories.
|
||||
*
|
||||
* Revision 1.17 1999/09/03 04:28:38 steve
|
||||
* elaborate the binary plus operator.
|
||||
*
|
||||
* Revision 1.16 1999/08/31 22:38:29 steve
|
||||
* Elaborate and emit to vvm procedural functions.
|
||||
*
|
||||
* Revision 1.15 1999/07/17 19:51:00 steve
|
||||
* netlist support for ternary operator.
|
||||
*
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: targets.cc,v 1.4 1999/05/01 02:57:53 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: targets.cc,v 1.5 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -37,6 +37,9 @@ const struct target *target_table[] = {
|
||||
|
||||
/*
|
||||
* $Log: targets.cc,v $
|
||||
* Revision 1.5 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 1999/05/01 02:57:53 steve
|
||||
* Handle much more complex event expressions.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
.TH verilog 1 "Septemeber 13th, 1999" Version 19990913
|
||||
.SH NAME
|
||||
verilog - Icarus Verilog Driver
|
||||
.SH SYNOPSIS
|
||||
.B verilog
|
||||
[-Dmacro[=defn]] [-Iincludepath] [-X] [-o outputfilename] [-s topmodule] sourcefile[s]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fIverilog\fP is the compiler driver script for compiling Verilog code
|
||||
to either a VVM-format (Verilog Virtual Machine) for simulation or to
|
||||
XNF (Xilinx Netlist Format) to be used in Xilinx FPGA's.
|
||||
|
||||
\fIverilog\fP is just massaging the input switches and then calls
|
||||
the preprocessor (ivlpp), the compiler (ivl) and (optional) the C++
|
||||
compiler.
|
||||
|
||||
Please read the official documentation (very minimal at this point)
|
||||
on how to use \fIivl et al\fP, since this man page just describes the
|
||||
"easy startscript" \fIverilog\fP.
|
||||
|
||||
.SH OPTIONS
|
||||
.l
|
||||
\fIverilog\fP accepts the following options:
|
||||
.TP 8
|
||||
.B -D\fImacro\fP
|
||||
Defines macro \fImacro\fP with the string `1' as its definition.
|
||||
.TP 8
|
||||
.B -D\fImacro=defn\fP
|
||||
Defines macro \fImacro\fP as \fIdefn\fP.
|
||||
.TP 8
|
||||
.B -I\fIincludepath\fP
|
||||
Append path \fIincludepath\fP to list of paths searched for include files.
|
||||
.TP 8
|
||||
.B -m\fImodule\fP
|
||||
Add this module to the list of modules to be loaded by the simulation.
|
||||
.B -X
|
||||
Generate XNF files as output. Default is VVM-format.
|
||||
.TP 8
|
||||
.B -x
|
||||
Executes the generated file directly after compilation.
|
||||
.TP 8
|
||||
.B -o \fIfilename\fP
|
||||
Place output in the file \fIfilename\fP. If not given, \fIverilog\fP tries to
|
||||
make a guess; if the input filename is "hello.v", the output
|
||||
filename will be "hello" (for VVM target) or "hello.xnf" (for XNF target).
|
||||
If several files are given on the command line, the \fIlast\fP filename will
|
||||
be used.
|
||||
.TP 8
|
||||
.B -s \fItopmodule name\fP
|
||||
To explicitly set the module \fIivl\fP will use as a top-level module.
|
||||
|
||||
.SH EXAMPLES
|
||||
These examples assume that you have a Verilog source file called hello.v in
|
||||
the current directory
|
||||
|
||||
To compile hello.v to an executable file called hello:
|
||||
|
||||
verilog hello.v
|
||||
|
||||
To compile hello.v to an executable file called runnable:
|
||||
|
||||
verilog -o runnable hello.v
|
||||
|
||||
To compile hello.v to a file in XNF-format called hello.xnf
|
||||
|
||||
verilog -X hello.v
|
||||
|
||||
|
||||
.SH "ENVIRONMENT"
|
||||
.ta \w'VPI_MODULE_PATH 'u
|
||||
VPI_MODULE_PATH path to PLI modules
|
||||
|
||||
.SH "AUTHORS"
|
||||
.nf
|
||||
.ta \w'verilog 'u
|
||||
verilog Stefan Petersen ([email protected])
|
||||
ivlpp Steve Williams ([email protected])
|
||||
ivl Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR ivlpp (N/A)
|
||||
.BR ivl (N/A)
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 1999 Stefan Petersen
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
#!/bin/sh
|
||||
|
||||
# verilog - A wrapper shell script for ivl
|
||||
# Copyright (C) 1999 Stefan Petersen ([email protected])
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Added support for the -t flag, for odd-ball target types. <[email protected]>
|
||||
# Added support for functors, especially for the XNF target. <[email protected]>
|
||||
|
||||
# Setup variables
|
||||
execPath=@libdir@/ivl
|
||||
execIVLPP=${execPath}/ivlpp
|
||||
execIVL=${execPath}/ivl
|
||||
execCpp=@CXX@
|
||||
|
||||
tmpDir=/tmp
|
||||
tmpPPFile=${tmpDir}/ivl$$.pp
|
||||
tmpCCFile=${tmpDir}/ivl$$.cc
|
||||
|
||||
includedir=@includedir@
|
||||
libdir=@libdir@
|
||||
VPIModulePath=@libdir@/ivl
|
||||
|
||||
target="vvm"
|
||||
targetSuffix=""
|
||||
functors=""
|
||||
flags=""
|
||||
|
||||
# If VPI module path aren't set up, warn at least
|
||||
#if test -z "${VPI_MODULE_PATH}" ; then
|
||||
# echo "Missing environment variable VPI_MODULE_PATH.";
|
||||
# echo "To be able to execute, set VPI_MODULE_PATH to ${VPIModulePath}";
|
||||
#fi
|
||||
|
||||
# Try to extract given parameters
|
||||
parameter=`getopt D:I:Xxf:m:o:s:t: "$@"`
|
||||
eval set -- "${parameter}"
|
||||
while true ; do
|
||||
|
||||
case "$1" in
|
||||
-D) extDefines="${extDefines} -D$2" ; shift 2 ;;
|
||||
-I) extIncPath="${extIncPath} -I $2" ; shift 2 ;;
|
||||
-X) target="xnf" ; shift ;;
|
||||
-f) flags="$flags -f$2" ; shift 2 ;;
|
||||
-m) flags="$flags -m$2" ; shift 2 ;;
|
||||
-o) outputFile=$2 ; shift 2 ;;
|
||||
-s) topModule="-s $2 " ; shift 2 ;;
|
||||
-t) target="$2" ; shift 2 ;;
|
||||
-x) execute="true"; shift ;;
|
||||
--) shift ; break ;;
|
||||
*) echo "Internal error! Arg is $1 " ; exit 1 ;;
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
# The rest is filenames
|
||||
verilogFile=$@;
|
||||
|
||||
flags="$flags -fVPI_MODULE_PATH=${VPIModulePath}"
|
||||
|
||||
if test -z "${verilogFile}" ; then
|
||||
echo "Missing infile";
|
||||
echo "verilog [-Dmacro[=defn]] [-Iincludepath] [-X] [-x] [-o outputfilename] [-s topmodule] sourcefile[s]" ;
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
# Choose a target file suffix based on the target type.
|
||||
case "$target" in
|
||||
vvm) targetSuffix="" ;;
|
||||
xnf) targetSuffix=".xnf"
|
||||
functors="-Fsynth -Fnodangle -Fxnfio" ;;
|
||||
*) targetSuffix=".$target" ;;
|
||||
esac
|
||||
|
||||
|
||||
# If no output file is given should we guess one or...?
|
||||
# Assumes a few silly things if several files are given
|
||||
if test -z "${outputFile}" ; then
|
||||
outputFile=`echo ${verilogFile} | sed -e 's;.* ;;' | sed -e 's;\..*$;;'`
|
||||
outputFile="${outputFile}${targetSuffix}" ;
|
||||
fi
|
||||
|
||||
# Preprocess
|
||||
${execIVLPP} ${extDefines} ${extIncPath} -L -o ${tmpPPFile} ${verilogFile}
|
||||
if test $? -ne 0 ; then
|
||||
echo "Preprocessing failed. Terminating compilation."
|
||||
rm -f ${tmpPPFile}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Compile preprocessed verilog file
|
||||
${execIVL} -t ${target} -o ${tmpCCFile} ${topModule} ${functors} ${flags} ${tmpPPFile}
|
||||
if test $? -ne 0 ; then
|
||||
echo "Verilog compilation failed. Terminating compilation."
|
||||
rm -f ${tmpCCFile}
|
||||
exit 1
|
||||
fi
|
||||
rm -f ${tmpPPFile}
|
||||
|
||||
|
||||
case "${target}" in
|
||||
|
||||
"xnf") mv ${tmpCCFile} ${outputFile} ;;
|
||||
|
||||
"vvm") ${execCpp} -rdynamic -I${includedir} -L${libdir} ${tmpCCFile} -o ${outputFile} -lvvm @dllib@ ;
|
||||
if test $? -ne 0 ; then
|
||||
echo "C++ compilation failed. Terminating compilation."
|
||||
rm -f ${tmpCCFile}
|
||||
exit 1
|
||||
fi
|
||||
rm -f ${tmpCCFile} ;;
|
||||
|
||||
*) mv ${tmpCCFile} ${outputFile} ;;
|
||||
|
||||
esac
|
||||
|
||||
if test ${execute} ; then
|
||||
./${outputFile}
|
||||
fi
|
||||
+196
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: verinum.cc,v 1.9 1999/07/20 05:12:22 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verinum.cc,v 1.16 2000/02/23 04:43:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "verinum.h"
|
||||
@@ -25,12 +25,12 @@
|
||||
# include <cassert>
|
||||
|
||||
verinum::verinum()
|
||||
: bits_(0), nbits_(0), has_len_(false), string_flag_(false)
|
||||
: bits_(0), nbits_(0), has_len_(false), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
}
|
||||
|
||||
verinum::verinum(const V*bits, unsigned nbits, bool has_len)
|
||||
: has_len_(has_len), string_flag_(false)
|
||||
: has_len_(has_len), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
nbits_ = nbits;
|
||||
bits_ = new V [nbits];
|
||||
@@ -40,7 +40,7 @@ verinum::verinum(const V*bits, unsigned nbits, bool has_len)
|
||||
}
|
||||
|
||||
verinum::verinum(const string&str)
|
||||
: has_len_(true), string_flag_(true)
|
||||
: has_len_(true), has_sign_(false), string_flag_(true)
|
||||
{
|
||||
nbits_ = str.length() * 8;
|
||||
bits_ = new V [nbits_];
|
||||
@@ -61,7 +61,7 @@ verinum::verinum(const string&str)
|
||||
}
|
||||
|
||||
verinum::verinum(verinum::V val, unsigned n)
|
||||
: has_len_(true), string_flag_(false)
|
||||
: has_len_(true), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
nbits_ = n;
|
||||
bits_ = new V[nbits_];
|
||||
@@ -70,7 +70,7 @@ verinum::verinum(verinum::V val, unsigned n)
|
||||
}
|
||||
|
||||
verinum::verinum(unsigned long val, unsigned n)
|
||||
: has_len_(true), string_flag_(false)
|
||||
: has_len_(true), has_sign_(false), string_flag_(false)
|
||||
{
|
||||
nbits_ = n;
|
||||
bits_ = new V[nbits_];
|
||||
@@ -86,6 +86,7 @@ verinum::verinum(const verinum&that)
|
||||
nbits_ = that.nbits_;
|
||||
bits_ = new V[nbits_];
|
||||
has_len_ = that.has_len_;
|
||||
has_sign_ = that.has_sign_;
|
||||
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1)
|
||||
bits_[idx] = that.bits_[idx];
|
||||
}
|
||||
@@ -97,6 +98,7 @@ verinum::verinum(const verinum&that, unsigned nbits)
|
||||
nbits_ = nbits;
|
||||
bits_ = new V[nbits_];
|
||||
has_len_ = true;
|
||||
has_sign_ = false;
|
||||
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1)
|
||||
bits_[idx] = that.bits_[idx];
|
||||
}
|
||||
@@ -116,6 +118,7 @@ verinum& verinum::operator= (const verinum&that)
|
||||
bits_[idx] = that.bits_[idx];
|
||||
|
||||
has_len_ = that.has_len_;
|
||||
has_sign_ = that.has_sign_;
|
||||
string_flag_ = that.string_flag_;
|
||||
return *this;
|
||||
}
|
||||
@@ -164,8 +167,9 @@ signed long verinum::as_long() const
|
||||
|
||||
signed long val = 0;
|
||||
|
||||
// Extend the sign bit to fill the long.
|
||||
if (bits_[nbits_-1] == V1)
|
||||
// Extend the sign bit to fill the long. (But only for signed
|
||||
// numbers.)
|
||||
if (has_sign_ && (bits_[nbits_-1] == V1))
|
||||
val = -1;
|
||||
|
||||
for (unsigned idx = nbits_ ; idx > 0 ; idx -= 1) {
|
||||
@@ -213,6 +217,18 @@ string verinum::as_string() const
|
||||
return result;
|
||||
}
|
||||
|
||||
bool verinum::is_before(const verinum&that) const
|
||||
{
|
||||
if (that.nbits_ > nbits_) return true;
|
||||
if (that.nbits_ < nbits_) return false;
|
||||
|
||||
for (unsigned idx = nbits_ ; idx > 0 ; idx -= 1) {
|
||||
if (bits_[idx-1] < that.bits_[idx-1]) return true;
|
||||
if (bits_[idx-1] > that.bits_[idx-1]) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool verinum::is_defined() const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1) {
|
||||
@@ -296,20 +312,186 @@ ostream& operator<< (ostream&o, const verinum&v)
|
||||
return o;
|
||||
}
|
||||
|
||||
bool operator == (const verinum&left, const verinum&right)
|
||||
verinum::V operator == (const verinum&left, const verinum&right)
|
||||
{
|
||||
if (left.len() != right.len())
|
||||
return false;
|
||||
return verinum::V0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < left.len() ; idx += 1)
|
||||
if (left[idx] != right[idx])
|
||||
return false;
|
||||
return verinum::V0;
|
||||
|
||||
return true;
|
||||
return verinum::V1;
|
||||
}
|
||||
|
||||
verinum::V operator <= (const verinum&left, const verinum&right)
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = left.len() ; idx > right.len() ; idx -= 1) {
|
||||
if (left[idx-1] != verinum::V0) return verinum::V0;
|
||||
}
|
||||
|
||||
for (idx = right.len() ; idx > left.len() ; idx -= 1) {
|
||||
if (right[idx-1] != verinum::V0) return verinum::V0;
|
||||
}
|
||||
|
||||
while (idx > 0) {
|
||||
if (left[idx-1] == verinum::Vx) return verinum::Vx;
|
||||
if (left[idx-1] == verinum::Vz) return verinum::Vx;
|
||||
if (right[idx-1] == verinum::Vx) return verinum::Vx;
|
||||
if (right[idx-1] == verinum::Vz) return verinum::Vx;
|
||||
if (left[idx-1] > right[idx-1]) return verinum::V0;
|
||||
idx -= 1;
|
||||
}
|
||||
|
||||
return verinum::V1;
|
||||
}
|
||||
|
||||
static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c)
|
||||
{
|
||||
unsigned sum = 0;
|
||||
switch (c) {
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
c = verinum::Vx;
|
||||
return verinum::Vx;
|
||||
case verinum::V0:
|
||||
break;
|
||||
case verinum::V1:
|
||||
sum += 1;
|
||||
}
|
||||
|
||||
switch (l) {
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
c = verinum::Vx;
|
||||
return verinum::Vx;
|
||||
case verinum::V0:
|
||||
break;
|
||||
case verinum::V1:
|
||||
sum += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (r) {
|
||||
case verinum::Vx:
|
||||
case verinum::Vz:
|
||||
c = verinum::Vx;
|
||||
return verinum::Vx;
|
||||
case verinum::V0:
|
||||
break;
|
||||
case verinum::V1:
|
||||
sum += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sum & 2)
|
||||
c = verinum::V1;
|
||||
else
|
||||
c = verinum::V0;
|
||||
if (sum & 1)
|
||||
return verinum::V1;
|
||||
else
|
||||
return verinum::V0;
|
||||
}
|
||||
|
||||
verinum v_not(const verinum&left)
|
||||
{
|
||||
verinum val = left;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
switch (val[idx]) {
|
||||
case verinum::V0:
|
||||
val.set(idx, verinum::V1);
|
||||
break;
|
||||
case verinum::V1:
|
||||
val.set(idx, verinum::V0);
|
||||
break;
|
||||
default:
|
||||
val.set(idx, verinum::Vx);
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Addition works a bit at a time, from the least significant up to
|
||||
* the most significant.
|
||||
*/
|
||||
verinum operator + (const verinum&left, const verinum&right)
|
||||
{
|
||||
unsigned min = left.len();
|
||||
if (right.len() < min) min = right.len();
|
||||
|
||||
unsigned max = left.len();
|
||||
if (right.len() > max) max = right.len();
|
||||
|
||||
verinum val (verinum::V0, max);
|
||||
|
||||
verinum::V carry = verinum::V0;
|
||||
for (unsigned idx = 0 ; idx < min ; idx += 1)
|
||||
val.set(idx, add_with_carry(left[idx], right[idx], carry));
|
||||
|
||||
if (left.len() > right.len()) {
|
||||
for (unsigned idx = min ; idx < max ; idx += 1)
|
||||
val.set(idx,add_with_carry(left[idx], verinum::V0, carry));
|
||||
} else {
|
||||
for (unsigned idx = min ; idx < max ; idx += 1)
|
||||
val.set(idx, add_with_carry(verinum::V0, right[idx], carry));
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
verinum operator - (const verinum&left, const verinum&r)
|
||||
{
|
||||
verinum right = v_not(r);
|
||||
unsigned min = left.len();
|
||||
if (right.len() < min) min = right.len();
|
||||
|
||||
unsigned max = left.len();
|
||||
if (right.len() > max) max = right.len();
|
||||
|
||||
verinum val (verinum::V0, max);
|
||||
|
||||
verinum::V carry = verinum::V1;
|
||||
for (unsigned idx = 0 ; idx < min ; idx += 1)
|
||||
val.set(idx, add_with_carry(left[idx], right[idx], carry));
|
||||
|
||||
if (left.len() > right.len()) {
|
||||
for (unsigned idx = min ; idx < max ; idx += 1)
|
||||
val.set(idx,add_with_carry(left[idx], verinum::V0, carry));
|
||||
} else {
|
||||
for (unsigned idx = min ; idx < max ; idx += 1)
|
||||
val.set(idx, add_with_carry(verinum::V0, right[idx], carry));
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: verinum.cc,v $
|
||||
* Revision 1.16 2000/02/23 04:43:43 steve
|
||||
* Some compilers do not accept the not symbol.
|
||||
*
|
||||
* Revision 1.15 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.14 2000/01/07 03:45:49 steve
|
||||
* Initial support for signed constants.
|
||||
*
|
||||
* Revision 1.13 2000/01/06 05:57:06 steve
|
||||
* Only sign-extend unsized numbers.
|
||||
*
|
||||
* Revision 1.12 1999/11/06 16:00:17 steve
|
||||
* Put number constants into a static table.
|
||||
*
|
||||
* Revision 1.11 1999/10/22 23:57:53 steve
|
||||
* do the <= in bits, not numbers.
|
||||
*
|
||||
* Revision 1.10 1999/10/10 23:29:37 steve
|
||||
* Support evaluating + operator at compile time.
|
||||
*
|
||||
* Revision 1.9 1999/07/20 05:12:22 steve
|
||||
* Implement the set method.
|
||||
*
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: verinum.h,v 1.5 1999/05/13 04:02:09 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verinum.h,v 1.11 2000/02/23 04:43:43 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -56,6 +56,9 @@ class verinum {
|
||||
// in some way.
|
||||
bool has_len() const { return has_len_; }
|
||||
|
||||
bool has_sign(bool flag) { has_sign_ = flag; return has_sign_; }
|
||||
bool has_sign() const { return has_sign_; }
|
||||
|
||||
// A number is "defined" if there are no x or z bits in its value.
|
||||
bool is_defined() const;
|
||||
|
||||
@@ -63,6 +66,9 @@ class verinum {
|
||||
// an ascii description instead of a number value.
|
||||
bool is_string() const { return string_flag_; }
|
||||
|
||||
// Comparison for use in sorting algorithms.
|
||||
bool is_before(const verinum&that) const;
|
||||
|
||||
// Individual bits can be accessed with the get and set
|
||||
// methods.
|
||||
V get(unsigned idx) const;
|
||||
@@ -79,6 +85,7 @@ class verinum {
|
||||
V* bits_;
|
||||
unsigned nbits_;
|
||||
bool has_len_;
|
||||
bool has_sign_;
|
||||
|
||||
// These are some convenience flags that help us do a better
|
||||
// job of pretty-printing values.
|
||||
@@ -90,10 +97,33 @@ class ostream;
|
||||
extern ostream& operator<< (ostream&, const verinum&);
|
||||
extern ostream& operator<< (ostream&, verinum::V);
|
||||
|
||||
extern bool operator == (const verinum&left, const verinum&right);
|
||||
extern verinum::V operator == (const verinum&left, const verinum&right);
|
||||
extern verinum::V operator <= (const verinum&left, const verinum&right);
|
||||
extern verinum operator + (const verinum&left, const verinum&right);
|
||||
extern verinum operator - (const verinum&left, const verinum&right);
|
||||
|
||||
extern verinum v_not(const verinum&left);
|
||||
|
||||
/*
|
||||
* $Log: verinum.h,v $
|
||||
* Revision 1.11 2000/02/23 04:43:43 steve
|
||||
* Some compilers do not accept the not symbol.
|
||||
*
|
||||
* Revision 1.10 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.9 2000/01/07 03:45:49 steve
|
||||
* Initial support for signed constants.
|
||||
*
|
||||
* Revision 1.8 1999/11/06 16:00:17 steve
|
||||
* Put number constants into a static table.
|
||||
*
|
||||
* Revision 1.7 1999/10/22 23:57:53 steve
|
||||
* do the <= in bits, not numbers.
|
||||
*
|
||||
* Revision 1.6 1999/10/10 23:29:37 steve
|
||||
* Support evaluating + operator at compile time.
|
||||
*
|
||||
* Revision 1.5 1999/05/13 04:02:09 steve
|
||||
* More precise handling of verinum bit lengths.
|
||||
*
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: verireal.cc,v 1.1 1999/06/15 02:50:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verireal.cc,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "verireal.h"
|
||||
@@ -92,6 +92,9 @@ verireal::~verireal()
|
||||
|
||||
/*
|
||||
* $Log: verireal.cc,v $
|
||||
* Revision 1.2 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/06/15 02:50:02 steve
|
||||
* Add lexical support for real numbers.
|
||||
*
|
||||
|
||||
+5
-2
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: verireal.h,v 1.1 1999/06/15 02:50:02 steve Exp $"
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: verireal.h,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
class verireal {
|
||||
@@ -37,6 +37,9 @@ class verireal {
|
||||
|
||||
/*
|
||||
* $Log: verireal.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/06/15 02:50:02 steve
|
||||
* Add lexical support for real numbers.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
HOW IT WORKS
|
||||
|
||||
The VPI interface for Icarus Verilog works by creating from a
|
||||
collection of PLI applications a single vpi module. The vpi module
|
||||
includes compiled code for the applications linked together (with any
|
||||
other libraries that the applications need) into a module with a
|
||||
single exported symbol, the vlog_startup_routines array.
|
||||
|
||||
The product that wishes to invoke the module (normally at run time)
|
||||
loads the module, locates the vlog_startup_routines table, and calls
|
||||
all the startup routines contained in that table. It is possible for a
|
||||
product to link with many modules. In that case, all the modules are
|
||||
linked in and startup routines are called in order.
|
||||
|
||||
The product that uses vpi modules uses the environment variable
|
||||
VPI_MODULE_PATH as a ':' separated list of directories. This is the
|
||||
module search path. When a module is specified by name (using whatever
|
||||
means the product supports) the module search path is scanned until
|
||||
the module is located.
|
||||
|
||||
The special module name "system.vpi" is part of the core Icarus
|
||||
Verilog distribution and includes implementations of the standard
|
||||
system tasks/functions.
|
||||
|
||||
COMPILING A VPI MODULE (LINUX)
|
||||
|
||||
To compile a module, first compile down to object files all the PLI
|
||||
applications that you wish to include in the module. Then, create a
|
||||
small "C" source file that defines only the startup table like so:
|
||||
|
||||
extern void hello_register();
|
||||
void (*vlog_startup_routines[])() = {
|
||||
hello_register,
|
||||
0
|
||||
};
|
||||
|
||||
Compile this table source down to its object file, as well. Finally,
|
||||
link the application with the command:
|
||||
|
||||
cc -o foo.vpi -shared <all the .o files>
|
||||
|
||||
No VPI libraries need to be included because the product that loads
|
||||
the module will supply all the standard vpi functions. If you use any
|
||||
non-vpi library functions, you may need to include libraries to
|
||||
support them.
|
||||
|
||||
The resulting foo.vpi file is the vpi module. Place it in a location
|
||||
where the product to use it can locate it.
|
||||
|
||||
|
||||
CAVEAT EMPTOR
|
||||
|
||||
Only the calltf function is supported. The compiletf and sizetf
|
||||
functions are invoked at compile time, and the ivl compiler does not
|
||||
yet support VPI.
|
||||
@@ -0,0 +1,4 @@
|
||||
Makefile
|
||||
sys_readmem_lex.c
|
||||
system.vpi
|
||||
dep
|
||||
@@ -0,0 +1,85 @@
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version. In order to redistribute the software in
|
||||
# binary form, you will need a Picture Elements Binary Software
|
||||
# License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.9 2000/01/23 23:54:36 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@ -fpic
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: system.vpi
|
||||
|
||||
%.o dep/%.d: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) -I$(srcdir) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = sys_table.o sys_display.o sys_finish.o sys_readmem.o sys_readmem_lex.o \
|
||||
sys_vcd.o
|
||||
|
||||
system.vpi: $O
|
||||
$(CC) -shared -o $@ $O
|
||||
|
||||
sys_readmem_lex.c: sys_readmem_lex.lex
|
||||
flex -t -Preadmem sys_readmem_lex.lex > sys_readmem_lex.c
|
||||
|
||||
clean:
|
||||
rm -f *.o dep/*.d
|
||||
|
||||
install: all installdirs $(libdir)/ivl/system.vpi \
|
||||
$(includedir)/vpi_user.h
|
||||
|
||||
$(libdir)/ivl/system.vpi: ./system.vpi
|
||||
$(INSTALL_DATA) ./system.vpi $(libdir)/ivl/system.vpi
|
||||
|
||||
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
|
||||
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/system.vpi
|
||||
rm -f $(includedir)/vpi_user.h
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
@@ -0,0 +1,454 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_display.c,v 1.11 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include <assert.h>
|
||||
# include <string.h>
|
||||
# include <ctype.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
struct strobe_cb_info {
|
||||
char*name;
|
||||
vpiHandle*items;
|
||||
unsigned nitems;
|
||||
};
|
||||
|
||||
static void array_from_iterator(struct strobe_cb_info*info, vpiHandle argv)
|
||||
{
|
||||
vpiHandle item;
|
||||
unsigned nitems = 1;
|
||||
vpiHandle*items = malloc(sizeof(vpiHandle));
|
||||
items[0] = vpi_scan(argv);
|
||||
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
|
||||
items = realloc(items, (nitems+1)*sizeof(vpiHandle));
|
||||
items[nitems] = item;
|
||||
nitems += 1;
|
||||
}
|
||||
|
||||
info->nitems = nitems;
|
||||
info->items = items;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If $display discovers a string as a parameter, this function is
|
||||
* called to process it as a format string. I need the argv handle as
|
||||
* well so that I can look for arguments as I move forward through the
|
||||
* string.
|
||||
*/
|
||||
static int format_str(char*fmt, int argc, vpiHandle*argv)
|
||||
{
|
||||
s_vpi_value value;
|
||||
char buf[256];
|
||||
char*cp = fmt;
|
||||
int idx;
|
||||
|
||||
assert(fmt);
|
||||
|
||||
idx = 0;
|
||||
|
||||
while (*cp) {
|
||||
size_t cnt = strcspn(cp, "%\\");
|
||||
if (cnt > 0) {
|
||||
if (cnt >= sizeof buf)
|
||||
cnt = sizeof buf - 1;
|
||||
strncpy(buf, cp, cnt);
|
||||
buf[cnt] = 0;
|
||||
vpi_printf("%s", buf);
|
||||
cp += cnt;
|
||||
|
||||
} else if (*cp == '%') {
|
||||
int fsize = -1;
|
||||
|
||||
cp += 1;
|
||||
if (isdigit(*cp))
|
||||
fsize = strtoul(cp, &cp, 10);
|
||||
|
||||
switch (*cp) {
|
||||
case 0:
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(argv[idx++], &value);
|
||||
vpi_printf("%s", value.value.str);
|
||||
cp += 1;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
value.format = vpiDecStrVal;
|
||||
vpi_get_value(argv[idx++], &value);
|
||||
vpi_printf("%s", value.value.str);
|
||||
cp += 1;
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
case 'x':
|
||||
case 'X':
|
||||
value.format = vpiHexStrVal;
|
||||
vpi_get_value(argv[idx++], &value);
|
||||
vpi_printf("%s", value.value.str);
|
||||
cp += 1;
|
||||
break;
|
||||
case 'm':
|
||||
vpi_printf("%s", vpi_get_str(vpiFullName, argv[idx]));
|
||||
idx += 1;
|
||||
cp += 1;
|
||||
break;
|
||||
case 'o':
|
||||
case 'O':
|
||||
value.format = vpiOctStrVal;
|
||||
vpi_get_value(argv[idx++], &value);
|
||||
vpi_printf("%s", value.value.str);
|
||||
cp += 1;
|
||||
break;
|
||||
case 't':
|
||||
case 'T':
|
||||
value.format = vpiDecStrVal;
|
||||
vpi_get_value(argv[idx++], &value);
|
||||
vpi_printf("%s", value.value.str);
|
||||
cp += 1;
|
||||
break;
|
||||
case '%':
|
||||
vpi_printf("%%");
|
||||
cp += 1;
|
||||
break;
|
||||
default:
|
||||
vpi_printf("%c", *cp);
|
||||
cp += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
cp += 1;
|
||||
switch (*cp) {
|
||||
case 0:
|
||||
break;
|
||||
case 'n':
|
||||
vpi_printf("\n");
|
||||
cp += 1;
|
||||
break;
|
||||
default:
|
||||
vpi_printf("%c", *cp);
|
||||
cp += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static void do_display(struct strobe_cb_info*info)
|
||||
{
|
||||
s_vpi_value value;
|
||||
int idx;
|
||||
|
||||
for (idx = 0 ; idx < info->nitems ; idx += 1) {
|
||||
vpiHandle item = info->items[idx];
|
||||
|
||||
switch (vpi_get(vpiType, item)) {
|
||||
|
||||
case 0:
|
||||
vpi_printf(" ");
|
||||
break;
|
||||
|
||||
case vpiConstant:
|
||||
if (vpi_get(vpiConstType, item) == vpiStringConst) {
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(item, &value);
|
||||
idx += format_str(value.value.str,
|
||||
info->nitems-idx-1,
|
||||
info->items+idx+1);
|
||||
} else {
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(item, &value);
|
||||
vpi_printf("%s", value.value.str);
|
||||
}
|
||||
break;
|
||||
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
case vpiMemoryWord:
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(item, &value);
|
||||
vpi_printf("%s", value.value.str);
|
||||
break;
|
||||
|
||||
case vpiTimeVar:
|
||||
value.format = vpiTimeVal;
|
||||
vpi_get_value(item, &value);
|
||||
vpi_printf("%u", value.value.time->low);
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_printf("?");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sys_display_calltf(char *name)
|
||||
{
|
||||
struct strobe_cb_info info;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
|
||||
array_from_iterator(&info, argv);
|
||||
|
||||
do_display(&info);
|
||||
|
||||
free(info.items);
|
||||
|
||||
if (strcmp(name,"$display") == 0)
|
||||
vpi_printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The strobe implementation takes the parameter handles that are
|
||||
* passed to the calltf and puts them in to an array for safe
|
||||
* keeping. That array (and other bookkeeping) is passed, via the
|
||||
* struct_cb_info object, to the REadOnlySych function strobe_cb,
|
||||
* where it is use to perform the actual formatting and printing.
|
||||
*/
|
||||
|
||||
static int strobe_cb(p_cb_data cb)
|
||||
{
|
||||
struct strobe_cb_info*info = (struct strobe_cb_info*)cb->user_data;
|
||||
|
||||
do_display(info);
|
||||
|
||||
vpi_printf("\n");
|
||||
|
||||
free(info->name);
|
||||
free(info->items);
|
||||
free(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_strobe_calltf(char*name)
|
||||
{
|
||||
struct t_cb_data cb;
|
||||
struct t_vpi_time time;
|
||||
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
|
||||
struct strobe_cb_info*info = calloc(1, sizeof(struct strobe_cb_info));
|
||||
|
||||
array_from_iterator(info, argv);
|
||||
info->name = strdup(name);
|
||||
|
||||
time.type = vpiSimTime;
|
||||
time.low = 0;
|
||||
time.high = 0;
|
||||
|
||||
cb.reason = cbReadOnlySynch;
|
||||
cb.cb_rtn = strobe_cb;
|
||||
cb.time = &time;
|
||||
cb.obj = 0;
|
||||
cb.user_data = (char*)info;
|
||||
vpi_register_cb(&cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The $monitor system task works by managing these static variables,
|
||||
* and the cbValueChange callbacks associated with registers and
|
||||
* nets. Note that it is proper to keep the state in static variables
|
||||
* because there can only be one monitor at a time pending (even
|
||||
* though that monitor may be watching many variables).
|
||||
*/
|
||||
|
||||
static struct strobe_cb_info monitor_info = { 0, 0, 0 };
|
||||
static int monitor_scheduled = 0;
|
||||
static vpiHandle *monitor_callbacks = 0;
|
||||
|
||||
static int monitor_cb_2(p_cb_data cb)
|
||||
{
|
||||
do_display(&monitor_info);
|
||||
vpi_printf("\n");
|
||||
monitor_scheduled = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_cb_1(p_cb_data cause)
|
||||
{
|
||||
struct t_cb_data cb;
|
||||
struct t_vpi_time time;
|
||||
|
||||
/* Reschedule this event so that it happens for the next
|
||||
trigger on this variable. */
|
||||
cb = *cause;
|
||||
vpi_register_cb(&cb);
|
||||
|
||||
if (monitor_scheduled) return 0;
|
||||
|
||||
/* This this action caused the first trigger, then schedule
|
||||
the monitor to happen at the end of the time slice and mark
|
||||
it as scheduled. */
|
||||
monitor_scheduled += 1;
|
||||
time.type = vpiSimTime;
|
||||
time.low = 0;
|
||||
time.high = 0;
|
||||
|
||||
cb.reason = cbReadOnlySynch;
|
||||
cb.cb_rtn = monitor_cb_2;
|
||||
cb.time = &time;
|
||||
cb.obj = 0;
|
||||
vpi_register_cb(&cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_monitor_calltf(char*name)
|
||||
{
|
||||
unsigned idx;
|
||||
struct t_cb_data cb;
|
||||
struct t_vpi_time time;
|
||||
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
|
||||
if (monitor_callbacks) {
|
||||
for (idx = 0 ; idx < monitor_info.nitems ; idx += 1)
|
||||
if (monitor_callbacks[idx])
|
||||
vpi_remove_cb(monitor_callbacks[idx]);
|
||||
|
||||
free(monitor_callbacks);
|
||||
monitor_callbacks = 0;
|
||||
|
||||
free(monitor_info.items);
|
||||
free(monitor_info.name);
|
||||
monitor_info.items = 0;
|
||||
monitor_info.nitems = 0;
|
||||
monitor_info.name = 0;
|
||||
}
|
||||
|
||||
array_from_iterator(&monitor_info, argv);
|
||||
monitor_info.name = strdup(name);
|
||||
|
||||
monitor_callbacks = calloc(monitor_info.nitems, sizeof(vpiHandle));
|
||||
|
||||
time.type = vpiSuppressTime;
|
||||
cb.reason = cbValueChange;
|
||||
cb.cb_rtn = monitor_cb_1;
|
||||
cb.time = &time;
|
||||
for (idx = 0 ; idx < monitor_info.nitems ; idx += 1) {
|
||||
|
||||
switch (vpi_get(vpiType, monitor_info.items[idx])) {
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
cb.obj = monitor_info.items[idx];
|
||||
monitor_callbacks[idx] = vpi_register_cb(&cb);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_display_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$display";
|
||||
tf_data.calltf = sys_display_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$display";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$write";
|
||||
tf_data.calltf = sys_display_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$write";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$strobe";
|
||||
tf_data.calltf = sys_strobe_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$strobe";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$monitor";
|
||||
tf_data.calltf = sys_monitor_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$monitor";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: sys_display.c,v $
|
||||
* Revision 1.11 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.10 2000/02/13 19:18:27 steve
|
||||
* Accept memory words as parameter to $display.
|
||||
*
|
||||
* Revision 1.9 1999/11/07 02:25:07 steve
|
||||
* Add the $monitor implementation.
|
||||
*
|
||||
* Revision 1.8 1999/11/06 23:32:14 steve
|
||||
* Unify display and strobe format routines.
|
||||
*
|
||||
* Revision 1.7 1999/11/06 22:16:50 steve
|
||||
* Get the $strobe task working.
|
||||
*
|
||||
* Revision 1.6 1999/10/29 03:37:22 steve
|
||||
* Support vpiValueChance callbacks.
|
||||
*
|
||||
* Revision 1.5 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.4 1999/10/10 14:50:50 steve
|
||||
* Add Octal dump format.
|
||||
*
|
||||
* Revision 1.3 1999/10/08 17:47:49 steve
|
||||
* Add the %t formatting escape.
|
||||
*
|
||||
* Revision 1.2 1999/09/29 01:41:18 steve
|
||||
* Support the $write system task, and have the
|
||||
* vpi_scan function free iterators as needed.
|
||||
*
|
||||
* Revision 1.1 1999/08/15 01:23:56 steve
|
||||
* Convert vvm to implement system tasks with vpi.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_finish.c,v 1.4 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
|
||||
static int sys_finish_calltf(char *xx)
|
||||
{
|
||||
vpi_sim_control(vpiFinish, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_finish_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$finish";
|
||||
tf_data.calltf = sys_finish_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sys_finish.c,v $
|
||||
* Revision 1.4 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/08/28 02:10:44 steve
|
||||
* Call the right vpiFinish code.
|
||||
*
|
||||
* Revision 1.2 1999/08/19 02:51:03 steve
|
||||
* Add vpi_sim_control
|
||||
*
|
||||
* Revision 1.1 1999/08/15 01:23:56 steve
|
||||
* Convert vvm to implement system tasks with vpi.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_readmem.c,v 1.5 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <assert.h>
|
||||
# include "sys_readmem_lex.h"
|
||||
|
||||
static int sys_readmem_calltf(char*name)
|
||||
{
|
||||
int code;
|
||||
int wwid;
|
||||
char*path;
|
||||
FILE*file;
|
||||
s_vpi_value value;
|
||||
vpiHandle words;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: file name parameter missing.\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiType, item) != vpiConstant) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiConstType, item) != vpiStringConst) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(item, &value);
|
||||
path = strdup(value.value.str);
|
||||
|
||||
/* Get and check the second paramter. It must be a memory. */
|
||||
item = vpi_scan(argv);
|
||||
if (item == 0) {
|
||||
vpi_printf("%s: Missing memory parameter\n", name);
|
||||
free(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiType, item) != vpiMemory) {
|
||||
vpi_printf("%s: Second parameter must be a memory.\n", name);
|
||||
free(path);
|
||||
vpi_free_object(argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXXX remaining parameters not supported. */
|
||||
vpi_free_object(argv);
|
||||
|
||||
/* Open the data file. */
|
||||
file = fopen(path, "r");
|
||||
if (file == 0) {
|
||||
vpi_printf("%s: Unable to open %s for reading.\n", name, path);
|
||||
free(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
words = vpi_iterate(vpiMemoryWord, item);
|
||||
assert(words);
|
||||
|
||||
item = vpi_scan(words);
|
||||
wwid = vpi_get(vpiSize, item);
|
||||
|
||||
value.format = vpiVectorVal;
|
||||
value.value.vector = calloc((wwid+31)/32, sizeof (s_vpi_vecval));
|
||||
if (strcmp(name,"$readmemb") == 0)
|
||||
sys_readmem_start_file(file, 1, wwid, value.value.vector);
|
||||
else
|
||||
sys_readmem_start_file(file, 0, wwid, value.value.vector);
|
||||
|
||||
while (item && ((code = readmemlex()) != 0)) {
|
||||
switch (code) {
|
||||
case MEM_ADDRESS:
|
||||
vpi_printf("XXXX addresses not supported\n");
|
||||
break;
|
||||
case MEM_WORD:
|
||||
vpi_put_value(item, &value, 0, vpiNoDelay);
|
||||
item = vpi_scan(words);
|
||||
break;
|
||||
default:
|
||||
vpi_printf("Huh?! (%d)\n", code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item) vpi_free_object(words);
|
||||
free(value.value.vector);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_readmem_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$readmemh";
|
||||
tf_data.calltf = sys_readmem_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$readmemh";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$readmemb";
|
||||
tf_data.calltf = sys_readmem_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$readmemb";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sys_readmem.c,v $
|
||||
* Revision 1.5 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.4 2000/01/23 23:54:36 steve
|
||||
* Compile time problems with vpi_user.h
|
||||
*
|
||||
* Revision 1.3 1999/12/15 04:35:34 steve
|
||||
* Add readmemb.
|
||||
*
|
||||
* Revision 1.2 1999/12/15 04:02:38 steve
|
||||
* Excess warning.
|
||||
*
|
||||
* Revision 1.1 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef __sys_readmem_lex_H
|
||||
#define __sys_readmem_lex_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: sys_readmem_lex.h,v 1.2 2000/01/23 23:54:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
# include "vpi_user.h"
|
||||
|
||||
# define MEM_ADDRESS 257
|
||||
# define MEM_WORD 258
|
||||
|
||||
extern void sys_readmem_start_file(FILE*in, int bin_flag,
|
||||
unsigned width, struct t_vpi_vecval*val);
|
||||
extern int readmemlex();
|
||||
|
||||
/*
|
||||
* $Log: sys_readmem_lex.h,v $
|
||||
* Revision 1.2 2000/01/23 23:54:36 steve
|
||||
* Compile time problems with vpi_user.h
|
||||
*
|
||||
* Revision 1.1 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_readmem_lex.lex,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
# include "sys_readmem_lex.h"
|
||||
# include <string.h>
|
||||
static void make_hex_value();
|
||||
static void make_bin_value();
|
||||
%}
|
||||
|
||||
%x BIN
|
||||
%x HEX
|
||||
|
||||
%option noyywrap
|
||||
%%
|
||||
|
||||
<*>"//".* { ; }
|
||||
<*>[ \t\f\n\r] { ; }
|
||||
|
||||
<*>@[0-9a-fA-F]+ { return MEM_ADDRESS; }
|
||||
<HEX>[0-9a-fA-FxXzZ_]+ { make_hex_value(); return MEM_WORD; }
|
||||
<BIN>[01_]+ { make_bin_value(); return MEM_WORD; }
|
||||
|
||||
%%
|
||||
static unsigned word_width = 0;
|
||||
static struct t_vpi_vecval*vecval = 0;
|
||||
|
||||
static void make_hex_value()
|
||||
{
|
||||
char*beg = yytext;
|
||||
char*end = beg + strlen(beg);
|
||||
struct t_vpi_vecval*cur;
|
||||
int idx;
|
||||
int width = 0, word_max = word_width;
|
||||
|
||||
for (idx = 0, cur = vecval ; idx < word_max ; idx += 32, cur += 1) {
|
||||
cur->aval = 0;
|
||||
cur->bval = 0;
|
||||
}
|
||||
|
||||
cur = vecval;
|
||||
while ((width < word_max) && (end > beg)) {
|
||||
int aval, bval;
|
||||
|
||||
end -= 1;
|
||||
if (*end == '_') continue;
|
||||
switch (*end) {
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
aval = *end - '0';
|
||||
bval = 0;
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
aval = *end - 'a' + 10;
|
||||
bval = 0;
|
||||
break;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
aval = *end - 'A' + 10;
|
||||
bval = 0;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
aval = 15;
|
||||
bval = 15;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
aval = 0;
|
||||
bval = 15;
|
||||
break;
|
||||
}
|
||||
|
||||
cur->aval |= aval << width;
|
||||
cur->bval |= bval << width;
|
||||
width += 4;
|
||||
if (width == 32) {
|
||||
cur += 1;
|
||||
width = 0;
|
||||
word_max -= 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void make_bin_value()
|
||||
{
|
||||
char*beg = yytext;
|
||||
char*end = beg + strlen(beg);
|
||||
struct t_vpi_vecval*cur;
|
||||
int idx;
|
||||
int width = 0, word_max = word_width;
|
||||
|
||||
for (idx = 0, cur = vecval ; idx < word_max ; idx += 32, cur += 1) {
|
||||
cur->aval = 0;
|
||||
cur->bval = 0;
|
||||
}
|
||||
|
||||
cur = vecval;
|
||||
while ((width < word_max) && (end > beg)) {
|
||||
int aval, bval;
|
||||
|
||||
end -= 1;
|
||||
if (*end == '_') continue;
|
||||
switch (*end) {
|
||||
case '0':
|
||||
case '1':
|
||||
aval = *end - '0';
|
||||
bval = 0;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
aval = 1;
|
||||
bval = 1;
|
||||
break;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
aval = 0;
|
||||
bval = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
cur->aval |= aval << width;
|
||||
cur->bval |= bval << width;
|
||||
width += 1;
|
||||
if (width == 32) {
|
||||
cur += 1;
|
||||
width = 0;
|
||||
word_max -= 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sys_readmem_start_file(FILE*in, int bin_flag,
|
||||
unsigned width, struct t_vpi_vecval *vv)
|
||||
{
|
||||
yyin = in;
|
||||
YY_FLUSH_BUFFER;
|
||||
BEGIN(bin_flag? BIN : HEX);
|
||||
word_width = width;
|
||||
vecval = vv;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_table.c,v 1.4 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
extern void sys_finish_register();
|
||||
extern void sys_display_register();
|
||||
extern void sys_readmem_register();
|
||||
extern void sys_vcd_register();
|
||||
|
||||
void (*vlog_startup_routines[])() = {
|
||||
sys_finish_register,
|
||||
sys_display_register,
|
||||
sys_readmem_register,
|
||||
sys_vcd_register,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: sys_table.c,v $
|
||||
* Revision 1.4 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.3 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.2 1999/11/07 20:33:30 steve
|
||||
* Add VCD output and related system tasks.
|
||||
*
|
||||
* Revision 1.1 1999/08/15 01:23:56 steve
|
||||
* Convert vvm to implement system tasks with vpi.
|
||||
*
|
||||
*/
|
||||
|
||||
+284
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: sys_vcd.c,v 1.7 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file contains the implementations of the VCD related
|
||||
* funcitons.
|
||||
*/
|
||||
|
||||
# include "vpi_user.h"
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
static FILE*dump_file = 0;
|
||||
|
||||
struct vcd_info {
|
||||
vpiHandle item;
|
||||
vpiHandle cb;
|
||||
struct t_vpi_time time;
|
||||
char*ident;
|
||||
struct vcd_info*next;
|
||||
};
|
||||
|
||||
static struct vcd_info*vcd_list = 0;
|
||||
unsigned long vcd_cur_time = 0;
|
||||
|
||||
static void show_this_item(struct vcd_info*info)
|
||||
{
|
||||
s_vpi_value value;
|
||||
|
||||
if (vpi_get(vpiSize, info->item) == 1) {
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(info->item, &value);
|
||||
fprintf(dump_file, "%s%s\n", value.value.str, info->ident);
|
||||
} else {
|
||||
value.format = vpiBinStrVal;
|
||||
vpi_get_value(info->item, &value);
|
||||
fprintf(dump_file, "b%s %s\n", value.value.str, info->ident);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function writes out all the traced variables, whether they
|
||||
* changed or not.
|
||||
*/
|
||||
static void vcd_checkpoint()
|
||||
{
|
||||
struct vcd_info*cur;
|
||||
|
||||
for (cur = vcd_list ; cur ; cur = cur->next)
|
||||
show_this_item(cur);
|
||||
}
|
||||
|
||||
static int variable_cb(p_cb_data cause)
|
||||
{
|
||||
unsigned long now = cause->time->low;
|
||||
struct t_cb_data cb;
|
||||
struct vcd_info*info = (struct vcd_info*)cause->user_data;
|
||||
|
||||
/* Reschedule this event so that it happens for the next
|
||||
trigger on this variable. */
|
||||
cb = *cause;
|
||||
vpi_register_cb(&cb);
|
||||
|
||||
if (now != vcd_cur_time) {
|
||||
fprintf(dump_file, "#%lu\n", now);
|
||||
vcd_cur_time = now;
|
||||
}
|
||||
|
||||
show_this_item(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_dumpall_calltf(char*name)
|
||||
{
|
||||
s_vpi_time now;
|
||||
vpi_get_time(0, &now);
|
||||
fprintf(dump_file, "#%u\n", now.low);
|
||||
vcd_cur_time = now.low;
|
||||
vcd_checkpoint();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_dumpfile_calltf(char*name)
|
||||
{
|
||||
char*path;
|
||||
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
|
||||
if (argv) {
|
||||
vpiHandle item = vpi_scan(argv);
|
||||
s_vpi_value value;
|
||||
|
||||
if (vpi_get(vpiType, item) != vpiConstant) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vpi_get(vpiConstType, item) != vpiStringConst) {
|
||||
vpi_printf("ERROR: %s parameter must be a constant\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
value.format = vpiStringVal;
|
||||
vpi_get_value(item, &value);
|
||||
path = strdup(value.value.str);
|
||||
|
||||
vpi_free_object(argv);
|
||||
|
||||
} else {
|
||||
path = strdup("dumpfile.vcd");
|
||||
}
|
||||
|
||||
assert(dump_file == 0);
|
||||
dump_file = fopen(path, "w");
|
||||
if (dump_file == 0) {
|
||||
vpi_printf("ERROR: Unable to open %s for output.\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned scan_scope(unsigned depth, vpiHandle argv, unsigned nident)
|
||||
{
|
||||
struct t_cb_data cb;
|
||||
struct vcd_info*info;
|
||||
char ident[64];
|
||||
|
||||
vpiHandle item;
|
||||
vpiHandle sublist;
|
||||
|
||||
cb.reason = cbValueChange;
|
||||
cb.cb_rtn = variable_cb;
|
||||
|
||||
for (item = vpi_scan(argv) ; item ; item = vpi_scan(argv)) {
|
||||
const char*type;
|
||||
|
||||
switch (vpi_get(vpiType, item)) {
|
||||
case vpiNet:
|
||||
case vpiReg:
|
||||
type = "wire";
|
||||
if (vpi_get(vpiType, item) == vpiReg)
|
||||
type = "reg";
|
||||
|
||||
sprintf(ident, "<%u", nident++);
|
||||
info = malloc(sizeof(*info));
|
||||
info->time.type = vpiSimTime;
|
||||
cb.time = &info->time;
|
||||
cb.user_data = (char*)info;
|
||||
cb.obj = item;
|
||||
info->item = item;
|
||||
info->ident = strdup(ident);
|
||||
info->cb = vpi_register_cb(&cb);
|
||||
info->next = vcd_list;
|
||||
vcd_list = info;
|
||||
fprintf(dump_file, "$var %s %u %s %s $end\n",
|
||||
type, vpi_get(vpiSize, item), ident,
|
||||
vpi_get_str(vpiFullName, item));
|
||||
break;
|
||||
|
||||
case vpiModule:
|
||||
sublist = vpi_iterate(vpiInternalScope, item);
|
||||
if (sublist && (depth > 0))
|
||||
nident = scan_scope(depth-1, sublist, nident);
|
||||
break;
|
||||
|
||||
default:
|
||||
vpi_printf("ERROR: $dumpvars: Unsupported parameter type\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nident;
|
||||
}
|
||||
|
||||
static int sys_dumpvars_calltf(char*name)
|
||||
{
|
||||
s_vpi_time now;
|
||||
vpiHandle item;
|
||||
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
|
||||
vpiHandle argv = vpi_iterate(vpiArgument, sys);
|
||||
|
||||
if (argv == 0) {
|
||||
vpi_printf("SORRY: %s requires arguments\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = vpi_scan(argv);
|
||||
|
||||
assert(dump_file);
|
||||
|
||||
scan_scope(99, argv, 0);
|
||||
|
||||
fprintf(dump_file, "$enddefinitions $end\n");
|
||||
|
||||
vpi_get_time(0, &now);
|
||||
fprintf(dump_file, "#%u\n", now.low);
|
||||
|
||||
vcd_checkpoint();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_vcd_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$dumpall";
|
||||
tf_data.calltf = sys_dumpall_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$dumpall";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$dumpfile";
|
||||
tf_data.calltf = sys_dumpfile_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$dumpfile";
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$dumpvars";
|
||||
tf_data.calltf = sys_dumpvars_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
tf_data.user_data = "$dumpvars";
|
||||
vpi_register_systf(&tf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: sys_vcd.c,v $
|
||||
* Revision 1.7 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 2000/02/17 06:04:30 steve
|
||||
* Fix overlap of identifiers when multiple modules used.
|
||||
*
|
||||
* Revision 1.5 2000/01/23 23:54:36 steve
|
||||
* Compile time problems with vpi_user.h
|
||||
*
|
||||
* Revision 1.4 2000/01/20 06:04:55 steve
|
||||
* $dumpall checkpointing in VCD dump.
|
||||
*
|
||||
* Revision 1.3 2000/01/13 04:48:50 steve
|
||||
* Catch some parameter problems.
|
||||
*
|
||||
* Revision 1.2 1999/11/28 00:56:08 steve
|
||||
* Build up the lists in the scope of a module,
|
||||
* and get $dumpvars to scan the scope for items.
|
||||
*
|
||||
* Revision 1.1 1999/11/07 20:33:30 steve
|
||||
* Add VCD output and related system tasks.
|
||||
*
|
||||
*/
|
||||
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
#ifndef __vpi_user_H
|
||||
#define __vpi_user_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: vpi_user.h,v 1.13 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct __vpiHandle *vpiHandle;
|
||||
|
||||
/*
|
||||
* This structure is created by the VPI application to provide hooks
|
||||
* into the application that the compiler/simulator can access.
|
||||
*/
|
||||
typedef struct t_vpi_systf_data {
|
||||
int type;
|
||||
int subtype;
|
||||
char *tfname;
|
||||
int (*calltf)(char*);
|
||||
int (*compiletf)(char*);
|
||||
int (*sizetf)();
|
||||
char *user_data;
|
||||
} s_vpi_systf_data, *p_vpi_systf_data;
|
||||
|
||||
/* The type in the above structure can have one of the following
|
||||
values: */
|
||||
#define vpiSysTask 1
|
||||
#define vpiSysFunc 2
|
||||
|
||||
|
||||
typedef struct t_vpi_time {
|
||||
int type;
|
||||
unsigned int high;
|
||||
unsigned int low;
|
||||
double real;
|
||||
} s_vpi_time, *p_vpi_time;
|
||||
|
||||
#define vpiScaledRealTime 1
|
||||
#define vpiSimTime 2
|
||||
#define vpiSuppressTime 3
|
||||
|
||||
typedef struct t_vpi_vecval {
|
||||
int aval, bval; /* ab encoding: 00=0, 10=1, 11=X, 01=Z */
|
||||
} s_vpi_vecval, *p_vpi_vecval;
|
||||
|
||||
/*
|
||||
* This structure holds values that are passed back and forth between
|
||||
* the simulator and the application.
|
||||
*/
|
||||
typedef struct t_vpi_value {
|
||||
int format;
|
||||
union {
|
||||
char*str;
|
||||
int scalar;
|
||||
int integer;
|
||||
double real;
|
||||
struct t_vpi_time *time;
|
||||
struct t_vpi_vecval *vector;
|
||||
struct t_vpi_strengthval *strength;
|
||||
char*misc;
|
||||
} value;
|
||||
} s_vpi_value, *p_vpi_value;
|
||||
|
||||
/* These are valid codes for the format of the t_vpi_value structure. */
|
||||
#define vpiBinStrVal 1
|
||||
#define vpiOctStrVal 2
|
||||
#define vpiDecStrVal 3
|
||||
#define vpiHexStrVal 4
|
||||
#define vpiScalerVal 5
|
||||
#define vpiIntVal 6
|
||||
#define vpiReadVal 7
|
||||
#define vpiStringVal 8
|
||||
#define vpiVectorVal 9
|
||||
#define vpiStrengthVal 10
|
||||
#define vpiTimeVal 11
|
||||
#define vpiObjTypeVal 12
|
||||
#define vpiSuppressVal 13
|
||||
|
||||
|
||||
/* OBJECT CODES */
|
||||
#define vpiConstant 7
|
||||
#define vpiIterator 27
|
||||
#define vpiMemory 29
|
||||
#define vpiMemoryWord 30
|
||||
#define vpiModule 32
|
||||
#define vpiNamedBegin 33
|
||||
#define vpiNamedFork 35
|
||||
#define vpiNet 36
|
||||
#define vpiReg 48
|
||||
#define vpiSysTaskCall 57
|
||||
#define vpiTimeVar 63
|
||||
#define vpiSysTfCall 85
|
||||
#define vpiArgument 89
|
||||
#define vpiInternalScope 92
|
||||
|
||||
#define vpiCallback 1000
|
||||
|
||||
/* PROPERTIES */
|
||||
#define vpiType 1
|
||||
#define vpiName 2
|
||||
#define vpiFullName 3
|
||||
#define vpiSize 4
|
||||
#define vpiConstType 43
|
||||
# define vpiDecConst 1
|
||||
# define vpiRealConst 2
|
||||
# define vpiBinaryConst 3
|
||||
# define vpiOctConst 4
|
||||
# define vpiHexConst 5
|
||||
# define vpiStringConst 6
|
||||
|
||||
/* DELAY MODES */
|
||||
#define vpiNoDelay 1
|
||||
#define vpiInertialDelay 2
|
||||
#define vpiTransportDelay 3
|
||||
#define vpiPureTransportDelay 4
|
||||
|
||||
#define vpiForceFlag 5
|
||||
#define vpiReleaseFlag 6
|
||||
|
||||
|
||||
/* VPI FUNCTIONS */
|
||||
extern void vpi_register_systf(const struct t_vpi_systf_data*ss);
|
||||
extern void vpi_printf(const char*fmt, ...);
|
||||
|
||||
/*
|
||||
* support for VPI callback functions.
|
||||
*/
|
||||
typedef struct t_cb_data {
|
||||
int reason;
|
||||
int (*cb_rtn)(struct t_cb_data*cb);
|
||||
vpiHandle obj;
|
||||
p_vpi_time time;
|
||||
p_vpi_value value;
|
||||
int index;
|
||||
char*user_data;
|
||||
} s_cb_data, *p_cb_data;
|
||||
|
||||
#define cbValueChange 1
|
||||
#define cbStmt 2
|
||||
#define cbForce 3
|
||||
#define cbRelease 4
|
||||
#define cbAtStartOfSimTime 5
|
||||
#define cbReadWriteSynch 6
|
||||
#define cbReadOnlySynch 7
|
||||
#define cbNextSimTime 8
|
||||
#define cbAfterDelay 9
|
||||
#define cbEndOfCompile 10
|
||||
#define cbStartOfSimulation 11
|
||||
#define cbEndOfSimulation 12
|
||||
#define cbError 13
|
||||
#define cbTchkViolation 14
|
||||
#define cbStartOfSave 15
|
||||
#define cbEndOfSave 16
|
||||
#define cbStartOfRestart 17
|
||||
#define cbEndOfRestart 18
|
||||
#define cbStartOfReset 19
|
||||
#define cbEndOfReset 20
|
||||
#define cbEnterInteractive 21
|
||||
#define cbExitInteractive 22
|
||||
#define cbInteractiveScopeChange 23
|
||||
#define cbUnresolvedSystf 24
|
||||
|
||||
extern vpiHandle vpi_register_cb(p_cb_data data);
|
||||
extern int vpi_remove_cb(vpiHandle ref);
|
||||
|
||||
/*
|
||||
* This function allows a vpi application to control the simulation
|
||||
* engine. The operation parameter specifies the function to
|
||||
* perform. The remaining parameters (if any) are interpreted by the
|
||||
* operation. The vpi_sim_control definition was added to P1364-2000
|
||||
* 14 July 1999. See PLI Task Force ID: PTF-161
|
||||
*
|
||||
* vpiFinish - perform the $finish operation, as soon as the user
|
||||
* function returns. This operation takes a single
|
||||
* parameter, a diagnostic exit code.
|
||||
*
|
||||
* vpiStop -
|
||||
* vpiReset -
|
||||
* vpiSetInteractiveScope -
|
||||
*/
|
||||
extern void vpi_sim_control(int operation, ...);
|
||||
#define vpiStop 1
|
||||
#define vpiFinish 2
|
||||
#define vpiReset 3
|
||||
#define vpiSetInteractiveScope 4
|
||||
|
||||
extern vpiHandle vpi_handle(int type, vpiHandle ref);
|
||||
extern vpiHandle vpi_iterate(int type, vpiHandle ref);
|
||||
extern vpiHandle vpi_scan(vpiHandle iter);
|
||||
extern vpiHandle vpi_handle_by_index(vpiHandle ref, int index);
|
||||
|
||||
extern void vpi_get_time(vpiHandle obj, s_vpi_time*t);
|
||||
extern int vpi_get(int property, vpiHandle ref);
|
||||
extern char* vpi_get_str(int property, vpiHandle ref);
|
||||
extern void vpi_get_value(vpiHandle expr, p_vpi_value value);
|
||||
extern vpiHandle vpi_put_value(vpiHandle obj, p_vpi_value value,
|
||||
p_vpi_time when, int flags);
|
||||
|
||||
extern int vpi_free_object(vpiHandle ref);
|
||||
|
||||
|
||||
/* This is the table of startup routines included in each module. */
|
||||
extern void (*vlog_startup_routines[])();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: vpi_user.h,v $
|
||||
* Revision 1.13 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.12 2000/02/13 19:18:28 steve
|
||||
* Accept memory words as parameter to $display.
|
||||
*
|
||||
* Revision 1.11 2000/01/20 06:04:55 steve
|
||||
* $dumpall checkpointing in VCD dump.
|
||||
*
|
||||
* Revision 1.10 1999/12/15 04:01:14 steve
|
||||
* Add the VPI implementation of $readmemh.
|
||||
*
|
||||
* Revision 1.9 1999/11/28 00:56:08 steve
|
||||
* Build up the lists in the scope of a module,
|
||||
* and get $dumpvars to scan the scope for items.
|
||||
*
|
||||
* Revision 1.8 1999/11/27 19:07:58 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.7 1999/11/10 02:52:24 steve
|
||||
* Create the vpiMemory handle type.
|
||||
*
|
||||
* Revision 1.6 1999/11/07 20:33:30 steve
|
||||
* Add VCD output and related system tasks.
|
||||
*
|
||||
* Revision 1.5 1999/11/07 02:25:08 steve
|
||||
* Add the $monitor implementation.
|
||||
*
|
||||
* Revision 1.4 1999/10/28 00:47:25 steve
|
||||
* Rewrite vvm VPI support to make objects more
|
||||
* persistent, rewrite the simulation scheduler
|
||||
* in C (to interface with VPI) and add VPI support
|
||||
* for callbacks.
|
||||
*
|
||||
* Revision 1.3 1999/08/19 02:51:03 steve
|
||||
* Add vpi_sim_control
|
||||
*
|
||||
* Revision 1.2 1999/08/18 03:44:49 steve
|
||||
* declare vou_sim_control
|
||||
*
|
||||
* Revision 1.1 1999/08/15 01:23:56 steve
|
||||
* Convert vvm to implement system tasks with vpi.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
@@ -9,12 +9,23 @@ useful for batch simulation.
|
||||
|
||||
Although none are required, these processing steps are recommended:
|
||||
nobufz
|
||||
sigfold
|
||||
nodangle
|
||||
propinit
|
||||
|
||||
So a sample command line to compile a Verilog file to C++ would be:
|
||||
|
||||
ivl -F nobufz -F sigfold -F propinit -t vvm -o foo.cc foo.vl
|
||||
ivl -F nobufz -F nodangle -F propinit -t vvm -o foo.cc foo.vl
|
||||
|
||||
Once the program is compiled down to C++ code, it needs to be further
|
||||
compiled and linked into an executable image. The command for doing
|
||||
this is highly dependent on the system where you use Icarus
|
||||
Verilog. For Linux, the compile command is typically:
|
||||
|
||||
c++ -rdynamic -o foo foo.cc -lvvm -ldl
|
||||
|
||||
On any system, the compiled program requires that the VPI_MODULE_PATH
|
||||
be set to a ':' separated list of directories to search for vpi files,
|
||||
the system.vpi file in particular. This is a run time requirement.
|
||||
|
||||
ATTRIBUTES
|
||||
|
||||
@@ -99,8 +110,17 @@ bits are at:
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
$Id: vvm.txt,v 1.1 1999/04/29 16:29:04 steve Exp $
|
||||
$Id: vvm.txt,v 1.4 1999/12/30 17:37:14 steve Exp $
|
||||
$Log: vvm.txt,v $
|
||||
Revision 1.4 1999/12/30 17:37:14 steve
|
||||
Remove the now useless sigfold functor.
|
||||
|
||||
Revision 1.3 1999/08/18 03:45:36 steve
|
||||
Update compile command line.
|
||||
|
||||
Revision 1.2 1999/08/15 01:23:56 steve
|
||||
Convert vvm to implement system tasks with vpi.
|
||||
|
||||
Revision 1.1 1999/04/29 16:29:04 steve
|
||||
Add vvm target documentation
|
||||
|
||||
|
||||
+30
-13
@@ -18,7 +18,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.3 1999/05/09 01:24:59 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.19 2000/02/13 19:18:28 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -35,43 +35,56 @@ bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
CC = @CC@ -I$(srcdir) -I$(srcdir)/../vpi
|
||||
CXX = @CXX@ -I$(srcdir) -I$(srcdir)/../vpi
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: libvvm.a
|
||||
|
||||
%.o dep/%.d: %.cc
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CXX) -Wall -fno-exceptions $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
$(CXX) -Wall -fno-exceptions $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
TF = display.o
|
||||
O = vvm_bit.o vvm_calltf.o vvm_event.o vvm_monitor.o vvm_pevent.o \
|
||||
vvm_simulation.o vvm_thread.o $(TF)
|
||||
%.o dep/%.d: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
O = vvm_bit.o vvm_calltf.o vvm_event.o vvm_gates.o vvm_mult.o \
|
||||
vvm_pevent.o vvm_thread.o vpip.o
|
||||
|
||||
P = vpi_callback.o \
|
||||
vpi_const.o vpi_iter.o vpi_memory.o vpi_null.o \
|
||||
vpi_priv.o vpi_scope.o vpi_signal.o vpi_simulation.o vpi_systask.o vpi_time.o
|
||||
|
||||
libvvm.a: $O
|
||||
rm -f $@
|
||||
ar cvqf $@ $O
|
||||
ar cvq $@ $O
|
||||
|
||||
vpip.o: $P
|
||||
$(LD) -r -o vpip.o $P
|
||||
|
||||
clean:
|
||||
rm -f *.o dep/*.d
|
||||
|
||||
install: all installdirs $(libdir)/libvvm.a \
|
||||
$(includedir)/vvm.h \
|
||||
$(includedir)/vvm_calltf.h \
|
||||
$(includedir)/vpi_priv.h \
|
||||
$(includedir)/vvm_func.h \
|
||||
$(includedir)/vvm_gates.h \
|
||||
$(includedir)/vvm_thread.h
|
||||
$(includedir)/vvm_thread.h \
|
||||
$(includedir)/vvm_calltf.h
|
||||
|
||||
$(libdir)/libvvm.a: ./libvvm.a
|
||||
$(INSTALL_PROGRAM) ./libvvm.a $(libdir)/libvvm.a
|
||||
$(INSTALL_DATA) ./libvvm.a $(libdir)/libvvm.a
|
||||
|
||||
$(includedir)/vvm.h: $(srcdir)/vvm.h
|
||||
$(INSTALL_DATA) $(srcdir)/vvm.h $(includedir)/vvm.h
|
||||
@@ -88,8 +101,11 @@ $(includedir)/vvm_gates.h: $(srcdir)/vvm_gates.h
|
||||
$(includedir)/vvm_thread.h: $(srcdir)/vvm_thread.h
|
||||
$(INSTALL_DATA) $(srcdir)/vvm_thread.h $(includedir)/vvm_thread.h
|
||||
|
||||
$(includedir)/vpi_priv.h: $(srcdir)/vpi_priv.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_priv.h $(includedir)/vpi_priv.h
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(bindir)
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/libvvm.a
|
||||
@@ -98,6 +114,7 @@ uninstall:
|
||||
rm -f $(includedir)/vvm_func.h
|
||||
rm -f $(includedir)/vvm_gates.h
|
||||
rm -f $(includedir)/vvm_thread.h
|
||||
rm -f $(includedir)/vpi_priv.h
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
-include $(patsubst %.o, dep/%.d, $O $P)
|
||||
|
||||
-264
@@ -1,264 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: display.cc,v 1.5 1999/05/31 15:46:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "vvm.h"
|
||||
# include "vvm_calltf.h"
|
||||
# include <iostream>
|
||||
|
||||
static void format_hex(vvm_simulation*sim, ostream&os,
|
||||
class vvm_calltf_parm*parm)
|
||||
{
|
||||
switch (parm->type()) {
|
||||
case vvm_calltf_parm::TIME:
|
||||
os << sim->get_sim_time();
|
||||
break;
|
||||
case vvm_calltf_parm::NONE:
|
||||
os << "z";
|
||||
break;
|
||||
case vvm_calltf_parm::ULONG:
|
||||
os << ((parm->as_ulong()&1) ? "0" : "1");
|
||||
break;
|
||||
case vvm_calltf_parm::STRING:
|
||||
os << parm->as_string();
|
||||
break;
|
||||
case vvm_calltf_parm::BITS:
|
||||
unsigned c = 0;
|
||||
for (unsigned idx = parm->as_bits()->get_width()
|
||||
; idx > 0 ; idx -= 1)
|
||||
c = (c << 1) | parm->as_bits()->get_bit(idx-1);
|
||||
cout.form("%x",c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void format_bit(vvm_simulation*sim, ostream&os,
|
||||
class vvm_calltf_parm*parm)
|
||||
{
|
||||
switch (parm->type()) {
|
||||
case vvm_calltf_parm::TIME:
|
||||
os << (sim->get_sim_time()&1);
|
||||
break;
|
||||
case vvm_calltf_parm::NONE:
|
||||
os << "z";
|
||||
break;
|
||||
case vvm_calltf_parm::ULONG:
|
||||
os << ((parm->as_ulong()&1) ? "0" : "1");
|
||||
break;
|
||||
case vvm_calltf_parm::STRING:
|
||||
os << parm->as_string();
|
||||
break;
|
||||
case vvm_calltf_parm::BITS:
|
||||
for (unsigned idx = parm->as_bits()->get_width()
|
||||
; idx > 0 ; idx -= 1)
|
||||
os << parm->as_bits()->get_bit(idx-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void format_dec(vvm_simulation*sim, ostream&os,
|
||||
class vvm_calltf_parm*parm)
|
||||
{
|
||||
switch (parm->type()) {
|
||||
case vvm_calltf_parm::TIME:
|
||||
os << sim->get_sim_time();
|
||||
break;
|
||||
case vvm_calltf_parm::NONE:
|
||||
os << "0";
|
||||
break;
|
||||
case vvm_calltf_parm::ULONG:
|
||||
os << parm->as_ulong();
|
||||
break;
|
||||
case vvm_calltf_parm::STRING:
|
||||
os << parm->as_string();
|
||||
break;
|
||||
case vvm_calltf_parm::BITS: {
|
||||
unsigned long val = 0;
|
||||
unsigned long mask = 1;
|
||||
const vvm_bits_t*bstr = parm->as_bits();
|
||||
for (unsigned idx = 0 ; idx < bstr->get_width() ; idx += 1) {
|
||||
if (bstr->get_bit(idx) == V1) val |= mask;
|
||||
mask <<= 1;
|
||||
}
|
||||
os << val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void format_name(ostream&os, class vvm_calltf_parm*parm)
|
||||
{
|
||||
switch (parm->type()) {
|
||||
case vvm_calltf_parm::TIME:
|
||||
os << "$time";
|
||||
break;
|
||||
case vvm_calltf_parm::NONE:
|
||||
break;
|
||||
case vvm_calltf_parm::ULONG:
|
||||
os << parm->as_ulong();
|
||||
break;
|
||||
case vvm_calltf_parm::STRING:
|
||||
os << "\"" << parm->as_string() << "\"";
|
||||
break;
|
||||
case vvm_calltf_parm::BITS:
|
||||
os << parm->sig_name();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned format(vvm_simulation*sim, const string&str,
|
||||
unsigned nparms,
|
||||
class vvm_calltf_parm*parms)
|
||||
{
|
||||
char prev = 0;
|
||||
unsigned next_parm = 0;
|
||||
unsigned idx = 0;
|
||||
while (idx < str.length()) {
|
||||
if (prev == '%') {
|
||||
switch (str[idx]) {
|
||||
case 'b':
|
||||
case 'B':
|
||||
format_bit(sim, cout, parms+next_parm);
|
||||
next_parm += 1;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'h':
|
||||
case 'H':
|
||||
format_hex(sim, cout, parms+next_parm);
|
||||
next_parm += 1;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
format_dec(sim, cout, parms+next_parm);
|
||||
next_parm += 1;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
format_name(cout, parms+next_parm);
|
||||
next_parm += 1;
|
||||
break;
|
||||
case '%':
|
||||
cout << str[idx];
|
||||
break;
|
||||
}
|
||||
|
||||
prev = 0;
|
||||
|
||||
} else {
|
||||
if (str[idx] != '%')
|
||||
cout << str[idx];
|
||||
else
|
||||
prev = '%';
|
||||
}
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
return next_parm;
|
||||
}
|
||||
|
||||
void Sdisplay(vvm_simulation*sim, const string&name,
|
||||
unsigned nparms, class vvm_calltf_parm*parms)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1)
|
||||
switch (parms[idx].type()) {
|
||||
case vvm_calltf_parm::NONE:
|
||||
cout << " ";
|
||||
break;
|
||||
case vvm_calltf_parm::TIME:
|
||||
cout << sim->get_sim_time();
|
||||
break;
|
||||
case vvm_calltf_parm::ULONG:
|
||||
cout << parms[idx].as_ulong();
|
||||
break;
|
||||
case vvm_calltf_parm::STRING:
|
||||
idx += format(sim, parms[idx].as_string(),
|
||||
nparms-idx-1, parms+idx+1);
|
||||
break;
|
||||
case vvm_calltf_parm::BITS:
|
||||
cout << *parms[idx].as_bits();
|
||||
break;
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
class monitor_event : public vvm_event {
|
||||
public:
|
||||
monitor_event(vvm_simulation*sim,
|
||||
unsigned nparms, class vvm_calltf_parm*parms)
|
||||
{ sim_ = sim;
|
||||
nparms_ = nparms;
|
||||
parms_ = new vvm_calltf_parm[nparms];
|
||||
for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
|
||||
parms_[idx] = parms[idx];
|
||||
}
|
||||
|
||||
~monitor_event() { delete[]parms_; }
|
||||
|
||||
private:
|
||||
vvm_simulation*sim_;
|
||||
unsigned nparms_;
|
||||
vvm_calltf_parm*parms_;
|
||||
void event_function();
|
||||
};
|
||||
|
||||
void monitor_event::event_function()
|
||||
{
|
||||
Sdisplay(sim_, "$display", nparms_, parms_);
|
||||
}
|
||||
|
||||
static monitor_event*mon = 0;
|
||||
|
||||
void Smonitor(vvm_simulation*sim, const string&name,
|
||||
unsigned nparms, class vvm_calltf_parm*parms)
|
||||
{
|
||||
if (mon) delete mon;
|
||||
mon = new monitor_event(sim, nparms, parms);
|
||||
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||
if (parms[idx].type() != vvm_calltf_parm::BITS)
|
||||
continue;
|
||||
|
||||
parms[idx].as_mon()->enable(mon);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: display.cc,v $
|
||||
* Revision 1.5 1999/05/31 15:46:36 steve
|
||||
* Handle time in more places.
|
||||
*
|
||||
* Revision 1.4 1999/05/12 04:02:17 steve
|
||||
* Add %x support contributed by Steve Wilson.
|
||||
*
|
||||
* Revision 1.3 1999/01/01 01:44:40 steve
|
||||
* Proberly print vectors in binary.
|
||||
*
|
||||
* Revision 1.2 1998/11/10 00:48:31 steve
|
||||
* Add support it vvm target for level-sensitive
|
||||
* triggers (i.e. the Verilog wait).
|
||||
* Fix display of $time is format strings.
|
||||
*
|
||||
* Revision 1.1 1998/11/09 23:44:10 steve
|
||||
* Add vvm library.
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef __vvm_machine_H
|
||||
#define __vvm_machine_H
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: machine.h,v 1.2 2000/02/23 02:56:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef NEED_LU
|
||||
#define LU "_"
|
||||
#else
|
||||
#define LU ""
|
||||
#endif
|
||||
|
||||
#ifdef NEED_TU
|
||||
#define TU "_"
|
||||
#else
|
||||
#define TU ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: machine.h,v $
|
||||
* Revision 1.2 2000/02/23 02:56:56 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 2000/01/24 00:18:20 steve
|
||||
* Handle systems that need underscores in symbols.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user