mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 14:27:01 +02:00
Compare commits
371
Commits
s20080111
...
performance
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afa2478801 | ||
|
|
79feb44f10 | ||
|
|
c03d76a0d7 | ||
|
|
a2dc1e0a29 | ||
|
|
6a1235ac28 | ||
|
|
7aebff2a86 | ||
|
|
b31124983a | ||
|
|
f256dfe16e | ||
|
|
7c152685dc | ||
|
|
5d86dd0bbd | ||
|
|
4f97321c75 | ||
|
|
d0f303463d | ||
|
|
35fe8fae00 | ||
|
|
2e95a740da | ||
|
|
2f4e5bf5b6 | ||
|
|
7e478cdeb8 | ||
|
|
2576543bb5 | ||
|
|
e453b347f4 | ||
|
|
f132e09475 | ||
|
|
2ee976d1c0 | ||
|
|
30570adf31 | ||
|
|
1c51ac4ac0 | ||
|
|
17a1358eb6 | ||
|
|
04a7f7054a | ||
|
|
e97a1ad610 | ||
|
|
e872310e4b | ||
|
|
95850ac112 | ||
|
|
d0e154b830 | ||
|
|
4010f6e710 | ||
|
|
d74f2fe38d | ||
|
|
db642e3850 | ||
|
|
523dff7ae7 | ||
|
|
db09f2fa7e | ||
|
|
c2061e8199 | ||
|
|
ff9166d4a5 | ||
|
|
73e2b297df | ||
|
|
6e5373c87e | ||
|
|
782bfab29e | ||
|
|
df15a0368c | ||
|
|
916f300448 | ||
|
|
7898f4e402 | ||
|
|
6f8bf90dc4 | ||
|
|
052870c0e5 | ||
|
|
1be1f65f33 | ||
|
|
fd6f017435 | ||
|
|
dfa6471227 | ||
|
|
a8f492776a | ||
|
|
6f0d98cf18 | ||
|
|
6f30813102 | ||
|
|
2fab3159dd | ||
|
|
f04fb0fc45 | ||
|
|
7a1180868a | ||
|
|
b2bdce98ab | ||
|
|
653e2661b2 | ||
|
|
9aa610f489 | ||
|
|
de7fff8ac6 | ||
|
|
2179797763 | ||
|
|
b5e9e44e07 | ||
|
|
5a0fe9ff83 | ||
|
|
f6fede5aae | ||
|
|
0fa3099ded | ||
|
|
6987d16bd3 | ||
|
|
5cc376ebd4 | ||
|
|
8190307dd3 | ||
|
|
3575f68c9f | ||
|
|
c1268d04fc | ||
|
|
ca756f3ec3 | ||
|
|
9af459f95b | ||
|
|
492b240304 | ||
|
|
d2106a3d3a | ||
|
|
cf2f4dd0af | ||
|
|
608c2574bd | ||
|
|
f17db21bf0 | ||
|
|
b26bdd3c19 | ||
|
|
6a9c5d8f7e | ||
|
|
e59f28d659 | ||
|
|
07ae300e0c | ||
|
|
4c5f24c7a7 | ||
|
|
be810c5ba6 | ||
|
|
5ec3b590bf | ||
|
|
88313670c0 | ||
|
|
d1daf6733f | ||
|
|
007056d671 | ||
|
|
2dcb1514a2 | ||
|
|
d71a1cb9c1 | ||
|
|
f9f68236bc | ||
|
|
dadb3a68d3 | ||
|
|
6121c06f15 | ||
|
|
b289d740e2 | ||
|
|
ec266ff52e | ||
|
|
ec773fe8cf | ||
|
|
4c3d764a86 | ||
|
|
a412149e2c | ||
|
|
deb7b01717 | ||
|
|
3189efacbc | ||
|
|
96ec4b7eba | ||
|
|
07c8fce530 | ||
|
|
9a00829ee4 | ||
|
|
680d3c8a3e | ||
|
|
6966c26f27 | ||
|
|
a5e3d06412 | ||
|
|
eb3dcc2786 | ||
|
|
c76e88cad5 | ||
|
|
6632e4c33b | ||
|
|
42913e46b8 | ||
|
|
e2ad59466a | ||
|
|
0cd946a7af | ||
|
|
102cbb67b4 | ||
|
|
3113392594 | ||
|
|
72b4256872 | ||
|
|
ca880c73fc | ||
|
|
f588656dd5 | ||
|
|
cef0d0071b | ||
|
|
35e48fb7b7 | ||
|
|
2934ceb548 | ||
|
|
6b908aeec3 | ||
|
|
a069b6dbe1 | ||
|
|
48f934abf7 | ||
|
|
a6dd97a5a6 | ||
|
|
2b4f7f8aed | ||
|
|
add84b153c | ||
|
|
2172c8a503 | ||
|
|
cbf96d73ee | ||
|
|
3c5bf034ca | ||
|
|
7166aea1d7 | ||
|
|
93b400c4d7 | ||
|
|
a506a18970 | ||
|
|
5b273178f5 | ||
|
|
cde87ed4a3 | ||
|
|
84a7efdb4f | ||
|
|
dfb7bf5211 | ||
|
|
a33619a0f5 | ||
|
|
a1495bb007 | ||
|
|
8e1f22cd82 | ||
|
|
db10de1a6a | ||
|
|
bbed408d68 | ||
|
|
ba3660b948 | ||
|
|
73dcace781 | ||
|
|
fd3ca037aa | ||
|
|
2d068ca89f | ||
|
|
dea1161c7e | ||
|
|
3a61b94e98 | ||
|
|
3a8a6976e1 | ||
|
|
6cc244766c | ||
|
|
6e3ec755e2 | ||
|
|
ca517b5519 | ||
|
|
10ab5cf698 | ||
|
|
523de1b69c | ||
|
|
3e591f730e | ||
|
|
34e90bb3a6 | ||
|
|
4f8b91e65c | ||
|
|
e91243e1c6 | ||
|
|
5484ee1732 | ||
|
|
a43f336c6c | ||
|
|
cc7187c172 | ||
|
|
d60df2d75b | ||
|
|
6d433364ac | ||
|
|
bbc80a84a6 | ||
|
|
c993fb8325 | ||
|
|
f662d76b2e | ||
|
|
0c29e540ea | ||
|
|
1a8be6d28c | ||
|
|
6491c5d43c | ||
|
|
a319939573 | ||
|
|
9db9aa4ccb | ||
|
|
cb5260b2ce | ||
|
|
c0d3bb370f | ||
|
|
b99206ac8e | ||
|
|
149bfa05d8 | ||
|
|
86a4025b58 | ||
|
|
2a5948d704 | ||
|
|
f5263c9447 | ||
|
|
f95a6fed14 | ||
|
|
436e2fca13 | ||
|
|
64c92f9fdd | ||
|
|
603ca0f2de | ||
|
|
efba4bfd09 | ||
|
|
785aad94c5 | ||
|
|
ffbf37b06b | ||
|
|
c3ac01d31b | ||
|
|
81e12bf7f6 | ||
|
|
abaab602bc | ||
|
|
bd170d05ad | ||
|
|
7b81eb3494 | ||
|
|
b775d178d2 | ||
|
|
10ea9904f1 | ||
|
|
e7d463704c | ||
|
|
c38e8182c2 | ||
|
|
7b705a0212 | ||
|
|
5ddd35565f | ||
|
|
a12a6d925a | ||
|
|
5ab0c20a7d | ||
|
|
35e511d0c0 | ||
|
|
935c3dc02d | ||
|
|
6d2ef15951 | ||
|
|
40fd07d46e | ||
|
|
5e30016910 | ||
|
|
33466250f5 | ||
|
|
bdab7698d2 | ||
|
|
54918cf5b9 | ||
|
|
844447b995 | ||
|
|
6eb9825ab7 | ||
|
|
23e60aa381 | ||
|
|
373123af6b | ||
|
|
54cf66d8b4 | ||
|
|
dffe1be819 | ||
|
|
d41f8fe52b | ||
|
|
6ca53c6810 | ||
|
|
9bb8e8146f | ||
|
|
321114e4db | ||
|
|
ef3aacfe36 | ||
|
|
bfb33230aa | ||
|
|
44767d8f70 | ||
|
|
fecd941a28 | ||
|
|
2be8534021 | ||
|
|
8cece424d1 | ||
|
|
e2dfeac86c | ||
|
|
a914eda5ef | ||
|
|
ba8a41ca28 | ||
|
|
a67d573ae6 | ||
|
|
f5418fe337 | ||
|
|
7035ded57a | ||
|
|
ad3a73f74f | ||
|
|
43e8a08c97 | ||
|
|
208c6a349d | ||
|
|
640231bbfa | ||
|
|
bdc48135e5 | ||
|
|
f7e840cd0a | ||
|
|
3c1e7c4260 | ||
|
|
5a1ec9b958 | ||
|
|
1bc56fcc93 | ||
|
|
13958cf374 | ||
|
|
b5b5a9935c | ||
|
|
bb14ac1fe0 | ||
|
|
04e8623ed6 | ||
|
|
225fcf6bf0 | ||
|
|
8c1cca423d | ||
|
|
7bc9742710 | ||
|
|
12f8af645f | ||
|
|
259e4294e3 | ||
|
|
ea74eb771e | ||
|
|
32b115d8fe | ||
|
|
14e3a886bd | ||
|
|
140fd45460 | ||
|
|
5b2f249dcc | ||
|
|
01eb298228 | ||
|
|
48990d8e2d | ||
|
|
77722a62c2 | ||
|
|
a2ea980a7a | ||
|
|
86301be3d2 | ||
|
|
bbb488f730 | ||
|
|
13d4a7352c | ||
|
|
d26ae866f8 | ||
|
|
8e6c2652ab | ||
|
|
94818c19a0 | ||
|
|
9b1baea6da | ||
|
|
ef9ee52e53 | ||
|
|
377f5eaa23 | ||
|
|
234648231b | ||
|
|
cc28a9a734 | ||
|
|
6f1445ff9d | ||
|
|
e0fbc15bd4 | ||
|
|
e141d2bb37 | ||
|
|
fe72d02cf6 | ||
|
|
c2bae1ad6c | ||
|
|
692caca9dc | ||
|
|
8b45797ccf | ||
|
|
8d3febff2b | ||
|
|
3221f70bcb | ||
|
|
cb920bd864 | ||
|
|
32a2e7aa39 | ||
|
|
52ac96ca15 | ||
|
|
f8caebd076 | ||
|
|
70c5c9fe14 | ||
|
|
75df8fb6bb | ||
|
|
ec87c7f6de | ||
|
|
b5ef6d7a37 | ||
|
|
285ff2859f | ||
|
|
a01bc5e245 | ||
|
|
c6ce3f6f38 | ||
|
|
fac1cc5a1c | ||
|
|
11a33a0907 | ||
|
|
8e704cbf93 | ||
|
|
3716e972ec | ||
|
|
538d3d1f4d | ||
|
|
528af27769 | ||
|
|
2bd13964cd | ||
|
|
105885402f | ||
|
|
b512671643 | ||
|
|
c064451e15 | ||
|
|
73f8c2e68c | ||
|
|
6103a72927 | ||
|
|
3bdf0a13d6 | ||
|
|
623073c722 | ||
|
|
e989f63192 | ||
|
|
39dd22ace4 | ||
|
|
ceef77e15f | ||
|
|
b0e4a6884a | ||
|
|
e7ea90c812 | ||
|
|
f9bf502324 | ||
|
|
d28fcb8941 | ||
|
|
2b5560957a | ||
|
|
b6f26e62df | ||
|
|
3f2fa29482 | ||
|
|
4d8db7b5bc | ||
|
|
2bab415626 | ||
|
|
110bc2e6eb | ||
|
|
331faa2217 | ||
|
|
f2ff25bfef | ||
|
|
bc1d3eb7cd | ||
|
|
63e2aa8d1a | ||
|
|
0ac36dc5af | ||
|
|
3a300725de | ||
|
|
85229a6cdc | ||
|
|
47d1d981d5 | ||
|
|
fb63bf7dba | ||
|
|
3d2e791e52 | ||
|
|
aaf8908676 | ||
|
|
4cf8920e48 | ||
|
|
e82293c981 | ||
|
|
1b410f0c7d | ||
|
|
51b1804660 | ||
|
|
40064b3181 | ||
|
|
0e6d6b7416 | ||
|
|
f4cf7b1799 | ||
|
|
9c0d2c13c9 | ||
|
|
f1f2806e3c | ||
|
|
db851c235f | ||
|
|
1595ae79fd | ||
|
|
f049426f25 | ||
|
|
5e8a1bd8cc | ||
|
|
fa759c1802 | ||
|
|
4c5481f254 | ||
|
|
1609de6ed9 | ||
|
|
d9ac146b8f | ||
|
|
31afec57b1 | ||
|
|
76039cf595 | ||
|
|
685095b229 | ||
|
|
abfccb65e9 | ||
|
|
388bb93beb | ||
|
|
1eb581ab37 | ||
|
|
2f9ad47890 | ||
|
|
47d65034db | ||
|
|
b297a0a9fe | ||
|
|
6256dd8040 | ||
|
|
5ec91ec914 | ||
|
|
76164d7711 | ||
|
|
89bf16b21e | ||
|
|
5b17f2039a | ||
|
|
db25bba0d0 | ||
|
|
10d25d2b88 | ||
|
|
3ea72109f8 | ||
|
|
b6b7d704b2 | ||
|
|
32d3e5ac46 | ||
|
|
ea1f448300 | ||
|
|
d992ec4bd4 | ||
|
|
592a303ce5 | ||
|
|
52a346ab38 | ||
|
|
0fa223434e | ||
|
|
e1bf2ec019 | ||
|
|
ded0fbe5ef | ||
|
|
0370f30b20 | ||
|
|
eac6333d6c | ||
|
|
1ff31db2cc | ||
|
|
59ee700634 | ||
|
|
e46f8220f3 | ||
|
|
7ff342f4da | ||
|
|
190aefcf89 | ||
|
|
cdfe3a8289 | ||
|
|
c899a6a52e | ||
|
|
e18b64768e |
@@ -72,11 +72,11 @@ reporting problems with. However, if you clearly explain what is right
|
||||
and wrong about the generated netlist, I will probably be able to fix
|
||||
the problem. It may take a few iterations.
|
||||
|
||||
In this case, if possible include not only the sample verilog program,
|
||||
In this case, if possible include not only the sample Verilog program,
|
||||
but the generated netlist file(s) and a clear indication of what went
|
||||
wrong. If it is not clear to me, I will ask for clarification.
|
||||
|
||||
* The Output is Correct, But Less Then Ideal
|
||||
* The Output is Correct, But Less Than Ideal
|
||||
|
||||
If the output is strictly correct, but just not good enough for
|
||||
practical use, I would like to know. These sorts of problems are
|
||||
|
||||
@@ -32,7 +32,7 @@ using namespace std;
|
||||
|
||||
/*
|
||||
* This class represents a component of a Verilog hierarchical name. A
|
||||
* hierarchical component contains a name string (prepresented here
|
||||
* hierarchical component contains a name string (represented here
|
||||
* with a perm_string) and an optional signed number. This signed
|
||||
* number is used if the scope is part of an array, for example an
|
||||
* array of module instances or a loop generated scope.
|
||||
|
||||
+76
-41
@@ -16,9 +16,6 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
# This version string is only used in the version message printed
|
||||
@@ -30,6 +27,7 @@ VERSION = 0.9.devel
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
SUBDIRS = @subdirs@
|
||||
|
||||
@@ -40,8 +38,6 @@ libdir = @libdir@
|
||||
includedir = @includedir@
|
||||
mandir = @mandir@
|
||||
|
||||
libdir64 = @libdir64@
|
||||
|
||||
dllib=@DLLIB@
|
||||
|
||||
CC = @CC@
|
||||
@@ -52,13 +48,16 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
LEX = @LEX@
|
||||
YACC = @YACC@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
GIT = @GIT@
|
||||
|
||||
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
|
||||
CXXFLAGS = -Wall @CXXFLAGS@
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @rdynamic@ @LDFLAGS@
|
||||
|
||||
all: dep ivl@EXEEXT@
|
||||
all: dep version.h ivl@EXEEXT@
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in ivlpp ; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
@@ -66,7 +65,7 @@ all: dep ivl@EXEEXT@
|
||||
|
||||
# In the windows world, the installer will need a dosify program to
|
||||
# dosify text files.
|
||||
ifeq (@MING32@,yes)
|
||||
ifeq (@MINGW32@,yes)
|
||||
all: dep dosify.exe
|
||||
dosify.exe: dosify.c
|
||||
$(CC) -o dosify.exe dosify.c
|
||||
@@ -100,19 +99,19 @@ distclean: clean
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
|
||||
|
||||
O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
||||
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o elab_expr.o \
|
||||
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
|
||||
elab_sig.o emit.o eval.o eval_attrib.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_force.o net_func.o \
|
||||
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
||||
net_proc.o net_scope.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o pform_types.o \
|
||||
net_proc.o net_scope.o net_tran.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_disciplines.o pform_dump.o pform_types.o \
|
||||
set_width.o symbol_search.o sync.o sys_funcs.o \
|
||||
verinum.o verireal.o target.o targets.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o PGenerate.o PSpec.o \
|
||||
PExpr.o PGate.o PGenerate.o PScope.o PSpec.o \
|
||||
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
@@ -125,9 +124,9 @@ ifeq (@WIN32@,yes)
|
||||
# The first step makes an ivl.exe that dlltool can use to make an
|
||||
# export and import library, and the last link makes a, ivl.exe
|
||||
# that really exports the things that the import library imports.
|
||||
ivl@EXEEXT@: $O ivl.def
|
||||
ivl@EXEEXT@: $O $(srcdir)/ivl.def
|
||||
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
|
||||
dlltool --dllname ivl@EXEEXT@ --def ivl.def \
|
||||
dlltool --dllname ivl@EXEEXT@ --def $(srcdir)/ivl.def \
|
||||
--output-lib libivl.a --output-exp ivl.exp
|
||||
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
|
||||
else
|
||||
@@ -146,8 +145,6 @@ iverilog-vpi: iverilog-vpi.sh
|
||||
-e 's;@IVCXX@;$(CXX);' \
|
||||
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
|
||||
-e 's;@INCLUDEDIR@;@includedir@;' \
|
||||
-e 's;@LIBDIR64@;@libdir64@;' \
|
||||
-e 's;@VPIDIR1@;@vpidir1@;' -e 's;@VPIDIR2@;@vpidir2@;' \
|
||||
-e 's;@LIBDIR@;@libdir@;' $< > $@
|
||||
chmod +x $@
|
||||
endif
|
||||
@@ -177,18 +174,50 @@ lexor.cc: $(srcdir)/lexor.lex
|
||||
lexor_keyword.o: lexor_keyword.cc parse.h
|
||||
|
||||
lexor_keyword.cc: lexor_keyword.gperf
|
||||
gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
gperf -o -i 7 -C -k 1-4,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
|
||||
iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man
|
||||
man -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
$(MAN) -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
|
||||
iverilog-vpi.pdf: iverilog-vpi.ps
|
||||
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
|
||||
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
|
||||
|
||||
ifeq (@MING32@,yes)
|
||||
# For VERSION_TAG in driver/main.c, first try git-describe, then look for a
|
||||
# version.h file in the source tree (included in snapshots and releases), and
|
||||
# finally use nothing.
|
||||
.PHONY: version.h
|
||||
# "true" and "false" in the next few lines are Unix shell command names
|
||||
ifeq ($(GIT),none)
|
||||
GIT_PRESENT = false
|
||||
else
|
||||
GIT_PRESENT = true
|
||||
endif
|
||||
version.h:
|
||||
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
|
||||
echo "Using git-describe for VERSION_TAG"; \
|
||||
tmp=`$(GIT) --git-dir $(srcdir)/.git describe \
|
||||
| sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \
|
||||
echo "$$tmp" | diff - $@ > /dev/null 2>&1 || echo "$$tmp" > $@ || exit 1; \
|
||||
elif test -r $(srcdir)/$@; then \
|
||||
echo "Using $(srcdir)/$@ for VERSION_TAG"; \
|
||||
diff $(srcdir)/$@ $@ > /dev/null 2>&1 || cp $(srcdir)/$@ $@; \
|
||||
else \
|
||||
echo "Using empty VERSION_TAG"; \
|
||||
echo '#define VERSION_TAG ""' > $@; \
|
||||
fi
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: dep iverilog-vpi.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
@@ -202,43 +231,49 @@ endif
|
||||
|
||||
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/include/constants.vams $(libdir)/ivl/include/disciplines.vams $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
|
||||
$(bindir)/iverilog-vpi: ./iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(bindir)/iverilog-vpi
|
||||
$(INSTALL_SCRIPT) ./iverilog-vpi $(DESTDIR)$(bindir)/iverilog-vpi
|
||||
|
||||
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(DESTDIR)$(libdir)/ivl/ivl@EXEEXT@
|
||||
|
||||
$(libdir)/ivl/include/constants.vams: $(srcdir)/constants.vams
|
||||
$(INSTALL_DATA) $(srcdir)/constants.vams $@
|
||||
|
||||
$(libdir)/ivl/include/disciplines.vams: $(srcdir)/disciplines.vams
|
||||
$(INSTALL_DATA) $(srcdir)/disciplines.vams $@
|
||||
|
||||
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl/xnf-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(DESTDIR)$(libdir)/ivl/xnf-s.conf
|
||||
|
||||
$(libdir)/ivl/xnf.conf: $(srcdir)/xnf.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf.conf $(libdir)/ivl/xnf.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf.conf $(DESTDIR)$(libdir)/ivl/xnf.conf
|
||||
|
||||
$(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(includedir)/ivl_target.h
|
||||
$(INSTALL_DATA) $(srcdir)/ivl_target.h $(DESTDIR)$(includedir)/ivl_target.h
|
||||
|
||||
$(includedir)/_pli_types.h: _pli_types.h
|
||||
$(INSTALL_DATA) $< $(includedir)/_pli_types.h
|
||||
$(INSTALL_DATA) $< $(DESTDIR)$(includedir)/_pli_types.h
|
||||
|
||||
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(DESTDIR)$(includedir)/vpi_user.h
|
||||
|
||||
$(includedir)/acc_user.h: $(srcdir)/acc_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/acc_user.h $(includedir)/acc_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/acc_user.h $(DESTDIR)$(includedir)/acc_user.h
|
||||
|
||||
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
|
||||
$(INSTALL_DATA) $(srcdir)/veriuser.h $(includedir)/veriuser.h
|
||||
$(INSTALL_DATA) $(srcdir)/veriuser.h $(DESTDIR)$(includedir)/veriuser.h
|
||||
|
||||
$(mandir)/man1/iverilog-vpi.1: $(srcdir)/iverilog-vpi.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(mandir)/man1/iverilog-vpi.1
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(DESTDIR)$(mandir)/man1/iverilog-vpi.1
|
||||
|
||||
$(prefix)/iverilog-vpi.pdf: iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(prefix)/iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(DESTDIR)$(prefix)/iverilog-vpi.pdf
|
||||
|
||||
# In windows installations, put a few examples and the quick_start
|
||||
# into the destination directory.
|
||||
@@ -261,22 +296,22 @@ $(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
|
||||
endif
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(includedir) $(libdir)/ivl \
|
||||
$(libdir)/ivl/include $(mandir) $(mandir)/man1
|
||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/ivl \
|
||||
$(DESTDIR)$(libdir)/ivl/include $(DESTDIR)$(mandir) $(DESTDIR)$(mandir)/man1
|
||||
|
||||
uninstall:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
for f in xnf.conf xnf-s.conf ivl@EXEEXT@; \
|
||||
do rm -f $(libdir)/ivl/$$f; done
|
||||
-rmdir $(libdir)/ivl/include
|
||||
-rmdir $(libdir)/ivl
|
||||
for f in xnf.conf xnf-s.conf ivl@EXEEXT@ include/constants.vams include/disciplines.vams; \
|
||||
do rm -f $(DESTDIR)$(libdir)/ivl/$$f; done
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl/include
|
||||
-rmdir $(DESTDIR)$(libdir)/ivl
|
||||
for f in verilog iverilog-vpi gverilog@EXEEXT@; \
|
||||
do rm -f $(bindir)/$$f; done
|
||||
do rm -f $(DESTDIR)$(bindir)/$$f; done
|
||||
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
|
||||
do rm -f $(includedir)/$$f; done
|
||||
rm -f $(mandir)/man1/iverilog-vpi.1 $(prefix)/iverilog-vpi.pdf
|
||||
do rm -f $(DESTDIR)$(includedir)/$$f; done
|
||||
rm -f $(DESTDIR)$(mandir)/man1/iverilog-vpi.1 $(DESTDIR)$(prefix)/iverilog-vpi.pdf
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2008 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,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Module.cc,v 1.27 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -29,7 +26,7 @@
|
||||
|
||||
/* n is a permallocated string. */
|
||||
Module::Module(perm_string n)
|
||||
: name_(n)
|
||||
: PScope(n, 0)
|
||||
{
|
||||
library_flag = false;
|
||||
default_nettype = NetNet::NONE;
|
||||
@@ -54,21 +51,6 @@ void Module::add_function(perm_string name, PFunction *func)
|
||||
funcs_[name] = func;
|
||||
}
|
||||
|
||||
PWire* Module::add_wire(PWire*wire)
|
||||
{
|
||||
PWire*&ep = wires_[wire->path()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
void Module::add_behavior(PProcess*b)
|
||||
{
|
||||
behaviors_.push_back(b);
|
||||
}
|
||||
|
||||
unsigned Module::port_count() const
|
||||
{
|
||||
return ports.count();
|
||||
@@ -111,15 +93,6 @@ unsigned Module::find_port(const char*name) const
|
||||
}
|
||||
|
||||
|
||||
PWire* Module::get_wire(const pform_name_t&name) const
|
||||
{
|
||||
map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
|
||||
if (obj == wires_.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
PGate* Module::get_gate(perm_string name)
|
||||
{
|
||||
for (list<PGate*>::iterator cur = gates_.begin()
|
||||
@@ -138,102 +111,3 @@ const list<PGate*>& Module::get_gates() const
|
||||
return gates_;
|
||||
}
|
||||
|
||||
const list<PProcess*>& Module::get_behaviors() const
|
||||
{
|
||||
return behaviors_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: Module.cc,v $
|
||||
* Revision 1.27 2007/05/24 04:07:11 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
*
|
||||
* Revision 1.26 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.25 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.24 2004/06/13 04:56:53 steve
|
||||
* Add support for the default_nettype directive.
|
||||
*
|
||||
* Revision 1.23 2004/02/20 06:22:56 steve
|
||||
* parameter keys are per_strings.
|
||||
*
|
||||
* Revision 1.22 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.21 2003/04/02 03:00:14 steve
|
||||
* Cope with empty module ports while binding by name.
|
||||
*
|
||||
* Revision 1.20 2003/03/06 04:37:12 steve
|
||||
* lex_strings.add module names earlier.
|
||||
*
|
||||
* Revision 1.19 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.18 2002/05/19 23:37:28 steve
|
||||
* Parse port_declaration_lists from the 2001 Standard.
|
||||
*
|
||||
* Revision 1.17 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.16 2001/10/20 05:21:51 steve
|
||||
* Scope/module names are char* instead of string.
|
||||
*
|
||||
* Revision 1.15 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.14 2000/11/15 20:31:05 steve
|
||||
* Fix warning about temporaries.
|
||||
*
|
||||
* Revision 1.13 2000/11/05 06:05:59 steve
|
||||
* Handle connectsion to internally unconnected modules (PR#38)
|
||||
*
|
||||
* Revision 1.12 2000/05/16 04:05:15 steve
|
||||
* Module ports are really special PEIdent
|
||||
* expressions, because a name can be used
|
||||
* many places in the port list.
|
||||
*
|
||||
* Revision 1.11 2000/03/12 17:09:40 steve
|
||||
* Support localparam.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Revision 1.5 1999/08/03 04:14:49 steve
|
||||
* Parse into pform arbitrarily complex module
|
||||
* port declarations.
|
||||
*
|
||||
* Revision 1.4 1999/07/31 19:14:47 steve
|
||||
* Add functions up to elaboration (Ed Carter)
|
||||
*
|
||||
* Revision 1.3 1999/07/03 02:12:51 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
* Revision 1.2 1999/06/17 05:34:42 steve
|
||||
* Clean up interface of the PWire class,
|
||||
* Properly match wire ranges.
|
||||
*
|
||||
* Revision 1.1 1998/11/03 23:28:51 steve
|
||||
* Introduce verilog to CVS.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __Module_H
|
||||
#define __Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2004 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2008 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,9 +18,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include <list>
|
||||
# include <map>
|
||||
@@ -28,10 +26,10 @@
|
||||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include "named.h"
|
||||
# include "PScope.h"
|
||||
# include "LineInfo.h"
|
||||
# include "netlist.h"
|
||||
# include "pform_types.h"
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PEIdent;
|
||||
class PGate;
|
||||
@@ -50,7 +48,7 @@ class NetScope;
|
||||
* therefore the handle for grasping the described circuit.
|
||||
*/
|
||||
|
||||
class Module : public LineInfo {
|
||||
class Module : public PScope, public LineInfo {
|
||||
|
||||
/* The module ports are in general a vector of port_t
|
||||
objects. Each port has a name and an ordered list of
|
||||
@@ -77,14 +75,35 @@ class Module : public LineInfo {
|
||||
|
||||
NetNet::Type default_nettype;
|
||||
|
||||
struct range_t {
|
||||
// True if this is an exclude
|
||||
bool exclude_flag;
|
||||
// lower bound
|
||||
// If low_open_flag is false and low_expr=0, then use -inf
|
||||
bool low_open_flag;
|
||||
PExpr*low_expr;
|
||||
// upper bound
|
||||
// If high_open_flag is false and high_expr=0, then use +inf
|
||||
bool high_open_flag;
|
||||
PExpr*high_expr;
|
||||
// Next range description in list
|
||||
struct range_t*next;
|
||||
};
|
||||
|
||||
/* The module has parameters that are evaluated when the
|
||||
module is elaborated. During parsing, I put the parameters
|
||||
into this map. */
|
||||
struct param_expr_t {
|
||||
PExpr*expr;
|
||||
struct param_expr_t : public LineInfo {
|
||||
param_expr_t() : type(IVL_VT_NO_TYPE), msb(0), lsb(0), signed_flag(false), expr(0), range(0) { }
|
||||
// Type information
|
||||
ivl_variable_type_t type;
|
||||
PExpr*msb;
|
||||
PExpr*lsb;
|
||||
bool signed_flag;
|
||||
// Value expression
|
||||
PExpr*expr;
|
||||
// If there are range constrants, list them here
|
||||
range_t*range;
|
||||
};
|
||||
map<perm_string,param_expr_t>parameters;
|
||||
map<perm_string,param_expr_t>localparams;
|
||||
@@ -113,9 +132,6 @@ class Module : public LineInfo {
|
||||
named array of PEident pointers. */
|
||||
svector<port_t*> ports;
|
||||
|
||||
/* Keep a table of named events declared in the module. */
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
/* These are the timescale for this module. The default is
|
||||
@@ -124,7 +140,7 @@ class Module : public LineInfo {
|
||||
|
||||
/* The module has a list of genvars that may be used in
|
||||
various generate schemes. */
|
||||
list<perm_string> genvars;
|
||||
map<perm_string,LineInfo*> genvars;
|
||||
|
||||
/* the module has a list of generate schemes that appear in
|
||||
the module definition. These are used at elaboration time. */
|
||||
@@ -132,16 +148,10 @@ class Module : public LineInfo {
|
||||
|
||||
list<PSpecPath*> specify_paths;
|
||||
|
||||
perm_string mod_name() const { return name_; }
|
||||
// The mod_name() is the name of the module type.
|
||||
perm_string mod_name() const { return pscope_name(); }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
|
||||
// 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(perm_string name, PTask*def);
|
||||
void add_function(perm_string name, PFunction*def);
|
||||
|
||||
@@ -149,13 +159,9 @@ class Module : public LineInfo {
|
||||
const svector<PEIdent*>& get_port(unsigned idx) const;
|
||||
unsigned find_port(const char*name) const;
|
||||
|
||||
// Find a wire by name. This is used for connecting gates to
|
||||
// existing wires, etc.
|
||||
PWire* get_wire(const pform_name_t&name) const;
|
||||
PGate* get_gate(perm_string name);
|
||||
|
||||
const list<PGate*>& get_gates() const;
|
||||
const list<PProcess*>& get_behaviors() const;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
bool elaborate(Design*, NetScope*scope) const;
|
||||
@@ -166,39 +172,16 @@ class Module : public LineInfo {
|
||||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
||||
map<pform_name_t,PWire*> wires_;
|
||||
list<PGate*> gates_;
|
||||
list<PProcess*> behaviors_;
|
||||
map<perm_string,PTask*> tasks_;
|
||||
map<perm_string,PFunction*> funcs_;
|
||||
|
||||
static void elaborate_parm_item_(perm_string name, const param_expr_t&cur,
|
||||
Design*des, NetScope*scope);
|
||||
|
||||
private: // Not implemented
|
||||
Module(const Module&);
|
||||
Module& operator= (const Module&);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: Module.h,v $
|
||||
* Revision 1.43 2007/05/24 04:07:11 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
*
|
||||
* Revision 1.42 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.41 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
* Revision 1.40 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.39 2006/03/30 01:49:07 steve
|
||||
* Fix instance arrays indexed by overridden parameters.
|
||||
*
|
||||
* Revision 1.38 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*/
|
||||
#endif
|
||||
|
||||
+3
-65
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2008 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
|
||||
@@ -24,6 +24,7 @@
|
||||
# include "PDelays.h"
|
||||
# include "PExpr.h"
|
||||
# include "verinum.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
PDelays::PDelays()
|
||||
{
|
||||
@@ -63,10 +64,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||
{
|
||||
|
||||
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
|
||||
if (NetExpr*tmp = dex->eval_tree()) {
|
||||
delete dex;
|
||||
dex = tmp;
|
||||
}
|
||||
eval_expr(dex);
|
||||
|
||||
/* If the delay expression is a real constant or vector
|
||||
constant, then evaluate it, scale it to the local time
|
||||
@@ -163,63 +161,3 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
decay_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.15 2006/07/08 21:48:46 steve
|
||||
* Handle real valued literals in net contexts.
|
||||
*
|
||||
* Revision 1.14 2006/06/02 04:48:49 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.13 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.12 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.11 2003/06/21 01:21:42 steve
|
||||
* Harmless fixup of warnings.
|
||||
*
|
||||
* Revision 1.10 2003/02/08 19:49:21 steve
|
||||
* Calculate delay statement delays using elaborated
|
||||
* expressions instead of pre-elaborated expression
|
||||
* trees.
|
||||
*
|
||||
* Remove the eval_pexpr methods from PExpr.
|
||||
*
|
||||
* Revision 1.9 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.8 2001/12/29 20:19:31 steve
|
||||
* Do not delete delay expressions of UDP instances.
|
||||
*
|
||||
* Revision 1.7 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
* Revision 1.6 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
*
|
||||
* Revision 1.5 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.4 2001/01/20 02:15:50 steve
|
||||
* apologize for not supporting non-constant delays.
|
||||
*
|
||||
* Revision 1.3 2001/01/14 23:04:55 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ bool PExpr::is_constant(Module*) const
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_fileline() << ": error: expression not valid in assign l-value: "
|
||||
<< *this << endl;
|
||||
@@ -191,7 +191,7 @@ PEIdent::~PEIdent()
|
||||
|
||||
/*
|
||||
* An identifier can be in a constant expression if (and only if) it is
|
||||
* a parameter.
|
||||
* a parameter or genvar.
|
||||
*
|
||||
* NOTE: This test does not work if the name is hierarchical!
|
||||
*/
|
||||
@@ -212,6 +212,11 @@ bool PEIdent::is_constant(Module*mod) const
|
||||
if (cur != mod->localparams.end()) return true;
|
||||
}
|
||||
|
||||
{ map<perm_string,LineInfo*>::const_iterator cur;
|
||||
cur = mod->genvars.find(tmp);
|
||||
if (cur != mod->genvars.end()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PExpr_H
|
||||
#define __PExpr_H
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2008 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
|
||||
@@ -74,6 +74,10 @@ class PExpr : public LineInfo {
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
// During the elaborate_sig phase, we may need to scan
|
||||
// expressions to find implicit net declarations.
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
// Procedural elaboration of the expression. The expr_width is
|
||||
// the width of the context of the expression (i.e. the
|
||||
// l-value width of an assignment),
|
||||
@@ -107,8 +111,7 @@ class PExpr : public LineInfo {
|
||||
|
||||
// This method elaborates the expression as gates, but
|
||||
// restricted for use as l-values of continuous assignments.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
|
||||
// This is similar to elaborate_lnet, except that the
|
||||
// expression is evaluated to be bi-directional. This is
|
||||
@@ -119,7 +122,7 @@ class PExpr : public LineInfo {
|
||||
// Expressions that can be in the l-value of procedural
|
||||
// assignments can be elaborated with this method. If the
|
||||
// is_force flag is true, then the set of valid l-value types
|
||||
// is slightly modified to accomodate the Verilog force
|
||||
// is slightly modified to accommodate the Verilog force
|
||||
// statement
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
@@ -157,8 +160,8 @@ class PEConcat : public PExpr {
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
@@ -177,7 +180,6 @@ class PEConcat : public PExpr {
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const;
|
||||
private:
|
||||
svector<PExpr*>parms_;
|
||||
@@ -255,7 +257,7 @@ class PEIdent : public PExpr {
|
||||
explicit PEIdent(const pform_name_t&);
|
||||
~PEIdent();
|
||||
|
||||
// Add another name to the string of heirarchy that is the
|
||||
// Add another name to the string of hierarchy that is the
|
||||
// current identifier.
|
||||
void append_name(perm_string);
|
||||
|
||||
@@ -264,9 +266,10 @@ class PEIdent : public PExpr {
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
// Identifiers are allowed (with restrictions) is assign l-values.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -303,6 +306,11 @@ class PEIdent : public PExpr {
|
||||
private:
|
||||
// Common functions to calculate parts of part/bit selects.
|
||||
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb) const;
|
||||
NetExpr* calculate_up_do_base_(Design*, NetScope*) const;
|
||||
bool calculate_param_range_(Design*, NetScope*,
|
||||
const NetExpr*msb_ex, long&msb,
|
||||
const NetExpr*lsb_ex, long&lsb) const;
|
||||
|
||||
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
|
||||
|
||||
private:
|
||||
@@ -318,6 +326,18 @@ class PEIdent : public PExpr {
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_param_part_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_param_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
@@ -379,13 +399,12 @@ class PEIdent : public PExpr {
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const;
|
||||
|
||||
NetNet*make_implicit_net_(Design*des, NetScope*scope) const;
|
||||
|
||||
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
unsigned&midx, unsigned&lidx) const;
|
||||
long&midx, long&lidx) const;
|
||||
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
|
||||
|
||||
};
|
||||
@@ -472,6 +491,8 @@ class PEUnary : public PExpr {
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
@@ -531,6 +552,8 @@ class PEBinary : public PExpr {
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
@@ -538,7 +561,7 @@ class PEBinary : public PExpr {
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
@@ -548,10 +571,10 @@ class PEBinary : public PExpr {
|
||||
PExpr*left_;
|
||||
PExpr*right_;
|
||||
|
||||
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetEBinary*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
|
||||
static void surpress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
|
||||
static void suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
|
||||
|
||||
private:
|
||||
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
|
||||
@@ -589,6 +612,11 @@ class PEBinary : public PExpr {
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_pow_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
@@ -597,7 +625,7 @@ class PEBinary : public PExpr {
|
||||
};
|
||||
|
||||
/*
|
||||
* Here are a few specilized classes for handling specific binary
|
||||
* Here are a few specialized classes for handling specific binary
|
||||
* operators.
|
||||
*/
|
||||
class PEBComp : public PEBinary {
|
||||
@@ -610,8 +638,8 @@ class PEBComp : public PEBinary {
|
||||
unsigned min, unsigned lval,
|
||||
bool&flag) const;
|
||||
|
||||
NetEBinary* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
NetExpr* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
};
|
||||
|
||||
class PEBShift : public PEBinary {
|
||||
@@ -641,6 +669,8 @@ class PETernary : public PExpr {
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
@@ -667,7 +697,7 @@ class PETernary : public PExpr {
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
|
||||
// Call of system function (name is not heirarchical)
|
||||
// Call of system function (name is not hierarchical)
|
||||
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n);
|
||||
~PECallFunction();
|
||||
|
||||
+3
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2008 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,16 +16,13 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PFunction.cc,v 1.7 2004/05/31 23:34:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
#include "PTask.h"
|
||||
|
||||
PFunction::PFunction(perm_string name)
|
||||
: name_(name), ports_(0), statement_(0)
|
||||
PFunction::PFunction(perm_string name, PScope*parent)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
{
|
||||
return_type_.type = PTF_NONE;
|
||||
}
|
||||
@@ -51,28 +48,3 @@ void PFunction::set_return(PTaskFuncArg t)
|
||||
{
|
||||
return_type_ = t;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PFunction.cc,v $
|
||||
* Revision 1.7 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
* speed and more type support.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.4 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -129,6 +129,7 @@ class PGAssign : public PGate {
|
||||
|
||||
void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
};
|
||||
@@ -166,6 +167,7 @@ class PGBuiltin : public PGate {
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
@@ -234,6 +236,7 @@ class PGModule : public PGate {
|
||||
void elaborate_udp_(Design*, PUdp *udp, NetScope*scope) const;
|
||||
void elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const;
|
||||
bool elaborate_sig_mod_(Design*des, NetScope*scope, Module*mod) const;
|
||||
bool elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const;
|
||||
|
||||
NetNet*resize_net_to_port_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned port_wid,
|
||||
|
||||
+2
-12
@@ -33,19 +33,9 @@ PGenerate::~PGenerate()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PGenerate::add_wire(PWire*wire)
|
||||
PWire* PGenerate::get_wire(perm_string name) const
|
||||
{
|
||||
PWire*&ep = wires[wire->path()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
PWire* PGenerate::get_wire(const pform_name_t&name) const
|
||||
{
|
||||
map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
|
||||
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
|
||||
if (obj == wires.end())
|
||||
return 0;
|
||||
else
|
||||
|
||||
+16
-5
@@ -37,7 +37,17 @@ class PGate;
|
||||
class PWire;
|
||||
|
||||
/*
|
||||
* This represents a generate scheme.
|
||||
* This represents a generate scheme. The interpretation of the
|
||||
* members depends on the scheme_type.
|
||||
*
|
||||
* GS_LOOP
|
||||
*
|
||||
* GS_CASE
|
||||
* loop_test is the expression to be compared.
|
||||
* generates contains only GS_CASE_ITEM schemes.
|
||||
* GS_CASE_ITEM
|
||||
* The parent points to the GS_CASE that contains this item.
|
||||
* the loop_test is compared with the parent->loop_test expression.
|
||||
*/
|
||||
class PGenerate : public LineInfo {
|
||||
|
||||
@@ -50,7 +60,8 @@ class PGenerate : public LineInfo {
|
||||
const unsigned id_number;
|
||||
perm_string scope_name;
|
||||
|
||||
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE};
|
||||
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
|
||||
GS_CASE, GS_CASE_ITEM};
|
||||
scheme_t scheme_type;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
@@ -60,9 +71,8 @@ class PGenerate : public LineInfo {
|
||||
PExpr*loop_test;
|
||||
PExpr*loop_step;
|
||||
|
||||
map<pform_name_t,PWire*>wires;
|
||||
PWire* add_wire(PWire*);
|
||||
PWire* get_wire(const pform_name_t&name) const;
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* get_wire(perm_string name) const;
|
||||
|
||||
list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
@@ -88,6 +98,7 @@ class PGenerate : public LineInfo {
|
||||
private:
|
||||
bool generate_scope_loop_(Design*des, NetScope*container);
|
||||
bool generate_scope_condit_(Design*des, NetScope*container, bool else_flag);
|
||||
bool generate_scope_case_(Design*des, NetScope*container);
|
||||
|
||||
// Elaborate_scope within a generated scope.
|
||||
void elaborate_subscope_(Design*des, NetScope*scope);
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
*/
|
||||
|
||||
# include "PScope.h"
|
||||
|
||||
PScope::PScope(perm_string n, PScope*p)
|
||||
: name_(n), parent_(p)
|
||||
{
|
||||
}
|
||||
|
||||
PScope::~PScope()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PScope::wires_find(perm_string name)
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
|
||||
if (cur == wires.end())
|
||||
return 0;
|
||||
else
|
||||
return (*cur).second;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#ifndef __PScope_H
|
||||
#define __PScope_H
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
*/
|
||||
|
||||
# include "StringHeap.h"
|
||||
# include "pform_types.h"
|
||||
# include <map>
|
||||
|
||||
class PEvent;
|
||||
class PProcess;
|
||||
class PWire;
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
* The PScope class is a base representation of an object that
|
||||
* represents lexical scope. For example, a module, a function/task, a
|
||||
* named block is derived from a PScope.
|
||||
*
|
||||
* NOTE: This is note the same concept as the "scope" of an elaborated
|
||||
* hierarchy. That is represented by NetScope objects after elaboration.
|
||||
*/
|
||||
class PScope {
|
||||
|
||||
public:
|
||||
// When created, a scope has a name and a parent. The name is
|
||||
// the name of the definition. For example, if this is a
|
||||
// module declaration, the name is the name after the "module"
|
||||
// keyword, and if this is a task scope, the name is the task
|
||||
// name. The parent is the lexical parent of this scope. Since
|
||||
// modules do not nest in Verilog, the parent must be nil for
|
||||
// modules. Scopes for tasks and functions point to their
|
||||
// containing module.
|
||||
PScope(perm_string name, PScope*parent);
|
||||
virtual ~PScope();
|
||||
|
||||
perm_string pscope_name() const { return name_; }
|
||||
PScope* pscope_parent() { return parent_; }
|
||||
|
||||
// Nets an variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
|
||||
protected:
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
|
||||
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
|
||||
|
||||
bool elaborate_behaviors_(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
PScope*parent_;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2008 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,16 +16,13 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PTask.cc,v 1.7 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PTask.h"
|
||||
|
||||
PTask::PTask()
|
||||
: ports_(0), statement_(0)
|
||||
PTask::PTask(perm_string name, PScope*parent)
|
||||
: PScope(name, parent), ports_(0), statement_(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PTask_H
|
||||
#define __PTask_H
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2008 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,11 +18,9 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PTask.h,v 1.14 2007/03/06 05:22:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "PScope.h"
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include <string>
|
||||
@@ -50,10 +48,10 @@ struct PTaskFuncArg {
|
||||
/*
|
||||
* The PTask holds the parsed definitions of a task.
|
||||
*/
|
||||
class PTask : public LineInfo {
|
||||
class PTask : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PTask();
|
||||
explicit PTask(perm_string name, PScope*parent);
|
||||
~PTask();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
@@ -89,10 +87,10 @@ class PTask : public LineInfo {
|
||||
*
|
||||
* The output value is not elaborated until elaborate_sig.
|
||||
*/
|
||||
class PFunction : public LineInfo {
|
||||
class PFunction : public PScope, public LineInfo {
|
||||
|
||||
public:
|
||||
explicit PFunction(perm_string name);
|
||||
explicit PFunction(perm_string name, PScope*parent);
|
||||
~PFunction();
|
||||
|
||||
void set_ports(svector<PWire *>*p);
|
||||
@@ -110,68 +108,9 @@ class PFunction : public LineInfo {
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
PTaskFuncArg return_type_;
|
||||
svector<PWire *> *ports_;
|
||||
Statement *statement_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.14 2007/03/06 05:22:49 steve
|
||||
* Support signed function return values.
|
||||
*
|
||||
* Revision 1.13 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
* speed and more type support.
|
||||
*
|
||||
* Revision 1.12 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.11 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
* Revision 1.10 2001/01/13 22:20:08 steve
|
||||
* Parse parameters within nested scopes.
|
||||
*
|
||||
* Revision 1.9 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.8 2000/03/08 04:36:53 steve
|
||||
* Redesign the implementation of scopes and parameters.
|
||||
* I now generate the scopes and notice the parameters
|
||||
* in a separate pass over the pform. Once the scopes
|
||||
* are generated, I can process overrides and evalutate
|
||||
* paremeters before elaboration begins.
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
* Revision 1.2 1999/07/24 02:11:19 steve
|
||||
* Elaborate task input ports.
|
||||
*
|
||||
* Revision 1.1 1999/07/03 02:12:51 steve
|
||||
* Elaborate user defined tasks.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -22,15 +22,15 @@
|
||||
# include "PExpr.h"
|
||||
# include <assert.h>
|
||||
|
||||
PWire::PWire(const pform_name_t&n,
|
||||
PWire::PWire(perm_string n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt)
|
||||
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
signed_(false), isint_(false),
|
||||
port_msb_(0), port_lsb_(0), port_set_(false),
|
||||
net_msb_(0), net_lsb_(0), net_set_(false), error_cnt_(0),
|
||||
lidx_(0), ridx_(0)
|
||||
lidx_(0), ridx_(0), discipline_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
@@ -44,9 +44,9 @@ NetNet::Type PWire::get_wire_type() const
|
||||
return type_;
|
||||
}
|
||||
|
||||
const pform_name_t& PWire::path() const
|
||||
perm_string PWire::basename() const
|
||||
{
|
||||
return hname_;
|
||||
return name_;
|
||||
}
|
||||
|
||||
bool PWire::set_wire_type(NetNet::Type t)
|
||||
@@ -135,25 +135,12 @@ bool PWire::get_isint() const
|
||||
return isint_;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since implicitly defined list of port declarations are no longer
|
||||
* considered fully defined we no longer need this routine to force
|
||||
* them to be fully defined.
|
||||
*
|
||||
void PWire::set_net_range()
|
||||
{
|
||||
net_msb_ = port_msb_;
|
||||
net_lsb_ = port_lsb_;
|
||||
net_set_ = true;
|
||||
}
|
||||
*/
|
||||
|
||||
void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||
{
|
||||
switch (type) {
|
||||
case SR_PORT:
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << hname_
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
@@ -165,7 +152,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||
|
||||
case SR_NET:
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << hname_
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
@@ -178,12 +165,12 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||
case SR_BOTH:
|
||||
if (port_set_ || net_set_) {
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << hname_
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << hname_
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
@@ -202,7 +189,7 @@ void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||
void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
{
|
||||
if (lidx_ != 0 || ridx_ != 0) {
|
||||
cerr << get_fileline() << ": error: Array ``" << hname_
|
||||
cerr << get_fileline() << ": error: Array ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
@@ -211,3 +198,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
}
|
||||
}
|
||||
|
||||
void PWire::set_discipline(discipline_t*d)
|
||||
{
|
||||
assert(discipline_ == 0);
|
||||
discipline_ = d;
|
||||
}
|
||||
|
||||
discipline_t* PWire::get_discipline(void) const
|
||||
{
|
||||
return discipline_;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ class ostream;
|
||||
|
||||
class PExpr;
|
||||
class Design;
|
||||
class discipline_t;
|
||||
|
||||
/*
|
||||
* The different type of PWire::set_range() calls.
|
||||
@@ -56,13 +57,13 @@ enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
|
||||
class PWire : public LineInfo {
|
||||
|
||||
public:
|
||||
PWire(const pform_name_t&hname,
|
||||
PWire(perm_string name,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
|
||||
// Return a hierarchical name.
|
||||
const pform_name_t&path() const;
|
||||
perm_string basename() const;
|
||||
|
||||
NetNet::Type get_wire_type() const;
|
||||
bool set_wire_type(NetNet::Type);
|
||||
@@ -78,10 +79,12 @@ class PWire : public LineInfo {
|
||||
ivl_variable_type_t get_data_type() const;
|
||||
|
||||
void set_range(PExpr*msb, PExpr*lsb, PWSRType type);
|
||||
void set_net_range();
|
||||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
|
||||
void set_discipline(discipline_t*);
|
||||
discipline_t* get_discipline(void) const;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
// Write myself to the specified stream.
|
||||
@@ -90,7 +93,7 @@ class PWire : public LineInfo {
|
||||
NetNet* elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
pform_name_t hname_;
|
||||
perm_string name_;
|
||||
NetNet::Type type_;
|
||||
NetNet::PortType port_type_;
|
||||
ivl_variable_type_t data_type_;
|
||||
@@ -112,6 +115,8 @@ class PWire : public LineInfo {
|
||||
PExpr*lidx_;
|
||||
PExpr*ridx_;
|
||||
|
||||
discipline_t*discipline_;
|
||||
|
||||
private: // not implemented
|
||||
PWire(const PWire&);
|
||||
PWire& operator= (const PWire&);
|
||||
|
||||
+8
-8
@@ -86,18 +86,13 @@ PAssignNB::~PAssignNB()
|
||||
{
|
||||
}
|
||||
|
||||
PBlock::PBlock(perm_string n, BL_TYPE t, const svector<Statement*>&st)
|
||||
: name_(n), bl_type_(t), list_(st)
|
||||
{
|
||||
}
|
||||
|
||||
PBlock::PBlock(BL_TYPE t, const svector<Statement*>&st)
|
||||
: bl_type_(t), list_(st)
|
||||
PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
|
||||
: PScope(n, parent), bl_type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
PBlock::PBlock(BL_TYPE t)
|
||||
: bl_type_(t)
|
||||
: PScope(perm_string(),0), bl_type_(t)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -107,6 +102,11 @@ PBlock::~PBlock()
|
||||
delete list_[idx];
|
||||
}
|
||||
|
||||
void PBlock::set_statement(const svector<Statement*>&st)
|
||||
{
|
||||
list_ = st;
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p)
|
||||
: path_(n), parms_(p)
|
||||
{
|
||||
|
||||
+17
-97
@@ -1,7 +1,7 @@
|
||||
#ifndef __Statement_H
|
||||
#define __Statement_H
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2008 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,15 +18,13 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
# include "PDelays.h"
|
||||
# include "PExpr.h"
|
||||
# include "PScope.h"
|
||||
# include "HName.h"
|
||||
# include "LineInfo.h"
|
||||
class PExpr;
|
||||
@@ -83,6 +81,7 @@ class Statement : public LineInfo {
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -147,25 +146,27 @@ class PAssignNB : public PAssign_ {
|
||||
* statements before constructing this object, so it knows a priori
|
||||
* what is contained.
|
||||
*/
|
||||
class PBlock : public Statement {
|
||||
class PBlock : public PScope, public Statement {
|
||||
|
||||
public:
|
||||
enum BL_TYPE { BL_SEQ, BL_PAR };
|
||||
|
||||
explicit PBlock(perm_string n, BL_TYPE t, const svector<Statement*>&st);
|
||||
explicit PBlock(BL_TYPE t, const svector<Statement*>&st);
|
||||
// If the block has a name, it is a scope and also has a parent.
|
||||
explicit PBlock(perm_string n, PScope*parent, BL_TYPE t);
|
||||
// If it doesn't have a name, it's not a scope
|
||||
explicit PBlock(BL_TYPE t);
|
||||
~PBlock();
|
||||
|
||||
BL_TYPE bl_type() const { return bl_type_; }
|
||||
|
||||
void set_statement(const svector<Statement*>&st);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
const BL_TYPE bl_type_;
|
||||
svector<Statement*>list_;
|
||||
};
|
||||
@@ -215,6 +216,7 @@ class PCase : public Statement {
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -250,6 +252,7 @@ class PCondit : public Statement {
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -284,6 +287,7 @@ class PDelayStatement : public Statement {
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
PExpr*delay_;
|
||||
@@ -331,6 +335,7 @@ class PEventStatement : public Statement {
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
|
||||
// This method is used to elaborate, but attach a previously
|
||||
// elaborated statement to the event.
|
||||
@@ -364,6 +369,7 @@ class PForever : public Statement {
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -379,6 +385,7 @@ class PForStatement : public Statement {
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -407,6 +414,7 @@ class PRepeat : public Statement {
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -452,6 +460,7 @@ class PWhile : public Statement {
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_sig(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -459,93 +468,4 @@ class PWhile : public Statement {
|
||||
Statement*statement_;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.44 2007/05/24 04:07:11 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
*
|
||||
* Revision 1.43 2007/03/05 05:59:10 steve
|
||||
* Handle processes within generate loops.
|
||||
*
|
||||
* Revision 1.42 2005/12/05 21:21:18 steve
|
||||
* Fixes for stubborn compilers.
|
||||
*
|
||||
* Revision 1.41 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.40 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.39 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.38 2003/05/19 02:50:58 steve
|
||||
* Implement the wait statement behaviorally instead of as nets.
|
||||
*
|
||||
* Revision 1.37 2003/01/30 16:23:07 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.36 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.35 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.34 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.33 2002/04/21 22:31:02 steve
|
||||
* Redo handling of assignment internal delays.
|
||||
* Leave it possible for them to be calculated
|
||||
* at run time.
|
||||
*
|
||||
* Revision 1.32 2002/04/21 04:59:07 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.31 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.30 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
* Revision 1.29 2000/09/09 15:21:26 steve
|
||||
* move lval elaboration to PExpr virtual methods.
|
||||
*
|
||||
* Revision 1.28 2000/09/03 17:58:35 steve
|
||||
* Change elaborate_lval to return NetAssign_ objects.
|
||||
*
|
||||
* Revision 1.27 2000/07/26 05:08:07 steve
|
||||
* Parse disable statements to pform.
|
||||
*
|
||||
* Revision 1.26 2000/05/11 23:37:26 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
* Revision 1.25 2000/04/22 04:20:19 steve
|
||||
* Add support for force assignment.
|
||||
*
|
||||
* Revision 1.24 2000/04/12 04:23:57 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*/
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -16,4 +16,4 @@ do
|
||||
done
|
||||
|
||||
echo "Precompiling lexor_keyword.gperf"
|
||||
gperf -o -i 7 -C -k 1-3,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc
|
||||
gperf -o -i 7 -C -k 1-4,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc
|
||||
|
||||
+3
-18
@@ -16,12 +16,9 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.13 2007/02/06 05:07:31 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
VERSION = 0.9.devel
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -33,7 +30,7 @@ bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
vpidir = @libdir@/ivl/@vpidir1@
|
||||
vpidir = @libdir@/ivl
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
@@ -48,14 +45,6 @@ SHARED = @shared@
|
||||
|
||||
all:
|
||||
|
||||
ifeq (@enable_vvp32@,yes)
|
||||
vpidir32 = $(libdir)/ivl/@vpidir2@
|
||||
ALL32 = all32
|
||||
INSTALL32 = install32
|
||||
UNINSTALL32 = uninstall32
|
||||
include $(srcdir)/enable_vvp32.mk
|
||||
endif
|
||||
|
||||
all: dep cadpli.vpl $(ALL32)
|
||||
|
||||
# No specific check operations.
|
||||
@@ -71,7 +60,7 @@ dep:
|
||||
O = cadpli.o
|
||||
|
||||
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
|
||||
ifeq (@MING32@,yes)
|
||||
ifeq (@MINGW32@,yes)
|
||||
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
|
||||
endif
|
||||
|
||||
@@ -97,8 +86,4 @@ uninstall: $(UNINSTALL32)
|
||||
|
||||
uninstall32:
|
||||
|
||||
ifeq (@enable_vvp32@,yes)
|
||||
include $(srcdir)/enable_vvp32.mk
|
||||
endif
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -12,10 +12,6 @@ AX_WIN32
|
||||
|
||||
AC_PROG_INSTALL
|
||||
|
||||
# vvp32 is by default disabled
|
||||
#enable_vvp32=no
|
||||
AC_SUBST(enable_vvp32)
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
@@ -62,15 +58,4 @@ AX_C_UNDERSCORES_TRAILING
|
||||
|
||||
AX_CPP_IDENT
|
||||
|
||||
# where to put vpi subdirectories
|
||||
AC_MSG_CHECKING(for VPI subdirectories)
|
||||
if test x${vpidir1} = x
|
||||
then
|
||||
vpidir1="."
|
||||
fi
|
||||
|
||||
AC_SUBST(vpidir1)
|
||||
AC_SUBST(vpidir2)
|
||||
AC_MSG_RESULT(${vpidir1} ${vpidir2})
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: enable_vvp32.mk,v 1.1 2003/10/09 01:07:20 steve Exp $"
|
||||
#
|
||||
|
||||
all32: bin32 bin32/cadpli.vpl
|
||||
|
||||
bin32:
|
||||
mkdir bin32
|
||||
|
||||
bin32/%.o: %.c
|
||||
$(CC) -m32 -Wall -I$(srcdir) -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $@
|
||||
|
||||
bin32/cadpli.vpl: $(addprefix bin32/,$O) ../vvp/bin32/libvpi.a ../libveriuser/bin32/libveriuser.o
|
||||
$(CC) $(SHARED) -m32 -o $@ $(addprefix bin32/,$O) ../libveriuser/bin32/libveriuser.o ../vvp/bin32/libvpi.a
|
||||
|
||||
install32: all32 $(vpidir32)/cadpli.vpl
|
||||
|
||||
$(vpidir32)/cadpli.vpl: bin32/cadpli.vpl
|
||||
$(INSTALL_PROGRAM) bin32/cadpli.vpl $(vpidir32)/cadpli.vpl
|
||||
|
||||
uninstall32:
|
||||
rm -f $(vpidir32)/cadpli.vpl
|
||||
+25
-5
@@ -1,7 +1,7 @@
|
||||
#ifndef __compiler_H
|
||||
#define __compiler_H
|
||||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2008 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
|
||||
@@ -76,6 +76,9 @@ extern bool warn_timescale;
|
||||
/* Warn about legal but questionable module port bindings. */
|
||||
extern bool warn_portbinding;
|
||||
|
||||
/* Warn about structures that may have infinite loops. */
|
||||
extern bool warn_inf_loop;
|
||||
|
||||
/* This is true if verbose output is requested. */
|
||||
extern bool verbose_flag;
|
||||
|
||||
@@ -83,6 +86,7 @@ extern bool debug_scopes;
|
||||
extern bool debug_eval_tree;
|
||||
extern bool debug_elaborate;
|
||||
extern bool debug_synth2;
|
||||
extern bool debug_optimizer;
|
||||
|
||||
/* Path to a directory useful for finding subcomponents. */
|
||||
extern const char*basedir;
|
||||
@@ -97,26 +101,42 @@ extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||
enum generation_t {
|
||||
GN_VER1995 = 1,
|
||||
GN_VER2001 = 2,
|
||||
GN_VER2001X = 3,
|
||||
GN_VER2005 = 3,
|
||||
GN_DEFAULT = 3
|
||||
};
|
||||
|
||||
extern generation_t generation_flag;
|
||||
|
||||
/* If this flag is true, enable extended types support. */
|
||||
extern bool gn_cadence_types_flag;
|
||||
|
||||
/* These functions test that specific features are enabled. */
|
||||
inline bool gn_cadence_types_enabled()
|
||||
{ return gn_cadence_types_flag && generation_flag==GN_VER2001X; }
|
||||
/* If this flag is true, enable miscellaneous extensions. */
|
||||
extern bool gn_icarus_misc_flag;
|
||||
|
||||
/* If this flag is true, then elaborate specify blocks. If this flag
|
||||
is false, then skip elaboration of specify behavior. */
|
||||
extern bool gn_specify_blocks_flag;
|
||||
|
||||
/* If this flag is true, then support/elaborate Verilog-AMS. */
|
||||
extern bool gn_verilog_ams_flag;
|
||||
|
||||
/* If this flag is false a warning is printed when the port declaration
|
||||
is scalar and the net/register definition is vectored. */
|
||||
extern bool gn_io_range_error_flag;
|
||||
|
||||
/* The bits of these GN_KEYWORDS_* constants define non-intersecting
|
||||
sets of keywords. The compiler enables groups of keywords by setting
|
||||
lexor_keyword_mask with the OR of the bits for the keywords to be
|
||||
enabled. */
|
||||
enum { GN_KEYWORDS_1364_1995 = 0x0001,
|
||||
GN_KEYWORDS_1364_2001 = 0x0002,
|
||||
GN_KEYWORDS_1364_2001_CONFIG = 0x0004,
|
||||
GN_KEYWORDS_1364_2005 = 0x0008,
|
||||
GN_KEYWORDS_VAMS_2_3 = 0x0010,
|
||||
GN_KEYWORDS_ICARUS = 0x8000
|
||||
};
|
||||
extern int lexor_keyword_mask;
|
||||
|
||||
/* This is the string to use to invoke the preprocessor. */
|
||||
extern char*ivlpp_string;
|
||||
|
||||
|
||||
+3
-26
@@ -9,6 +9,9 @@ AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_CHECK_TOOL(STRIP, strip, true)
|
||||
AC_CHECK_PROGS(XGPERF,gperf,none)
|
||||
AC_CHECK_PROGS(MAN,man,none)
|
||||
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
|
||||
AC_CHECK_PROGS(GIT,git,none)
|
||||
if test "$XGPERF" = "none"
|
||||
then
|
||||
echo ""
|
||||
@@ -42,11 +45,6 @@ AC_SUBST(EXEEXT)
|
||||
# Combined check for Microsoft-related bogosities; sets WIN32 if found
|
||||
AX_WIN32
|
||||
|
||||
# vvp32 is by default disabled
|
||||
#enable_vvp32=no
|
||||
AC_SUBST(enable_vvp32)
|
||||
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
AC_CHECK_HEADERS(getopt.h malloc.h inttypes.h libiberty.h iosfwd sys/wait.h)
|
||||
@@ -123,27 +121,6 @@ AX_C_UNDERSCORES_TRAILING
|
||||
|
||||
AX_CPP_IDENT
|
||||
|
||||
# If not otherwise specified, set the libdir64 variable
|
||||
# to the same as libdir.
|
||||
AC_MSG_CHECKING(for libdir64 path)
|
||||
if test x${libdir64} = x
|
||||
then
|
||||
libdir64="${libdir}"
|
||||
fi
|
||||
AC_SUBST(libdir64)
|
||||
AC_MSG_RESULT(${libdir64})
|
||||
|
||||
# where to put vpi subdirectories
|
||||
AC_MSG_CHECKING(for VPI subdirectories)
|
||||
if test x${vpidir1} = x
|
||||
then
|
||||
vpidir1="."
|
||||
fi
|
||||
|
||||
AC_SUBST(vpidir1)
|
||||
AC_SUBST(vpidir2)
|
||||
AC_MSG_RESULT(${vpidir1} ${vpidir2})
|
||||
|
||||
# XXX disable tgt-fpga for the moment
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// Mathematical and physical constants
|
||||
|
||||
`ifdef CONSTANTS_VAMS
|
||||
`else
|
||||
`define CONSTANTS_VAMS 1
|
||||
|
||||
// M_ is a mathematical constant
|
||||
`define M_E 2.7182818284590452354
|
||||
`define M_LOG2E 1.4426950408889634074
|
||||
`define M_LOG10E 0.43429448190325182765
|
||||
`define M_LN2 0.69314718055994530942
|
||||
`define M_LN10 2.30258509299404568402
|
||||
`define M_PI 3.14159265358979323846
|
||||
`define M_TWO_PI 6.28318530717958647693
|
||||
`define M_PI_2 1.57079632679489661923
|
||||
`define M_PI_4 0.78539816339744830962
|
||||
`define M_1_PI 0.31830988618379067154
|
||||
`define M_2_PI 0.63661977236758134308
|
||||
`define M_2_SQRTPI 1.12837916709551257390
|
||||
`define M_SQRT2 1.41421356237309504880
|
||||
`define M_SQRT1_2 0.70710678118654752440
|
||||
|
||||
/*
|
||||
* Do we need these? For now they are not available.
|
||||
*
|
||||
// The following constants have been taken from http://physics.nist.gov
|
||||
// P_ is a physical constant
|
||||
// charge of electron in coulombs
|
||||
`define P_Q 1.602176462e-19
|
||||
// speed of light in vacuum in meters/sec
|
||||
`define P_C 2.99792458e8
|
||||
// Boltzmann's constant in joules/kelvin
|
||||
`define P_K 1.3806503e-23
|
||||
// Planck's constant in joules*sec
|
||||
`define P_H 6.62606876e-34
|
||||
// permittivity of vacuum in farads/meter
|
||||
`define P_EPS0 8.854187817e-12
|
||||
// permeability of vacuum in henrys/meter
|
||||
`define P_U0 (4.0e-7 * `M_PI)
|
||||
// zero celsius in kelvin
|
||||
`define P_CELSIUS0 273.15
|
||||
*/
|
||||
`endif
|
||||
@@ -23,6 +23,7 @@
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "functor.h"
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
||||
@@ -828,6 +829,32 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the select input is constant, then replace with a BUFZ */
|
||||
flag = obj->pin_Sel().nexus()->drivers_constant();
|
||||
verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx;
|
||||
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
|
||||
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
|
||||
tmp->set_line(*obj);
|
||||
|
||||
if (debug_optimizer)
|
||||
cerr << obj->get_fileline() << ": debug: "
|
||||
<< "Replace binary MUX with constant select=" << sel_val
|
||||
<< " with a BUFZ to the selected input." << endl;
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
connect(tmp->pin(0), obj->pin_Result());
|
||||
if (sel_val == verinum::V1)
|
||||
connect(tmp->pin(1), obj->pin_Data(1));
|
||||
else
|
||||
connect(tmp->pin(1), obj->pin_Data(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+194
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2008 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,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.176 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -91,6 +88,34 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&o, ivl_switch_type_t val)
|
||||
{
|
||||
switch (val) {
|
||||
case IVL_SW_TRAN:
|
||||
o << "tran";
|
||||
break;
|
||||
case IVL_SW_TRANIF0:
|
||||
o << "tranif0";
|
||||
break;
|
||||
case IVL_SW_TRANIF1:
|
||||
o << "tranif1";
|
||||
break;
|
||||
case IVL_SW_RTRAN:
|
||||
o << "rtran";
|
||||
break;
|
||||
case IVL_SW_RTRANIF0:
|
||||
o << "rtranif0";
|
||||
break;
|
||||
case IVL_SW_RTRANIF1:
|
||||
o << "rtranif1";
|
||||
break;
|
||||
case IVL_SW_TRAN_VP:
|
||||
o << "tran(VP)";
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void dump_scope_path(ostream&o, const NetScope*scope)
|
||||
{
|
||||
if (const NetScope*parent = scope->parent()) {
|
||||
@@ -115,6 +140,10 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "" << "specify delay";
|
||||
if (posedge_) o << " posedge";
|
||||
if (negedge_) o << " negedge";
|
||||
if (is_condit()) {
|
||||
if (has_condit()) o << " if";
|
||||
else o << " ifnone";
|
||||
}
|
||||
o << " src "
|
||||
<< "(" << transition_delays_[IVL_PE_01]
|
||||
<< "," << transition_delays_[IVL_PE_10]
|
||||
@@ -246,6 +275,15 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
|
||||
}
|
||||
}
|
||||
|
||||
void NetAbs::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Absolute value (NetAbs): " << name()
|
||||
<< " width=" << width() << " pin_count=" << pin_count()
|
||||
<< endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
|
||||
@@ -282,8 +320,13 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
|
||||
void NetConcat::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetConcat: "
|
||||
<< name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time() << "," << *decay_time() << ")";
|
||||
else
|
||||
o << " #(0,0,0)";
|
||||
o << " scope=" << scope_path(scope())
|
||||
<< " width=" << width_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -303,6 +346,22 @@ void NetMult::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetPow::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_POW (NetPow): " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " delay=(";
|
||||
if (rise_time())
|
||||
o << *rise_time() << "," << *fall_time() << ","
|
||||
<< *decay_time();
|
||||
else
|
||||
o << "0,0,0";
|
||||
|
||||
o << ")" << 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()
|
||||
@@ -336,7 +395,14 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "" << "constant " << width_ << "'b";
|
||||
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
|
||||
o << value_[idx-1];
|
||||
o << ": " << name() << endl;
|
||||
o << ": " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
@@ -353,7 +419,14 @@ void NetFF::dump_node(ostream&o, unsigned ind) const
|
||||
void NetLiteral::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant real " << real_
|
||||
<< ": " << name() << endl;
|
||||
<< ": " << name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
@@ -448,12 +521,16 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
||||
case PV:
|
||||
pt = "PV";
|
||||
break;
|
||||
case BI:
|
||||
pt = "BI";
|
||||
break;
|
||||
}
|
||||
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
|
||||
<< name() << " off=" << off_ << " wid=" << wid_ <<endl;
|
||||
<< name();
|
||||
if (rise_time())
|
||||
o << " #(" << *rise_time()
|
||||
<< "," << *fall_time()
|
||||
<< "," << *decay_time() << ")";
|
||||
else
|
||||
o << " #(.,.,.)";
|
||||
o << " off=" << off_ << " wid=" << wid_ <<endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -520,8 +597,12 @@ void NetSysFunc::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << scope_path(def_) << "(";
|
||||
o << ")" << endl;
|
||||
o << setw(ind) << "" << "USER FUNC: "
|
||||
<< scope_path(def_);
|
||||
if (rise_time())
|
||||
o << " #(" <<*rise_time()
|
||||
<<","<<*fall_time()
|
||||
<< "," <<*decay_time() << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -555,6 +636,20 @@ void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "" << "endtask" << endl;
|
||||
}
|
||||
|
||||
void NetTran::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << type_ << " " << name()
|
||||
<< " island " << island;
|
||||
if (type_ == IVL_SW_TRAN_VP) {
|
||||
o << " width=" << vector_width()
|
||||
<< " part=" << part_width()
|
||||
<< " offset=" << part_offset();
|
||||
}
|
||||
o << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUDP::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "UDP (" << udp_name() << "): ";
|
||||
@@ -796,10 +891,36 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "function " << scope_path(scope_) << endl;
|
||||
if (result_sig_)
|
||||
o << setw(ind+2) << "" << "Return signal: "
|
||||
<< result_sig_->name() << endl;
|
||||
o << setw(ind) << "" << "function definition for " << scope_path(scope_) << endl;
|
||||
if (result_sig_) {
|
||||
o << setw(ind+2) << "" << "Return signal: ";
|
||||
if (result_sig_->get_signed()) o << "+";
|
||||
o << result_sig_->name() << "[" << result_sig_->msb() << ":"
|
||||
<< result_sig_->lsb() << "]" << endl;
|
||||
}
|
||||
o << setw(ind+2) << "" << "Arguments: ";
|
||||
if (port_count() == 0) o << "<none>";
|
||||
o << endl;
|
||||
for (unsigned idx = 0; idx < port_count(); idx += 1) {
|
||||
o << setw(ind+4) << "" << "Arg[" << idx+1 << "] = ";
|
||||
switch (port(idx)->port_type()) {
|
||||
default:
|
||||
o << "implicit-port? ";
|
||||
break;
|
||||
case NetNet::PINPUT:
|
||||
o << "input ";
|
||||
break;
|
||||
case NetNet::POUTPUT:
|
||||
o << "output ";
|
||||
break;
|
||||
case NetNet::PINOUT:
|
||||
o << "inout ";
|
||||
break;
|
||||
}
|
||||
if (port(idx)->get_signed()) o << "+";
|
||||
o << port(idx)->name() << "[" << port(idx)->msb() << ":"
|
||||
<< port(idx)->lsb() << "]" << endl;
|
||||
}
|
||||
if (statement_)
|
||||
statement_->dump(o, ind+2);
|
||||
else
|
||||
@@ -884,8 +1005,37 @@ void NetScope::dump(ostream&o) const
|
||||
o << "[" << *(*pp).second.msb
|
||||
<< ":" << *(*pp).second.lsb << "] ";
|
||||
|
||||
o << (*pp).first << " = " <<
|
||||
*(*pp).second.expr << ";" << endl;
|
||||
o << (*pp).first << " = " << *(*pp).second.expr;
|
||||
|
||||
for (range_t*ran = (*pp).second.range ; ran ; ran = ran->next) {
|
||||
if (ran->exclude_flag)
|
||||
o << " exclude ";
|
||||
else
|
||||
o << " from ";
|
||||
|
||||
if (ran->low_open_flag)
|
||||
o << "(";
|
||||
else
|
||||
o << "[";
|
||||
if (ran->low_expr)
|
||||
o << *ran->low_expr;
|
||||
else if (ran->low_open_flag==false)
|
||||
o << "-inf";
|
||||
else
|
||||
o << "<?>";
|
||||
if (ran->high_expr)
|
||||
o << ":" << *ran->high_expr;
|
||||
else if (ran->high_open_flag==false)
|
||||
o << ":inf";
|
||||
else
|
||||
o << ":<?>";
|
||||
if (ran->high_open_flag)
|
||||
o << ")";
|
||||
else
|
||||
o << "]";
|
||||
}
|
||||
|
||||
o << ";" << endl;
|
||||
}
|
||||
|
||||
for (pp = localparams.begin()
|
||||
@@ -950,7 +1100,10 @@ void NetScope::dump(ostream&o) const
|
||||
o << " MISSING FUNCTION DEFINITION" << endl;
|
||||
break;
|
||||
case TASK:
|
||||
task_def()->dump(o, 4);
|
||||
if (task_def())
|
||||
task_def()->dump(o, 4);
|
||||
else
|
||||
o << " MISSING TASK DEFINITION" << endl;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1006,6 +1159,20 @@ void NetExpr::dump(ostream&o) const
|
||||
|
||||
void NetEBinary::dump(ostream&o) const
|
||||
{
|
||||
if (op_ == 'm' || op_ == 'M') {
|
||||
if (op_ == 'm')
|
||||
o << "min";
|
||||
else
|
||||
o << "max";
|
||||
|
||||
o << "(";
|
||||
left_->dump(o);
|
||||
o << ", ";
|
||||
right_->dump(o);
|
||||
o << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
o << "(";
|
||||
left_->dump(o);
|
||||
o << ")";
|
||||
@@ -1162,11 +1329,9 @@ void NetESignal::dump(ostream&o) const
|
||||
void NetEParam::dump(ostream&o) const
|
||||
{
|
||||
if (scope_ != 0)
|
||||
o << "<" << scope_path(scope_) << "." << name_ << ">";
|
||||
else if (name_)
|
||||
o << "<" << name_ << ">";
|
||||
o << "<" << scope_path(scope_) << "." << (*reference_).first << ">";
|
||||
else
|
||||
o << "<" "???" ">";
|
||||
o << "<" << (*reference_).first << ">";
|
||||
}
|
||||
|
||||
void NetETernary::dump(ostream&o) const
|
||||
@@ -1191,6 +1356,9 @@ void NetEUFunc::dump(ostream&o) const
|
||||
void NetEUnary::dump(ostream&o) const
|
||||
{
|
||||
switch (op_) {
|
||||
case 'm':
|
||||
o << "abs";
|
||||
break;
|
||||
case 'N':
|
||||
o << "~|";
|
||||
break;
|
||||
@@ -1217,6 +1385,7 @@ void Design::dump(ostream&o) const
|
||||
if (nodes_) {
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
do {
|
||||
assert(cur);
|
||||
cur->dump_node(o, 0);
|
||||
cur = cur->node_next_;
|
||||
} while (cur != nodes_->node_next_);
|
||||
@@ -1229,4 +1398,3 @@ void Design::dump(ostream&o) const
|
||||
idx->dump(o, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+16
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2008 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,29 +16,24 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: priv.c,v 1.2 2003/10/06 21:26:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "sys_priv.h"
|
||||
# include "discipline.h"
|
||||
|
||||
PLI_UINT64 timerec_to_time64(const struct t_vpi_time*time)
|
||||
nature_t::nature_t(perm_string name, perm_string access)
|
||||
: name_(name), access_(access)
|
||||
{
|
||||
PLI_UINT64 tmp;
|
||||
|
||||
tmp = time->high;
|
||||
tmp <<= 32;
|
||||
tmp |= (PLI_UINT64) time->low;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: priv.c,v $
|
||||
* Revision 1.2 2003/10/06 21:26:27 steve
|
||||
* Include sys_priv.h instead of priv.h
|
||||
*
|
||||
* Revision 1.1 2003/10/02 21:16:11 steve
|
||||
* Include timerec_to_time64 implementation.
|
||||
*
|
||||
*/
|
||||
nature_t::~nature_t()
|
||||
{
|
||||
}
|
||||
|
||||
discipline_t::discipline_t(perm_string name, ddomain_t domain,
|
||||
nature_t*pot, nature_t*flow)
|
||||
: name_(name), domain_(domain), potential_(pot), flow_(flow)
|
||||
{
|
||||
}
|
||||
|
||||
discipline_t::~discipline_t()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef __discipline_H
|
||||
#define __discipline_H
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* The discipline types include the discipline, nature and other
|
||||
* related types for managing declared and used disciplines in a
|
||||
* Verilog-AMS program.
|
||||
*/
|
||||
|
||||
# include "StringHeap.h"
|
||||
# include <iostream>
|
||||
# include <map>
|
||||
# include "LineInfo.h"
|
||||
|
||||
typedef enum { DD_NONE, DD_DISCRETE, DD_CONTINUOUS } ddomain_t;
|
||||
extern std::ostream& operator << (std::ostream&, ddomain_t);
|
||||
|
||||
class nature_t : public LineInfo {
|
||||
public:
|
||||
explicit nature_t(perm_string name, perm_string access);
|
||||
~nature_t();
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
// Identifier for the access function for this nature
|
||||
perm_string access() const { return access_; }
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
perm_string access_;
|
||||
};
|
||||
|
||||
class discipline_t : public LineInfo {
|
||||
public:
|
||||
explicit discipline_t (perm_string name, ddomain_t dom,
|
||||
nature_t*pot, nature_t*flow);
|
||||
~discipline_t();
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
ddomain_t domain() const { return domain_; }
|
||||
const nature_t*potential() const { return potential_; }
|
||||
const nature_t*flow() const { return flow_; }
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
ddomain_t domain_;
|
||||
nature_t*potential_;
|
||||
nature_t*flow_;
|
||||
|
||||
private: // not implemented
|
||||
discipline_t(const discipline_t&);
|
||||
discipline_t& operator = (const discipline_t&);
|
||||
};
|
||||
|
||||
extern map<perm_string,nature_t*> natures;
|
||||
extern map<perm_string,discipline_t*> disciplines;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
|
||||
// Standard definitions for Verilog-AMS
|
||||
`ifdef DISCIPLINES_VAMS
|
||||
`else
|
||||
`define DISCIPLINES_VAMS 1
|
||||
|
||||
discipline \logic ;
|
||||
domain discrete;
|
||||
enddiscipline
|
||||
|
||||
discipline ddiscrete;
|
||||
domain discrete;
|
||||
enddiscipline
|
||||
|
||||
nature Current;
|
||||
units = "A";
|
||||
access = I;
|
||||
idt_nature = Charge;
|
||||
`ifdef CURRENT_ABSTOL
|
||||
abstol = `CURRENT_ABSTOL
|
||||
`else
|
||||
abstol = 1e-12;
|
||||
`endif
|
||||
endnature
|
||||
|
||||
nature Charge;
|
||||
units = "coul";
|
||||
access = Q;
|
||||
ddt_nature = Current;
|
||||
`ifdef CHARGE_ABSTOL
|
||||
abstol = `CHARGE_ABSTOL;
|
||||
`else
|
||||
abstol = 1e-14;
|
||||
`endif
|
||||
endnature
|
||||
|
||||
nature Voltage;
|
||||
units = "V";
|
||||
access = V;
|
||||
idt_nature = Flux;
|
||||
`ifdef VOLTAGE_ABSTOL
|
||||
abstol = `VOLTAGE_ABSTOL;
|
||||
`else
|
||||
abstol = 1e-6;
|
||||
`endif
|
||||
endnature
|
||||
|
||||
nature Flux;
|
||||
units = "Wb";
|
||||
access = Phi;
|
||||
ddt_nature = Voltage;
|
||||
`ifdef FLUX_ABSTOL
|
||||
abstol = `flux_ABSTOL;
|
||||
`else
|
||||
abstol = 1e-9;
|
||||
`endif
|
||||
endnature
|
||||
|
||||
discipline electrical;
|
||||
potential Voltage;
|
||||
flow Current;
|
||||
enddiscipline
|
||||
|
||||
discipline voltage;
|
||||
potential Voltage;
|
||||
enddiscipline
|
||||
|
||||
discipline current;
|
||||
flow Current;
|
||||
enddiscipline
|
||||
|
||||
`endif // !`ifdef DISCIPLINES_VAMS
|
||||
@@ -16,16 +16,14 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.7.2.1 2006/10/04 17:08:59 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.8.3
|
||||
VERSION = 0.9.devel
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
@@ -47,6 +45,8 @@ LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: iverilog-vpi@EXEEXT@
|
||||
|
||||
check: all
|
||||
|
||||
clean:
|
||||
rm -f *.o config.h
|
||||
rm -f iverilog-vpi@EXEEXT@
|
||||
|
||||
+19
-12
@@ -33,6 +33,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
static void setup_ivl_environment();
|
||||
static void assign(char **ptr, char *str);
|
||||
|
||||
/* The compile options: compiler, flags, etc. are in here */
|
||||
#include "config.h"
|
||||
@@ -77,6 +78,7 @@ static void myExit(int exitVal)
|
||||
deInitDynString(gstr.pCFLAGS);
|
||||
deInitDynString(gstr.pLDLIBS);
|
||||
deInitDynString(gstr.pNewPath);
|
||||
free(gstr.pLD);
|
||||
|
||||
exit(exitVal);
|
||||
}
|
||||
@@ -120,7 +122,7 @@ static void init()
|
||||
initDynString(&gstr.pLDLIBS);
|
||||
initDynString(&gstr.pNewPath);
|
||||
/* By default use the C compiler to link the programs. */
|
||||
gstr.pLD = IVERILOG_VPI_CC;
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CC);
|
||||
}
|
||||
|
||||
/* return true if "str" is terminated with with "end", case insensitive */
|
||||
@@ -306,7 +308,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for C++ source files (*.cc) */
|
||||
else if (endsIn(dot_cc_ext, argv[idx])) {
|
||||
/* We need to link with the C++ compiler. */
|
||||
gstr.pLD = IVERILOG_VPI_CXX;
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CXX);
|
||||
++srcFileCnt;
|
||||
append(&gstr.pCXSRC, argv[idx]);
|
||||
append(&gstr.pCXSRC, " ");
|
||||
@@ -317,7 +319,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for C++ source files (*.cpp) */
|
||||
else if (endsIn(dot_cpp_ext, argv[idx])) {
|
||||
/* We need to link with the C++ compiler. */
|
||||
gstr.pLD = IVERILOG_VPI_CXX;
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CXX);
|
||||
++srcFileCnt;
|
||||
append(&gstr.pCXSRC, argv[idx]);
|
||||
append(&gstr.pCXSRC, " ");
|
||||
@@ -334,6 +336,14 @@ static int parse(int argc, char *argv[])
|
||||
assignn(&gstr.pOUT, argv[idx],
|
||||
strlen(argv[idx])-strlen(dot_o_ext));
|
||||
}
|
||||
/* Check for the -mingw option */
|
||||
else if (startsWith(mingw_option, argv[idx]))
|
||||
assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1,
|
||||
strlen(argv[idx])-(sizeof(mingw_option)-1));
|
||||
/* Check for the -ivl option */
|
||||
else if (startsWith(ivl_option, argv[idx]))
|
||||
assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1,
|
||||
strlen(argv[idx])-(sizeof(ivl_option)-1));
|
||||
/* Check for the --name option */
|
||||
else if (startsWith(name_option, argv[idx])) {
|
||||
assignn(&gstr.pOUT, argv[idx]+sizeof(name_option)-1,
|
||||
@@ -354,14 +364,6 @@ static int parse(int argc, char *argv[])
|
||||
append(&gstr.pDEFS, " ");
|
||||
append(&gstr.pDEFS, argv[idx]);
|
||||
}
|
||||
/* Check for the -mingw option */
|
||||
else if (startsWith(mingw_option, argv[idx]))
|
||||
assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1,
|
||||
strlen(argv[idx])-(sizeof(mingw_option)-1));
|
||||
/* Check for the -ivl option */
|
||||
else if (startsWith(ivl_option, argv[idx]))
|
||||
assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1,
|
||||
strlen(argv[idx])-(sizeof(ivl_option)-1));
|
||||
/* Check for the --cflags option */
|
||||
else if (stricmp("--cflags", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
@@ -482,6 +484,7 @@ static void setup_mingw_environment()
|
||||
assign(&gstr.pNewPath,"PATH=");
|
||||
append(&gstr.pNewPath,gstr.pMINGW);
|
||||
appendBackSlash(&gstr.pNewPath);
|
||||
append(&gstr.pNewPath, "\\");
|
||||
append(&gstr.pNewPath,"bin;");
|
||||
append(&gstr.pNewPath,pOldPATH);
|
||||
|
||||
@@ -512,12 +515,14 @@ static void setup_ivl_environment()
|
||||
append(&gstr.pCFLAGS," -I");
|
||||
append(&gstr.pCFLAGS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCFLAGS);
|
||||
append(&gstr.pCFLAGS, "\\");
|
||||
append(&gstr.pCFLAGS,"include");
|
||||
|
||||
/* Build up the LDFLAGS option string */
|
||||
assign(&gstr.pLDLIBS,"-L");
|
||||
append(&gstr.pLDLIBS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pLDLIBS);
|
||||
append(&gstr.pLDLIBS, "\\");
|
||||
append(&gstr.pLDLIBS,"lib ");
|
||||
append(&gstr.pLDLIBS,IVERILOG_VPI_LDLIBS);
|
||||
}
|
||||
@@ -537,7 +542,9 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
|
||||
assignn(&src, ptr1, len);
|
||||
|
||||
/* Build the object file name */
|
||||
ostart = strrchr(ptr1, '/') + 1;
|
||||
ostart = strrchr(ptr1, '/');
|
||||
if (ostart == NULL) ostart = ptr1;
|
||||
else ostart += 1;
|
||||
olen = strrchr(ptr1, '.') - ostart;
|
||||
assignn(&obj, ostart, olen);
|
||||
append(&obj, ".o");
|
||||
|
||||
+17
-9
@@ -16,16 +16,14 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.26 2007/02/06 05:07:31 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.8
|
||||
VERSION = 0.9.devel
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
@@ -40,6 +38,8 @@ CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
@@ -67,7 +67,7 @@ cfparse.h cfparse.c: cfparse.y
|
||||
bison --verbose -t -d -o cfparse.c --name-prefix=cf $(srcdir)/cfparse.y
|
||||
|
||||
|
||||
main.o: main.c globals.h
|
||||
main.o: main.c globals.h ../version.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
|
||||
|
||||
build_string.o: build_string.c globals.h
|
||||
@@ -75,15 +75,23 @@ cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
|
||||
cfparse.o: cfparse.c globals.h cfparse_misc.h
|
||||
|
||||
iverilog.ps: $(srcdir)/iverilog.man
|
||||
man -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
$(MAN) -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
|
||||
iverilog.pdf: iverilog.ps
|
||||
ps2pdf iverilog.ps iverilog.pdf
|
||||
$(PS2PDF) iverilog.ps iverilog.pdf
|
||||
|
||||
ifeq (@MING32@,yes)
|
||||
ifeq (@MINGW32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: iverilog.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cfparse_misc.h,v 1.6 2004/02/15 18:03:30 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The vlltype supports the passing of detailed source file location
|
||||
|
||||
+2
-2
@@ -31,10 +31,10 @@ extern const char*base;
|
||||
extern char* iconfig_path;
|
||||
extern char* iconfig_common_path;
|
||||
|
||||
/* Ths is the optional -M<dependfile> value, if one was supplied. */
|
||||
/* This is the optional -M<dependfile> value, if one was supplied. */
|
||||
extern const char*depfile;
|
||||
|
||||
/* Ths is the optional -N<path> value, if one was supplied. */
|
||||
/* This is the optional -N<path> value, if one was supplied. */
|
||||
extern const char*npath;
|
||||
|
||||
/* This is the name of the output file that the user selected. */
|
||||
|
||||
+40
-8
@@ -1,11 +1,11 @@
|
||||
.TH iverilog 1 "$Date: 2007/06/05 01:56:12 $" Version "$Date: 2007/06/05 01:56:12 $"
|
||||
.TH iverilog 1 "April 22nd, 2008" Version "0.9.devel"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[-ESVv] [-Bpath] [-ccmdfile|-fcmdfile] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-g1|-g2|-g2x|-gspecify|-gxtypes|-gio-range-error]
|
||||
[-dname] [-g1995|-g2001|-g2005|-g<feature>]
|
||||
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
|
||||
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
|
||||
|
||||
@@ -43,21 +43,30 @@ Verilog source.
|
||||
.B -D\fImacro=defn\fP
|
||||
Defines macro \fImacro\fP as \fIdefn\fP.
|
||||
.TP 8
|
||||
.B -d\fIname\fP
|
||||
Activate a class of compiler debugging messages. The \fB-d\fP switch may
|
||||
be used as often as necessary to activate all the desired messages.
|
||||
Supported names are scopes, eval_tree, elaborate, and synth2;
|
||||
any other names are ignored.
|
||||
.TP 8
|
||||
.B -E
|
||||
Preprocess the Verilog source, but do not compile it. The output file
|
||||
is the Verilog input, but with file inclusions and macro references
|
||||
expanded and removed. This is useful, for example, to preprocess
|
||||
Verilog source for use by other compilers.
|
||||
.TP 8
|
||||
.B -g1\fI|\fP-g2\fI|\fP-g2x
|
||||
.B -g1995\fI|\fP-g2001\fI|\fP-g2005
|
||||
Select the Verilog language \fIgeneration\fP to support in the
|
||||
compiler. This selects between \fIIEEE1364-1995\fP(1),
|
||||
\fIIEEE1364-2001\fP(2), or \fIVerilog with extension\fP(2x). Normally,
|
||||
compiler. This selects between \fIIEEE1364-1995\fP,
|
||||
\fIIEEE1364-2001\fP(2), or \fIIEEE1364-2005\fP. Normally,
|
||||
Icarus Verilog defaults to the latest known generation of the
|
||||
language. This flag is most useful to restrict the language to a set
|
||||
supported by tools of specific generations, for compatibility with
|
||||
other tools.
|
||||
.TP 8
|
||||
.B -gverilog-ams\fI|-fP-gno-verilog-ams
|
||||
Enable or disable (default) support for Verilog-AMS.
|
||||
.TP 8
|
||||
.B -gspecify\fI|\fP-gno-specify
|
||||
Enable (default) or disable specify block support. When enabled,
|
||||
specify block code is elaborated. When disabled, specify blocks are
|
||||
@@ -245,6 +254,21 @@ inherit timescale from another file. Both probably mean that
|
||||
timescales are inconsistent, and simulation timing can be confusing
|
||||
and dependent on compilation order.
|
||||
|
||||
.TP 8
|
||||
.B infloop
|
||||
This enables warnings for \fRalways\fP statements that may have runtime
|
||||
infinite loops (has paths with no or zero delay). This class of warnings
|
||||
is not included in \fB-Wall\fP and hence does not have a \fBno-\fP variant.
|
||||
A fatal error message will always be printed when the compiler can
|
||||
determine that there will definitely be an infinite loop (all paths have
|
||||
no or zero delay).
|
||||
|
||||
When you suspect an always statement is producing a runtime infinite loop
|
||||
use this flag to find the always statements that need to have their logic
|
||||
verified. It is expected that many of the warnings will be false
|
||||
positives, since the code treats the value of all variables and signals
|
||||
as indeterminate.
|
||||
|
||||
.SH "SYSTEM FUNCTION TABLE FILES"
|
||||
If the source file name as a \fB.sft\fP suffix, then it is taken to be
|
||||
a system function table file. A System function table file is used to
|
||||
@@ -360,12 +384,17 @@ and directory strings.
|
||||
|
||||
Variable values come from the operating system environment, and not
|
||||
from preprocessor defines elsewhere in the file or the command line.
|
||||
|
||||
|
||||
.SH PREDEFINED MACROS
|
||||
|
||||
The following macro is predefined by the compiler:
|
||||
The following macros are predefined by the compiler:
|
||||
.TP 8
|
||||
.B __ICARUS__ = 1\fP
|
||||
This is defined always when compiling with Icarus Verilog.
|
||||
|
||||
.TP 8
|
||||
.B __VAMS_ENABLE__ = 1\fp
|
||||
This is defined if Verilog-AMS is enabled.
|
||||
|
||||
.SH EXAMPLES
|
||||
These examples assume that you have a Verilog source file called hello.v in
|
||||
@@ -396,9 +425,12 @@ Steve Williams ([email protected])
|
||||
vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
|
||||
Tips on using, debugging, and developing the compiler can be found at
|
||||
.BR "<http://iverilog.wikia.com/>"
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002 Stephen Williams
|
||||
Copyright \(co 2002-2008 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+84
-27
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2008 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,6 +18,7 @@
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "version.h"
|
||||
|
||||
const char NOTICE[] =
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
@@ -108,7 +109,9 @@ const char*depfile = 0;
|
||||
const char*generation = "2x";
|
||||
const char*gen_specify = "specify";
|
||||
const char*gen_xtypes = "xtypes";
|
||||
const char*gen_icarus = "icarus-misc";
|
||||
const char*gen_io_range_error = "io-range-error";
|
||||
const char*gen_verilog_ams = "no-verilog-ams";
|
||||
|
||||
/* Boolean: true means use a default include dir, false means don't */
|
||||
int gen_std_include = 1;
|
||||
@@ -156,7 +159,7 @@ typedef struct t_command_file {
|
||||
p_command_file cmd_file_head = NULL; /* The FIFO head */
|
||||
p_command_file cmd_file_tail = NULL; /* The FIFO tail */
|
||||
|
||||
/* Function to add a comamnd file name to the FIFO. */
|
||||
/* Function to add a command file name to the FIFO. */
|
||||
void add_cmd_file(const char* filename)
|
||||
{
|
||||
p_command_file new;
|
||||
@@ -173,7 +176,7 @@ void add_cmd_file(const char* filename)
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to return the top comamnd file name from the FIFO. */
|
||||
/* Function to return the top command file name from the FIFO. */
|
||||
char *get_cmd_file()
|
||||
{
|
||||
char *filename;
|
||||
@@ -202,7 +205,7 @@ static FILE*fopen_safe(const char*path)
|
||||
if (fd != -1)
|
||||
file = _fdopen(fd, "w");
|
||||
|
||||
return file;
|
||||
return file;
|
||||
}
|
||||
#else
|
||||
# include <fcntl.h>
|
||||
@@ -215,7 +218,7 @@ static FILE*fopen_safe(const char*path)
|
||||
if (fd != -1)
|
||||
file = fdopen(fd, "w");
|
||||
|
||||
return file;
|
||||
return file;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -324,6 +327,9 @@ static int t_default(char*cmd, unsigned ncmd)
|
||||
remove(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
}
|
||||
#ifdef __MINGW32__ /* MinGW just returns the exit status, so return it! */
|
||||
return rc;
|
||||
#else
|
||||
|
||||
if (rc != 0) {
|
||||
if (rc == 127) {
|
||||
@@ -339,6 +345,7 @@ static int t_default(char*cmd, unsigned ncmd)
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -357,6 +364,11 @@ static void process_warning_switch(const char*name)
|
||||
} else if (strcmp(name,"timescale") == 0) {
|
||||
if (! strchr(warning_flags, 't'))
|
||||
strcat(warning_flags, "t");
|
||||
/* Since the infinite loop check is not part of 'all' it
|
||||
* does not have a no- version. */
|
||||
} else if (strcmp(name,"infloop") == 0) {
|
||||
if (! strchr(warning_flags, 'l'))
|
||||
strcat(warning_flags, "l");
|
||||
} else if (strcmp(name,"no-implicit") == 0) {
|
||||
char*cp = strchr(warning_flags, 'i');
|
||||
if (cp) while (*cp) {
|
||||
@@ -424,50 +436,79 @@ void process_file_name(const char*name, int lib_flag)
|
||||
|
||||
int process_generation(const char*name)
|
||||
{
|
||||
if (strcmp(name,"1") == 0)
|
||||
generation = "1";
|
||||
if (strcmp(name,"1995") == 0)
|
||||
generation = "1995";
|
||||
|
||||
else if (strcmp(name,"2") == 0)
|
||||
generation = "2";
|
||||
else if (strcmp(name,"2001") == 0)
|
||||
generation = "2001";
|
||||
|
||||
else if (strcmp(name,"2x") == 0)
|
||||
generation = "2x";
|
||||
else if (strcmp(name,"2005") == 0)
|
||||
generation = "2005";
|
||||
|
||||
else if (strcmp(name,"xtypes") == 0)
|
||||
else if (strcmp(name,"1") == 0) { /* Deprecated: use 1995 */
|
||||
generation = "1995";
|
||||
gen_xtypes = "no-xtypes";
|
||||
gen_icarus = "no-icarus-misc";
|
||||
|
||||
} else if (strcmp(name,"2") == 0) { /* Deprecated: use 2001 */
|
||||
generation = "2001";
|
||||
gen_xtypes = "no-xtypes";
|
||||
gen_icarus = "no-icarus-misc";
|
||||
|
||||
} else if (strcmp(name,"2x") == 0) { /* Deprecated: use 2005/xtypes */
|
||||
generation = "2005";
|
||||
gen_xtypes = "xtypes";
|
||||
gen_icarus = "icarus-misc";
|
||||
|
||||
} else if (strcmp(name,"xtypes") == 0)
|
||||
gen_xtypes = "xtypes";
|
||||
|
||||
else if (strcmp(name,"no-xtypes") == 0)
|
||||
else if (strcmp(name,"no-xtypes") == 0)
|
||||
gen_xtypes = "no-xtypes";
|
||||
|
||||
else if (strcmp(name,"specify") == 0)
|
||||
else if (strcmp(name,"icarus-misc") == 0)
|
||||
gen_icarus = "icarus-misc";
|
||||
|
||||
else if (strcmp(name,"no-icarus-misc") == 0)
|
||||
gen_icarus = "no-icarus-misc";
|
||||
|
||||
else if (strcmp(name,"specify") == 0)
|
||||
gen_specify = "specify";
|
||||
|
||||
else if (strcmp(name,"no-specify") == 0)
|
||||
else if (strcmp(name,"no-specify") == 0)
|
||||
gen_specify = "no-specify";
|
||||
|
||||
else if (strcmp(name,"std-include") == 0)
|
||||
else if (strcmp(name,"std-include") == 0)
|
||||
gen_std_include = 1;
|
||||
|
||||
else if (strcmp(name,"no-std-include") == 0)
|
||||
else if (strcmp(name,"no-std-include") == 0)
|
||||
gen_std_include = 0;
|
||||
|
||||
else if (strcmp(name,"io-range-error") == 0)
|
||||
else if (strcmp(name,"io-range-error") == 0)
|
||||
gen_io_range_error = "io-range-error";
|
||||
|
||||
else if (strcmp(name,"no-io-range-error") == 0)
|
||||
else if (strcmp(name,"no-io-range-error") == 0)
|
||||
gen_io_range_error = "no-io-range-error";
|
||||
|
||||
else if (strcmp(name,"verilog-ams") == 0)
|
||||
gen_verilog_ams = "verilog-ams";
|
||||
|
||||
else if (strcmp(name,"no-verilog-ams") == 0)
|
||||
gen_verilog_ams = "no-verilog-ams";
|
||||
|
||||
else {
|
||||
fprintf(stderr, "Unknown/Unsupported Language generation "
|
||||
"%s\n\n", name);
|
||||
fprintf(stderr, "Supported generations are:\n");
|
||||
fprintf(stderr, " 1 -- IEEE1364-1995 (Verilog 1)\n"
|
||||
" 2 -- IEEE1364-2001 (Verilog 2001)\n"
|
||||
" 2x -- Verilog with extensions\n"
|
||||
fprintf(stderr, " 1995 -- IEEE1364-1995\n"
|
||||
" 2001 -- IEEE1364-2001\n"
|
||||
" 2005 -- IEEE1364-2005\n"
|
||||
"Other generation flags:\n"
|
||||
" specify | no-specify\n"
|
||||
" verilog-ams | no-verinlog-ams\n"
|
||||
" std-include | no-std-include\n"
|
||||
" xtypes | no-xtypes\n"
|
||||
" icarus-misc | no-icarus-misc\n"
|
||||
" io-range-error | no-io-range-error\n");
|
||||
return 1;
|
||||
}
|
||||
@@ -557,6 +598,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
fprintf(defines_file, "D:__ICARUS__=1\n");
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0)
|
||||
fprintf(defines_file, "D:__VAMS_ENABLE__=1\n");
|
||||
|
||||
/* Create another temporary file for passing configuration
|
||||
information to ivl. */
|
||||
@@ -593,7 +636,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "B:c:D:Ef:g:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
case 'B':
|
||||
@@ -620,6 +663,9 @@ int main(int argc, char **argv)
|
||||
case 'p':
|
||||
fprintf(iconfig_file, "flag:%s\n", optarg);
|
||||
break;
|
||||
case 'd':
|
||||
fprintf(iconfig_file, "debug:%s\n", optarg);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
rc = process_generation(optarg);
|
||||
@@ -698,8 +744,8 @@ int main(int argc, char **argv)
|
||||
pbase = base;
|
||||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION " ($Name: $)\n\n");
|
||||
printf("Copyright 1998-2007 Stephen Williams\n");
|
||||
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
|
||||
printf("Copyright 1998-2008 Stephen Williams\n");
|
||||
puts(NOTICE);
|
||||
|
||||
if (version_flag)
|
||||
@@ -718,11 +764,20 @@ int main(int argc, char **argv)
|
||||
how to handle them. */
|
||||
fprintf(iconfig_file, "sys_func:%s%csystem.sft\n", base, sep);
|
||||
|
||||
/* If verilog-ams is enabled, then include the va_math module
|
||||
as well. */
|
||||
if (strcmp(gen_verilog_ams,"verilog-ams") == 0) {
|
||||
fprintf(iconfig_file, "sys_func:%s%cva_math.sft\n", base, sep);
|
||||
fprintf(iconfig_file, "module:va_math\n");
|
||||
}
|
||||
|
||||
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
|
||||
fprintf(iconfig_file, "generation:%s\n", generation);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_specify);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
|
||||
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
|
||||
fprintf(iconfig_file, "out:%s\n", opath);
|
||||
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
|
||||
@@ -803,8 +858,11 @@ int main(int argc, char **argv)
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
fclose(iconfig_file);
|
||||
if ( ! getenv("IVERILOG_ICONFIG"))
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(iconfig_path);
|
||||
remove(defines_path);
|
||||
remove(compiled_defines_path);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
@@ -834,4 +892,3 @@ int main(int argc, char **argv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+24
-86
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2002 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2008 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,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: dup_expr.cc,v 1.21 2006/11/04 06:10:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -27,14 +24,17 @@
|
||||
|
||||
NetEBComp* NetEBComp::dup_expr() const
|
||||
{
|
||||
NetEBComp*result = new NetEBComp(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
return result;
|
||||
NetEBComp*tmp = new NetEBComp(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEConst* NetEConst::dup_expr() const
|
||||
{
|
||||
NetEConst*tmp = new NetEConst(value_);
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
@@ -42,6 +42,7 @@ NetEConst* NetEConst::dup_expr() const
|
||||
NetEConstParam* NetEConstParam::dup_expr() const
|
||||
{
|
||||
NetEConstParam*tmp = new NetEConstParam(scope_, name_, value());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
@@ -49,6 +50,7 @@ NetEConstParam* NetEConstParam::dup_expr() const
|
||||
NetECRealParam* NetECRealParam::dup_expr() const
|
||||
{
|
||||
NetECRealParam*tmp = new NetECRealParam(scope_, name_, value());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
@@ -67,9 +69,12 @@ NetEScope* NetEScope::dup_expr() const
|
||||
|
||||
NetESelect* NetESelect::dup_expr() const
|
||||
{
|
||||
return new NetESelect(expr_->dup_expr(),
|
||||
base_? base_->dup_expr() : 0,
|
||||
expr_width());
|
||||
NetESelect*tmp = new NetESelect(expr_->dup_expr(),
|
||||
base_? base_->dup_expr() : 0,
|
||||
expr_width());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESFunc* NetESFunc::dup_expr() const
|
||||
@@ -83,14 +88,16 @@ NetESFunc* NetESFunc::dup_expr() const
|
||||
tmp->parm(idx, tmp->parm(idx)->dup_expr());
|
||||
}
|
||||
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal* NetESignal::dup_expr() const
|
||||
{
|
||||
NetESignal*tmp = new NetESignal(net_);
|
||||
NetESignal*tmp = new NetESignal(net_, word_);
|
||||
assert(tmp);
|
||||
tmp->expr_width(expr_width());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -99,6 +106,8 @@ NetETernary* NetETernary::dup_expr() const
|
||||
NetETernary*tmp = new NetETernary(cond_->dup_expr(),
|
||||
true_val_->dup_expr(),
|
||||
false_val_->dup_expr());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -112,9 +121,10 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
||||
tmp_parms[idx] = parms_[idx]->dup_expr();
|
||||
}
|
||||
|
||||
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
|
||||
tmp = new NetEUFunc(scope_, func_, result_sig_->dup_expr(), tmp_parms);
|
||||
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -122,6 +132,7 @@ NetEUnary* NetEUnary::dup_expr() const
|
||||
{
|
||||
NetEUnary*tmp = new NetEUnary(op_, expr_->dup_expr());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -129,79 +140,6 @@ NetEUReduce* NetEUReduce::dup_expr() const
|
||||
{
|
||||
NetEUReduce*tmp = new NetEUReduce(op_, expr_->dup_expr());
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.21 2006/11/04 06:10:13 steve
|
||||
* Handle dup of pad as well as normal select.
|
||||
*
|
||||
* Revision 1.20 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.19 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.18 2004/06/17 16:06:18 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
*
|
||||
* Revision 1.17 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
* speed and more type support.
|
||||
*
|
||||
* Revision 1.16 2003/10/31 02:47:11 steve
|
||||
* NetEUReduce has its own dup_expr method.
|
||||
*
|
||||
* Revision 1.15 2003/05/30 02:55:32 steve
|
||||
* Support parameters in real expressions and
|
||||
* as real expressions, and fix multiply and
|
||||
* divide with real results.
|
||||
*
|
||||
* Revision 1.14 2003/04/22 04:48:29 steve
|
||||
* Support event names as expressions elements.
|
||||
*
|
||||
* Revision 1.13 2003/03/15 18:08:43 steve
|
||||
* Comparison operators do have defined width.
|
||||
*
|
||||
* Revision 1.12 2003/03/15 04:46:28 steve
|
||||
* Better organize the NetESFunc return type guesses.
|
||||
*
|
||||
* Revision 1.11 2003/03/10 23:40:53 steve
|
||||
* Keep parameter constants for the ivl_target API.
|
||||
*
|
||||
* Revision 1.10 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.9 2002/11/09 00:25:27 steve
|
||||
* Add dup_expr for user defined function calls.
|
||||
*
|
||||
* Revision 1.8 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.7 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.6 2001/11/19 01:54:14 steve
|
||||
* Port close cropping behavior from mcrgb
|
||||
* Move window array reset to libmc.
|
||||
*
|
||||
* Revision 1.5 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.4 2000/05/07 18:20:07 steve
|
||||
* Import MCD support from Stephen Tell, and add
|
||||
* system function parameter support to the IVL core.
|
||||
*
|
||||
* Revision 1.3 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*/
|
||||
|
||||
|
||||
+434
-175
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2008 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
|
||||
@@ -30,7 +30,7 @@
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* The default behavor for the test_width method is to just return the
|
||||
* The default behavior for the test_width method is to just return the
|
||||
* minimum width that is passed in.
|
||||
*/
|
||||
unsigned PExpr::test_width(Design*des, NetScope*scope,
|
||||
@@ -96,7 +96,7 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope,
|
||||
* and right sides, and creating one of a variety of different NetExpr
|
||||
* types.
|
||||
*/
|
||||
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
||||
NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
assert(left_);
|
||||
@@ -110,11 +110,11 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_eval_expr_base_(des, lp, rp, expr_wid);
|
||||
NetExpr*tmp = elaborate_eval_expr_base_(des, lp, rp, expr_wid);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void PEBinary::surpress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp)
|
||||
void PEBinary::suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp)
|
||||
{
|
||||
// If either operand is unsigned, then treat the whole
|
||||
// expression as unsigned. This test needs to be done here
|
||||
@@ -128,26 +128,15 @@ void PEBinary::surpress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp)
|
||||
lp->cast_signed(false);
|
||||
}
|
||||
|
||||
NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des,
|
||||
NetExpr* PEBinary::elaborate_eval_expr_base_(Design*des,
|
||||
NetExpr*lp,
|
||||
NetExpr*rp,
|
||||
int expr_wid) const
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
eval_expr(lp);
|
||||
eval_expr(rp);
|
||||
|
||||
return elaborate_expr_base_(des, lp, rp, expr_wid);
|
||||
}
|
||||
@@ -157,7 +146,7 @@ NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des,
|
||||
* operands are elaborated as necessary, and all I need to do is make
|
||||
* the correct NetEBinary object and connect the parameters.
|
||||
*/
|
||||
NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
NetExpr* PEBinary::elaborate_expr_base_(Design*des,
|
||||
NetExpr*lp, NetExpr*rp,
|
||||
int expr_wid) const
|
||||
{
|
||||
@@ -168,7 +157,7 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
<< *this << " expr_wid=" << expr_wid << endl;
|
||||
}
|
||||
|
||||
NetEBinary*tmp;
|
||||
NetExpr*tmp;
|
||||
|
||||
switch (op_) {
|
||||
default:
|
||||
@@ -178,6 +167,8 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
|
||||
case 'a':
|
||||
case 'o':
|
||||
lp = condition_reduce(lp);
|
||||
rp = condition_reduce(rp);
|
||||
tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
@@ -195,11 +186,12 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
case '%':
|
||||
/* The % operator does not support real arguments in
|
||||
baseline Verilog. But we allow it in our extended
|
||||
form of verilog. */
|
||||
if (generation_flag < GN_VER2001X) {
|
||||
if (lp->expr_type()==IVL_VT_REAL || rp->expr_type()==IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: Modulus operator may not "
|
||||
"have REAL operands." << endl;
|
||||
form of Verilog. */
|
||||
if (! gn_icarus_misc_flag) {
|
||||
if (lp->expr_type()==IVL_VT_REAL ||
|
||||
rp->expr_type()==IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: Modulus operator "
|
||||
"may not have REAL operands." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
@@ -210,6 +202,56 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
break;
|
||||
|
||||
case 'l': // <<
|
||||
if (NetEConst*lpc = dynamic_cast<NetEConst*> (lp)) {
|
||||
if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
|
||||
// Handle the super-special case that both
|
||||
// operands are constants. Precalculate the
|
||||
// entire value here.
|
||||
verinum lpval = lpc->value();
|
||||
unsigned shift = rpc->value().as_ulong();
|
||||
verinum result = lpc->value() << shift;
|
||||
// If the l-value has explicit size, or
|
||||
// there is a context determined size, use that.
|
||||
if (lpval.has_len() || expr_wid > 0) {
|
||||
int use_len = lpval.len();
|
||||
if (expr_wid < use_len)
|
||||
use_len = expr_wid;
|
||||
result = verinum(result, lpval.len());
|
||||
}
|
||||
|
||||
tmp = new NetEConst(result);
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Precalculate " << *this
|
||||
<< " to constant " << *tmp << endl;
|
||||
|
||||
} else {
|
||||
// Handle the special case that the left
|
||||
// operand is constant. If it is unsized, we
|
||||
// may have to expand it to an integer width.
|
||||
verinum lpval = lpc->value();
|
||||
if (lpval.len() < integer_width && !lpval.has_len()) {
|
||||
lpval = verinum(lpval, integer_width);
|
||||
lpc = new NetEConst(lpval);
|
||||
lpc->set_line(*lp);
|
||||
}
|
||||
|
||||
tmp = new NetEBShift(op_, lpc, rp);
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Adjust " << *this
|
||||
<< " to this " << *tmp
|
||||
<< " to allow for integer widths." << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Left side is not constant, so handle it the
|
||||
// default way.
|
||||
tmp = new NetEBShift(op_, lp, rp);
|
||||
}
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case 'r': // >>
|
||||
case 'R': // >>>
|
||||
tmp = new NetEBShift(op_, lp, rp);
|
||||
@@ -237,10 +279,11 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
if (lp->expr_type() == IVL_VT_REAL
|
||||
|| rp->expr_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: Case equality may not "
|
||||
<< "have real operands." << endl;
|
||||
if (lp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< "may not have real operands." << endl;
|
||||
return 0;
|
||||
}
|
||||
/* Fall through... */
|
||||
@@ -268,6 +311,12 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
des->errors += 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'm': // min(l,r)
|
||||
case 'M': // max(l,r)
|
||||
tmp = new NetEBMinMax(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
@@ -278,8 +327,8 @@ unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned, bool&) const
|
||||
return 1;
|
||||
}
|
||||
|
||||
NetEBinary* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const
|
||||
NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const
|
||||
{
|
||||
assert(left_);
|
||||
assert(right_);
|
||||
@@ -313,7 +362,7 @@ NetEBinary* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
surpress_operand_sign_if_needed_(lp, rp);
|
||||
suppress_operand_sign_if_needed_(lp, rp);
|
||||
|
||||
return elaborate_eval_expr_base_(des, lp, rp, use_wid);
|
||||
}
|
||||
@@ -531,12 +580,8 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, int expr_w
|
||||
PExpr*expr = parms_[idx];
|
||||
if (expr) {
|
||||
NetExpr*tmp1 = expr->elaborate_expr(des, scope, -1, true);
|
||||
if (NetExpr*tmp2 = tmp1->eval_tree()) {
|
||||
delete tmp1;
|
||||
fun->parm(idx, tmp2);
|
||||
} else {
|
||||
fun->parm(idx, tmp1);
|
||||
}
|
||||
eval_expr(tmp1);
|
||||
fun->parm(idx, tmp1);
|
||||
|
||||
} else {
|
||||
missing_parms += 1;
|
||||
@@ -628,7 +673,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
if (NetNet*res = dscope->find_signal(dscope->basename())) {
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
|
||||
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms);
|
||||
func->set_line(*this);
|
||||
func->cast_signed(res->get_signed());
|
||||
return func;
|
||||
@@ -641,10 +686,13 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Keep track of the concatenation/repeat depth.
|
||||
static int concat_depth = 0;
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
concat_depth += 1;
|
||||
NetExpr* repeat = 0;
|
||||
|
||||
if (debug_elaborate) {
|
||||
@@ -668,6 +716,32 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (!rep->value().is_defined()) {
|
||||
cerr << get_fileline() << ": error: Concatenation repeat "
|
||||
<< "may not be undefined (" << rep->value()
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
concat_depth -= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rep->value().is_negative()) {
|
||||
cerr << get_fileline() << ": error: Concatenation repeat "
|
||||
<< "may not be negative (" << rep->value().as_long()
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
concat_depth -= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rep->value().is_zero() && concat_depth < 2) {
|
||||
cerr << get_fileline() << ": error: Concatenation repeat "
|
||||
<< "may not be zero in this context." << endl;
|
||||
des->errors += 1;
|
||||
concat_depth -= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = rep;
|
||||
}
|
||||
|
||||
@@ -705,6 +779,15 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
tmp->set_width(wid_sum * tmp->repeat());
|
||||
|
||||
if (wid_sum == 0 && concat_depth < 2) {
|
||||
cerr << get_fileline() << ": error: Concatenation may not "
|
||||
<< "have zero width in this context." << endl;
|
||||
des->errors += 1;
|
||||
concat_depth -= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
concat_depth -= 1;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -799,6 +882,51 @@ bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we know that this is an indexed part select (up or down) this
|
||||
* method calculates the up/down base, as far at it can be calculated.
|
||||
*/
|
||||
NetExpr* PEIdent::calculate_up_do_base_(Design*des, NetScope*scope) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.lsb != 0);
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool PEIdent::calculate_param_range_(Design*des, NetScope*scope,
|
||||
const NetExpr*par_msb, long&par_msv,
|
||||
const NetExpr*par_lsb, long&par_lsv) const
|
||||
{
|
||||
if (par_msb == 0) {
|
||||
// If the parameter doesn't have an explicit range, then
|
||||
// just return range values of 0:0. The par_msv==0 is
|
||||
// correct. The par_msv is not necessarily correct, but
|
||||
// clients of this function don't need a correct value.
|
||||
ivl_assert(*this, par_lsb == 0);
|
||||
par_msv = 0;
|
||||
par_lsv = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
const NetEConst*tmp = dynamic_cast<const NetEConst*> (par_msb);
|
||||
ivl_assert(*this, tmp);
|
||||
|
||||
par_msv = tmp->value().as_long();
|
||||
|
||||
tmp = dynamic_cast<const NetEConst*> (par_lsb);
|
||||
ivl_assert(*this, tmp);
|
||||
|
||||
par_lsv = tmp->value().as_long();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned PEIdent::test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const
|
||||
@@ -1011,6 +1139,131 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static verinum param_part_select_bits(const verinum&par_val, long wid,
|
||||
long lsv, long par_lsv)
|
||||
{
|
||||
verinum result (verinum::Vx, wid, true);
|
||||
|
||||
for (long idx = 0 ; idx < wid ; idx += 1) {
|
||||
long off = idx + lsv - par_lsv;
|
||||
if (off < 0)
|
||||
result.set(idx, verinum::Vx);
|
||||
else if (off < (long)par_val.len())
|
||||
result.set(idx, par_val.get(off));
|
||||
else if (par_val.is_string()) // Pad strings with nulls.
|
||||
result.set(idx, verinum::V0);
|
||||
else if (par_val.has_len()) // Pad sized parameters with X
|
||||
result.set(idx, verinum::Vx);
|
||||
else // Unsized parameters are "infinite" width.
|
||||
result.set(idx, sign_bit(par_val));
|
||||
}
|
||||
|
||||
// If the input is a string, and the part select is working on
|
||||
// byte boundaries, then make the result into a string.
|
||||
if (par_val.is_string() && (labs(lsv-par_lsv)%8 == 0) && (wid%8 == 0))
|
||||
return result.as_string();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_param_part_(Design*des, NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
{
|
||||
long msv, lsv;
|
||||
bool flag = calculate_parts_(des, scope, msv, lsv);
|
||||
if (!flag)
|
||||
return 0;
|
||||
|
||||
long par_msv, par_lsv;
|
||||
flag = calculate_param_range_(des, scope, par_msb, par_msv, par_lsb, par_lsv);
|
||||
if (!flag)
|
||||
return 0;
|
||||
|
||||
// Notice that the par_msv is not used is this function other
|
||||
// then for this test. It is used to tell the direction that
|
||||
// the bits are numbers, so that we can make sure the
|
||||
// direction matches the part select direction. After that,
|
||||
// we only need the par_lsv.
|
||||
if (msv>lsv && par_msv<par_lsv || msv<lsv && par_msv>=par_lsv) {
|
||||
cerr << get_fileline() << ": error: Part select "
|
||||
<< "[" << msv << ":" << lsv << "] is out of order." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long wid = 1 + labs(msv-lsv);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: Calculate part select "
|
||||
<< "[" << msv << ":" << lsv << "] from range "
|
||||
<< "[" << par_msv << ":" << par_lsv << "]." << endl;
|
||||
|
||||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||
ivl_assert(*this, par_ex);
|
||||
|
||||
verinum result = param_part_select_bits(par_ex->value(), wid, lsv, par_lsv);
|
||||
NetEConst*result_ex = new NetEConst(result);
|
||||
result_ex->set_line(*this);
|
||||
|
||||
return result_ex;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_param_idx_up_(Design*des, NetScope*scope,
|
||||
const NetExpr*par,
|
||||
NetScope*found_in,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
{
|
||||
|
||||
long par_msv, par_lsv;
|
||||
bool flag = calculate_param_range_(des, scope, par_msb, par_msv, par_lsb, par_lsv);
|
||||
if (!flag)
|
||||
return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
if (base == 0)
|
||||
return 0;
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
||||
const NetEConst*par_ex = dynamic_cast<const NetEConst*> (par);
|
||||
ivl_assert(*this, par_ex);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: Calculate part select "
|
||||
<< "[" << *base << "+:" << wid << "] from range "
|
||||
<< "[" << par_msv << ":" << par_lsv << "]." << endl;
|
||||
|
||||
// Handle the special case that the base is constant. In this
|
||||
// case, just precalculate the entire constant result.
|
||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||
long lsv = base_c->value().as_long();
|
||||
|
||||
// Watch out for reversed bit numbering. We're making
|
||||
// the part select from LSB to MSB.
|
||||
if (par_msv < par_lsv)
|
||||
lsv = lsv - wid + 1;
|
||||
|
||||
verinum result = param_part_select_bits(par_ex->value(), wid,
|
||||
lsv, par_lsv);
|
||||
NetEConst*result_ex = new NetEConst(result);
|
||||
result_ex->set_line(*this);
|
||||
return result_ex;
|
||||
}
|
||||
|
||||
if ((par_msb < par_lsb) && (wid>1))
|
||||
base = make_add_expr(base, 1-(long)wid);
|
||||
|
||||
NetExpr*tmp = par->dup_expr();
|
||||
tmp = new NetESelect(tmp, base, wid);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the case that the identifier is a parameter reference. The
|
||||
* parameter expression has already been located for us (as the par
|
||||
@@ -1023,84 +1276,29 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
{
|
||||
NetExpr*tmp = par->dup_expr();
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
if (use_sel == index_component_t::SEL_PART) {
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
ivl_assert(*this, index_tail.lsb);
|
||||
// NOTE TO SELF: This is the way I want to see this code
|
||||
// structured. This closely follows the structure of the
|
||||
// elaborate_expr_net_ code, which splits all the various
|
||||
// selects to different methods.
|
||||
if (use_sel == index_component_t::SEL_PART)
|
||||
return elaborate_expr_param_part_(des, scope, par, found_in,
|
||||
par_msb, par_lsb);
|
||||
|
||||
/* If the identifier has a part select, we support
|
||||
it by pulling the right bits out and making a
|
||||
sized unsigned constant. This code assumes the
|
||||
lsb of a parameter is 0 and the msb is the
|
||||
width of the parameter. */
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_param_idx_up_(des, scope, par, found_in,
|
||||
par_msb, par_lsb);
|
||||
|
||||
verinum*lsn = index_tail.lsb->eval_const(des, scope);
|
||||
verinum*msn = index_tail.msb->eval_const(des, scope);
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"Part select expressions must be "
|
||||
"constant expressions." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
// NOTE TO SELF (continued): The code below should be
|
||||
// rewritten in the above format, as I get to it.
|
||||
|
||||
long lsb = lsn->as_long();
|
||||
long msb = msn->as_long();
|
||||
if ((lsb < 0) || (msb < lsb)) {
|
||||
cerr << get_fileline() << ": error: invalid part "
|
||||
<< "select: " << path_
|
||||
<< "["<<msb<<":"<<lsb<<"]" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
unsigned long ulsb=lsb;
|
||||
unsigned long umsb=msb;
|
||||
NetExpr*tmp = par->dup_expr();
|
||||
|
||||
NetEConst*le = dynamic_cast<NetEConst*>(tmp);
|
||||
assert(le);
|
||||
|
||||
verinum result (verinum::V0, msb-lsb+1, true);
|
||||
verinum exl = le->value();
|
||||
|
||||
/* Pull the bits from the parameter, one at a
|
||||
time. If the bit is within the range, simply
|
||||
copy it to the result. If the bit is outside
|
||||
the range, we sign extend signed unsized
|
||||
numbers, zero extend unsigned unsigned numbers,
|
||||
and X extend sized numbers. */
|
||||
for (unsigned long idx = ulsb ; idx <= umsb ; idx += 1) {
|
||||
if (idx < exl.len())
|
||||
result.set(idx-lsb, exl.get(idx));
|
||||
else if (exl.is_string())
|
||||
result.set(idx-lsb, verinum::V0);
|
||||
else if (exl.has_len())
|
||||
result.set(idx-lsb, verinum::Vx);
|
||||
else if (exl.has_sign())
|
||||
result.set(idx-lsb, exl.get(exl.len()-1));
|
||||
else
|
||||
result.set(idx-lsb, verinum::V0);
|
||||
}
|
||||
|
||||
/* If the input is a string, and the part select
|
||||
is working on byte boundaries, then the result
|
||||
can be made into a string. */
|
||||
if (exl.is_string()
|
||||
&& (lsb%8 == 0)
|
||||
&& (result.len()%8 == 0))
|
||||
result = verinum(result.as_string());
|
||||
|
||||
delete tmp;
|
||||
tmp = new NetEConst(result);
|
||||
|
||||
} else if (use_sel == index_component_t::SEL_IDX_UP || use_sel == index_component_t::SEL_IDX_DO) {
|
||||
if (use_sel == index_component_t::SEL_IDX_DO) {
|
||||
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
@@ -1141,17 +1339,18 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
ivl_assert(*this, !index_tail.lsb);
|
||||
|
||||
const NetEConst*par_me =dynamic_cast<const NetEConst*>(par_msb);
|
||||
const NetEConst*par_le =dynamic_cast<const NetEConst*>(par_lsb);
|
||||
|
||||
ivl_assert(*this, par_me || !par_msb);
|
||||
ivl_assert(*this, par_le || !par_lsb);
|
||||
ivl_assert(*this, par_me || !par_le);
|
||||
|
||||
/* Handle the case where a parameter has a bit
|
||||
select attached to it. Generate a NetESelect
|
||||
object to select the bit as desired. */
|
||||
NetExpr*mtmp = index_tail.msb->elaborate_expr(des, scope, -1,false);
|
||||
if (! dynamic_cast<NetEConst*>(mtmp)) {
|
||||
NetExpr*re = mtmp->eval_tree();
|
||||
if (re) {
|
||||
delete mtmp;
|
||||
mtmp = re;
|
||||
}
|
||||
}
|
||||
eval_expr(mtmp);
|
||||
|
||||
/* Let's first try to get constant values for both
|
||||
the parameter and the bit select. If they are
|
||||
@@ -1168,7 +1367,20 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
verinum rv = re->value();
|
||||
verinum::V rb = verinum::Vx;
|
||||
|
||||
long par_mv = lv.len()-1;
|
||||
long par_lv = 0;
|
||||
if (par_me) {
|
||||
par_mv = par_me->value().as_long();
|
||||
par_lv = par_le->value().as_long();
|
||||
}
|
||||
/* Convert the index to cannonical bit address. */
|
||||
long ridx = rv.as_long();
|
||||
if (par_mv >= par_lv) {
|
||||
ridx -= par_lv;
|
||||
} else {
|
||||
ridx = par_mv - ridx + par_lv;
|
||||
}
|
||||
|
||||
if ((ridx >= 0) && ((unsigned long) ridx < lv.len())) {
|
||||
rb = lv[ridx];
|
||||
|
||||
@@ -1186,13 +1398,6 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
|
||||
} else {
|
||||
|
||||
const NetEConst*par_me =dynamic_cast<const NetEConst*>(par_msb);
|
||||
const NetEConst*par_le =dynamic_cast<const NetEConst*>(par_lsb);
|
||||
|
||||
assert(par_me || !par_msb);
|
||||
assert(par_le || !par_lsb);
|
||||
assert(par_me || !par_le);
|
||||
|
||||
if (par_me) {
|
||||
long par_mv = par_me->value().as_long();
|
||||
long par_lv = par_le->value().as_long();
|
||||
@@ -1224,6 +1429,11 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
perm_string name = peek_tail_name(path_);
|
||||
NetEConstParam*ptmp
|
||||
= new NetEConstParam(found_in, name, ctmp->value());
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Elaborate parameter <" << name
|
||||
<< "> as constant " << *ptmp << endl;
|
||||
delete tmp;
|
||||
tmp = ptmp;
|
||||
}
|
||||
@@ -1275,8 +1485,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||
// Special case: The index is out of range, so the value
|
||||
// of this expression is a 'bx vector the width of a word.
|
||||
if (!net->array_index_is_valid(addr)) {
|
||||
verinum xxx (verinum::Vx, net->vector_width());
|
||||
NetEConst*resx = new NetEConst(xxx);
|
||||
NetEConst*resx = make_const_x(net->vector_width());
|
||||
resx->set_line(*this);
|
||||
delete word_index;
|
||||
return resx;
|
||||
@@ -1298,9 +1507,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||
if (long base = net->array_first()) {
|
||||
|
||||
word_index = make_add_expr(word_index, 0-base);
|
||||
if (NetExpr*tmp = word_index->eval_tree()) {
|
||||
word_index = tmp;
|
||||
}
|
||||
eval_expr(word_index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1344,16 +1551,7 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
negative values. However, the width that they represent is
|
||||
unsigned. Remember that any order is possible,
|
||||
i.e., [1:0], [-4:6], etc. */
|
||||
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
|
||||
if (wid > net->vector_width()) {
|
||||
cerr << get_fileline() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range." << endl;
|
||||
des->errors += 1;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return net;
|
||||
}
|
||||
ivl_assert(*this, wid <= net->vector_width());
|
||||
unsigned long wid = 1 + labs(msv-lsv);
|
||||
|
||||
if (net->sig()->sb_to_idx(msv) < net->sig()->sb_to_idx(lsv)) {
|
||||
cerr << get_fileline() << ": error: part select ["
|
||||
@@ -1364,27 +1562,79 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
return net;
|
||||
}
|
||||
|
||||
long sb_lsb = net->sig()->sb_to_idx(lsv);
|
||||
long sb_msb = net->sig()->sb_to_idx(msv);
|
||||
|
||||
if (net->sig()->sb_to_idx(msv) >= net->vector_width()) {
|
||||
cerr << get_fileline() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range." << endl;
|
||||
des->errors += 1;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return net;
|
||||
}
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// If the part select covers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sig()->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
if (sb_lsb == 0 && wid == net->vector_width())
|
||||
return net;
|
||||
|
||||
NetExpr*ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)));
|
||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||
ss->set_line(*this);
|
||||
// If the part select covers NONE of the vector, then return a
|
||||
// constant X.
|
||||
|
||||
return ss;
|
||||
if ((sb_lsb >= (signed) net->vector_width()) || (sb_msb < 0)) {
|
||||
NetEConst*tmp = make_const_x(wid);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// If the part select is entirely within the vector, then make
|
||||
// a simple part select.
|
||||
if (sb_lsb >= 0 && sb_msb < (signed)net->vector_width()) {
|
||||
NetExpr*ex = new NetEConst(verinum(sb_lsb));
|
||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
// Now the hard stuff. The part select is falling off at least
|
||||
// one end. We're going to need a NetEConcat to mix the
|
||||
// selection with overrun.
|
||||
|
||||
NetEConst*bot = 0;
|
||||
if (sb_lsb < 0) {
|
||||
bot = make_const_x( 0-sb_lsb );
|
||||
bot->set_line(*this);
|
||||
sb_lsb = 0;
|
||||
}
|
||||
NetEConst*top = 0;
|
||||
if (sb_msb >= (signed)net->vector_width()) {
|
||||
top = make_const_x( 1+sb_msb-net->vector_width() );
|
||||
top->set_line(*this);
|
||||
sb_msb = net->vector_width()-1;
|
||||
}
|
||||
|
||||
unsigned concat_count = 1;
|
||||
if (bot) concat_count += 1;
|
||||
if (top) concat_count += 1;
|
||||
|
||||
NetEConcat*concat = new NetEConcat(concat_count);
|
||||
concat->set_line(*this);
|
||||
|
||||
if (bot) {
|
||||
concat_count -= 1;
|
||||
concat->set(concat_count, bot);
|
||||
}
|
||||
if (sb_lsb == 0 && sb_msb+1 == (signed)net->vector_width()) {
|
||||
concat_count -= 1;
|
||||
concat->set(concat_count, net);
|
||||
} else {
|
||||
NetExpr*ex = new NetEConst(verinum(sb_lsb));
|
||||
ex->set_line(*this);
|
||||
NetESelect*ss = new NetESelect(net, ex, 1+sb_msb-sb_lsb);
|
||||
ss->set_line(*this);
|
||||
concat_count -= 1;
|
||||
concat->set(concat_count, ss);
|
||||
}
|
||||
if (top) {
|
||||
concat_count -= 1;
|
||||
concat->set(concat_count, top);
|
||||
}
|
||||
ivl_assert(*this, concat_count==0);
|
||||
|
||||
return concat;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1393,14 +1643,7 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetESignal*net, NetScope*found_in) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.lsb != 0);
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetExpr*base = calculate_up_do_base_(des, scope);
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
@@ -1412,7 +1655,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||
long lsv = base_c->value().as_long();
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// If the part select covers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sig()->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
@@ -1471,10 +1714,11 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
if (NetEConst*base_c = dynamic_cast<NetEConst*> (base)) {
|
||||
long lsv = base_c->value().as_long();
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// If the part select covers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sig()->sb_to_idx(lsv) == (wid-1) && wid == net->vector_width())
|
||||
if (net->sig()->sb_to_idx(lsv) == (signed) (wid-1) &&
|
||||
wid == net->vector_width())
|
||||
return net;
|
||||
|
||||
// Otherwise, make a part select that covers the right range.
|
||||
@@ -1524,8 +1768,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
/* The bit select is out of range of the
|
||||
vector. This is legal, but returns a
|
||||
constant 1'bx value. */
|
||||
verinum x (verinum::Vx);
|
||||
NetEConst*tmp = new NetEConst(x);
|
||||
NetEConst*tmp = make_const_x(1);
|
||||
tmp->set_line(*this);
|
||||
|
||||
cerr << get_fileline() << ": warning: Bit select ["
|
||||
@@ -1539,7 +1782,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
// If the vector is only one bit, we are done. The
|
||||
// bit select will return the scaler itself.
|
||||
// bit select will return the scalar itself.
|
||||
if (net->vector_width() == 1)
|
||||
return net;
|
||||
|
||||
@@ -1676,6 +1919,12 @@ static bool test_ternary_operand_compat(ivl_variable_type_t l,
|
||||
return true;
|
||||
if (l == IVL_VT_BOOL && r == IVL_VT_LOGIC)
|
||||
return true;
|
||||
|
||||
if (l == IVL_VT_REAL && (r == IVL_VT_LOGIC || r == IVL_VT_BOOL))
|
||||
return true;
|
||||
if (r == IVL_VT_REAL && (l == IVL_VT_LOGIC || l == IVL_VT_BOOL))
|
||||
return true;
|
||||
|
||||
if (l == r)
|
||||
return true;
|
||||
|
||||
@@ -1745,13 +1994,23 @@ NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||
NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
/* Reduction operators and ! always have a self determined width. */
|
||||
switch (op_) {
|
||||
case '!':
|
||||
case '&': // Reduction AND
|
||||
case '|': // Reduction OR
|
||||
case '^': // Reduction XOR
|
||||
case 'A': // Reduction NAND (~&)
|
||||
case 'N': // Reduction NOR (~|)
|
||||
case 'X': // Reduction NXOR (~^)
|
||||
expr_wid = -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope, expr_wid, false);
|
||||
if (ip == 0) return 0;
|
||||
|
||||
/* Should we evaluate expressions ahead of time,
|
||||
* just like in PEBinary::elaborate_expr() ?
|
||||
*/
|
||||
|
||||
NetExpr*tmp;
|
||||
switch (op_) {
|
||||
default:
|
||||
@@ -1766,15 +2025,15 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||
if (expr_wid > 0)
|
||||
val = pad_to_width(val, expr_wid);
|
||||
|
||||
/* When taking the - of a number, turn it into a
|
||||
signed expression and extend it one bit to
|
||||
accommodate a possible sign bit. */
|
||||
/* When taking the - of a number, extend it one
|
||||
bit to accommodate a possible sign bit. */
|
||||
verinum zero (verinum::V0, val.len()+1, val.has_len());
|
||||
zero.has_sign(val.has_sign());
|
||||
verinum nval = zero - val;
|
||||
|
||||
if (val.has_len())
|
||||
nval = verinum(nval, val.len());
|
||||
nval.has_sign(true);
|
||||
nval.has_sign(val.has_sign());
|
||||
tmp = new NetEConst(nval);
|
||||
tmp->set_line(*this);
|
||||
delete ip;
|
||||
|
||||
+3
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2008 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
|
||||
@@ -33,7 +33,7 @@
|
||||
* assignment. This is common code for the = and <= statements.
|
||||
*
|
||||
* What gets generated depends on the structure of the l-value. If the
|
||||
* l-value is a simple name (i.e., foo <= <value>) the the NetAssign_
|
||||
* l-value is a simple name (i.e., foo <= <value>) then the NetAssign_
|
||||
* is created the width of the foo reg and connected to all the
|
||||
* bits.
|
||||
*
|
||||
@@ -333,9 +333,7 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
if (long base = reg->array_first()) {
|
||||
|
||||
word = make_add_expr(word, 0-base);
|
||||
if (NetExpr*tmp = word->eval_tree()) {
|
||||
word = tmp;
|
||||
}
|
||||
eval_expr(word);
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
@@ -485,4 +483,3 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+801
-377
File diff suppressed because it is too large
Load Diff
+27
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2008 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
|
||||
@@ -53,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -2);
|
||||
NetExpr*tmp = elaborate_expr_base_(des, lp, rp, -2);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* continue on even if the repeat expression doesn't
|
||||
@@ -108,7 +109,8 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
<< "concatenation has indefinite width: "
|
||||
<< *ex << endl;
|
||||
des->errors += 1;
|
||||
|
||||
delete tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp->set(idx, ex);
|
||||
@@ -173,21 +175,31 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
switch (use_sel) {
|
||||
case index_component_t::SEL_NONE:
|
||||
break;
|
||||
|
||||
default:
|
||||
case index_component_t::SEL_PART:
|
||||
cerr << get_fileline() << ": sorry: Cannot part select "
|
||||
"bits of parameters." << endl;
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
break;
|
||||
delete res;
|
||||
return 0;
|
||||
|
||||
case index_component_t::SEL_BIT:
|
||||
|
||||
/* We have here a bit select. Insert a NetESelect node
|
||||
to handle it. */
|
||||
NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope);
|
||||
if (tmp != 0) {
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
if (tmp == 0) {
|
||||
delete res;
|
||||
return 0;
|
||||
}
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Bit select [" << *tmp << "]"
|
||||
<< " in parameter expression." << endl;
|
||||
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
res->set_line(*this);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -213,10 +225,11 @@ NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
NetExpr*c = expr_->elaborate_pexpr(des, scope);
|
||||
NetExpr*t = tru_->elaborate_pexpr(des, scope);
|
||||
NetExpr*f = fal_->elaborate_pexpr(des, scope);
|
||||
if (c == 0) return 0;
|
||||
if (t == 0) return 0;
|
||||
if (f == 0) return 0;
|
||||
return new NetETernary(c, t, f);
|
||||
if (c == 0 || t == 0 || f == 0) return 0;
|
||||
|
||||
NetETernary*tmp = new NetETernary(c, t, f);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
@@ -234,10 +247,12 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
tmp = new NetEUnary(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '~':
|
||||
tmp = new NetEUBits(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '!': // Logical NOT
|
||||
case '&': // Reduction AND
|
||||
case '|': // Reduction OR
|
||||
@@ -249,6 +264,6 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
+207
-79
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2008 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
|
||||
@@ -22,6 +22,7 @@
|
||||
# include "netmisc.h"
|
||||
# include <cstring>
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
# include <stdio.h>
|
||||
|
||||
/*
|
||||
@@ -43,6 +44,84 @@
|
||||
# include "util.h"
|
||||
# include <typeinfo>
|
||||
# include <assert.h>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
void Module::elaborate_parm_item_(perm_string name, const param_expr_t&cur,
|
||||
Design*des, NetScope*scope)
|
||||
{
|
||||
PExpr*ex = cur.expr;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
if (val == 0) return;
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = cur.signed_flag;
|
||||
|
||||
/* If the parameter declaration includes msb and lsb,
|
||||
then use them to calculate a width for the
|
||||
result. Then make sure the constant expression of the
|
||||
parameter value is coerced to have the correct
|
||||
and defined width. */
|
||||
if (cur.msb) {
|
||||
assert(cur.lsb);
|
||||
msb = cur.msb ->elaborate_pexpr(des, scope);
|
||||
assert(msb);
|
||||
lsb = cur.lsb ->elaborate_pexpr(des, scope);
|
||||
assert(lsb);
|
||||
}
|
||||
|
||||
if (signed_flag) {
|
||||
/* If explicitly signed, then say so. */
|
||||
val->cast_signed(true);
|
||||
} else if (cur.msb) {
|
||||
/* If there is a range, then the signedness comes
|
||||
from the type and not the expression. */
|
||||
val->cast_signed(signed_flag);
|
||||
} else {
|
||||
/* otherwise, let the expression describe
|
||||
itself. */
|
||||
signed_flag = val->has_sign();
|
||||
}
|
||||
|
||||
NetScope::range_t*range_list = 0;
|
||||
for (Module::range_t*range = cur.range ; range ; range = range->next) {
|
||||
NetScope::range_t*tmp = new NetScope::range_t;
|
||||
tmp->exclude_flag = range->exclude_flag;
|
||||
tmp->low_open_flag = range->low_open_flag;
|
||||
tmp->high_open_flag = range->high_open_flag;
|
||||
|
||||
if (range->low_expr) {
|
||||
tmp->low_expr = elab_and_eval(des, scope, range->low_expr, -1);
|
||||
ivl_assert(*range->low_expr, tmp->low_expr);
|
||||
} else {
|
||||
tmp->low_expr = 0;
|
||||
}
|
||||
|
||||
if (range->high_expr && range->high_expr==range->low_expr) {
|
||||
// Detect the special case of a "point"
|
||||
// range. These are called out by setting the high
|
||||
// and low expression ranges to the same
|
||||
// expression. The exclude_flags should be false
|
||||
// in this case
|
||||
ivl_assert(*range->high_expr, tmp->low_open_flag==false && tmp->high_open_flag==false);
|
||||
tmp->high_expr = tmp->low_expr;
|
||||
|
||||
} else if (range->high_expr) {
|
||||
tmp->high_expr = elab_and_eval(des, scope, range->high_expr, -1);
|
||||
ivl_assert(*range->high_expr, tmp->high_expr);
|
||||
} else {
|
||||
tmp->high_expr = 0;
|
||||
}
|
||||
|
||||
tmp->next = range_list;
|
||||
range_list = tmp;
|
||||
}
|
||||
|
||||
val = scope->set_parameter(name, val, cur.type, msb, lsb, signed_flag, range_list, cur);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
const replace_t&replacements) const
|
||||
@@ -77,7 +156,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, 0, 0, false);
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
@@ -88,7 +168,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, 0, 0, false);
|
||||
scope->set_parameter((*cur).first, tmp, (*cur).second.type,
|
||||
0, 0, false, 0, (*cur).second);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,42 +181,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
PExpr*ex = (*cur).second.expr;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = (*cur).second.signed_flag;
|
||||
|
||||
/* If the parameter declaration includes msb and lsb,
|
||||
then use them to calculate a width for the
|
||||
result. Then make sure the constant expression of the
|
||||
parameter value is coerced to have the correct
|
||||
and defined width. */
|
||||
if ((*cur).second.msb) {
|
||||
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
|
||||
assert(msb);
|
||||
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
|
||||
}
|
||||
|
||||
if (signed_flag) {
|
||||
/* If explicitly signed, then say so. */
|
||||
val->cast_signed(true);
|
||||
} else if ((*cur).second.msb) {
|
||||
/* If there is a range, then the signedness comes
|
||||
from the type and not the expression. */
|
||||
val->cast_signed(signed_flag);
|
||||
} else {
|
||||
/* otherwise, let the expression describe
|
||||
itself. */
|
||||
signed_flag = val->has_sign();
|
||||
}
|
||||
|
||||
val = scope->set_parameter((*cur).first, val,
|
||||
msb, lsb, signed_flag);
|
||||
assert(val);
|
||||
delete val;
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
|
||||
/* run parameter replacements that were collected from the
|
||||
@@ -155,6 +201,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
<< "Replace " << (*cur).first
|
||||
<< " with expression " << *val
|
||||
<< " from " << val->get_fileline() << "." << endl;
|
||||
cerr << get_fileline() << ": : "
|
||||
<< "Type=" << val->expr_type() << endl;
|
||||
}
|
||||
bool flag = scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
@@ -167,31 +215,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
PExpr*ex = (*cur).second.expr;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = false;
|
||||
|
||||
/* If the parameter declaration includes msb and lsb,
|
||||
then use them to calculate a width for the
|
||||
result. Then make sure the constant expression of the
|
||||
parameter value is coerced to have the correct
|
||||
and defined width. */
|
||||
if ((*cur).second.msb) {
|
||||
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
|
||||
assert(msb);
|
||||
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
|
||||
signed_flag = (*cur).second.signed_flag;
|
||||
}
|
||||
|
||||
val->cast_signed(signed_flag);
|
||||
val = scope->set_parameter((*cur).first, val,
|
||||
msb, lsb, signed_flag);
|
||||
assert(val);
|
||||
delete val;
|
||||
elaborate_parm_item_((*cur).first, (*cur).second, des, scope);
|
||||
}
|
||||
|
||||
// Run through the defparams for this module, elaborate the
|
||||
@@ -257,6 +281,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
}
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope::TASK);
|
||||
task_scope->set_line((*cur).second);
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
}
|
||||
|
||||
@@ -280,6 +305,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
}
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope::FUNC);
|
||||
func_scope->set_line((*cur).second);
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
}
|
||||
|
||||
@@ -301,8 +327,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
|
||||
for (proc_it_t cur = behaviors_.begin()
|
||||
; cur != behaviors_.end() ; cur ++ ) {
|
||||
for (proc_it_t cur = behaviors.begin()
|
||||
; cur != behaviors.end() ; cur ++ ) {
|
||||
|
||||
(*cur) -> statement() -> elaborate_scope(des, scope);
|
||||
}
|
||||
@@ -333,6 +359,15 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
|
||||
case GS_ELSE:
|
||||
return generate_scope_condit_(des, container, true);
|
||||
|
||||
case GS_CASE:
|
||||
return generate_scope_case_(des, container);
|
||||
return true;
|
||||
|
||||
case GS_CASE_ITEM:
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Case item outside of a case generate scheme?" << endl;
|
||||
return false;
|
||||
|
||||
default:
|
||||
cerr << get_fileline() << ": sorry: Generate of this sort"
|
||||
<< " is not supported yet!" << endl;
|
||||
@@ -345,12 +380,17 @@ bool PGenerate::generate_scope(Design*des, NetScope*container)
|
||||
*/
|
||||
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
{
|
||||
// Check that the loop_index variable was declared in a
|
||||
// genvar statement.
|
||||
|
||||
// MISSING CODE!
|
||||
|
||||
// We're going to need a genvar...
|
||||
int genvar;
|
||||
|
||||
// The initial value for the genvar does not need (nor can it
|
||||
// use) the genvar itself, so we can evaluate this expression
|
||||
// the same way any other paramter value is evaluated.
|
||||
// the same way any other parameter value is evaluated.
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||
if (init == 0) {
|
||||
@@ -360,12 +400,24 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since we will be adding the genvar value as a local parameter
|
||||
// to each instances scope. We need to make sure a parameter does
|
||||
// not already exist.
|
||||
const NetExpr*tmsb;
|
||||
const NetExpr*tlsb;
|
||||
const NetExpr*texpr = container->get_parameter(loop_index, tmsb, tlsb);
|
||||
if (texpr != 0) {
|
||||
cerr << get_fileline() << ": error: Cannot have a genvar "
|
||||
<< "and parameter with the same name: " << loop_index << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
genvar = init->value().as_long();
|
||||
delete init_ex;
|
||||
|
||||
if (debug_elaborate)
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
|
||||
|
||||
container->genvar_tmp = loop_index;
|
||||
container->genvar_tmp_val = genvar;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
@@ -385,12 +437,13 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (debug_elaborate)
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Create generated scope " << use_name << endl;
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
|
||||
// Set in the scope a localparam for the value of the
|
||||
// genvar within this instance of the generate
|
||||
@@ -402,9 +455,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
NetEConstParam*gp = new NetEConstParam(scope,
|
||||
loop_index,
|
||||
genvar_verinum);
|
||||
scope->set_localparam(loop_index, gp);
|
||||
|
||||
if (debug_elaborate)
|
||||
// The file and line information should really come
|
||||
// from the genvar statement, not the for loop.
|
||||
scope->set_localparam(loop_index, gp, *this);
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Create implicit localparam "
|
||||
<< loop_index << " = " << genvar_verinum << endl;
|
||||
@@ -416,7 +470,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||
assert(step);
|
||||
if (debug_elaborate)
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: genvar step from "
|
||||
<< genvar << " to " << step->value().as_long() << endl;
|
||||
|
||||
@@ -446,7 +500,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||
// scope.
|
||||
if ( (test->value().as_long() == 0 && !else_flag)
|
||||
|| (test->value().as_long() != 0 && else_flag) ) {
|
||||
if (debug_elaborate)
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate condition "
|
||||
<< (else_flag? "(else)" : "(if)")
|
||||
<< " value=" << test->value() << ": skip generation"
|
||||
@@ -463,7 +517,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (debug_elaborate)
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate condition "
|
||||
<< (else_flag? "(else)" : "(if)")
|
||||
<< " value=" << test->value() << ": Generate scope="
|
||||
@@ -471,12 +525,79 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
|
||||
elaborate_subscope_(des, scope);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
||||
{
|
||||
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
||||
assert(case_value_co);
|
||||
|
||||
// The name of the scope to generate, whatever that item is.
|
||||
hname_t use_name (scope_name);
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate case "
|
||||
<< "switch value=" << case_value_co->value() << endl;
|
||||
|
||||
PGenerate*default_item = 0;
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generator_it_t;
|
||||
generator_it_t cur = generates.begin();
|
||||
while (cur != generates.end()) {
|
||||
PGenerate*item = *cur;
|
||||
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
|
||||
|
||||
// Detect that the item is a default.
|
||||
if (item->loop_test == 0) {
|
||||
default_item = item;
|
||||
cur ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
NetExpr*item_value_ex = elab_and_eval(des, container, item->loop_test, -1);
|
||||
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
||||
assert(item_value_co);
|
||||
|
||||
// If we stumble on the item that matches, then break
|
||||
// out now.
|
||||
if (case_value_co->value() == item_value_co->value()) {
|
||||
delete item_value_co;
|
||||
break;
|
||||
}
|
||||
|
||||
delete item_value_co;
|
||||
cur ++;
|
||||
}
|
||||
|
||||
delete case_value_co;
|
||||
case_value_co = 0;
|
||||
|
||||
PGenerate*item = (cur == generates.end())? default_item : *cur;
|
||||
if (item == 0) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "No generate items found" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Generate case matches item at "
|
||||
<< item->get_fileline() << endl;
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
scope->set_line(get_file(), get_lineno());
|
||||
item->elaborate_subscope_(des, scope);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
||||
{
|
||||
// Scan the generated scope for nested generate schemes,
|
||||
@@ -604,6 +725,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
|
||||
// Create the new scope as a MODULE with my name.
|
||||
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE);
|
||||
my_scope->set_line(get_file(), mod->get_file(),
|
||||
get_lineno(), mod->get_lineno());
|
||||
my_scope->set_module_name(mod->mod_name());
|
||||
my_scope->default_nettype(mod->default_nettype);
|
||||
|
||||
@@ -685,7 +808,11 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
|
||||
/* Stash the instance array of scopes into the parent
|
||||
scope. Later elaboration passes will use this vector to
|
||||
further elaborate the array. */
|
||||
further elaborate the array.
|
||||
|
||||
Note that the array is ordered from LSB to MSB. We will use
|
||||
that fact in the main elaborate to connect things in the
|
||||
correct order. */
|
||||
sc->instance_arrays[get_name()] = instances;
|
||||
}
|
||||
|
||||
@@ -738,8 +865,8 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetScope*my_scope = scope;
|
||||
|
||||
if (name_ != 0) {
|
||||
hname_t use_name(name_);
|
||||
if (pscope_name() != 0) {
|
||||
hname_t use_name(pscope_name());
|
||||
if (scope->child(use_name)) {
|
||||
cerr << get_fileline() << ": error: block/scope name "
|
||||
<< use_name << " already used in this context."
|
||||
@@ -750,6 +877,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
my_scope = new NetScope(scope, use_name, bl_type_==BL_PAR
|
||||
? NetScope::FORK_JOIN
|
||||
: NetScope::BEGIN_END);
|
||||
my_scope->set_line(get_file(), get_lineno());
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
|
||||
|
||||
+401
-163
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2008 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
|
||||
@@ -28,46 +28,84 @@
|
||||
# include "PGenerate.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
# include "compiler.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* This local function checks if a named signal is connected to a
|
||||
* port. It looks in the array of ports passed, for NetEIdent objects
|
||||
* within the port_t that have a matching name.
|
||||
*/
|
||||
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
|
||||
NetNet*sig)
|
||||
static bool get_const_argument(NetExpr*exp, verinum&res)
|
||||
{
|
||||
perm_string name = sig->name();
|
||||
switch (exp->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*cv = dynamic_cast<NetECReal*>(exp);
|
||||
if (cv == 0) return false;
|
||||
verireal tmp = cv->value();
|
||||
res = verinum(tmp.as_long());
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
NetEConst*cv = dynamic_cast<NetEConst*>(exp);
|
||||
if (cv == 0) return false;
|
||||
res = cv->value();
|
||||
break;
|
||||
}
|
||||
|
||||
Module::port_t*pp = ports[idx];
|
||||
// Skip internally unconnected ports.
|
||||
if (pp == 0)
|
||||
continue;
|
||||
|
||||
// This port has an internal connection. In this case,
|
||||
// the port has 0 or more NetEIdent objects concatenated
|
||||
// together that form the port.
|
||||
|
||||
// Note that module ports should not have any heirarchy
|
||||
// in their names: they are in the root of the module
|
||||
// scope by definition.
|
||||
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
perm_string pname = peek_tail_name(pp->expr[cc]->path());
|
||||
assert(pp->expr[cc]);
|
||||
if (pname == name)
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
assert(0);;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Statement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
}
|
||||
|
||||
bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
for (map<perm_string,PWire*>::const_iterator wt = wires.begin()
|
||||
; wt != wires.end() ; wt ++ ) {
|
||||
|
||||
PWire*cur = (*wt).second;
|
||||
NetNet*sig = cur->elaborate_sig(des, scope);
|
||||
|
||||
|
||||
/* If the signal is an input and is also declared as a
|
||||
reg, then report an error. */
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (scope->type() == NetScope::MODULE)
|
||||
&& (sig->port_type() == NetNet::PINPUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: "
|
||||
<< cur->basename() << " in "
|
||||
<< scope->module_name()
|
||||
<< " declared as input and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (scope->type() == NetScope::MODULE)
|
||||
&& (sig->port_type() == NetNet::PINOUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: "
|
||||
<< cur->basename() << " in "
|
||||
<< scope->module_name()
|
||||
<< " declared as inout and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
@@ -81,15 +119,27 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (pp == 0)
|
||||
continue;
|
||||
|
||||
map<pform_name_t,PWire*>::const_iterator wt;
|
||||
// The port has a name and an array of expressions. The
|
||||
// expression are all identifiers that should reference
|
||||
// wires within the scope.
|
||||
map<perm_string,PWire*>::const_iterator wt;
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
pform_name_t port_path (pp->expr[cc]->path());
|
||||
wt = wires_.find(port_path);
|
||||
// A concatenated wire of a port really should not
|
||||
// have any hierarchy.
|
||||
if (port_path.size() != 1) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Port " << port_path << " has a funny name?"
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (wt == wires_.end()) {
|
||||
wt = wires.find(peek_tail_name(port_path));
|
||||
|
||||
if (wt == wires.end()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Port " << pp->expr[cc]->path() << " ("
|
||||
<< (idx+1) << ") of module " << name_
|
||||
<< "Port " << port_path << " ("
|
||||
<< (idx+1) << ") of module " << mod_name()
|
||||
<< " is not declared within module." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
@@ -98,7 +148,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if ((*wt).second->get_port_type() == NetNet::NOT_A_PORT) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Port " << pp->expr[cc]->path() << " ("
|
||||
<< (idx+1) << ") of module " << name_
|
||||
<< (idx+1) << ") of module " << mod_name()
|
||||
<< " has no direction declaration."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
@@ -106,60 +156,9 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
|
||||
; wt != wires_.end() ; wt ++ ) {
|
||||
flag = elaborate_sig_wires_(des, scope) && flag;
|
||||
|
||||
PWire*cur = (*wt).second;
|
||||
NetNet*sig = cur->elaborate_sig(des, scope);
|
||||
|
||||
// If this wire is a signal of the module (as opposed to
|
||||
// a port of a function) and is a port, then check that
|
||||
// the module knows about it. We know that the signal is
|
||||
// the name of a signal within a subscope of a module
|
||||
// (a task, a function, etc.) if the name for the PWire
|
||||
// has hierarchy.
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
|
||||
|
||||
if (! signal_is_in_port(ports, sig)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: Signal "
|
||||
<< sig->name() << " has a declared direction "
|
||||
<< "but is not a port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If the signal is an input and is also declared as a
|
||||
reg, then report an error. */
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (sig->port_type() == NetNet::PINPUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: "
|
||||
<< cur->path() << " in module "
|
||||
<< scope->module_name()
|
||||
<< " declared as input and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (sig->port_type() == NetNet::PINOUT)
|
||||
&& (sig->type() == NetNet::REG)) {
|
||||
|
||||
cerr << cur->get_fileline() << ": error: "
|
||||
<< cur->path() << " in module "
|
||||
<< scope->module_name()
|
||||
<< " declared as inout and as a reg type." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Run through all the generate schemes to enaborate the
|
||||
// Run through all the generate schemes to elaborate the
|
||||
// signals that they hold. Note that the generate schemes hold
|
||||
// the scopes that they instantiated, so we don't pass any
|
||||
// scope in.
|
||||
@@ -216,14 +215,144 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
|
||||
// initial and always blocks may contain begin-end and
|
||||
// fork-join blocks that can introduce scopes. Therefore, I
|
||||
// get to scan processes here.
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
|
||||
for (proc_it_t cur = behaviors.begin()
|
||||
; cur != behaviors.end() ; cur ++ ) {
|
||||
|
||||
(*cur) -> statement() -> elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PExpr::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PEConcat::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||
flag = parms_[idx]->elaborate_sig(des, scope) && flag;
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet* sig = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
// If implicit net creation is turned off, then stop now.
|
||||
if (scope->default_nettype() == NetNet::NONE)
|
||||
return true;
|
||||
if (error_implicit)
|
||||
return true;
|
||||
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0)
|
||||
return false;
|
||||
|
||||
if (par != 0)
|
||||
return true;
|
||||
|
||||
if (sig == 0)
|
||||
sig = make_implicit_net_(des, scope);
|
||||
|
||||
return sig != 0;
|
||||
}
|
||||
|
||||
bool PEBinary::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
flag = left_->elaborate_sig(des, scope) && flag;
|
||||
flag = right_->elaborate_sig(des, scope) && flag;
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PETernary::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
flag = tru_->elaborate_sig(des, scope) && flag;
|
||||
flag = fal_->elaborate_sig(des, scope) && flag;
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PEUnary::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
return expr_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
bool PGate::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PGBuiltin::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
const PExpr* pin_expr = pin(idx);
|
||||
if (pin_expr == 0) {
|
||||
// If there is no pin expression for this port,
|
||||
// then skip it. Do not bother generating an error
|
||||
// message here, that will be done during
|
||||
// elaboration where these semantic details are tested.
|
||||
continue;
|
||||
}
|
||||
ivl_assert(*this, pin_expr);
|
||||
flag = pin_expr->elaborate_sig(des, scope) && flag;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGAssign::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
/* Normally, l-values to continuous assignments are NOT allowed
|
||||
to implicitly declare nets. However, so many tools do allow
|
||||
it that Icarus Verilog will allow it, at least if extensions
|
||||
are enabled. */
|
||||
if (gn_icarus_misc_flag)
|
||||
return pin(0)->elaborate_sig(des, scope);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
Module*rmod) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
// First, elaborate the signals that may be created implicitly
|
||||
// by ports to this module instantiation. Handle the case that
|
||||
// the ports are passed by name (pins_ != 0) or position.
|
||||
if (pins_)
|
||||
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
|
||||
const PExpr*tmp = pins_[idx].parm;
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
flag = tmp->elaborate_sig(des, scope) && flag;
|
||||
}
|
||||
else
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
const PExpr*tmp = pin(idx);
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
flag = tmp->elaborate_sig(des, scope) && flag;
|
||||
}
|
||||
|
||||
|
||||
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
|
||||
|
||||
for (unsigned idx = 0 ; idx < instance.count() ; idx += 1) {
|
||||
@@ -249,10 +378,53 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
if (pins_)
|
||||
for (unsigned idx = 0 ; idx < npins_ ; idx += 1) {
|
||||
const PExpr*tmp = pins_[idx].parm;
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
flag = tmp->elaborate_sig(des, scope) && flag;
|
||||
}
|
||||
else
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
const PExpr*tmp = pin(idx);
|
||||
if (tmp == 0)
|
||||
continue;
|
||||
flag = tmp->elaborate_sig(des, scope) && flag;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
// Handle the special case that this is a CASE scheme. In this
|
||||
// case the PGenerate itself does not have the generated
|
||||
// item. Look instead for the case ITEM that has a scope
|
||||
// generated for it.
|
||||
if (scheme_type == PGenerate::GS_CASE) {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: generate case"
|
||||
<< " elaborate_sig in scope "
|
||||
<< scope_path(container) << "." << endl;
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generates.begin()
|
||||
; cur != generates.end() ; cur ++) {
|
||||
PGenerate*item = *cur;
|
||||
if (! item->scope_list_.empty()) {
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
typedef list<NetScope*>::const_iterator scope_list_it_t;
|
||||
for (scope_list_it_t cur = scope_list_.begin()
|
||||
; cur != scope_list_.end() ; cur ++ ) {
|
||||
@@ -276,7 +448,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
{
|
||||
// Scan the declared PWires to elaborate the obvious signals
|
||||
// in the current scope.
|
||||
typedef map<pform_name_t,PWire*>::const_iterator wires_it_t;
|
||||
typedef map<perm_string,PWire*>::const_iterator wires_it_t;
|
||||
for (wires_it_t wt = wires.begin()
|
||||
; wt != wires.end() ; wt ++ ) {
|
||||
|
||||
@@ -284,7 +456,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: Elaborate PWire "
|
||||
<< cur->path() << " in scope " << scope_path(scope) << endl;
|
||||
<< cur->basename() << " in scope " << scope_path(scope) << endl;
|
||||
|
||||
cur->elaborate_sig(des, scope);
|
||||
}
|
||||
@@ -316,6 +488,8 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
perm_string fname = scope->basename();
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
|
||||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
/* Make sure the function has at least one input port. If it
|
||||
fails this test, print an error message. Keep going so we
|
||||
can find more errors. */
|
||||
@@ -416,21 +590,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
name. We know by design that the port name is given
|
||||
as two components: <func>.<port>. */
|
||||
|
||||
pform_name_t path = (*ports_)[idx]->path();
|
||||
ivl_assert(*this, path.size() == 2);
|
||||
|
||||
perm_string pname = peek_tail_name(path);
|
||||
perm_string ppath = peek_head_name(path);
|
||||
|
||||
if (ppath != scope->basename()) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< "port " << (*ports_)[idx]->path()
|
||||
<< " has wrong name for function "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
perm_string pname = (*ports_)[idx]->basename();
|
||||
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
ports[idx] = 0;
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< scope_path(scope) << " is missing port "
|
||||
@@ -438,9 +602,27 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
scope->dump(cerr);
|
||||
cerr << get_fileline() << ": Continuing..." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
||||
cerr << get_fileline() << ": internal error: function "
|
||||
<< scope_path(scope) << " port " << pname
|
||||
<< " is a port but is not a port?" << endl;
|
||||
des->errors += 1;
|
||||
scope->dump(cerr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
if (tmp->port_type() != NetNet::PINPUT) {
|
||||
cerr << tmp->get_fileline() << ": error: function "
|
||||
<< scope_path(scope) << " port " << pname
|
||||
<< " is not an input port." << endl;
|
||||
cerr << tmp->get_fileline() << ": : Function arguments "
|
||||
<< "must be input ports." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -448,7 +630,16 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
|
||||
|
||||
assert(def);
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Attach function definition to scope "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
|
||||
scope->set_func_def(def);
|
||||
|
||||
// Look for further signals in the sub-statement
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -464,24 +655,12 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope->type() == NetScope::TASK);
|
||||
|
||||
elaborate_sig_wires_(des, scope);
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->count() : 0);
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
|
||||
/* Parse the port name into the task name and the reg
|
||||
name. We know by design that the port name is given
|
||||
as two components: <task>.<port>. */
|
||||
|
||||
pform_name_t path = (*ports_)[idx]->path();
|
||||
ivl_assert(*this, path.size() == 2);
|
||||
|
||||
perm_string scope_name = peek_head_name(path);
|
||||
perm_string port_name = peek_tail_name(path);
|
||||
|
||||
/* check that the current scope really does have the
|
||||
name of the first component of the task port name. Do
|
||||
this by looking up the task scope in the parent of
|
||||
the current scope. */
|
||||
ivl_assert(*this, scope->basename() == scope_name);
|
||||
perm_string port_name = (*ports_)[idx]->basename();
|
||||
|
||||
/* Find the signal for the port. We know by definition
|
||||
that it is in the scope of the task, so look only in
|
||||
@@ -493,6 +672,7 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
||||
<< "Could not find port " << port_name
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
scope->dump(cerr);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
@@ -500,11 +680,94 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports);
|
||||
scope->set_task_def(def);
|
||||
|
||||
// Look for further signals in the sub-statement
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
bool PGate::elaborate_sig(Design*des, NetScope*scope) const
|
||||
void PBlock::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
return true;
|
||||
NetScope*my_scope = scope;
|
||||
|
||||
if (pscope_name() != 0) {
|
||||
hname_t use_name (pscope_name());
|
||||
my_scope = scope->child(use_name);
|
||||
if (my_scope == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find child scope " << pscope_name()
|
||||
<< " in this context?" << endl;
|
||||
des->errors += 1;
|
||||
my_scope = scope;
|
||||
} else {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "elaborate_sig descending into "
|
||||
<< scope_path(my_scope) << "." << endl;
|
||||
|
||||
elaborate_sig_wires_(des, my_scope);
|
||||
}
|
||||
}
|
||||
|
||||
// elaborate_sig in the statements included in the
|
||||
// block. There may be named blocks in there.
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1)
|
||||
list_[idx] -> elaborate_sig(des, my_scope);
|
||||
}
|
||||
|
||||
void PCase::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (items_ == 0)
|
||||
return;
|
||||
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
||||
if ( (*items_)[idx]->stat )
|
||||
(*items_)[idx]->stat ->elaborate_sig(des,scope);
|
||||
}
|
||||
}
|
||||
|
||||
void PCondit::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (if_)
|
||||
if_->elaborate_sig(des, scope);
|
||||
if (else_)
|
||||
else_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PDelayStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PForever::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PForStatement::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PRepeat::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (statement_)
|
||||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -516,27 +779,6 @@ bool PGate::elaborate_sig(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
|
||||
/* The parser may produce hierarchical names for wires. I here
|
||||
follow the scopes down to the base where I actually want to
|
||||
elaborate the NetNet object. */
|
||||
{ pform_name_t tmp_path = hname_;
|
||||
tmp_path.pop_back();
|
||||
while (! tmp_path.empty()) {
|
||||
name_component_t cur = tmp_path.front();
|
||||
tmp_path.pop_front();
|
||||
|
||||
scope = scope->child( hname_t(cur.name) );
|
||||
|
||||
if (scope == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Bad scope component for name "
|
||||
<< hname_ << endl;
|
||||
assert(scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetNet::Type wtype = type_;
|
||||
if (wtype == NetNet::IMPLICIT)
|
||||
wtype = NetNet::WIRE;
|
||||
@@ -619,12 +861,12 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (port_msb_ == 0) {
|
||||
if (!gn_io_range_error_flag) {
|
||||
cerr << get_fileline()
|
||||
<< ": warning: Scalar port ``" << hname_
|
||||
<< ": warning: Scalar port ``" << name_
|
||||
<< "'' has a vectored net declaration ["
|
||||
<< nmsb << ":" << nlsb << "]." << endl;
|
||||
} else {
|
||||
cerr << get_fileline()
|
||||
<< ": error: Scalar port ``" << hname_
|
||||
<< ": error: Scalar port ``" << name_
|
||||
<< "'' has a vectored net declaration ["
|
||||
<< nmsb << ":" << nlsb << "]." << endl;
|
||||
des->errors += 1;
|
||||
@@ -636,7 +878,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (net_msb_ == 0) {
|
||||
cerr << port_msb_->get_fileline()
|
||||
<< ": error: Vectored port ``"
|
||||
<< hname_ << "'' [" << pmsb << ":" << plsb
|
||||
<< name_ << "'' [" << pmsb << ":" << plsb
|
||||
<< "] has a scalar net declaration at "
|
||||
<< get_fileline() << "." << endl;
|
||||
des->errors += 1;
|
||||
@@ -647,7 +889,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (port_msb_ != 0 && net_msb_ != 0) {
|
||||
cerr << port_msb_->get_fileline()
|
||||
<< ": error: Vectored port ``"
|
||||
<< hname_ << "'' [" << pmsb << ":" << plsb
|
||||
<< name_ << "'' [" << pmsb << ":" << plsb
|
||||
<< "] has a net declaration [" << nmsb << ":"
|
||||
<< nlsb << "] at " << net_msb_->get_fileline()
|
||||
<< " that does not match." << endl;
|
||||
@@ -687,28 +929,26 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if ((lexp == 0) || (rexp == 0)) {
|
||||
cerr << get_fileline() << ": internal error: There is "
|
||||
<< "a problem evaluating indices for ``"
|
||||
<< hname_ << "''." << endl;
|
||||
<< name_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst*lcon = dynamic_cast<NetEConst*> (lexp);
|
||||
NetEConst*rcon = dynamic_cast<NetEConst*> (rexp);
|
||||
bool const_flag = true;
|
||||
verinum lval, rval;
|
||||
const_flag &= get_const_argument(lexp, lval);
|
||||
const_flag &= get_const_argument(rexp, rval);
|
||||
delete rexp;
|
||||
delete lexp;
|
||||
|
||||
if ((lcon == 0) || (rcon == 0)) {
|
||||
if (!const_flag) {
|
||||
cerr << get_fileline() << ": internal error: The indices "
|
||||
<< "are not constant for array ``"
|
||||
<< hname_ << "''." << endl;
|
||||
<< name_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum lval = lcon->value();
|
||||
verinum rval = rcon->value();
|
||||
|
||||
delete lexp;
|
||||
delete rexp;
|
||||
|
||||
array_dimensions = 1;
|
||||
array_s0 = lval.as_long();
|
||||
array_e0 = rval.as_long();
|
||||
@@ -748,24 +988,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
perm_string name = peek_tail_name(hname_);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Create signal "
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name_
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
|
||||
NetNet*sig = array_dimensions > 0
|
||||
? new NetNet(scope, name, wtype, msb, lsb, array_s0, array_e0)
|
||||
: new NetNet(scope, name, wtype, msb, lsb);
|
||||
? new NetNet(scope, name_, wtype, msb, lsb, array_s0, array_e0)
|
||||
: new NetNet(scope, name_, wtype, msb, lsb);
|
||||
|
||||
ivl_variable_type_t use_data_type = data_type_;
|
||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Signal " << name
|
||||
<< "Signal " << name_
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< " defaults to data type " << use_data_type << endl;
|
||||
}
|
||||
@@ -785,4 +1024,3 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
||||
+247
-88
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.374 2007/06/05 21:35:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -88,16 +85,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
assert(pin(0));
|
||||
assert(pin(1));
|
||||
|
||||
/* Normally, l-values to continuous assignments are NOT allowed
|
||||
to implicitly declare nets. However, so many tools do allow
|
||||
it that Icarus Verilog will allow it, at least if extensions
|
||||
are enabled. */
|
||||
bool implicit_lval_ok = false;
|
||||
if (generation_flag == GN_VER2001X)
|
||||
implicit_lval_ok = true;
|
||||
|
||||
/* Elaborate the l-value. */
|
||||
NetNet*lval = pin(0)->elaborate_lnet(des, scope, implicit_lval_ok);
|
||||
NetNet*lval = pin(0)->elaborate_lnet(des, scope);
|
||||
if (lval == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -124,6 +113,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
return;
|
||||
}
|
||||
|
||||
/* If either lval or rid are real then both must be real. */
|
||||
if ((lval->data_type() == IVL_VT_REAL ||
|
||||
rid->data_type() == IVL_VT_REAL) &&
|
||||
lval->data_type() != rid->data_type()) {
|
||||
cerr << get_fileline() << ": sorry: Both the r-value and "
|
||||
"the l-value must be real in this context." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
ivl_assert(*this, rid);
|
||||
if (rid->pin_count() != 1) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
@@ -270,7 +269,7 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
generated NetNet. */
|
||||
NetNet*rval = pin(1)->elaborate_net(des, scope,
|
||||
lval->vector_width(),
|
||||
rise_time, fall_time, decay_time,
|
||||
0, 0, 0,
|
||||
drive0, drive1);
|
||||
if (rval == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to elaborate r-value: "
|
||||
@@ -288,6 +287,16 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
assert(lval && rval);
|
||||
assert(rval->pin_count() == 1);
|
||||
|
||||
/* If either lval or rval are real then both must be real. */
|
||||
if ((lval->data_type() == IVL_VT_REAL ||
|
||||
rval->data_type() == IVL_VT_REAL) &&
|
||||
lval->data_type() != rval->data_type()) {
|
||||
cerr << get_fileline() << ": sorry: Both the r-value and "
|
||||
"the l-value must be real in this context." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the r-value insists on being smaller then the l-value
|
||||
(perhaps it is explicitly sized) the pad it out to be the
|
||||
right width so that something is connected to all the bits
|
||||
@@ -311,6 +320,12 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
rval = osig;
|
||||
}
|
||||
|
||||
/* If there is a rise/fall/decay time, then attach that delay
|
||||
to the drivers for this net. */
|
||||
if (rise_time || fall_time || decay_time) {
|
||||
rval->pin(0).drivers_delays(rise_time, fall_time, decay_time);
|
||||
}
|
||||
|
||||
connect(lval->pin(0), rval->pin(0));
|
||||
|
||||
if (lval->local_flag())
|
||||
@@ -387,7 +402,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope, true);
|
||||
NetNet*lval_sig = pin(0)->elaborate_lnet(des, scope);
|
||||
assert(lval_sig);
|
||||
|
||||
/* Detect the special case that the l-value width exactly
|
||||
@@ -404,7 +419,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
/* Allocate all the netlist nodes for the gates. */
|
||||
NetLogic**cur = new NetLogic*[count];
|
||||
NetNode**cur = new NetNode*[count];
|
||||
assert(cur);
|
||||
|
||||
/* Calculate the gate delays from the delay expressions
|
||||
@@ -644,6 +659,67 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
cur[idx] = new NetLogic(scope, inm, pin_count(),
|
||||
NetLogic::XOR, instance_width);
|
||||
break;
|
||||
case TRAN:
|
||||
if (pin_count() != 2) {
|
||||
cerr << get_fileline() << ": error: Pin count for "
|
||||
<< "tran device." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_TRAN);
|
||||
}
|
||||
break;
|
||||
case RTRAN:
|
||||
if (pin_count() != 2) {
|
||||
cerr << get_fileline() << ": error: Pin count for "
|
||||
<< "rtran device." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRAN);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case TRANIF0:
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_fileline() << ": error: Pin count for "
|
||||
<< "tranif0 device." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_TRANIF0);
|
||||
}
|
||||
break;
|
||||
case RTRANIF0:
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_fileline() << ": error: Pin count for "
|
||||
<< "rtranif0 device." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRANIF0);
|
||||
}
|
||||
break;
|
||||
case TRANIF1:
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_fileline() << ": error: Pin count for "
|
||||
<< "tranif1 device." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_TRANIF1);
|
||||
}
|
||||
break;
|
||||
case RTRANIF1:
|
||||
if (pin_count() != 3) {
|
||||
cerr << get_fileline() << ": error: Pin count for "
|
||||
<< "rtranif1 device." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
} else {
|
||||
cur[idx] = new NetTran(scope, inm, IVL_SW_RTRANIF1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cerr << get_fileline() << ": internal error: unhandled "
|
||||
"gate type." << endl;
|
||||
@@ -655,13 +731,18 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
cur[idx]->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
cur[idx]->rise_time(rise_time);
|
||||
cur[idx]->fall_time(fall_time);
|
||||
cur[idx]->decay_time(decay_time);
|
||||
/* The logic devices have some uniform processing. Then
|
||||
all may have output delays and output drive strength. */
|
||||
if (NetLogic*log = dynamic_cast<NetLogic*> (cur[idx])) {
|
||||
log->rise_time(rise_time);
|
||||
log->fall_time(fall_time);
|
||||
log->decay_time(decay_time);
|
||||
|
||||
cur[idx]->pin(0).drive0(drive_type(strength0()));
|
||||
cur[idx]->pin(0).drive1(drive_type(strength1()));
|
||||
log->pin(0).drive0(drive_type(strength0()));
|
||||
log->pin(0).drive1(drive_type(strength1()));
|
||||
}
|
||||
|
||||
cur[idx]->set_line(*this);
|
||||
des->add_node(cur[idx]);
|
||||
}
|
||||
|
||||
@@ -783,6 +864,9 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// "cur" is an array of pointers, and we don't need it any more.
|
||||
delete[]cur;
|
||||
}
|
||||
|
||||
NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
|
||||
@@ -797,6 +881,31 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*sig);
|
||||
|
||||
// Handle the special case of a bi-directional part
|
||||
// select. Create a NetTran(VP) instead of a uni-directional
|
||||
// NetPartSelect node.
|
||||
if (dir == NetNet::PINOUT) {
|
||||
unsigned wida = sig->vector_width();
|
||||
unsigned widb = tmp->vector_width();
|
||||
bool part_b = widb < wida;
|
||||
NetTran*node = new NetTran(scope, scope->local_symbol(),
|
||||
part_b? wida : widb,
|
||||
part_b? widb : wida,
|
||||
0);
|
||||
if (part_b) {
|
||||
connect(node->pin(0), sig->pin(0));
|
||||
connect(node->pin(1), tmp->pin(0));
|
||||
} else {
|
||||
connect(node->pin(0), tmp->pin(0));
|
||||
connect(node->pin(1), sig->pin(0));
|
||||
}
|
||||
|
||||
node->set_line(*this);
|
||||
des->add_node(node);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetPartSelect*node = 0;
|
||||
|
||||
switch (dir) {
|
||||
@@ -825,15 +934,7 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
|
||||
break;
|
||||
|
||||
case NetNet::PINOUT:
|
||||
if (sig->vector_width() > tmp->vector_width()) {
|
||||
node = new NetPartSelect(sig, 0, tmp->vector_width(),
|
||||
NetPartSelect::BI);
|
||||
connect(node->pin(0), tmp->pin(0));
|
||||
} else {
|
||||
node = new NetPartSelect(tmp, 0, sig->vector_width(),
|
||||
NetPartSelect::BI);
|
||||
connect(node->pin(0), sig->pin(0));
|
||||
}
|
||||
ivl_assert(*this, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1014,7 +1115,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
unsigned prts_vector_width = 0;
|
||||
|
||||
for (unsigned inst = 0 ; inst < instance.count() ; inst += 1) {
|
||||
NetScope*inst_scope = instance[inst];
|
||||
// Scan the instances from MSB to LSB. The port
|
||||
// will be assembled in that order as well.
|
||||
NetScope*inst_scope = instance[instance.count()-inst-1];
|
||||
|
||||
// Scan the module sub-ports for this instance...
|
||||
for (unsigned ldx = 0 ; ldx < mport.count() ; ldx += 1) {
|
||||
@@ -1115,7 +1218,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
assignment, as the port will continuous assign
|
||||
into the port. */
|
||||
|
||||
sig = pins[idx]->elaborate_lnet(des, scope, true);
|
||||
sig = pins[idx]->elaborate_lnet(des, scope);
|
||||
if (sig == 0) {
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "Output port expression must support "
|
||||
@@ -1450,7 +1553,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||
<< endl;
|
||||
|
||||
} else {
|
||||
NetNet*sig = pins[0]->elaborate_lnet(des, scope, true);
|
||||
NetNet*sig = pins[0]->elaborate_lnet(des, scope);
|
||||
if (sig == 0) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Output port expression is not valid." << endl;
|
||||
@@ -1492,6 +1595,10 @@ bool PGModule::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (mod != pform_modules.end())
|
||||
return elaborate_sig_mod_(des, scope, (*mod).second);
|
||||
|
||||
map<perm_string,PUdp*>::const_iterator udp = pform_primitives.find(type_);
|
||||
if (udp != pform_primitives.end())
|
||||
return elaborate_sig_udp_(des, scope, (*udp).second);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1690,7 +1797,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
netlist. The compound statement is exactly equivalent. */
|
||||
|
||||
if (delay || event_) {
|
||||
unsigned wid = lv->lwidth();
|
||||
unsigned wid = count_lval_width(lv);
|
||||
|
||||
rv->set_width(wid);
|
||||
rv = pad_to_width(rv, wid);
|
||||
@@ -1840,18 +1947,19 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
: NetBlock::SEQU;
|
||||
|
||||
NetScope*nscope = 0;
|
||||
if (name_.str() != 0) {
|
||||
nscope = scope->child(hname_t(name_));
|
||||
if (pscope_name() != 0) {
|
||||
nscope = scope->child(hname_t(pscope_name()));
|
||||
if (nscope == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
"unable to find block scope " << scope_path(scope)
|
||||
<< "<" << name_ << ">" << endl;
|
||||
<< "<" << pscope_name() << ">" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(nscope);
|
||||
|
||||
elaborate_behaviors_(des, nscope);
|
||||
}
|
||||
|
||||
NetBlock*cur = new NetBlock(type, nscope);
|
||||
@@ -1863,7 +1971,7 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
// statement. There is no need to keep the block node. Also,
|
||||
// don't elide named blocks, because they might be referenced
|
||||
// elsewhere.
|
||||
if ((list_.count() == 1) && (name_.str() == 0)) {
|
||||
if ((list_.count() == 1) && (pscope_name() == 0)) {
|
||||
assert(list_[0]);
|
||||
NetProc*tmp = list_[0]->elaborate(des, nscope);
|
||||
return tmp;
|
||||
@@ -2023,14 +2131,8 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (expr->expr_width() > 1) {
|
||||
assert(expr->expr_width() > 1);
|
||||
verinum zero (verinum::V0, expr->expr_width());
|
||||
NetEConst*ezero = new NetEConst(zero);
|
||||
ezero->set_width(expr->expr_width());
|
||||
NetEBComp*cmp = new NetEBComp('n', expr, ezero);
|
||||
expr = cmp;
|
||||
}
|
||||
// Make sure the condition expression evaluates to a condition.
|
||||
expr = condition_reduce(expr);
|
||||
|
||||
// Well, I actually need to generate code to handle the
|
||||
// conditional, so elaborate.
|
||||
@@ -2097,12 +2199,7 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
||||
/* Attempt to pre-evaluate the parameters. It may be
|
||||
possible to at least partially reduce the
|
||||
expression. */
|
||||
if (eparms[idx]) {
|
||||
if (NetExpr*tmp = eparms[idx]->eval_tree()) {
|
||||
delete eparms[idx];
|
||||
eparms[idx] = tmp;
|
||||
}
|
||||
}
|
||||
if (eparms[idx]) eval_expr(eparms[idx]);
|
||||
}
|
||||
|
||||
NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms);
|
||||
@@ -2699,10 +2796,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
/* precalculate as much as possible of the wait expression. */
|
||||
if (NetExpr*tmp = expr->eval_tree()) {
|
||||
delete expr;
|
||||
expr = tmp;
|
||||
}
|
||||
eval_expr(expr);
|
||||
|
||||
/* Detect the unusual case that the wait expression is
|
||||
constant. Constant true is OK (it becomes transparent) but
|
||||
@@ -2745,11 +2839,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
|
||||
wait. */
|
||||
assert(expr->expr_width() == 1);
|
||||
expr = new NetEBComp('N', expr, new NetEConst(verinum(verinum::V1)));
|
||||
NetExpr*tmp = expr->eval_tree();
|
||||
if (tmp) {
|
||||
delete expr;
|
||||
expr = tmp;
|
||||
}
|
||||
eval_expr(expr);
|
||||
|
||||
NetEvent*wait_event = new NetEvent(scope->local_symbol());
|
||||
scope->add_event(wait_event);
|
||||
@@ -2836,14 +2926,14 @@ NetProc* PForever::elaborate(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
/*
|
||||
* Force is like a procedural assignment, most notably prodedural
|
||||
* Force is like a procedural assignment, most notably procedural
|
||||
* continuous assignment:
|
||||
*
|
||||
* force <lval> = <rval>
|
||||
*
|
||||
* The <lval> can be anything that a normal behavioral assignment can
|
||||
* take, plus net signals. This is a little bit more lax then the
|
||||
* other proceedural assignments.
|
||||
* other procedural assignments.
|
||||
*/
|
||||
NetForce* PForce::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
@@ -2908,7 +2998,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
NetNet*sig = des->find_signal(scope, id1->path());
|
||||
if (sig == 0) {
|
||||
cerr << id1->get_fileline() << ": register ``" << id1->path()
|
||||
<< "'' unknown in this context." << endl;
|
||||
<< "'' unknown in " << scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -2933,6 +3023,15 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
assert(etmp->expr_width() >= lv->lwidth());
|
||||
}
|
||||
|
||||
/* Based on the specific type of the l-value, do cleanup
|
||||
processing on the r-value. */
|
||||
if (etmp->expr_type() != IVL_VT_REAL) {
|
||||
unsigned wid = count_lval_width(lv);
|
||||
etmp->set_width(wid);
|
||||
etmp = pad_to_width(etmp, wid);
|
||||
assert(etmp->expr_width() >= wid);
|
||||
}
|
||||
|
||||
NetAssign*init = new NetAssign(lv, etmp);
|
||||
init->set_line(*this);
|
||||
|
||||
@@ -3024,6 +3123,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "No function definition for function "
|
||||
<< scope_path(scope) << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3121,6 +3221,11 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
void PTask::elaborate(Design*des, NetScope*task) const
|
||||
{
|
||||
// Elaborate any processes that are part of this scope that
|
||||
// aren't the definition itself. This can happen, for example,
|
||||
// with variable initialization statements in this scope.
|
||||
elaborate_behaviors_(des, task);
|
||||
|
||||
NetTaskDef*def = task->task_def();
|
||||
assert(def);
|
||||
|
||||
@@ -3252,6 +3357,29 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const
|
||||
verinum(1));
|
||||
} while (0);
|
||||
|
||||
/* If this is an always block and we have no or zero delay then
|
||||
* a runtime infinite loop will happen. If we possible have some
|
||||
* delay then print a warning that an infinite loop is possible.
|
||||
*/
|
||||
if (type() == PProcess::PR_ALWAYS) {
|
||||
DelayType dly_type = top->statement()->delay_type();
|
||||
|
||||
if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) {
|
||||
cerr << get_fileline() << ": error: always statement"
|
||||
<< " does not have any delay." << endl;
|
||||
cerr << get_fileline() << ": : A runtime infinite"
|
||||
<< " loop will occur." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
|
||||
} else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) {
|
||||
cerr << get_fileline() << ": warning: always statement"
|
||||
<< " may not have any delay." << endl;
|
||||
cerr << get_fileline() << ": : A runtime infinite"
|
||||
<< " loop may be possible." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3265,16 +3393,6 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
if (!gn_specify_blocks_flag)
|
||||
return;
|
||||
|
||||
/* Check for various path types that are not supported. */
|
||||
if (conditional && !condition) {
|
||||
cerr << get_fileline() << ": sorry: ifnone specify paths"
|
||||
<< " are not supported." << endl;
|
||||
cerr << get_fileline() << ": : Use -g no-specify to ignore"
|
||||
<< " specify blocks." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
ivl_assert(*this, conditional || (condition==0));
|
||||
|
||||
ndelays = delays.size();
|
||||
@@ -3306,7 +3424,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
delete cur;
|
||||
}
|
||||
|
||||
switch (ndelays) {
|
||||
switch (delays.size()) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
@@ -3315,15 +3433,14 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
break;
|
||||
default:
|
||||
cerr << get_fileline() << ": error: Incorrect delay configuration."
|
||||
<< endl;
|
||||
<< " Given " << delays.size() << " delay expressions." << endl;
|
||||
ndelays = 1;
|
||||
des->errors += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
NetNet*condit_sig = 0;
|
||||
if (conditional) {
|
||||
ivl_assert(*this, condition);
|
||||
if (conditional && condition) {
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, condition, -1);
|
||||
ivl_assert(*condition, tmp);
|
||||
@@ -3344,7 +3461,9 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
cerr << get_fileline() << ": debug: Path to " << (*cur);
|
||||
if (condit_sig)
|
||||
cerr << " if " << condit_sig->name();
|
||||
cerr << endl;
|
||||
else if (conditional)
|
||||
cerr << " ifnone";
|
||||
cerr << " from ";
|
||||
}
|
||||
|
||||
NetNet*dst_sig = scope->find_signal(*cur);
|
||||
@@ -3364,7 +3483,8 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
NetDelaySrc*path = new NetDelaySrc(scope, scope->local_symbol(),
|
||||
src.size(), condit_sig);
|
||||
src.size(), condit_sig,
|
||||
conditional);
|
||||
path->set_line(*this);
|
||||
|
||||
// The presence of the data_source_expression indicates
|
||||
@@ -3407,6 +3527,11 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
NetNet*src_sig = scope->find_signal(*cur_src);
|
||||
assert(src_sig);
|
||||
|
||||
if (debug_elaborate) {
|
||||
if (cur_src != src.begin()) cerr << " and ";
|
||||
cerr << src_sig->name();
|
||||
}
|
||||
|
||||
if ( (src_sig->port_type() != NetNet::PINPUT)
|
||||
&& (src_sig->port_type() != NetNet::PINOUT) ) {
|
||||
|
||||
@@ -3419,6 +3544,9 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
connect(src_sig->pin(0), path->pin(idx));
|
||||
idx += 1;
|
||||
}
|
||||
if (debug_elaborate) {
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
if (condit_sig)
|
||||
connect(condit_sig->pin(0), path->pin(idx));
|
||||
@@ -3525,13 +3653,7 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||
// Elaborate the behaviors, making processes out of them. This
|
||||
// involves scanning the PProcess* list, creating a NetProcTop
|
||||
// for each process.
|
||||
const list<PProcess*>&sl = get_behaviors();
|
||||
|
||||
for (list<PProcess*>::const_iterator st = sl.begin()
|
||||
; st != sl.end() ; st ++ ) {
|
||||
|
||||
result_flag &= (*st)->elaborate(des, scope);
|
||||
}
|
||||
result_flag &= elaborate_behaviors_(des, scope);
|
||||
|
||||
// Elaborate the specify paths of the module.
|
||||
|
||||
@@ -3548,6 +3670,27 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
// Handle the special case that this is a CASE scheme. In this
|
||||
// case the PGenerate itself does not have the generated
|
||||
// item. Look instead for the case ITEM that has a scope
|
||||
// generated for it.
|
||||
if (scheme_type == PGenerate::GS_CASE) {
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: generate case"
|
||||
<< " elaborating in scope "
|
||||
<< scope_path(container) << "." << endl;
|
||||
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generates.begin()
|
||||
; cur != generates.end() ; cur ++) {
|
||||
PGenerate*item = *cur;
|
||||
if (! item->scope_list_.empty()) {
|
||||
flag &= item->elaborate(des, container);
|
||||
}
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
typedef list<NetScope*>::const_iterator scope_list_it_t;
|
||||
for (scope_list_it_t cur = scope_list_.begin()
|
||||
; cur != scope_list_.end() ; cur ++ ) {
|
||||
@@ -3598,6 +3741,22 @@ bool PGenerate::elaborate_(Design*des, NetScope*scope) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PScope::elaborate_behaviors_(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool result_flag = true;
|
||||
|
||||
// Elaborate the behaviors, making processes out of them. This
|
||||
// involves scanning the PProcess* list, creating a NetProcTop
|
||||
// for each process.
|
||||
for (list<PProcess*>::const_iterator st = behaviors.begin()
|
||||
; st != behaviors.end() ; st ++ ) {
|
||||
|
||||
result_flag &= (*st)->elaborate(des, scope);
|
||||
}
|
||||
|
||||
return result_flag;
|
||||
}
|
||||
|
||||
struct root_elem {
|
||||
Module *mod;
|
||||
NetScope *scope;
|
||||
@@ -3634,6 +3793,7 @@ Design* elaborate(list<perm_string>roots)
|
||||
|
||||
// Make the root scope.
|
||||
NetScope*scope = des->make_root_scope(*root);
|
||||
scope->set_line(rmod);
|
||||
scope->time_unit(rmod->time_unit);
|
||||
scope->time_precision(rmod->time_precision);
|
||||
scope->default_nettype(rmod->default_nettype);
|
||||
@@ -3703,4 +3863,3 @@ Design* elaborate(list<perm_string>roots)
|
||||
|
||||
return des;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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
|
||||
@@ -49,6 +49,12 @@ bool NetUDP::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAbs::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_abs(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAddSub::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_add_sub(this);
|
||||
@@ -128,6 +134,12 @@ bool NetPartSelect::emit_node(struct target_t*tgt) const
|
||||
return tgt->part_select(this);
|
||||
}
|
||||
|
||||
bool NetPow::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_pow(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetReplicate::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->replicate(this);
|
||||
@@ -153,6 +165,11 @@ bool NetUserFunc::emit_node(struct target_t*tgt) const
|
||||
return tgt->net_function(this);
|
||||
}
|
||||
|
||||
bool NetTran::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->tran(this);
|
||||
}
|
||||
|
||||
bool NetBUFZ::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->bufz(this);
|
||||
@@ -372,7 +389,9 @@ bool NetScope::emit_defs(struct target_t*tgt) const
|
||||
case TASK:
|
||||
tgt->task_def(this);
|
||||
break;
|
||||
default: /* BEGIN_END and FORK_JOIN, do nothing */
|
||||
default: /* BEGIN_END and FORK_JOIN, GENERATE... */
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
|
||||
flag &= cur->emit_defs(tgt);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+291
-369
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -26,7 +26,7 @@
|
||||
* iverilog -tpal -ppart=generic-22v10-plcc -opal_reg.jed pal_reg.v
|
||||
*
|
||||
* The output file name (passed through the -o<file> switch) can be
|
||||
* any file you desire. If the compilation and fittin all succeed, the
|
||||
* any file you desire. If the compilation and fitting all succeed, the
|
||||
* output file will be a JEDEC file that you can take to your favorite
|
||||
* PROM programmer to program the part.
|
||||
*
|
||||
@@ -45,7 +45,7 @@
|
||||
*
|
||||
* The output drivers are controlled by a single active low output
|
||||
* enable. I used bufif0 devices in this example, but the exact same
|
||||
* thing can be achived with a continuous assignment like so:
|
||||
* thing can be achieved with a continuous assignment like so:
|
||||
*
|
||||
* assign out = oe? 8'hzz : Q;
|
||||
*
|
||||
@@ -76,7 +76,7 @@ endmodule
|
||||
* a PLCC package.
|
||||
*
|
||||
* Note that this module has no logic in it. It is a convention I use
|
||||
* that I put all the functionality in a seperate module (seen above)
|
||||
* that I put all the functionality in a separate module (seen above)
|
||||
* and isolate the Icarus Verilog specific $attribute madness into a
|
||||
* top-level module. The advantage of this style is that the entire
|
||||
* module can be `ifdef'ed out when doing simulation and you don't
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
*
|
||||
* 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
|
||||
* scanning a scope, and the remaining parameters 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.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module is a synthesizeable square-root function. It is also a
|
||||
* This module is a synthesizable square-root function. It is also a
|
||||
* detailed example of how to target Xilinx Virtex parts using
|
||||
* Icarus Verilog. In fact, for no particular reason other than to
|
||||
* be excessively specific, I will step through the process of
|
||||
@@ -30,7 +30,7 @@
|
||||
* In addition to Icarus Verilog, you will need implementation
|
||||
* software from Xilinx. As of this writing, this example was tested
|
||||
* with Foundation 4.2i, but it should work the same with ISE and
|
||||
* Webpack software.
|
||||
* WebPACK software.
|
||||
*
|
||||
* This example source contains all the Verilog needed to do
|
||||
* everything described below. We use conditional compilation to
|
||||
@@ -55,7 +55,7 @@
|
||||
* "PASSED" and finishes the simulation.
|
||||
*
|
||||
* When you take a close look at the "main" module below, you will see
|
||||
* that it uses Verilog constructs that are not synthesizeable. This
|
||||
* that it uses Verilog constructs that are not synthesizable. This
|
||||
* is fine, as we will never try to synthesize it.
|
||||
*
|
||||
* LIBRARY PARTS
|
||||
@@ -78,7 +78,7 @@
|
||||
* Without any preprocessor directives, the only module is the sqrt32
|
||||
* module, so sqrt32 is compiled as the root. The ports of the module
|
||||
* are automatically made into ports of the sqrt32.edf netlist, and
|
||||
* the contents of the sqrt32 module are connected approprately.
|
||||
* the contents of the sqrt32 module are connected appropriately.
|
||||
*
|
||||
* COMPLETE CHIP DESIGNS
|
||||
*
|
||||
|
||||
+303
-69
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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,6 +18,7 @@
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
@@ -25,6 +26,57 @@
|
||||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
|
||||
{
|
||||
NetNet* sig;
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
verireal vrl(tmp->value().as_double());
|
||||
NetECReal rlval(vrl);
|
||||
sig = rlval.synthesize(des);
|
||||
} else {
|
||||
cerr << obj->get_fileline() << ": sorry: Cannot convert "
|
||||
"bit based value (" << *expr << ") to real." << endl;
|
||||
des->errors += 1;
|
||||
sig = 0;
|
||||
}
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/* Note that lsig, rsig and real_args are references. */
|
||||
bool process_binary_args(Design*des, NetExpr*left, NetExpr*right,
|
||||
NetNet*&lsig, NetNet*&rsig, bool&real_args,
|
||||
NetExpr*obj)
|
||||
{
|
||||
if (left->expr_type() == IVL_VT_REAL ||
|
||||
right->expr_type() == IVL_VT_REAL) {
|
||||
real_args = true;
|
||||
|
||||
/* Currently we will have a runtime assert if both expressions
|
||||
are not real, though we can convert constants. */
|
||||
if (left->expr_type() == IVL_VT_REAL) {
|
||||
lsig = left->synthesize(des);
|
||||
} else {
|
||||
lsig = convert_to_real_const(des, left, obj);
|
||||
}
|
||||
|
||||
if (right->expr_type() == IVL_VT_REAL) {
|
||||
rsig = right->synthesize(des);
|
||||
} else {
|
||||
rsig = convert_to_real_const(des, right, obj);
|
||||
}
|
||||
} else {
|
||||
real_args = false;
|
||||
lsig = left->synthesize(des);
|
||||
rsig = right->synthesize(des);
|
||||
|
||||
}
|
||||
|
||||
if (lsig == 0 || rsig == 0) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: cannot synthesize expression: "
|
||||
@@ -40,8 +92,12 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
{
|
||||
assert((op()=='+') || (op()=='-'));
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(expr_width() >= lsig->vector_width());
|
||||
assert(expr_width() >= rsig->vector_width());
|
||||
@@ -87,45 +143,53 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
if (lsig->vector_width() != rsig->vector_width()) {
|
||||
cerr << get_fileline() << ": internal error: bitwise (" << op_
|
||||
<< ") widths do not match: " << lsig->vector_width()
|
||||
<< " != " << rsig->vector_width() << endl;
|
||||
cerr << get_fileline() << ": : width="
|
||||
<< lsig->vector_width() << ": " << *left_ << endl;
|
||||
cerr << get_fileline() << ": : width="
|
||||
<< rsig->vector_width() << ": " << *right_ << endl;
|
||||
/* You cannot do bitwise operations on real values. */
|
||||
if (lsig->data_type() == IVL_VT_REAL ||
|
||||
rsig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: " << human_readable_op(op_)
|
||||
<< " operator may not have REAL operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width) width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
assert(lsig->vector_width() == rsig->vector_width());
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, lsig->vector_width());
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(expr_type());
|
||||
|
||||
perm_string oname = scope->local_symbol();
|
||||
unsigned wid = lsig->vector_width();
|
||||
NetLogic*gate;
|
||||
|
||||
switch (op()) {
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND, wid);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND, width);
|
||||
break;
|
||||
case 'A':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NAND, width);
|
||||
break;
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::OR, wid);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::OR, width);
|
||||
break;
|
||||
case '^':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XOR, wid);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XOR, width);
|
||||
break;
|
||||
case 'O':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NOR, wid);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::NOR, width);
|
||||
break;
|
||||
case 'X':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, wid);
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, width);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -144,28 +208,38 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
NetNet* NetEBComp::synthesize(Design*des)
|
||||
{
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (real_args) {
|
||||
width = 1;
|
||||
} else {
|
||||
width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width) width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
unsigned width = lsig->vector_width();
|
||||
if (rsig->vector_width() > width)
|
||||
width = rsig->vector_width();
|
||||
|
||||
lsig = pad_to_width(des, lsig, width);
|
||||
rsig = pad_to_width(des, rsig, width);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
|
||||
bool signed_compare = lsig->get_signed() && rsig->get_signed();
|
||||
|
||||
/* Handle the special case of a single bit equality
|
||||
operation. Make an XNOR gate instead of a comparator. */
|
||||
if ((width == 1) && ((op_ == 'e') || (op_ == 'E'))) {
|
||||
if ((width == 1) && ((op_ == 'e') || (op_ == 'E')) && !real_args) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XNOR, 1);
|
||||
gate->set_line(*this);
|
||||
@@ -179,7 +253,7 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
/* Handle the special case of a single bit inequality
|
||||
operation. This is similar to single bit equality, but uses
|
||||
an XOR instead of an XNOR gate. */
|
||||
if ((width == 1) && ((op_ == 'n') || (op_ == 'N'))) {
|
||||
if ((width == 1) && ((op_ == 'n') || (op_ == 'N')) && !real_args) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
|
||||
3, NetLogic::XOR, 1);
|
||||
gate->set_line(*this);
|
||||
@@ -202,22 +276,38 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
switch (op_) {
|
||||
case '<':
|
||||
connect(dev->pin_ALB(), osig->pin(0));
|
||||
dev->set_signed(signed_compare);
|
||||
break;
|
||||
case '>':
|
||||
connect(dev->pin_AGB(), osig->pin(0));
|
||||
dev->set_signed(signed_compare);
|
||||
break;
|
||||
case 'e': // ==
|
||||
case 'E': // === ?
|
||||
if (real_args) {
|
||||
cerr << get_fileline() << ": error: Case equality may "
|
||||
"not have real operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
case 'e': // ==
|
||||
connect(dev->pin_AEB(), osig->pin(0));
|
||||
break;
|
||||
case 'G': // >=
|
||||
connect(dev->pin_AGEB(), osig->pin(0));
|
||||
dev->set_signed(signed_compare);
|
||||
break;
|
||||
case 'L': // <=
|
||||
connect(dev->pin_ALEB(), osig->pin(0));
|
||||
dev->set_signed(signed_compare);
|
||||
break;
|
||||
case 'n': // !=
|
||||
case 'N': // !==
|
||||
if (real_args) {
|
||||
cerr << get_fileline() << ": error: Case inequality may "
|
||||
"not have real operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
case 'n': // !=
|
||||
connect(dev->pin_ANEB(), osig->pin(0));
|
||||
break;
|
||||
|
||||
@@ -233,28 +323,60 @@ NetNet* NetEBComp::synthesize(Design*des)
|
||||
|
||||
NetNet* NetEBPow::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_fileline() << ": internal error: Do not yet know how to handle"
|
||||
<< " power operator in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetPow*powr = new NetPow(scope, scope->local_symbol(), width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
des->add_node(powr);
|
||||
|
||||
powr->set_signed( has_sign() );
|
||||
powr->set_line(*this);
|
||||
|
||||
connect(powr->pin_DataA(), lsig->pin(0));
|
||||
connect(powr->pin_DataB(), rsig->pin(0));
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->set_line(*this);
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
connect(powr->pin_Result(), osig->pin(0));
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEBMult::synthesize(Design*des)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (lsig == 0)
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rsig == 0)
|
||||
return 0;
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
|
||||
NetMult*mult = new NetMult(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
des->add_node(mult);
|
||||
@@ -266,8 +388,7 @@ NetNet* NetEBMult::synthesize(Design*des)
|
||||
connect(mult->pin_DataB(), rsig->pin(0));
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
osig->data_type(lsig->data_type());
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->set_line(*this);
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
@@ -279,13 +400,21 @@ NetNet* NetEBMult::synthesize(Design*des)
|
||||
|
||||
NetNet* NetEBDiv::synthesize(Design*des)
|
||||
{
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
NetNet *lsig=0, *rsig=0;
|
||||
unsigned width;
|
||||
bool real_args=false;
|
||||
if (process_binary_args(des, left_, right_, lsig, rsig,
|
||||
real_args, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (real_args) width = 1;
|
||||
else width = expr_width();
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
NetNet::IMPLICIT, width);
|
||||
osig->set_line(*this);
|
||||
osig->data_type(lsig->data_type());
|
||||
osig->local_flag(true);
|
||||
@@ -294,7 +423,7 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
|
||||
case '/': {
|
||||
NetDivide*div = new NetDivide(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
@@ -307,8 +436,16 @@ NetNet* NetEBDiv::synthesize(Design*des)
|
||||
}
|
||||
|
||||
case '%': {
|
||||
/* Baseline Verilog does not support the % operator with
|
||||
real arguments, but we allow it in our extended form. */
|
||||
if (real_args && !gn_icarus_misc_flag) {
|
||||
cerr << get_fileline() << ": error: Modulus operator "
|
||||
"may not have REAL operands." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
NetModulo*div = new NetModulo(scope, scope->local_symbol(),
|
||||
expr_width(),
|
||||
width,
|
||||
lsig->vector_width(),
|
||||
rsig->vector_width());
|
||||
div->set_line(*this);
|
||||
@@ -339,11 +476,16 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
|
||||
if (lsig == 0)
|
||||
return 0;
|
||||
if (lsig == 0 || rsig == 0) return 0;
|
||||
|
||||
if (rsig == 0)
|
||||
/* You cannot currently do logical operations on real values. */
|
||||
if (lsig->data_type() == IVL_VT_REAL ||
|
||||
rsig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": sorry: " << human_readable_op(op_)
|
||||
<< " is currently unsupported for real values." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
@@ -411,17 +553,20 @@ NetNet* NetEBLogic::synthesize(Design*des)
|
||||
|
||||
NetNet* NetEBShift::synthesize(Design*des)
|
||||
{
|
||||
if (! dynamic_cast<NetEConst*>(right_)) {
|
||||
NetExpr*tmp = right_->eval_tree();
|
||||
if (tmp) {
|
||||
delete right_;
|
||||
right_ = tmp;
|
||||
}
|
||||
}
|
||||
eval_expr(right_);
|
||||
|
||||
NetNet*lsig = left_->synthesize(des);
|
||||
if (lsig == 0)
|
||||
|
||||
if (lsig == 0) return 0;
|
||||
|
||||
/* Cannot shift a real values. */
|
||||
if (lsig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: shift operator ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") cannot shift a real values." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool right_flag = op_ == 'r' || op_ == 'R';
|
||||
bool signed_flag = op_ == 'R';
|
||||
@@ -508,8 +653,8 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
}
|
||||
|
||||
NetNet*rsig = right_->synthesize(des);
|
||||
if (rsig == 0)
|
||||
return 0;
|
||||
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
@@ -627,6 +772,16 @@ NetNet* NetEUBits::synthesize(Design*des)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
if (isig == 0) return 0;
|
||||
|
||||
if (isig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: bit-wise negation ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") may not have a REAL operand." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
@@ -659,6 +814,16 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
{
|
||||
NetNet*isig = expr_->synthesize(des);
|
||||
|
||||
if (isig == 0) return 0;
|
||||
|
||||
if (isig->data_type() == IVL_VT_REAL) {
|
||||
cerr << get_fileline() << ": error: reduction operator ("
|
||||
<< human_readable_op(op_)
|
||||
<< ") may not have a REAL operand." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope*scope = isig->scope();
|
||||
assert(scope);
|
||||
|
||||
@@ -710,8 +875,8 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
{
|
||||
|
||||
NetNet*sub = expr_->synthesize(des);
|
||||
if (sub == 0)
|
||||
return 0;
|
||||
|
||||
if (sub == 0) return 0;
|
||||
|
||||
NetScope*scope = sub->scope();
|
||||
|
||||
@@ -764,6 +929,7 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
|
||||
connect(pad->pin(1), sub->pin(0));
|
||||
connect(pad->pin(0), net->pin(0));
|
||||
net->set_signed(true);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -803,9 +969,27 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
*/
|
||||
NetNet* NetETernary::synthesize(Design *des)
|
||||
{
|
||||
NetNet*csig = cond_->synthesize(des);
|
||||
NetNet*tsig = true_val_->synthesize(des);
|
||||
NetNet*fsig = false_val_->synthesize(des);
|
||||
NetNet*csig = cond_->synthesize(des),
|
||||
*tsig = true_val_->synthesize(des),
|
||||
*fsig = false_val_->synthesize(des);
|
||||
|
||||
if (csig == 0 || tsig == 0 || fsig == 0) return 0;
|
||||
|
||||
if (tsig->data_type() != fsig->data_type()) {
|
||||
cerr << get_fileline() << ": error: True and False clauses of "
|
||||
"ternary expression have different types." << endl;
|
||||
cerr << get_fileline() << ": : True clause is: "
|
||||
<< tsig->data_type() << endl;
|
||||
cerr << get_fileline() << ": : False clause is: "
|
||||
<< fsig->data_type() << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {
|
||||
cerr << get_fileline() << ": internal error: True and False "
|
||||
"clauses of ternary both have NO TYPE." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
perm_string path = csig->scope()->local_symbol();
|
||||
|
||||
@@ -876,3 +1060,53 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetNet* NetESFunc::synthesize(Design*des)
|
||||
{
|
||||
cerr << get_fileline() << ": sorry: cannot synthesize system function: "
|
||||
<< *this << " in this context" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* NetEUFunc::synthesize(Design*des)
|
||||
{
|
||||
svector<NetNet*> eparms (parms_.count());
|
||||
|
||||
/* Synthesize the arguments. */
|
||||
bool errors = false;
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
NetNet*tmp = parms_[idx]->synthesize(des);
|
||||
if (tmp == 0) {
|
||||
cerr << get_fileline() << ": error: Unable to synthesize "
|
||||
"port " << idx << " of call to "
|
||||
<< func_->basename() << "." << endl;
|
||||
errors = true;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
eparms[idx] = tmp;
|
||||
}
|
||||
if (errors) return 0;
|
||||
|
||||
NetUserFunc*net = new NetUserFunc(scope_, scope_->local_symbol(), func_);
|
||||
net->set_line(*this);
|
||||
des->add_node(net);
|
||||
|
||||
/* Create an output signal and connect it to the function. */
|
||||
NetNet*osig = new NetNet(scope_, scope_->local_symbol(), NetNet::WIRE,
|
||||
result_sig_->vector_width());
|
||||
osig->local_flag(true);
|
||||
osig->data_type(result_sig_->expr_type());
|
||||
connect(net->pin(0), osig->pin(0));
|
||||
|
||||
/* Connect the pins to the arguments. */
|
||||
NetFuncDef*def = func_->func_def();
|
||||
for (unsigned idx = 0; idx < eparms.count(); idx += 1) {
|
||||
NetNet*tmp = pad_to_width(des, eparms[idx],
|
||||
def->port(idx)->vector_width());
|
||||
connect(net->pin(idx+1), tmp->pin(0));
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ types as nets.
|
||||
|
||||
- Ports
|
||||
|
||||
Module and task ports in standard verilog are restricted to logic
|
||||
Module and task ports in standard Verilog are restricted to logic
|
||||
types. This extension removes that restriction, allowing any type to
|
||||
pass through the port consistent with the continuous assignment
|
||||
connectivity that is implied by the type.
|
||||
|
||||
+19
-58
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.cc,v 1.35 2005/07/07 16:22:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -43,6 +40,10 @@ void functor_t::process(class Design*, class NetProcTop*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_abs(class Design*, class NetAbs*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_add_sub(class Design*, class NetAddSub*)
|
||||
{
|
||||
}
|
||||
@@ -83,6 +84,10 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_pow(class Design*, class NetPow*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::sign_extend(class Design*, class NetSignExtend*)
|
||||
{
|
||||
}
|
||||
@@ -173,6 +178,11 @@ void NetNode::functor_node(Design*, functor_t*)
|
||||
{
|
||||
}
|
||||
|
||||
void NetAbs::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_abs(des, this);
|
||||
}
|
||||
|
||||
void NetAddSub::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_add_sub(des, this);
|
||||
@@ -223,6 +233,11 @@ void NetMux::functor_node(Design*des, functor_t*fun)
|
||||
fun->lpm_mux(des, this);
|
||||
}
|
||||
|
||||
void NetPow::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_pow(des, this);
|
||||
}
|
||||
|
||||
void NetSignExtend::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->sign_extend(des, this);
|
||||
@@ -291,57 +306,3 @@ int proc_match_t::event_wait(NetEvWait*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.35 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.34 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.33 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.32 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.31 2002/08/16 05:18:27 steve
|
||||
* Fix intermix of node functors and node delete.
|
||||
*
|
||||
* Revision 1.30 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.29 2002/08/10 22:07:38 steve
|
||||
* Remove useless error messages.
|
||||
*
|
||||
* Revision 1.28 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.27 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.26 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
* Revision 1.25 2001/07/25 03:10:49 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.24 2000/11/19 20:48:30 steve
|
||||
* Fix cases where signal iteration might die early.
|
||||
*
|
||||
* Revision 1.23 2000/11/18 04:53:04 steve
|
||||
* Watch out in functor, it may delete the last signal.
|
||||
*
|
||||
* Revision 1.22 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.21 2000/08/01 02:48:41 steve
|
||||
* Support <= in synthesis of DFF and ram devices.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __functor_H
|
||||
#define __functor_H
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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,9 +18,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.h,v 1.23 2005/07/07 16:22:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The functor is an object that can be applied to a design to
|
||||
@@ -51,6 +48,9 @@ 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 abs(). */
|
||||
virtual void lpm_abs(class Design*des, class NetAbs*);
|
||||
|
||||
/* This method is called for each structural adder. */
|
||||
virtual void lpm_add_sub(class Design*des, class NetAddSub*);
|
||||
|
||||
@@ -81,6 +81,9 @@ struct functor_t {
|
||||
/* This method is called for each MUX. */
|
||||
virtual void lpm_mux(class Design*des, class NetMux*);
|
||||
|
||||
/* This method is called for each power. */
|
||||
virtual void lpm_pow(class Design*des, class NetPow*);
|
||||
|
||||
/* This method is called for each unary reduction gate. */
|
||||
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
|
||||
|
||||
@@ -97,44 +100,4 @@ struct proc_match_t {
|
||||
virtual int block(class NetBlock*);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.23 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.22 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.21 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.19 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.18 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.17 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.16 2000/08/01 02:48:42 steve
|
||||
* Support <= in synthesis of DFF and ram devices.
|
||||
*
|
||||
* Revision 1.15 2000/07/16 04:56:07 steve
|
||||
* Handle some edge cases during node scans.
|
||||
*
|
||||
* Revision 1.14 2000/07/15 05:13:44 steve
|
||||
* Detect muxing Vz as a bufufN.
|
||||
*
|
||||
* Revision 1.13 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*/
|
||||
#endif
|
||||
|
||||
+2
-18
@@ -26,20 +26,9 @@ CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
|
||||
|
||||
# These are used for linking...
|
||||
LD=$CC
|
||||
LDFLAGS32="@SHARED@ -L@LIBDIR@"
|
||||
LDFLAGS64="@SHARED@ -L@LIBDIR64@"
|
||||
LDFLAGS="$LDFLAGS64"
|
||||
LDFLAGS="@SHARED@ -L@LIBDIR@"
|
||||
LDLIBS="-lveriuser -lvpi"
|
||||
|
||||
INSTDIR64="@VPIDIR1@"
|
||||
INSTDIR32="@VPIDIR2@"
|
||||
if test x$INSTDIR32 = x
|
||||
then
|
||||
INSTDIR32=$INSTDIR64
|
||||
fi
|
||||
|
||||
INSTDIR="$INSTDIR64"
|
||||
|
||||
CCSRC=
|
||||
CXSRC=
|
||||
OBJ=
|
||||
@@ -96,11 +85,6 @@ do
|
||||
-D*) DEFS="$DEFS $parm"
|
||||
;;
|
||||
|
||||
-m32) LDFLAGS="-m32 $LDFLAGS32"
|
||||
CFLAGS="-m32 $CFLAGS"
|
||||
INSTDIR="$INSTDIR32"
|
||||
;;
|
||||
|
||||
--cflags)
|
||||
echo "$CFLAGS"
|
||||
exit;
|
||||
@@ -117,7 +101,7 @@ do
|
||||
;;
|
||||
|
||||
--install-dir)
|
||||
echo "@LIBDIR@/ivl/$INSTDIR"
|
||||
echo "@LIBDIR@/ivl"
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -9,6 +9,7 @@ ivl_design_roots
|
||||
ivl_design_time_precision
|
||||
|
||||
ivl_const_bits
|
||||
ivl_const_delay
|
||||
ivl_const_real
|
||||
ivl_const_signed
|
||||
ivl_const_type
|
||||
@@ -52,6 +53,9 @@ ivl_file_table_index
|
||||
ivl_file_table_item
|
||||
ivl_file_table_size
|
||||
|
||||
ivl_island_flag_set
|
||||
ivl_island_flag_test
|
||||
|
||||
ivl_logic_attr
|
||||
ivl_logic_attr_cnt
|
||||
ivl_logic_attr_val
|
||||
@@ -77,6 +81,7 @@ ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
ivl_lpm_datab
|
||||
ivl_lpm_define
|
||||
ivl_lpm_delay
|
||||
ivl_lpm_enable
|
||||
ivl_lpm_file
|
||||
ivl_lpm_lineno
|
||||
@@ -113,12 +118,16 @@ ivl_nexus_ptr_pin
|
||||
ivl_nexus_ptr_lpm
|
||||
ivl_nexus_ptr_log
|
||||
ivl_nexus_ptr_sig
|
||||
ivl_nexus_ptr_switch
|
||||
|
||||
ivl_parameter_basename
|
||||
ivl_parameter_expr
|
||||
ivl_parameter_file
|
||||
ivl_parameter_lineno
|
||||
|
||||
ivl_path_condit
|
||||
ivl_path_delay
|
||||
ivl_path_is_condit
|
||||
ivl_path_scope
|
||||
ivl_path_source
|
||||
ivl_path_source_negedge
|
||||
@@ -129,8 +138,12 @@ ivl_scope_attr_val
|
||||
ivl_scope_basename
|
||||
ivl_scope_children
|
||||
ivl_scope_def
|
||||
ivl_scope_def_file
|
||||
ivl_scope_def_lineno
|
||||
ivl_scope_event
|
||||
ivl_scope_events
|
||||
ivl_scope_file
|
||||
ivl_scope_lineno
|
||||
ivl_scope_logs
|
||||
ivl_scope_log
|
||||
ivl_scope_lpms
|
||||
@@ -143,6 +156,8 @@ ivl_scope_port
|
||||
ivl_scope_ports
|
||||
ivl_scope_sigs
|
||||
ivl_scope_sig
|
||||
ivl_scope_switch
|
||||
ivl_scope_switches
|
||||
ivl_scope_time_precision
|
||||
ivl_scope_time_units
|
||||
ivl_scope_type
|
||||
@@ -156,7 +171,9 @@ ivl_signal_attr_val
|
||||
ivl_signal_basename
|
||||
ivl_signal_data_type
|
||||
ivl_signal_dimensions
|
||||
ivl_signal_file
|
||||
ivl_signal_integer
|
||||
ivl_signal_lineno
|
||||
ivl_signal_local
|
||||
ivl_signal_lsb
|
||||
ivl_signal_msb
|
||||
@@ -205,6 +222,19 @@ ivl_stmt_parm_count
|
||||
ivl_stmt_rval
|
||||
ivl_stmt_sub_stmt
|
||||
|
||||
ivl_switch_a
|
||||
ivl_switch_b
|
||||
ivl_switch_basename
|
||||
ivl_switch_enable
|
||||
ivl_switch_file
|
||||
ivl_switch_island
|
||||
ivl_switch_lineno
|
||||
ivl_switch_offset
|
||||
ivl_switch_part
|
||||
ivl_switch_scope
|
||||
ivl_switch_type
|
||||
ivl_switch_width
|
||||
|
||||
ivl_udp_init
|
||||
ivl_udp_name
|
||||
ivl_udp_nin
|
||||
|
||||
+149
-20
@@ -1,7 +1,7 @@
|
||||
#ifndef __ivl_target_H
|
||||
#define __ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2008 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,9 +18,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.182 2007/04/02 01:12:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <inttypes.h>
|
||||
|
||||
@@ -83,6 +80,13 @@ _BEGIN_DECL
|
||||
* processes. Structural expressions are instead treated as logic
|
||||
* gates.
|
||||
*
|
||||
* ivl_island_t
|
||||
* Certain types of objects may belong to islands. The island that
|
||||
* they belong to is represented by the ivl_island_t cookie. To
|
||||
* know if object belong to the same island, it is sufficient to
|
||||
* compare island cookies. If a==b, then island a is the same as
|
||||
* island b.
|
||||
*
|
||||
* ivl_lpm_t
|
||||
* This object is the base class for all the various LPM type
|
||||
* device nodes. This object carries a few base properties
|
||||
@@ -126,6 +130,9 @@ _BEGIN_DECL
|
||||
* ivl_process_t object holds one of these, but a statement may in
|
||||
* turn contain other statements.
|
||||
*
|
||||
* ivl_switch_t
|
||||
* Switches are the tran/tranif devices in the design.
|
||||
*
|
||||
* -- A Note About Bit Sets --
|
||||
* Some objects hold a value as an array of bits. In these cases there
|
||||
* is some method that retrieves the width of the value and another
|
||||
@@ -146,6 +153,7 @@ typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
||||
typedef struct ivl_design_s *ivl_design_t;
|
||||
typedef struct ivl_event_s *ivl_event_t;
|
||||
typedef struct ivl_expr_s *ivl_expr_t;
|
||||
typedef struct ivl_island_s *ivl_island_t;
|
||||
typedef struct ivl_lpm_s *ivl_lpm_t;
|
||||
typedef struct ivl_lval_s *ivl_lval_t;
|
||||
typedef struct ivl_net_const_s*ivl_net_const_t;
|
||||
@@ -158,6 +166,7 @@ typedef struct ivl_parameter_s*ivl_parameter_t;
|
||||
typedef struct ivl_process_s *ivl_process_t;
|
||||
typedef struct ivl_scope_s *ivl_scope_t;
|
||||
typedef struct ivl_signal_s *ivl_signal_t;
|
||||
typedef struct ivl_switch_s *ivl_switch_t;
|
||||
typedef struct ivl_memory_s *ivl_memory_t; /* DEPRECATED */
|
||||
typedef struct ivl_statement_s*ivl_statement_t;
|
||||
|
||||
@@ -229,8 +238,20 @@ typedef enum ivl_logic_e {
|
||||
IVL_LO_UDP = 21
|
||||
} ivl_logic_t;
|
||||
|
||||
/* This is the type of a ivl_switch_t object */
|
||||
typedef enum ivl_switch_type_e {
|
||||
IVL_SW_TRAN = 0,
|
||||
IVL_SW_TRANIF0 = 1,
|
||||
IVL_SW_TRANIF1 = 2,
|
||||
IVL_SW_RTRAN = 3,
|
||||
IVL_SW_RTRANIF0 = 4,
|
||||
IVL_SW_RTRANIF1 = 5,
|
||||
IVL_SW_TRAN_VP = 6
|
||||
} ivl_switch_type_t;
|
||||
|
||||
/* This is the type of an LPM object. */
|
||||
typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_ABS = 32,
|
||||
IVL_LPM_ADD = 0,
|
||||
IVL_LPM_ARRAY = 30,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
@@ -245,9 +266,10 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_MOD = 13,
|
||||
IVL_LPM_MULT = 4,
|
||||
IVL_LPM_MUX = 5,
|
||||
IVL_LPM_PART_BI= 28, /* part select: bi-directional (part on 0) */
|
||||
/* IVL_LPM_PART_BI= 28, / obsolete */
|
||||
IVL_LPM_PART_VP= 15, /* part select: vector to part */
|
||||
IVL_LPM_PART_PV= 17, /* part select: part written to vector */
|
||||
IVL_LPM_POW = 31,
|
||||
IVL_LPM_RE_AND = 20,
|
||||
IVL_LPM_RE_NAND= 21,
|
||||
IVL_LPM_RE_NOR = 22,
|
||||
@@ -382,7 +404,7 @@ typedef const struct ivl_attribute_s*ivl_attribute_t;
|
||||
|
||||
/* DELAYPATH
|
||||
* Delaypath objects represent delay paths called out by a specify
|
||||
* block in the verilog source file. The destination signal references
|
||||
* block in the Verilog source file. The destination signal references
|
||||
* the path object, which in turn points to the source for the path.
|
||||
*
|
||||
* ivl_path_scope
|
||||
@@ -397,8 +419,10 @@ typedef const struct ivl_attribute_s*ivl_attribute_t;
|
||||
* ivl_path_condit
|
||||
* This returns the nexus that tracks the condition for the
|
||||
* delay. If the delay path is unconditional, this returns nil.
|
||||
* ivl_path_is_condit
|
||||
* Is this a conditional structure? Needed for ifnone.
|
||||
*
|
||||
* ivl_path_srouce_posedge
|
||||
* ivl_path_source_posedge
|
||||
* ivl_path_source_negedge
|
||||
* These functions return true if the source is edge sensitive.
|
||||
*/
|
||||
@@ -406,6 +430,7 @@ extern ivl_scope_t ivl_path_scope(ivl_delaypath_t obj);
|
||||
extern ivl_nexus_t ivl_path_source(ivl_delaypath_t obj);
|
||||
extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t pt);
|
||||
extern ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj);
|
||||
extern int ivl_path_is_condit(ivl_delaypath_t obj);
|
||||
|
||||
extern int ivl_path_source_posedge(ivl_delaypath_t obj);
|
||||
extern int ivl_path_source_negedge(ivl_delaypath_t obj);
|
||||
@@ -472,7 +497,7 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
|
||||
* The is the type of the node.
|
||||
*
|
||||
* ivl_const_bits
|
||||
* This returns a pointer to an array of conststant characters,
|
||||
* This returns a pointer to an array of constant characters,
|
||||
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
|
||||
* terminated.
|
||||
*
|
||||
@@ -485,6 +510,9 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
|
||||
* ivl_const_width
|
||||
* Return the width, in logical bits, of the constant.
|
||||
*
|
||||
* ivl_const_delay
|
||||
* T0 delay for a transition (0, 1 and Z).
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
*
|
||||
* The const_type of the literal constant must match the
|
||||
@@ -500,6 +528,7 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
|
||||
*/
|
||||
extern ivl_variable_type_t ivl_const_type(ivl_net_const_t net);
|
||||
extern const char* ivl_const_bits(ivl_net_const_t net);
|
||||
extern ivl_expr_t ivl_const_delay(ivl_net_const_t net, unsigned transition);
|
||||
extern ivl_nexus_t ivl_const_nex(ivl_net_const_t net);
|
||||
extern int ivl_const_signed(ivl_net_const_t net);
|
||||
extern unsigned ivl_const_width(ivl_net_const_t net);
|
||||
@@ -693,6 +722,16 @@ extern unsigned ivl_file_table_index(const char *);
|
||||
extern unsigned ivl_file_table_size(void);
|
||||
|
||||
|
||||
/* ISLAND
|
||||
*
|
||||
* ivl_island_flag_set
|
||||
* ivl_island_flag_test
|
||||
* Allow the user to test or set a boolean flag associated with the
|
||||
* island.
|
||||
*/
|
||||
extern int ivl_island_flag_set(ivl_island_t net, unsigned flag, int value);
|
||||
extern int ivl_island_flag_test(ivl_island_t net, unsigned flag);
|
||||
|
||||
/* LOGIC
|
||||
* These types and functions support manipulation of logic gates. The
|
||||
* ivl_logic_t enumeration identifies the various kinds of gates that
|
||||
@@ -746,7 +785,7 @@ extern unsigned ivl_file_table_size(void);
|
||||
* SEMANTIC NOTES
|
||||
* The ivl_logic_width applies to all the pins of a logic device. If a
|
||||
* logic device has width, that means that it is actually an array of
|
||||
* logic devices tha each process a bit slice of the
|
||||
* logic devices that each process a bit slice of the
|
||||
* inputs/output. That implies that the widths of all the inputs and
|
||||
* the output must be identical.
|
||||
*
|
||||
@@ -870,6 +909,9 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* Return the name of the device. The name is the name of the
|
||||
* device with the scope part, and the basename is without the scope.
|
||||
*
|
||||
* ivl_lpm_delay
|
||||
* LPM devices have a delay for each transition (0, 1 and Z).
|
||||
*
|
||||
* ivl_lpm_scope
|
||||
* LPM devices exist within a scope. Return the scope that contains
|
||||
* this device.
|
||||
@@ -925,7 +967,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* The ivl_lpm_q nexus is the output from the concatenation.
|
||||
*
|
||||
* The ivl_lpm_data function returns the connections for the inputs to
|
||||
* the concatentation. The ivl_lpm_size function returns the number of
|
||||
* the concatenation. The ivl_lpm_size function returns the number of
|
||||
* inputs help by the device.
|
||||
*
|
||||
* - Divide (IVL_LPM_DIVIDE)
|
||||
@@ -947,6 +989,16 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* Multiply may be signed. If so, the output should be sign extended
|
||||
* to fill in its result.
|
||||
*
|
||||
* - Power (IVL_LPM_POW)
|
||||
* The power takes two inputs and generates an output. Unlike other
|
||||
* arithmetic nodes, the width only refers to the output. The inputs
|
||||
* have independent widths, to reflect the arithmetic truth that the
|
||||
* width of a general power is the XXXX of the widths of the
|
||||
* inputs.
|
||||
*
|
||||
* Power may be signed. If so, the output should be sign extended
|
||||
* to fill in its result.
|
||||
*
|
||||
* - Part Select (IVL_LPM_PART_VP and IVL_LPM_PART_PV)
|
||||
* There are two part select devices, one that extracts a part from a
|
||||
* vector, and another that writes a part of a vector. The _VP is
|
||||
@@ -999,7 +1051,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* The ivl_lpm_data() method returns the inputs of the MUX device. The
|
||||
* ivl_lpm_size() method returns the number of data inputs there
|
||||
* are. All the data inputs have the same width, the width of the
|
||||
* ivl_lpm_q output. The type of the device is devined from the
|
||||
* ivl_lpm_q output. The type of the device is divined from the
|
||||
* inputs and the Q. All the types must be exactly the same.
|
||||
*
|
||||
* - D-FlipFlop (IVL_LPM_FF)
|
||||
@@ -1052,7 +1104,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* output, but the distance has its own width.
|
||||
*
|
||||
* The ivl_lpm_signed() flag means for IVL_LPM_SHIFTR that the right
|
||||
* shift is *signed*. For SHIFTL, then signed-ness is emaningless.
|
||||
* shift is *signed*. For SHIFTL, then signed-ness is meaningless.
|
||||
*
|
||||
* - System function call (IVL_LPM_SFUNC)
|
||||
* This device represents a netlist call to a system function. The
|
||||
@@ -1073,8 +1125,8 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
* function are connected to the net, as is the output.
|
||||
*
|
||||
* The function definition is associated with a scope, and the
|
||||
* ivl_lpm_define fuction returns the scope that is that definition.
|
||||
* See the ivl_scope_* fuctions for how to get at the actual
|
||||
* ivl_lpm_define function returns the scope that is that definition.
|
||||
* See the ivl_scope_* functions for how to get at the actual
|
||||
* definition.
|
||||
*
|
||||
* As with many LPM nodes, the ivl_lpm_q function returns the nexus
|
||||
@@ -1089,6 +1141,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net);
|
||||
|
||||
extern const char* ivl_lpm_name(ivl_lpm_t net); /* (Obsolete) */
|
||||
extern const char* ivl_lpm_basename(ivl_lpm_t net);
|
||||
extern ivl_expr_t ivl_lpm_delay(ivl_lpm_t net, unsigned transition);
|
||||
extern ivl_scope_t ivl_lpm_scope(ivl_lpm_t net);
|
||||
extern int ivl_lpm_signed(ivl_lpm_t net);
|
||||
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
|
||||
@@ -1112,12 +1165,12 @@ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
|
||||
IVL_LPM_MUX IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
|
||||
IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX */
|
||||
@@ -1173,7 +1226,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
* SEMANTIC NOTES
|
||||
* The ivl_lval_width is not necessarily the same as the width of the
|
||||
* signal or memory word it represents. It is the width of the vector
|
||||
* it receives and assigns. This may be less then the width of the
|
||||
* it receives and assigns. This may be less than the width of the
|
||||
* signal (or even 1) if only a part of the l-value signal is to be
|
||||
* assigned.
|
||||
*
|
||||
@@ -1192,7 +1245,7 @@ extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
* an expression that calculates the address of the array word. If
|
||||
* the referenced signal has more than one word, this expression must
|
||||
* be present. If the signal has exactly one word (it is not an array)
|
||||
* then the ivl_lval_idx exression must *not* be present.
|
||||
* then the ivl_lval_idx expression must *not* be present.
|
||||
*
|
||||
* For array words, the ivl_lval_width is the width of the word.
|
||||
*/
|
||||
@@ -1293,6 +1346,7 @@ extern unsigned ivl_nexus_ptr_pin(ivl_nexus_ptr_t net);
|
||||
extern ivl_net_const_t ivl_nexus_ptr_con(ivl_nexus_ptr_t net);
|
||||
extern ivl_net_logic_t ivl_nexus_ptr_log(ivl_nexus_ptr_t net);
|
||||
extern ivl_lpm_t ivl_nexus_ptr_lpm(ivl_nexus_ptr_t net);
|
||||
extern ivl_switch_t ivl_nexus_ptr_switch(ivl_nexus_ptr_t net);
|
||||
extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
|
||||
/* PARAMETER
|
||||
@@ -1320,11 +1374,18 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
* ivl_parameter_expr
|
||||
* Return the value of the parameter. This should be a simple
|
||||
* constant expression, an IVL_EX_STRING or IVL_EX_NUMBER.
|
||||
*
|
||||
* ivl_parameter_file
|
||||
* ivl_parameter_lineno
|
||||
* Returns the file and line where this parameter is define
|
||||
*/
|
||||
extern const char* ivl_parameter_basename(ivl_parameter_t net);
|
||||
extern ivl_scope_t ivl_parameter_scope(ivl_parameter_t net);
|
||||
extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
|
||||
|
||||
extern const char* ivl_parameter_file(ivl_parameter_t net);
|
||||
extern unsigned ivl_parameter_lineno(ivl_parameter_t net);
|
||||
|
||||
|
||||
/* SCOPE
|
||||
* Scopes of various sort have these properties. Use these methods to
|
||||
@@ -1372,10 +1433,18 @@ extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
|
||||
* ivl_scope_def function must return a statement for scopes that
|
||||
* are type FUNCTION or TASK, and must return nil otherwise.
|
||||
*
|
||||
* ivl_scope_def_file
|
||||
* ivl_scope_def_lineno
|
||||
* Returns the file and line where this scope is defined.
|
||||
*
|
||||
* ivl_scope_event
|
||||
* ivl_scope_events
|
||||
* Scopes have 0 or more event objects in them.
|
||||
*
|
||||
* ivl_scope_file
|
||||
* ivl_scope_lineno
|
||||
* Returns the instantiation file and line for this scope.
|
||||
*
|
||||
* ivl_scope_var
|
||||
* ivl_scope_vars
|
||||
* REMOVED
|
||||
@@ -1446,9 +1515,13 @@ extern int ivl_scope_children(ivl_scope_t net,
|
||||
ivl_scope_f func, void*cd);
|
||||
|
||||
extern ivl_statement_t ivl_scope_def(ivl_scope_t net);
|
||||
extern const char* ivl_scope_def_file(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_def_lineno(ivl_scope_t net);
|
||||
|
||||
extern unsigned ivl_scope_events(ivl_scope_t net);
|
||||
extern ivl_event_t ivl_scope_event(ivl_scope_t net, unsigned idx);
|
||||
extern const char* ivl_scope_file(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_lineno(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_logs(ivl_scope_t net);
|
||||
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_lpms(ivl_scope_t net);
|
||||
@@ -1462,6 +1535,8 @@ extern unsigned ivl_scope_ports(ivl_scope_t net);
|
||||
extern ivl_signal_t ivl_scope_port(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_sigs(ivl_scope_t net);
|
||||
extern ivl_signal_t ivl_scope_sig(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_switches(ivl_scope_t net);
|
||||
extern ivl_switch_t ivl_scope_switch(ivl_scope_t net, unsigned idx);
|
||||
extern ivl_scope_type_t ivl_scope_type(ivl_scope_t net);
|
||||
extern const char* ivl_scope_tname(ivl_scope_t net);
|
||||
extern int ivl_scope_time_precision(ivl_scope_t net);
|
||||
@@ -1488,7 +1563,7 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||
* ivl_signal_array_count
|
||||
* The signal may be arrayed. If so, the array_count is >1. Each
|
||||
* word of the array has its own nexus. The array_base is the
|
||||
* address is the Verilg source for the canonical zero word. This
|
||||
* address is the Verilog source for the canonical zero word. This
|
||||
* may be negative, positive or zero.
|
||||
*
|
||||
* Note that arraying of the signal into words is distinct from the
|
||||
@@ -1555,6 +1630,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||
* the attribute value (a string) associated with a key. This
|
||||
* function returns the attribute value for the given key. If the
|
||||
* key does not exist, the function returns 0.
|
||||
*
|
||||
* ivl_signal_file
|
||||
* ivl_signal_lineno
|
||||
* Returns the file and line where this signal is defined.
|
||||
*/
|
||||
|
||||
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
||||
@@ -1576,6 +1655,9 @@ extern const char* ivl_signal_name(ivl_signal_t net);
|
||||
extern const char* ivl_signal_basename(ivl_signal_t net);
|
||||
extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
|
||||
|
||||
extern const char* ivl_signal_file(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_lineno(ivl_signal_t net);
|
||||
|
||||
extern unsigned ivl_signal_attr_cnt(ivl_signal_t net);
|
||||
extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
|
||||
|
||||
@@ -1780,6 +1862,53 @@ extern ivl_expr_t ivl_stmt_rval(ivl_statement_t net);
|
||||
IVL_ST_WAIT, IVL_ST_WHILE */
|
||||
extern ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net);
|
||||
|
||||
/* SWITCHES
|
||||
*
|
||||
* The switches represent the tran devices in the design.
|
||||
*
|
||||
* FUNCTION SUMMARY
|
||||
*
|
||||
* ivl_switch_type
|
||||
* Return the enumerated value that is the type of the switch.
|
||||
*
|
||||
* ivl_switch_basename
|
||||
* This is the name given to the device in the source code.
|
||||
*
|
||||
* ivl_switch_a
|
||||
* ivl_switch_b
|
||||
* The a and b ports are the two ports of the switch.
|
||||
*
|
||||
* ivl_switch_enable
|
||||
* If the device has an enable (tranifX) then this is the enable
|
||||
* port.
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
* The a/b ports can be any type, but the types must exactly
|
||||
* match, including vector widths. The enable must be a scalar.
|
||||
*
|
||||
* The IVL_SW_TRAN_VP is an exception to the above. In this case,
|
||||
* the B side may be a different size, and the a side will have a
|
||||
* a fixed width. The unused bits are padded to Z on the A side.
|
||||
*/
|
||||
extern ivl_switch_type_t ivl_switch_type(ivl_switch_t net);
|
||||
extern ivl_scope_t ivl_switch_scope(ivl_switch_t net);
|
||||
extern const char*ivl_switch_basename(ivl_switch_t net);
|
||||
extern ivl_nexus_t ivl_switch_a(ivl_switch_t net);
|
||||
extern ivl_nexus_t ivl_switch_b(ivl_switch_t net);
|
||||
extern ivl_nexus_t ivl_switch_enable(ivl_switch_t net);
|
||||
extern ivl_island_t ivl_switch_island(ivl_switch_t net);
|
||||
|
||||
/* These are only support for IVL_SW_TRAN_VP switches. */
|
||||
extern unsigned ivl_switch_width(ivl_switch_t net);
|
||||
extern unsigned ivl_switch_part(ivl_switch_t net);
|
||||
extern unsigned ivl_switch_offset(ivl_switch_t net);
|
||||
|
||||
/* Not implemented yet
|
||||
extern unsigned ivl_switch_attr_cnt(ivl_switch_t net);
|
||||
extern ivl_attribute_t ivl_switch_attr_val(ivl_switch_t net, unsigned idx);
|
||||
*** */
|
||||
extern const char* ivl_switch_file(ivl_switch_t net);
|
||||
extern unsigned ivl_switch_lineno(ivl_switch_t net);
|
||||
|
||||
#if defined(__MINGW32__) || defined (__CYGWIN32__)
|
||||
# define DLLEXPORT __declspec(dllexport)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef __ivl_target_priv_H
|
||||
#define __ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
*/
|
||||
|
||||
# include <inttypes.h>
|
||||
|
||||
/*
|
||||
* This deader has declarations related to the ivl_target.h API that
|
||||
* are not to be exported outside of the core via the ivl_target.h
|
||||
* interface.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Information about islands. Connected branches within a net are
|
||||
* collected into islands. Branches that are purely ddiscrete do not
|
||||
* have disciplines and do not belong to islands.
|
||||
*/
|
||||
|
||||
class discipline_t;
|
||||
|
||||
struct ivl_island_s {
|
||||
discipline_t*discipline;
|
||||
// user accessible flags. They are initially false, always.
|
||||
vector<bool> flags;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,3 @@
|
||||
lexor.c
|
||||
parse.c
|
||||
parse.h
|
||||
parse.output
|
||||
Makefile
|
||||
ivlpp
|
||||
|
||||
+3
-7
@@ -47,12 +47,12 @@ LDFLAGS = @LDFLAGS@
|
||||
all: ivlpp@EXEEXT@
|
||||
|
||||
clean:
|
||||
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp@EXEEXT@
|
||||
rm -f *.o lexor.c ivlpp@EXEEXT@
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
||||
O = main.o lexor.o parse.o
|
||||
O = main.o lexor.o
|
||||
|
||||
ivlpp@EXEEXT@: $O
|
||||
$(CC) $(LDFLAGS) $O -o ivlpp@EXEEXT@ @EXTRALIBS@
|
||||
@@ -60,9 +60,6 @@ ivlpp@EXEEXT@: $O
|
||||
lexor.c: lexor.lex
|
||||
flex -olexor.c $(srcdir)/lexor.lex
|
||||
|
||||
parse.h parse.c: parse.y
|
||||
bison --verbose -t -d -o parse.c $(srcdir)/parse.y
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
|
||||
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
|
||||
@@ -74,6 +71,5 @@ installdirs: ../mkinstalldirs
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
|
||||
lexor.o: lexor.c parse.h globals.h
|
||||
lexor.o: lexor.c globals.h
|
||||
main.o: main.c globals.h
|
||||
parse.o: parse.c
|
||||
|
||||
+2
-2
@@ -39,7 +39,7 @@ extern unsigned error_count;
|
||||
|
||||
extern FILE *depend_file;
|
||||
|
||||
/* This is the entry to the parser. */
|
||||
extern int yyparse();
|
||||
/* This is the entry to the lexer. */
|
||||
extern int yylex();
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
|
||||
THE IVL PREPROCESSOR
|
||||
|
||||
The ivlpp command is a verilog preprocessor that handles file
|
||||
The ivlpp command is a Verilog preprocessor that handles file
|
||||
inclusion and macro substitution. The program runs separate from the
|
||||
actual compiler so as to ease the task of the compiler proper, and
|
||||
provides a means of preprocessing files off-line.
|
||||
|
||||
+1207
-917
File diff suppressed because it is too large
Load Diff
+24
-20
@@ -1,5 +1,5 @@
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1999-2007 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1999-2008 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
|
||||
@@ -202,23 +202,27 @@ int main(int argc, char*argv[])
|
||||
FILE*precomp_out = NULL;
|
||||
|
||||
/* Define preprocessor keywords that I plan to just pass. */
|
||||
define_macro("celldefine", "`celldefine", 1, 0);
|
||||
define_macro("default_nettype", "`default_nettype", 1, 0);
|
||||
define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0);
|
||||
define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0);
|
||||
define_macro("delay_mode_path", "`delay_mode_path", 1, 0);
|
||||
define_macro("disable_portfaults", "`disable_portfaults", 1, 0);
|
||||
define_macro("enable_portfaults", "`enable_portfaults", 1, 0);
|
||||
define_macro("endcelldefine", "`endcelldefine", 1, 0);
|
||||
define_macro("endprotect", "`endprotect", 1, 0);
|
||||
define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0);
|
||||
define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0);
|
||||
define_macro("protect", "`protect", 1, 0);
|
||||
define_macro("resetall", "`resetall", 1, 0);
|
||||
define_macro("suppress_faults", "`suppress_faults", 1, 0);
|
||||
define_macro("timescale", "`timescale", 1, 0);
|
||||
define_macro("unconnected_drive", "`unconnected_drive", 1, 0);
|
||||
define_macro("uselib", "`uselib", 1, 0);
|
||||
define_macro("celldefine", "`celldefine", 1, 0);
|
||||
define_macro("default_decay_time", "`default_decay_time", 1, 0);
|
||||
define_macro("default_nettype", "`default_nettype", 1, 0);
|
||||
define_macro("default_trireg_strength", "`default_trireg_strength", 1, 0);
|
||||
define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0);
|
||||
define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0);
|
||||
define_macro("delay_mode_path", "`delay_mode_path", 1, 0);
|
||||
define_macro("delay_mode_zero", "`delay_mode_zero", 1, 0);
|
||||
define_macro("disable_portfaults", "`disable_portfaults", 1, 0);
|
||||
define_macro("enable_portfaults", "`enable_portfaults", 1, 0);
|
||||
define_macro("endcelldefine", "`endcelldefine", 1, 0);
|
||||
define_macro("endprotect", "`endprotect", 1, 0);
|
||||
define_macro("line", "`line", 1, 0);
|
||||
define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0);
|
||||
define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0);
|
||||
define_macro("protect", "`protect", 1, 0);
|
||||
define_macro("resetall", "`resetall", 1, 0);
|
||||
define_macro("suppress_faults", "`suppress_faults", 1, 0);
|
||||
define_macro("timescale", "`timescale", 1, 0);
|
||||
define_macro("unconnected_drive", "`unconnected_drive", 1, 0);
|
||||
define_macro("uselib", "`uselib", 1, 0);
|
||||
|
||||
include_cnt = 2;
|
||||
include_dir = malloc(include_cnt*sizeof(char*));
|
||||
@@ -352,9 +356,9 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
|
||||
/* Pass to the lexical analyzer the list of input file, and
|
||||
start the parser. */
|
||||
start scanning. */
|
||||
reset_lexor(out, source_list);
|
||||
if (yyparse()) return -1;
|
||||
if (yylex()) return -1;
|
||||
|
||||
if(depend_file) {
|
||||
fclose(depend_file);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2008 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
|
||||
@@ -34,7 +34,8 @@
|
||||
# include <ctype.h>
|
||||
# include <string.h>
|
||||
# include "lexor_keyword.h"
|
||||
|
||||
# include "discipline.h"
|
||||
# include <list>
|
||||
|
||||
# define YY_USER_INIT reset_lexor();
|
||||
# define yylval VLlval
|
||||
@@ -48,6 +49,11 @@
|
||||
*/
|
||||
extern YYLTYPE yylloc;
|
||||
|
||||
static char* strdupnew(char const *str)
|
||||
{
|
||||
return str ? strcpy(new char [strlen(str)+1], str) : 0;
|
||||
}
|
||||
|
||||
static const char* set_file_name(char*text)
|
||||
{
|
||||
perm_string path = filename_strings.make(text);
|
||||
@@ -78,6 +84,8 @@ static int dec_buf_div2(char *buf);
|
||||
|
||||
static void process_timescale(const char*txt);
|
||||
|
||||
static list<int> keyword_mask_stack;
|
||||
|
||||
static int comment_enter;
|
||||
%}
|
||||
|
||||
@@ -88,10 +96,14 @@ static int comment_enter;
|
||||
%s UDPTABLE
|
||||
%x PPTIMESCALE
|
||||
%x PPDEFAULT_NETTYPE
|
||||
%x PPBEGIN_KEYWORDS
|
||||
%s EDGES
|
||||
%x REAL_SCALE
|
||||
|
||||
W [ \t\b\f\r]+
|
||||
|
||||
S [afpnumkKMGT]
|
||||
|
||||
%%
|
||||
|
||||
^"#line"[ ]+\"[^\"]*\"[ ]+[0-9]+.* { line_directive(); }
|
||||
@@ -141,6 +153,7 @@ W [ \t\b\f\r]+
|
||||
"->" { return K_TRIGGER; }
|
||||
"+:" { return K_PO_POS; }
|
||||
"-:" { return K_PO_NEG; }
|
||||
"<+" { return K_CONTRIBUTE; }
|
||||
|
||||
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
|
||||
and ")", but since I know that this is really ( * ), replace it
|
||||
@@ -205,22 +218,11 @@ W [ \t\b\f\r]+
|
||||
int rc = lexor_keyword_code(yytext, yyleng);
|
||||
switch (rc) {
|
||||
case IDENTIFIER:
|
||||
yylval.text = strdup(yytext);
|
||||
yylval.text = strdupnew(yytext);
|
||||
if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
|
||||
rc = PATHPULSE_IDENTIFIER;
|
||||
break;
|
||||
|
||||
case K_bool:
|
||||
case K_logic:
|
||||
case K_wone:
|
||||
if (! gn_cadence_types_enabled()) {
|
||||
yylval.text = strdup(yytext);
|
||||
rc = IDENTIFIER;
|
||||
} else {
|
||||
yylval.text = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case K_edge:
|
||||
BEGIN(EDGES);
|
||||
break;
|
||||
@@ -230,12 +232,24 @@ W [ \t\b\f\r]+
|
||||
break;
|
||||
}
|
||||
|
||||
/* If this identifier names a discipline, then return this as
|
||||
a DISCIPLINE_IDENTIFIER and return the discipline as the
|
||||
value instead. */
|
||||
if (rc == IDENTIFIER && gn_verilog_ams_flag) {
|
||||
perm_string tmp = lex_strings.make(yylval.text);
|
||||
map<perm_string,discipline_t*>::iterator cur = disciplines.find(tmp);
|
||||
if (cur != disciplines.end()) {
|
||||
yylval.discipline = (*cur).second;
|
||||
rc = DISCIPLINE_IDENTIFIER;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
\\[^ \t\b\f\r\n]+ {
|
||||
yylval.text = strdup(yytext+1);
|
||||
yylval.text = strdupnew(yytext+1);
|
||||
return IDENTIFIER; }
|
||||
|
||||
\$([a-zA-Z0-9$_]+) {
|
||||
@@ -255,7 +269,7 @@ W [ \t\b\f\r]+
|
||||
return K_Ssetup;
|
||||
if (strcmp(yytext,"$width") == 0)
|
||||
return K_Swidth;
|
||||
yylval.text = strdup(yytext);
|
||||
yylval.text = strdupnew(yytext);
|
||||
return SYSTEM_IDENTIFIER; }
|
||||
|
||||
|
||||
@@ -275,6 +289,46 @@ W [ \t\b\f\r]+
|
||||
based_size = yylval.number->as_ulong();
|
||||
return DEC_NUMBER; }
|
||||
|
||||
/* These rules handle the scaled real literals from Verilog-AMS. The
|
||||
value is a number with a single letter scale factor. If
|
||||
verilog-ams is not enabled, then reject this rule. If it is
|
||||
enabled, then collect the scale and use it to scale the value. */
|
||||
[0-9][0-9_]*\.[0-9][0-9_]*/{S} {
|
||||
if (!gn_verilog_ams_flag) REJECT;
|
||||
BEGIN(REAL_SCALE);
|
||||
yymore(); }
|
||||
|
||||
[0-9][0-9_]*/{S} {
|
||||
if (!gn_verilog_ams_flag) REJECT;
|
||||
BEGIN(REAL_SCALE);
|
||||
yymore(); }
|
||||
|
||||
<REAL_SCALE>{S} {
|
||||
size_t token_len = strlen(yytext);
|
||||
char*tmp = new char[token_len + 5];
|
||||
int scale = 0;
|
||||
strcpy(tmp, yytext);
|
||||
switch (tmp[token_len-1]) {
|
||||
case 'a': scale = -18; break; /* atto- */
|
||||
case 'f': scale = -15; break; /* femto- */
|
||||
case 'p': scale = -12; break; /* pico- */
|
||||
case 'n': scale = -9; break; /* nano- */
|
||||
case 'u': scale = -6; break; /* micro- */
|
||||
case 'm': scale = -3; break; /* milli- */
|
||||
case 'k': scale = 3; break; /* kilo- */
|
||||
case 'K': scale = 3; break; /* kilo- */
|
||||
case 'M': scale = 6; break; /* mega- */
|
||||
case 'G': scale = 9; break; /* giga- */
|
||||
case 'T': scale = 12; break; /* tera- */
|
||||
default: assert(0); break;
|
||||
}
|
||||
snprintf(tmp+token_len-1, 5, "e%d", scale);
|
||||
yylval.realtime = new verireal(tmp);
|
||||
delete[]tmp;
|
||||
|
||||
BEGIN(0);
|
||||
return REALTIME; }
|
||||
|
||||
[0-9][0-9_]*\.[0-9][0-9_]*([Ee][+-]?[0-9][0-9_]*)? {
|
||||
yylval.realtime = new verireal(yytext);
|
||||
return REALTIME; }
|
||||
@@ -296,21 +350,76 @@ W [ \t\b\f\r]+
|
||||
/* These are directives that I do not yet support. I think that IVL
|
||||
should handle these, not an external preprocessor. */
|
||||
|
||||
^{W}?`celldefine{W}?.* { }
|
||||
^{W}?`celldefine{W}?.* { }
|
||||
^{W}?`default_decay_time{W}?.* { }
|
||||
^{W}?`default_trireg_strength{W}?.* { }
|
||||
^{W}?`delay_mode_distributed{W}?.* { }
|
||||
^{W}?`delay_mode_unit{W}?.* { }
|
||||
^{W}?`delay_mode_path{W}?.* { }
|
||||
^{W}?`disable_portfaults{W}?.* { }
|
||||
^{W}?`enable_portfaults{W}?.* { }
|
||||
^{W}?`endcelldefine{W}?.* { }
|
||||
`endprotect { }
|
||||
^{W}?`nosuppress_faults{W}?.* { }
|
||||
^{W}?`nounconnected_drive{W}?.* { }
|
||||
`protect { }
|
||||
^{W}?`resetall{W}?.* { }
|
||||
^{W}?`suppress_faults{W}?.* { }
|
||||
^{W}?`unconnected_drive{W}?.* { }
|
||||
^{W}?`uselib{W}?.* { }
|
||||
^{W}?`delay_mode_unit{W}?.* { }
|
||||
^{W}?`delay_mode_path{W}?.* { }
|
||||
^{W}?`delay_mode_zero{W}?.* { }
|
||||
^{W}?`disable_portfaults{W}?.* { }
|
||||
^{W}?`enable_portfaults{W}?.* { }
|
||||
^{W}?`endcelldefine{W}?.* { }
|
||||
`endprotect { }
|
||||
^{W}?`line{W}?.* { }
|
||||
^{W}?`nosuppress_faults{W}?.* { }
|
||||
^{W}?`nounconnected_drive{W}?.* { }
|
||||
`protect { }
|
||||
^{W}?`resetall{W}?.* { }
|
||||
^{W}?`suppress_faults{W}?.* { }
|
||||
^{W}?`unconnected_drive{W}?.* { }
|
||||
^{W}?`uselib{W}?.* { }
|
||||
|
||||
^{W}?`begin_keywords{W}? { BEGIN(PPBEGIN_KEYWORDS); }
|
||||
|
||||
<PPBEGIN_KEYWORDS>\"[a-zA-Z0-9 -]*\".* {
|
||||
keyword_mask_stack.push_front(lexor_keyword_mask);
|
||||
|
||||
char*word = yytext+1;
|
||||
char*tail = strchr(word, '"');
|
||||
tail[0] = 0;
|
||||
if (strcmp(word,"1364-1995") == 0) {
|
||||
lexor_keyword_mask = GN_KEYWORDS_1364_1995;
|
||||
} else if (strcmp(word,"1364-2001") == 0) {
|
||||
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|
||||
|GN_KEYWORDS_1364_2001
|
||||
|GN_KEYWORDS_1364_2001_CONFIG;
|
||||
} else if (strcmp(word,"1364-2001-noconfig") == 0) {
|
||||
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|
||||
|GN_KEYWORDS_1364_2001;
|
||||
} else if (strcmp(word,"1364-2005") == 0) {
|
||||
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|
||||
|GN_KEYWORDS_1364_2001
|
||||
|GN_KEYWORDS_1364_2001_CONFIG
|
||||
|GN_KEYWORDS_1364_2005;
|
||||
} else if (strcmp(word,"VAMS-2.3") == 0) {
|
||||
lexor_keyword_mask = GN_KEYWORDS_1364_1995
|
||||
|GN_KEYWORDS_1364_2001
|
||||
|GN_KEYWORDS_1364_2001_CONFIG
|
||||
|GN_KEYWORDS_1364_2005
|
||||
|GN_KEYWORDS_VAMS_2_3;
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d: Ignoring unknown keywords string: %s\n",
|
||||
yylloc.text, yylloc.first_line, word);
|
||||
}
|
||||
BEGIN(0);
|
||||
}
|
||||
|
||||
<PPBEGIN_KEYWORDS>.* {
|
||||
fprintf(stderr, "%s:%d: Malformed keywords specification: %s\n",
|
||||
yylloc.text, yylloc.first_line, yytext);
|
||||
BEGIN(0);
|
||||
}
|
||||
|
||||
^{W}?`end_keywords{W}?.* {
|
||||
if (!keyword_mask_stack.empty()) {
|
||||
lexor_keyword_mask = keyword_mask_stack.front();
|
||||
keyword_mask_stack.pop_front();
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d: Mismatched end_keywords directive\n",
|
||||
yylloc.text, yylloc.first_line);
|
||||
}
|
||||
}
|
||||
|
||||
/* Notice and handle the default_nettype directive. The lexor
|
||||
detects the default_nettype keyword, and the second part of the
|
||||
@@ -337,7 +446,7 @@ W [ \t\b\f\r]+
|
||||
error_count += 1;
|
||||
}
|
||||
pform_set_default_nettype(net_type, yylloc.text, yylloc.first_line);
|
||||
}
|
||||
}
|
||||
<PPDEFAULT_NETTYPE>\n {
|
||||
yylloc.first_line += 1;
|
||||
BEGIN(0); }
|
||||
@@ -978,5 +1087,5 @@ void reset_lexor()
|
||||
yylloc.first_line = 1;
|
||||
|
||||
/* Announce the first file name. */
|
||||
yylloc.text = set_file_name(strdup(vl_file.c_str()));
|
||||
yylloc.text = set_file_name(strdupnew(vl_file.c_str()));
|
||||
}
|
||||
|
||||
+160
-111
@@ -6,127 +6,176 @@
|
||||
#include "parse.h"
|
||||
#include <string.h>
|
||||
#include "lexor_keyword.h"
|
||||
#include "compiler.h"
|
||||
|
||||
%}
|
||||
struct lexor_keyword { const char*name; int tokenType; };
|
||||
struct lexor_keyword { const char*name; int mask; int tokenType; };
|
||||
%%
|
||||
always, K_always
|
||||
and, K_and
|
||||
assign, K_assign
|
||||
begin, K_begin
|
||||
bool, K_bool
|
||||
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
|
||||
endgenerate, K_endgenerate
|
||||
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
|
||||
generate, K_generate
|
||||
genvar, K_genvar
|
||||
highz0, K_highz0
|
||||
highz1, K_highz1
|
||||
if, K_if
|
||||
ifnone, K_ifnone
|
||||
initial, K_initial
|
||||
inout, K_inout
|
||||
input, K_input
|
||||
integer, K_integer
|
||||
join, K_join
|
||||
large, K_large
|
||||
localparam, K_localparam
|
||||
logic, K_logic
|
||||
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
|
||||
real, K_real
|
||||
realtime, K_realtime
|
||||
reg, K_reg
|
||||
release, K_release
|
||||
repeat, K_repeat
|
||||
rnmos, K_rnmos
|
||||
rpmos, K_rpmos
|
||||
rtran, K_rtran
|
||||
rtranif0, K_rtranif0
|
||||
rtranif1, K_rtranif1
|
||||
scalared, K_scalared
|
||||
signed, K_signed
|
||||
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
|
||||
wone, K_wone
|
||||
wor, K_wor
|
||||
xnor, K_xnor
|
||||
xor, K_xor
|
||||
abs, GN_KEYWORDS_VAMS_2_3, K_abs
|
||||
abstol, GN_KEYWORDS_VAMS_2_3, K_abstol
|
||||
access, GN_KEYWORDS_VAMS_2_3, K_access
|
||||
acos, GN_KEYWORDS_VAMS_2_3, K_acos
|
||||
acosh, GN_KEYWORDS_VAMS_2_3, K_acosh
|
||||
always, GN_KEYWORDS_1364_1995, K_always
|
||||
analog, GN_KEYWORDS_VAMS_2_3, K_analog
|
||||
and, GN_KEYWORDS_1364_1995, K_and
|
||||
asin, GN_KEYWORDS_VAMS_2_3, K_asin
|
||||
asinh, GN_KEYWORDS_VAMS_2_3, K_asinh
|
||||
assign, GN_KEYWORDS_1364_1995, K_assign
|
||||
atan, GN_KEYWORDS_VAMS_2_3, K_atan
|
||||
atan2, GN_KEYWORDS_VAMS_2_3, K_atan2
|
||||
atanh, GN_KEYWORDS_VAMS_2_3, K_atanh
|
||||
begin, GN_KEYWORDS_1364_1995, K_begin
|
||||
bool, GN_KEYWORDS_ICARUS, K_bool
|
||||
buf, GN_KEYWORDS_1364_1995, K_buf
|
||||
bufif0, GN_KEYWORDS_1364_1995, K_bufif0
|
||||
bufif1, GN_KEYWORDS_1364_1995, K_bufif1
|
||||
case, GN_KEYWORDS_1364_1995, K_case
|
||||
casex, GN_KEYWORDS_1364_1995, K_casex
|
||||
casez, GN_KEYWORDS_1364_1995, K_casez
|
||||
ceil, GN_KEYWORDS_VAMS_2_3, K_ceil
|
||||
cmos, GN_KEYWORDS_1364_1995, K_cmos
|
||||
continuous, GN_KEYWORDS_VAMS_2_3, K_continuous
|
||||
cos, GN_KEYWORDS_VAMS_2_3, K_cos
|
||||
cosh, GN_KEYWORDS_VAMS_2_3, K_cosh
|
||||
ddt_nature, GN_KEYWORDS_VAMS_2_3, K_ddt_nature
|
||||
deassign, GN_KEYWORDS_1364_1995, K_deassign
|
||||
default, GN_KEYWORDS_1364_1995, K_default
|
||||
defparam, GN_KEYWORDS_1364_1995, K_defparam
|
||||
disable, GN_KEYWORDS_1364_1995, K_disable
|
||||
discipline, GN_KEYWORDS_VAMS_2_3, K_discipline
|
||||
discrete, GN_KEYWORDS_VAMS_2_3, K_discrete
|
||||
domain, GN_KEYWORDS_VAMS_2_3, K_domain
|
||||
edge, GN_KEYWORDS_1364_1995, K_edge
|
||||
else, GN_KEYWORDS_1364_1995, K_else
|
||||
end, GN_KEYWORDS_1364_1995, K_end
|
||||
endcase, GN_KEYWORDS_1364_1995, K_endcase
|
||||
enddiscipline, GN_KEYWORDS_VAMS_2_3, K_enddiscipline
|
||||
endfunction, GN_KEYWORDS_1364_1995, K_endfunction
|
||||
endgenerate, GN_KEYWORDS_1364_1995, K_endgenerate
|
||||
endmodule, GN_KEYWORDS_1364_1995, K_endmodule
|
||||
endnature, GN_KEYWORDS_VAMS_2_3, K_endnature
|
||||
endprimitive, GN_KEYWORDS_1364_1995, K_endprimitive
|
||||
endspecify, GN_KEYWORDS_1364_1995, K_endspecify
|
||||
endtable, GN_KEYWORDS_1364_1995, K_endtable
|
||||
endtask, GN_KEYWORDS_1364_1995, K_endtask
|
||||
event, GN_KEYWORDS_1364_1995, K_event
|
||||
exclude, GN_KEYWORDS_VAMS_2_3, K_exclude
|
||||
exp, GN_KEYWORDS_VAMS_2_3, K_exp
|
||||
floor, GN_KEYWORDS_VAMS_2_3, K_floor
|
||||
flow, GN_KEYWORDS_VAMS_2_3, K_flow
|
||||
for, GN_KEYWORDS_1364_1995, K_for
|
||||
force, GN_KEYWORDS_1364_1995, K_force
|
||||
forever, GN_KEYWORDS_1364_1995, K_forever
|
||||
fork, GN_KEYWORDS_1364_1995, K_fork
|
||||
from, GN_KEYWORDS_VAMS_2_3, K_from
|
||||
function, GN_KEYWORDS_1364_1995, K_function
|
||||
generate, GN_KEYWORDS_1364_2001, K_generate
|
||||
genvar, GN_KEYWORDS_1364_2001, K_genvar
|
||||
ground, GN_KEYWORDS_VAMS_2_3, K_ground
|
||||
highz0, GN_KEYWORDS_1364_1995, K_highz0
|
||||
highz1, GN_KEYWORDS_1364_1995, K_highz1
|
||||
hypot, GN_KEYWORDS_VAMS_2_3, K_hypot
|
||||
idt_nature, GN_KEYWORDS_VAMS_2_3, K_idt_nature
|
||||
if, GN_KEYWORDS_1364_1995, K_if
|
||||
ifnone, GN_KEYWORDS_1364_1995, K_ifnone
|
||||
inf, GN_KEYWORDS_VAMS_2_3, K_inf
|
||||
initial, GN_KEYWORDS_1364_1995, K_initial
|
||||
inout, GN_KEYWORDS_1364_1995, K_inout
|
||||
input, GN_KEYWORDS_1364_1995, K_input
|
||||
integer, GN_KEYWORDS_1364_1995, K_integer
|
||||
join, GN_KEYWORDS_1364_1995, K_join
|
||||
large, GN_KEYWORDS_1364_1995, K_large
|
||||
ln, GN_KEYWORDS_VAMS_2_3, K_ln
|
||||
localparam, GN_KEYWORDS_1364_2001, K_localparam
|
||||
log, GN_KEYWORDS_VAMS_2_3, K_log
|
||||
logic, GN_KEYWORDS_ICARUS, K_logic
|
||||
macromodule, GN_KEYWORDS_1364_1995, K_macromodule
|
||||
max, GN_KEYWORDS_VAMS_2_3, K_max
|
||||
medium, GN_KEYWORDS_1364_1995, K_medium
|
||||
min, GN_KEYWORDS_VAMS_2_3, K_min
|
||||
module, GN_KEYWORDS_1364_1995, K_module
|
||||
nand, GN_KEYWORDS_1364_1995, K_nand
|
||||
nature, GN_KEYWORDS_VAMS_2_3, K_nature
|
||||
negedge, GN_KEYWORDS_1364_1995, K_negedge
|
||||
nmos, GN_KEYWORDS_1364_1995, K_nmos
|
||||
nor, GN_KEYWORDS_1364_1995, K_nor
|
||||
not, GN_KEYWORDS_1364_1995, K_not
|
||||
notif0, GN_KEYWORDS_1364_1995, K_notif0
|
||||
notif1, GN_KEYWORDS_1364_1995, K_notif1
|
||||
or, GN_KEYWORDS_1364_1995, K_or
|
||||
output, GN_KEYWORDS_1364_1995, K_output
|
||||
parameter, GN_KEYWORDS_1364_1995, K_parameter
|
||||
pmos, GN_KEYWORDS_1364_1995, K_pmos
|
||||
posedge, GN_KEYWORDS_1364_1995, K_posedge
|
||||
potential, GN_KEYWORDS_VAMS_2_3, K_potential
|
||||
pow, GN_KEYWORDS_VAMS_2_3, K_pow
|
||||
primitive, GN_KEYWORDS_1364_1995, K_primitive
|
||||
pull0, GN_KEYWORDS_1364_1995, K_pull0
|
||||
pull1, GN_KEYWORDS_1364_1995, K_pull1
|
||||
pulldown, GN_KEYWORDS_1364_1995, K_pulldown
|
||||
pullup, GN_KEYWORDS_1364_1995, K_pullup
|
||||
rcmos, GN_KEYWORDS_1364_1995, K_rcmos
|
||||
real, GN_KEYWORDS_1364_1995, K_real
|
||||
realtime, GN_KEYWORDS_1364_1995, K_realtime
|
||||
reg, GN_KEYWORDS_1364_1995, K_reg
|
||||
release, GN_KEYWORDS_1364_1995, K_release
|
||||
repeat, GN_KEYWORDS_1364_1995, K_repeat
|
||||
rnmos, GN_KEYWORDS_1364_1995, K_rnmos
|
||||
rpmos, GN_KEYWORDS_1364_1995, K_rpmos
|
||||
rtran, GN_KEYWORDS_1364_1995, K_rtran
|
||||
rtranif0, GN_KEYWORDS_1364_1995, K_rtranif0
|
||||
rtranif1, GN_KEYWORDS_1364_1995, K_rtranif1
|
||||
scalared, GN_KEYWORDS_1364_1995, K_scalared
|
||||
signed, GN_KEYWORDS_1364_2001, K_signed
|
||||
sin, GN_KEYWORDS_VAMS_2_3, K_sin
|
||||
sinh, GN_KEYWORDS_VAMS_2_3, K_sinh
|
||||
small, GN_KEYWORDS_1364_1995, K_small
|
||||
specify, GN_KEYWORDS_1364_1995, K_specify
|
||||
specparam, GN_KEYWORDS_1364_1995, K_specparam
|
||||
sqrt, GN_KEYWORDS_VAMS_2_3, K_sqrt
|
||||
string, GN_KEYWORDS_VAMS_2_3, K_string
|
||||
strong0, GN_KEYWORDS_1364_1995, K_strong0
|
||||
strong1, GN_KEYWORDS_1364_1995, K_strong1
|
||||
supply0, GN_KEYWORDS_1364_1995, K_supply0
|
||||
supply1, GN_KEYWORDS_1364_1995, K_supply1
|
||||
table, GN_KEYWORDS_1364_1995, K_table
|
||||
tan, GN_KEYWORDS_VAMS_2_3, K_tan
|
||||
tanh, GN_KEYWORDS_VAMS_2_3, K_tanh
|
||||
task, GN_KEYWORDS_1364_1995, K_task
|
||||
time, GN_KEYWORDS_1364_1995, K_time
|
||||
tran, GN_KEYWORDS_1364_1995, K_tran
|
||||
tranif0, GN_KEYWORDS_1364_1995, K_tranif0
|
||||
tranif1, GN_KEYWORDS_1364_1995, K_tranif1
|
||||
tri, GN_KEYWORDS_1364_1995, K_tri
|
||||
tri0, GN_KEYWORDS_1364_1995, K_tri0
|
||||
tri1, GN_KEYWORDS_1364_1995, K_tri1
|
||||
triand, GN_KEYWORDS_1364_1995, K_triand
|
||||
trior, GN_KEYWORDS_1364_1995, K_trior
|
||||
trireg, GN_KEYWORDS_1364_1995, K_trireg
|
||||
units, GN_KEYWORDS_VAMS_2_3, K_units
|
||||
vectored, GN_KEYWORDS_1364_1995, K_vectored
|
||||
wait, GN_KEYWORDS_1364_1995, K_wait
|
||||
wand, GN_KEYWORDS_1364_1995, K_wand
|
||||
weak0, GN_KEYWORDS_1364_1995, K_weak0
|
||||
weak1, GN_KEYWORDS_1364_1995, K_weak1
|
||||
while, GN_KEYWORDS_1364_1995, K_while
|
||||
wire, GN_KEYWORDS_1364_1995, K_wire
|
||||
wone, GN_KEYWORDS_1364_1995, K_wone
|
||||
wor, GN_KEYWORDS_1364_1995, K_wor
|
||||
xnor, GN_KEYWORDS_1364_1995, K_xnor
|
||||
xor, GN_KEYWORDS_1364_1995, K_xor
|
||||
%%
|
||||
|
||||
int lexor_keyword_mask = 0;
|
||||
|
||||
int lexor_keyword_code(const char*str, unsigned nstr)
|
||||
{
|
||||
const struct lexor_keyword*rc = check_identifier(str, nstr);
|
||||
if (rc == 0)
|
||||
return IDENTIFIER;
|
||||
else if ((rc->mask & lexor_keyword_mask) == 0)
|
||||
return IDENTIFIER;
|
||||
else
|
||||
return rc->tokenType;
|
||||
}
|
||||
|
||||
+5
-37
@@ -30,7 +30,6 @@ VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
libdir64 = @libdir64@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@
|
||||
@@ -58,12 +57,6 @@ getlongp.o getp.o getsimtime.o io_print.o math.o mc_scan_plusargs.o \
|
||||
nodeinfo.o nump.o putlongp.o putp.o spname.o typep.o workarea.o \
|
||||
veriusertfs.o priv.o $A
|
||||
|
||||
ifeq (@enable_vvp32@,yes)
|
||||
ALL32 = all32
|
||||
INSTALL32 = install32
|
||||
UNINSTALL32 = uninstall32
|
||||
endif
|
||||
|
||||
all: dep libveriuser.a $(ALL32)
|
||||
|
||||
check: all
|
||||
@@ -93,40 +86,15 @@ clean:
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
|
||||
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
|
||||
install:: all installdirs $(libdir)/libveriuser.a $(INSTALL32)
|
||||
|
||||
$(libdir64)/libveriuser.a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(libdir64)/libveriuser.a
|
||||
$(libdir)/libveriuser.a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir64)
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
|
||||
|
||||
uninstall::
|
||||
rm -f $(libdir64)/libveriuser.a
|
||||
|
||||
ifeq (@enable_vvp32@,yes)
|
||||
all32: bin32 bin32/libveriuser.a
|
||||
|
||||
bin32:
|
||||
mkdir bin32
|
||||
|
||||
bin32/%.o: %.c
|
||||
$(CC) -m32 $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $@
|
||||
|
||||
bin32/libveriuser.o: $(addprefix bin32/,$O)
|
||||
$(LD) -melf_i386 -r -o $@ $(addprefix bin32/,$O)
|
||||
|
||||
bin32/libveriuser.a: bin32/libveriuser.o
|
||||
rm -f $@
|
||||
ar cvq $@ bin32/libveriuser.o
|
||||
$(RANLIB) $@
|
||||
|
||||
install32: $(libdir)/libveriuser.a
|
||||
|
||||
$(libdir)/libveriuser.a: bin32/libveriuser.a
|
||||
$(INSTALL_DATA) bin32/libveriuser.a $(libdir)/libveriuser.a
|
||||
|
||||
-include $(patsubst bin32/%.o, bin32/%.d, $(addprefix bin32/,$O))
|
||||
endif
|
||||
rm -f $(libdir)/libveriuser.a
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2003-2008 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,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_fetch_value.c,v 1.5 2003/06/17 16:55:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <acc_user.h>
|
||||
# include <vpi_user.h>
|
||||
@@ -104,7 +101,8 @@ static char* fetch_strength_value(handle obj)
|
||||
val.format = vpiStrengthVal;
|
||||
vpi_get_value(obj, &val);
|
||||
|
||||
vpip_format_strength(str, &val);
|
||||
/* Should this iterate over the bits? It now matches the old code. */
|
||||
vpip_format_strength(str, &val, 0);
|
||||
|
||||
if (pli_trace) {
|
||||
fprintf(pli_trace, "acc_fetch_value(<%s>, \"%%v\") --> %s\n",
|
||||
@@ -125,30 +123,3 @@ char* acc_fetch_value(handle obj, const char*fmt, s_acc_value*value)
|
||||
vpi_printf("XXXX acc_fetch_value(..., \"%s\", ...)\n", fmt);
|
||||
return "<acc_fetch_value>";
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: a_fetch_value.c,v $
|
||||
* Revision 1.5 2003/06/17 16:55:07 steve
|
||||
* 1) setlinebuf() for vpi_trace
|
||||
* 2) Addes error checks for trace file opens
|
||||
* 3) removes now extraneous flushes
|
||||
* 4) fixes acc_next() bug
|
||||
*
|
||||
* Revision 1.4 2003/05/18 00:16:35 steve
|
||||
* Add PLI_TRACE tracing of PLI1 modules.
|
||||
*
|
||||
* Add tf_isetdelay and friends, and add
|
||||
* callback return values for acc_vcl support.
|
||||
*
|
||||
* Revision 1.3 2003/04/24 02:02:37 steve
|
||||
* Clean up some simple warnings.
|
||||
*
|
||||
* Revision 1.2 2003/04/20 02:49:07 steve
|
||||
* acc_fetch_value support for %v format.
|
||||
*
|
||||
* Revision 1.1 2003/04/12 18:57:14 steve
|
||||
* More acc_ function stubs.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
|
||||
|
||||
/*
|
||||
* The acc_next_* functions need to be reentrant, so we need to
|
||||
* rescan all the items upto the previous one, then return
|
||||
* rescan all the items up to the previous one, then return
|
||||
* the next one.
|
||||
*/
|
||||
iter = vpi_iterate(vpiScope, scope); // ICARUS extension
|
||||
|
||||
@@ -10,10 +10,6 @@ AC_PROG_RANLIB
|
||||
AC_EXEEXT
|
||||
AX_CPP_IDENT
|
||||
|
||||
# vvp32 is by default disabled
|
||||
#enable_vvp32=no
|
||||
AC_SUBST(enable_vvp32)
|
||||
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
@@ -29,14 +25,4 @@ AX_C_PICFLAG
|
||||
AC_SUBST(EXEEXT)
|
||||
AC_SUBST(EXTRALIBS)
|
||||
|
||||
# If not otherwise specified, set the libdir64 variable
|
||||
# to the same as libdir.
|
||||
AC_MSG_CHECKING(for libdir64 path)
|
||||
if test x${libdir64} = x
|
||||
then
|
||||
libdir64="${libdir}"
|
||||
fi
|
||||
AC_SUBST(libdir64)
|
||||
AC_MSG_RESULT(${libdir64})
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <acc_user.h>
|
||||
|
||||
/*
|
||||
* tf_getinstance implemented using equvalent acc_ routing
|
||||
* tf_getinstance implemented using equivalent acc_ routing
|
||||
*/
|
||||
char *tf_getcstringp(int n)
|
||||
{
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
extern char* __acc_newstring(const char*txt);
|
||||
|
||||
/*
|
||||
* Trace file for loggint ACC and TF calls.
|
||||
* Trace file for logging ACC and TF calls.
|
||||
*/
|
||||
FILE* pli_trace;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* Contains the routines required to implement veriusertfs routines
|
||||
* via VPI. This is extremly ugly, so don't look after eating dinner.
|
||||
* via VPI. This is extremely ugly, so don't look after eating dinner.
|
||||
*/
|
||||
|
||||
# include <string.h>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-2005 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1998-2008 Stephen Williams ([email protected])";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -18,9 +18,6 @@ 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
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.cc,v 1.95 2007/04/19 02:52:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -60,6 +57,7 @@ const char NOTICE[] =
|
||||
# include "netlist.h"
|
||||
# include "target.h"
|
||||
# include "compiler.h"
|
||||
# include "discipline.h"
|
||||
|
||||
#if defined(__MINGW32__) && !defined(HAVE_GETOPT_H)
|
||||
extern "C" int getopt(int argc, char*argv[], const char*fmt);
|
||||
@@ -85,12 +83,14 @@ const char*target = "null";
|
||||
/*
|
||||
* These are the language support control flags. These support which
|
||||
* language features (the generation) to support. The generation_flag
|
||||
* is a major moce, and the gn_* flags control specifc sub-features.
|
||||
* is a major mode, and the gn_* flags control specific sub-features.
|
||||
*/
|
||||
generation_t generation_flag = GN_DEFAULT;
|
||||
bool gn_icarus_misc_flag = true;
|
||||
bool gn_cadence_types_flag = true;
|
||||
bool gn_specify_blocks_flag = true;
|
||||
bool gn_io_range_error_flag = true;
|
||||
bool gn_verilog_ams_flag = false;
|
||||
|
||||
map<string,const char*> flags;
|
||||
char*vpi_module_list = 0;
|
||||
@@ -113,6 +113,7 @@ FILE *depend_file = NULL;
|
||||
bool warn_implicit = false;
|
||||
bool warn_timescale = false;
|
||||
bool warn_portbinding = false;
|
||||
bool warn_inf_loop = false;
|
||||
|
||||
bool error_implicit = false;
|
||||
|
||||
@@ -123,6 +124,8 @@ bool debug_scopes = false;
|
||||
bool debug_eval_tree = false;
|
||||
bool debug_elaborate = false;
|
||||
bool debug_synth2 = false;
|
||||
bool debug_optimizer = false;
|
||||
|
||||
/*
|
||||
* Verbose messages enabled.
|
||||
*/
|
||||
@@ -199,14 +202,30 @@ const char *net_func_to_name(const net_func func)
|
||||
|
||||
static void process_generation_flag(const char*gen)
|
||||
{
|
||||
if (strcmp(gen,"1") == 0) {
|
||||
if (strcmp(gen,"1") == 0) { // FIXME: Deprecated for 1995
|
||||
generation_flag = GN_VER1995;
|
||||
|
||||
} else if (strcmp(gen,"2") == 0) {
|
||||
} else if (strcmp(gen,"2") == 0) { // FIXME: Deprecated for 2001
|
||||
generation_flag = GN_VER2001;
|
||||
|
||||
} else if (strcmp(gen,"2x") == 0) {
|
||||
generation_flag = GN_VER2001X;
|
||||
} else if (strcmp(gen,"2x") == 0) { // FIXME: Deprecated for 2001
|
||||
generation_flag = GN_VER2001;
|
||||
gn_icarus_misc_flag = true;
|
||||
|
||||
} else if (strcmp(gen,"1995") == 0) {
|
||||
generation_flag = GN_VER1995;
|
||||
|
||||
} else if (strcmp(gen,"2001") == 0) {
|
||||
generation_flag = GN_VER2001;
|
||||
|
||||
} else if (strcmp(gen,"2005") == 0) {
|
||||
generation_flag = GN_VER2005;
|
||||
|
||||
} else if (strcmp(gen,"icarus-misc") == 0) {
|
||||
gn_icarus_misc_flag = true;
|
||||
|
||||
} else if (strcmp(gen,"no-icarus-misc") == 0) {
|
||||
gn_icarus_misc_flag = false;
|
||||
|
||||
} else if (strcmp(gen,"xtypes") == 0) {
|
||||
gn_cadence_types_flag = true;
|
||||
@@ -220,6 +239,12 @@ static void process_generation_flag(const char*gen)
|
||||
} else if (strcmp(gen,"no-specify") == 0) {
|
||||
gn_specify_blocks_flag = false;
|
||||
|
||||
} else if (strcmp(gen,"verilog-ams") == 0) {
|
||||
gn_verilog_ams_flag = true;
|
||||
|
||||
} else if (strcmp(gen,"no-verilog-ams") == 0) {
|
||||
gn_verilog_ams_flag = false;
|
||||
|
||||
} else if (strcmp(gen,"io-range-error") == 0) {
|
||||
gn_io_range_error_flag = true;
|
||||
|
||||
@@ -356,9 +381,9 @@ static void read_iconfig_file(const char*ipath)
|
||||
basedir = strdup(cp);
|
||||
|
||||
} else if (strcmp(buf, "debug") == 0) {
|
||||
if (strcmp(cp, "scope") == 0) {
|
||||
if (strcmp(cp, "scopes") == 0) {
|
||||
debug_scopes = true;
|
||||
cerr << "debug: Enable scope debug" << endl;
|
||||
cerr << "debug: Enable scopes debug" << endl;
|
||||
} else if (strcmp(cp,"eval_tree") == 0) {
|
||||
debug_eval_tree = true;
|
||||
cerr << "debug: Enable eval_tree debug" << endl;
|
||||
@@ -368,6 +393,9 @@ static void read_iconfig_file(const char*ipath)
|
||||
} else if (strcmp(cp,"synth2") == 0) {
|
||||
debug_synth2 = true;
|
||||
cerr << "debug: Enable synth2 debug" << endl;
|
||||
} else if (strcmp(cp,"optimizer") == 0) {
|
||||
debug_optimizer = true;
|
||||
cerr << "debug: Enable optimizer debug" << endl;
|
||||
} else {
|
||||
}
|
||||
|
||||
@@ -434,6 +462,9 @@ static void read_iconfig_file(const char*ipath)
|
||||
case 'i':
|
||||
warn_implicit = true;
|
||||
break;
|
||||
case 'l':
|
||||
warn_inf_loop = true;
|
||||
break;
|
||||
case 'p':
|
||||
warn_portbinding = true;
|
||||
break;
|
||||
@@ -591,6 +622,29 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
}
|
||||
|
||||
lexor_keyword_mask = 0;
|
||||
switch (generation_flag) {
|
||||
case GN_VER1995:
|
||||
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
||||
break;
|
||||
case GN_VER2001:
|
||||
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
||||
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
|
||||
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
|
||||
break;
|
||||
case GN_VER2005:
|
||||
lexor_keyword_mask |= GN_KEYWORDS_1364_1995;
|
||||
lexor_keyword_mask |= GN_KEYWORDS_1364_2001;
|
||||
lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG;
|
||||
lexor_keyword_mask |= GN_KEYWORDS_1364_2005;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gn_cadence_types_flag)
|
||||
lexor_keyword_mask |= GN_KEYWORDS_ICARUS;
|
||||
|
||||
if (gn_verilog_ams_flag)
|
||||
lexor_keyword_mask |= GN_KEYWORDS_VAMS_2_3;
|
||||
|
||||
if (verbose_flag) {
|
||||
if (times_flag)
|
||||
@@ -604,11 +658,14 @@ int main(int argc, char*argv[])
|
||||
case GN_VER2001:
|
||||
cout << "IEEE1364-2001";
|
||||
break;
|
||||
case GN_VER2001X:
|
||||
cout << "IEEE1364-2001+Extensions";
|
||||
case GN_VER2005:
|
||||
cout << "IEEE1364-2005";
|
||||
break;
|
||||
}
|
||||
|
||||
if (gn_verilog_ams_flag)
|
||||
cout << ",verilog-ams";
|
||||
|
||||
if (gn_specify_blocks_flag)
|
||||
cout << ",specify";
|
||||
else
|
||||
@@ -619,6 +676,11 @@ int main(int argc, char*argv[])
|
||||
else
|
||||
cout << ",no-xtypes";
|
||||
|
||||
if (gn_icarus_misc_flag)
|
||||
cout << ",icarus-misc";
|
||||
else
|
||||
cout << ",no-icarus-misc";
|
||||
|
||||
cout << endl << "PARSING INPUT" << endl;
|
||||
}
|
||||
|
||||
@@ -627,6 +689,16 @@ int main(int argc, char*argv[])
|
||||
|
||||
if (pf_path) {
|
||||
ofstream out (pf_path);
|
||||
out << "PFORM DUMP NATURES:" << endl;
|
||||
for (map<perm_string,nature_t*>::iterator cur = natures.begin()
|
||||
; cur != natures.end() ; cur ++ ) {
|
||||
pform_dump(out, (*cur).second);
|
||||
}
|
||||
out << "PFORM DUMP DISCIPLINES:" << endl;
|
||||
for (map<perm_string,discipline_t*>::iterator cur = disciplines.begin()
|
||||
; cur != disciplines.end() ; cur ++ ) {
|
||||
pform_dump(out, (*cur).second);
|
||||
}
|
||||
out << "PFORM DUMP MODULES:" << endl;
|
||||
for (map<perm_string,Module*>::iterator mod = pform_modules.begin()
|
||||
; mod != pform_modules.end()
|
||||
@@ -728,7 +800,7 @@ int main(int argc, char*argv[])
|
||||
|
||||
des->set_flags(flags);
|
||||
|
||||
/* Done iwth all the pform data. Delete the modules. */
|
||||
/* Done with all the pform data. Delete the modules. */
|
||||
for (map<perm_string,Module*>::iterator idx = pform_modules.begin()
|
||||
; idx != pform_modules.end() ; idx ++) {
|
||||
|
||||
@@ -753,6 +825,11 @@ int main(int argc, char*argv[])
|
||||
func(des);
|
||||
}
|
||||
|
||||
if (verbose_flag) {
|
||||
cout << "CALCULATING ISLANDS" << endl;
|
||||
}
|
||||
des->join_islands();
|
||||
|
||||
if (net_path) {
|
||||
if (verbose_flag)
|
||||
cerr<<" dumping netlist to " <<net_path<< "..." <<endl;
|
||||
@@ -830,103 +907,3 @@ int main(int argc, char*argv[])
|
||||
|
||||
return des? des->errors : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.95 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.94 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
*
|
||||
* Revision 1.93 2006/09/28 04:35:18 steve
|
||||
* Support selective control of specify and xtypes features.
|
||||
*
|
||||
* Revision 1.92 2005/07/14 23:38:43 steve
|
||||
* Display as version 0.9.devel
|
||||
*
|
||||
* Revision 1.91 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.90 2005/06/28 04:25:55 steve
|
||||
* Remove reference to SystemVerilog.
|
||||
*
|
||||
* Revision 1.89 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.88 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.87 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.86 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.85 2004/09/25 01:58:44 steve
|
||||
* Add a debug_elaborate flag
|
||||
*
|
||||
* Revision 1.84 2004/09/10 23:51:42 steve
|
||||
* Fix the evaluation of constant ternary expressions.
|
||||
*
|
||||
* Revision 1.83 2004/09/05 17:44:42 steve
|
||||
* Add support for module instance arrays.
|
||||
*
|
||||
* Revision 1.82 2004/03/10 04:51:24 steve
|
||||
* Add support for system function table files.
|
||||
*
|
||||
* Revision 1.81 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.80 2004/02/15 00:19:29 steve
|
||||
* Report elaboration errors without crashing.
|
||||
*
|
||||
* Revision 1.79 2003/11/26 01:37:14 steve
|
||||
* Properly initialize vpi_module_list with system.
|
||||
*
|
||||
* Revision 1.78 2003/11/13 05:55:33 steve
|
||||
* Move the DLL= flag to target config files.
|
||||
*
|
||||
* Revision 1.77 2003/11/13 04:09:49 steve
|
||||
* Pass flags through the temporary config file.
|
||||
*
|
||||
* Revision 1.76 2003/11/13 03:10:38 steve
|
||||
* ivl -F and -t flags are onpassed throught the -C file.
|
||||
*
|
||||
* Revision 1.75 2003/11/10 20:59:03 steve
|
||||
* Design::get_flag returns const char* instead of string.
|
||||
*
|
||||
* Revision 1.74 2003/11/01 04:22:30 steve
|
||||
* Accept functors in the config file.
|
||||
*
|
||||
* Revision 1.73 2003/10/26 22:43:42 steve
|
||||
* Improve -V messages,
|
||||
*
|
||||
* Revision 1.72 2003/09/26 02:17:14 steve
|
||||
* Delete pform when done with it.
|
||||
*
|
||||
* Revision 1.71 2003/09/25 00:25:14 steve
|
||||
* Summary list of missing modules.
|
||||
*
|
||||
* Revision 1.70 2003/09/23 05:57:36 steve
|
||||
* Pass -m flag from driver via iconfig file.
|
||||
*
|
||||
* Revision 1.69 2003/09/22 01:12:08 steve
|
||||
* Pass more ivl arguments through the iconfig file.
|
||||
*
|
||||
* Revision 1.68 2003/06/20 00:53:19 steve
|
||||
* Module attributes from the parser
|
||||
* through to elaborated form.
|
||||
*
|
||||
* Revision 1.67 2003/04/24 05:25:27 steve
|
||||
* Dump design even on errors.
|
||||
*
|
||||
* Revision 1.66 2003/03/01 06:25:30 steve
|
||||
* Add the lex_strings string handler, and put
|
||||
* scope names and system task/function names
|
||||
* into this table. Also, permallocate event
|
||||
* names from the beginning.
|
||||
*/
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ critical, but these are the versions I use.
|
||||
msys-1.0 <http://www.mingw/org>
|
||||
msysDTK-1.0 <http://www.mingw.org>
|
||||
Mingw32-5.x <http://www.mingw.org>
|
||||
... including the sub-packages binutils, gcc-core and gcc-g++
|
||||
if you are given the option.
|
||||
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
|
||||
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
|
||||
@@ -91,7 +93,7 @@ commands below.
|
||||
The obvious step 2, then, is install the mingw compilers. These can be
|
||||
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
|
||||
is a convenient remote installer. Download this program and run
|
||||
it. The installer will ask wich components you want to install. You
|
||||
it. The installer will ask which components you want to install. You
|
||||
need only the base C compiler and the C++ compiler. (You may install
|
||||
other languages if you wish.)
|
||||
|
||||
@@ -150,7 +152,7 @@ You will need these gnuwin32 packages to compile Icarus Verilog:
|
||||
I suggest creating a common directory for holding all your gnuwin32
|
||||
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
|
||||
has a "setup" link for each of these packages. Click the setup to
|
||||
download the installer for each of the desired programes, then execute
|
||||
download the installer for each of the desired programs, then execute
|
||||
the downloaded .exe files to invoke the installer. Install into the
|
||||
c:\gunwin32 directory.
|
||||
|
||||
|
||||
+283
-150
@@ -20,6 +20,7 @@
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
# include <cstdlib>
|
||||
|
||||
/*
|
||||
* This source file contains all the implementations of the Design
|
||||
@@ -31,6 +32,7 @@
|
||||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include <sstream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
Design:: Design()
|
||||
: errors(0), nodes_(0), procs_(0), lcounter_(0)
|
||||
@@ -242,6 +244,260 @@ void Design::evaluate_parameters()
|
||||
(*scope)->evaluate_parameters(this);
|
||||
}
|
||||
|
||||
void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
||||
{
|
||||
long msb = 0;
|
||||
long lsb = 0;
|
||||
bool range_flag = false;
|
||||
|
||||
/* Evaluate the msb expression, if it is present. */
|
||||
if ((*cur).second.msb) {
|
||||
eval_expr((*cur).second.msb);
|
||||
if (! eval_as_long(msb, (*cur).second.msb)) {
|
||||
cerr << (*cur).second.expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate msb expression "
|
||||
<< "for parameter " << (*cur).first << ": "
|
||||
<< *(*cur).second.msb << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
range_flag = true;
|
||||
}
|
||||
|
||||
/* Evaluate the lsb expression, if it is present. */
|
||||
if ((*cur).second.lsb) {
|
||||
eval_expr((*cur).second.lsb);
|
||||
if (! eval_as_long(lsb, (*cur).second.lsb)) {
|
||||
cerr << (*cur).second.expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate lsb expression "
|
||||
<< "for parameter " << (*cur).first << ": "
|
||||
<< *(*cur).second.lsb << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
range_flag = true;
|
||||
}
|
||||
|
||||
|
||||
/* Evaluate the parameter expression, if necessary. */
|
||||
NetExpr*expr = (*cur).second.expr;
|
||||
assert(expr);
|
||||
|
||||
eval_expr(expr);
|
||||
|
||||
/* The eval_expr may delete any replace the expr pointer, so the
|
||||
second.expr value cannot be relied on. Might as well replace
|
||||
it now with the expression that we evaluated. */
|
||||
(*cur).second.expr = expr;
|
||||
|
||||
switch (expr->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
if (! dynamic_cast<const NetECReal*>(expr)) {
|
||||
cerr << expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate real parameter value: "
|
||||
<< *expr << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
if (! dynamic_cast<const NetEConst*>(expr)) {
|
||||
cerr << expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate parameter "
|
||||
<< (*cur).first
|
||||
<< " value: " << *expr << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unhandled expression type?" << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the parameter has range information, then make
|
||||
sure the value is set right. Note that if the
|
||||
parameter doesn't have an explicit range, then it
|
||||
will get the signedness from the expression itself. */
|
||||
if (range_flag) {
|
||||
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
|
||||
NetEConst*val = dynamic_cast<NetEConst*>(expr);
|
||||
assert(val);
|
||||
|
||||
verinum value = val->value();
|
||||
|
||||
if (! (value.has_len()
|
||||
&& (value.len() == wid)
|
||||
&& (value.has_sign() == (*cur).second.signed_flag))) {
|
||||
|
||||
verinum tmp (value, wid);
|
||||
tmp.has_sign ( (*cur).second.signed_flag );
|
||||
delete val;
|
||||
val = new NetEConst(tmp);
|
||||
expr = val;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no value ranges to test the value against,
|
||||
// then we are done.
|
||||
if ((*cur).second.range == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
|
||||
ivl_assert(*(*cur).second.expr, (*cur).second.expr);
|
||||
ivl_assert(*(*cur).second.expr, val);
|
||||
|
||||
verinum value = val->value();
|
||||
|
||||
bool from_flag = (*cur).second.range == 0? true : false;
|
||||
for (range_t*value_range = (*cur).second.range
|
||||
; value_range ; value_range = value_range->next) {
|
||||
|
||||
// If we already know that the value is
|
||||
// within a "from" range, then do not test
|
||||
// any more of the from ranges.
|
||||
if (from_flag && value_range->exclude_flag==false)
|
||||
continue;
|
||||
|
||||
if (value_range->low_expr) {
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(value_range->low_expr);
|
||||
ivl_assert(*value_range->low_expr, tmp);
|
||||
if (value_range->low_open_flag && value <= tmp->value())
|
||||
continue;
|
||||
else if (value < tmp->value())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value_range->high_expr) {
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(value_range->high_expr);
|
||||
ivl_assert(*value_range->high_expr, tmp);
|
||||
if (value_range->high_open_flag && value >= tmp->value())
|
||||
continue;
|
||||
else if (value > tmp->value())
|
||||
continue;
|
||||
}
|
||||
|
||||
// Within the range. If this is a "from"
|
||||
// range, then set the from_flag and continue.
|
||||
if (value_range->exclude_flag == false) {
|
||||
from_flag = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// OH NO! In an excluded range. signal an error.
|
||||
from_flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// If we found no from range that contains the
|
||||
// value, then report an error.
|
||||
if (! from_flag) {
|
||||
cerr << val->get_fileline() << ": error: "
|
||||
<< "Parameter value " << value
|
||||
<< " is out of range for parameter " << (*cur).first
|
||||
<< "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
|
||||
{
|
||||
NetExpr*expr = (*cur).second.expr;
|
||||
assert(expr);
|
||||
|
||||
NetECReal*res = 0;
|
||||
eval_expr(expr);
|
||||
|
||||
switch (expr->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
if (NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
|
||||
res = tmp;
|
||||
} else {
|
||||
ivl_assert(*expr, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
verireal val (tmp->value().as_long());
|
||||
res = new NetECReal(val);
|
||||
res->set_line(*tmp);
|
||||
} else {
|
||||
ivl_assert(*expr, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ivl_assert(*expr, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
(*cur).second.expr = res;
|
||||
double value = res->value().as_double();
|
||||
|
||||
bool from_flag = (*cur).second.range == 0? true : false;
|
||||
for (range_t*value_range = (*cur).second.range
|
||||
; value_range ; value_range = value_range->next) {
|
||||
|
||||
if (from_flag && value_range->exclude_flag==false)
|
||||
continue;
|
||||
|
||||
if (value_range->low_expr) {
|
||||
double tmp;
|
||||
bool flag = eval_as_double(tmp, value_range->low_expr);
|
||||
ivl_assert(*value_range->low_expr, flag);
|
||||
if (value_range->low_open_flag && value <= tmp)
|
||||
continue;
|
||||
else if (value < tmp)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value_range->high_expr) {
|
||||
double tmp;
|
||||
bool flag = eval_as_double(tmp, value_range->high_expr);
|
||||
ivl_assert(*value_range->high_expr, flag);
|
||||
if (value_range->high_open_flag && value >= tmp)
|
||||
continue;
|
||||
else if (value > tmp)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value_range->exclude_flag == false) {
|
||||
from_flag = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// All the above tests failed, so we must have tripped
|
||||
// an exclude rule.
|
||||
from_flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (! from_flag) {
|
||||
cerr << res->get_fileline() << ": error: "
|
||||
<< "Parameter value " << value
|
||||
<< " is out of range for parameter " << (*cur).first
|
||||
<< "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void NetScope::evaluate_parameters(Design*des)
|
||||
{
|
||||
NetScope*cur = sub_;
|
||||
@@ -256,163 +512,29 @@ void NetScope::evaluate_parameters(Design*des)
|
||||
// scanning code. Now the parameter expression can be fully
|
||||
// evaluated, or it cannot be evaluated at all.
|
||||
|
||||
typedef map<perm_string,param_expr_t>::iterator mparm_it_t;
|
||||
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
for (param_ref_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
long msb = 0;
|
||||
long lsb = 0;
|
||||
bool range_flag = false;
|
||||
NetExpr*expr;
|
||||
|
||||
/* Evaluate the msb expression, if it is present. */
|
||||
expr = (*cur).second.msb;
|
||||
|
||||
if (expr) {
|
||||
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
|
||||
|
||||
if (! tmp) {
|
||||
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate msb expression "
|
||||
<< "for parameter " << (*cur).first << ": "
|
||||
<< *expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.msb = nexpr;
|
||||
|
||||
tmp = dynamic_cast<NetEConst*>(nexpr);
|
||||
}
|
||||
|
||||
assert(tmp);
|
||||
msb = tmp->value().as_long();
|
||||
range_flag = true;
|
||||
}
|
||||
|
||||
/* Evaluate the lsb expression, if it is present. */
|
||||
expr = (*cur).second.lsb;
|
||||
if (expr) {
|
||||
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
|
||||
|
||||
if (! tmp) {
|
||||
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate lsb expression "
|
||||
<< "for parameter " << (*cur).first << ": "
|
||||
<< *expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.lsb = nexpr;
|
||||
|
||||
tmp = dynamic_cast<NetEConst*>(nexpr);
|
||||
}
|
||||
|
||||
assert(tmp);
|
||||
lsb = tmp->value().as_long();
|
||||
|
||||
assert(range_flag);
|
||||
}
|
||||
|
||||
|
||||
/* Evaluate the parameter expression, if necessary. */
|
||||
expr = (*cur).second.expr;
|
||||
assert(expr);
|
||||
|
||||
switch (expr->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
if (! dynamic_cast<const NetECReal*>(expr)) {
|
||||
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate real parameter value: "
|
||||
<< *expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.expr = nexpr;
|
||||
}
|
||||
switch ((*cur).second.type) {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
evaluate_parameter_logic_(des, cur);
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
if (! dynamic_cast<const NetEConst*>(expr)) {
|
||||
|
||||
// Try to evaluate the expression.
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate parameter "
|
||||
<< (*cur).first
|
||||
<< " value: " <<
|
||||
*expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The evaluate worked, replace the old
|
||||
// expression with this constant value.
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.expr = nexpr;
|
||||
|
||||
// Set the signedness flag.
|
||||
(*cur).second.expr
|
||||
->cast_signed( (*cur).second.signed_flag );
|
||||
}
|
||||
case IVL_VT_REAL:
|
||||
evaluate_parameter_real_(des, cur);
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << (*cur).second.expr->get_fileline()
|
||||
<< ": internal error: "
|
||||
<< "unhandled expression type?" << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the parameter has range information, then make
|
||||
sure the value is set right. */
|
||||
if (range_flag) {
|
||||
unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
|
||||
wid += 1;
|
||||
|
||||
NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
|
||||
assert(val);
|
||||
|
||||
verinum value = val->value();
|
||||
|
||||
if (! (value.has_len()
|
||||
&& (value.len() == wid)
|
||||
&& (value.has_sign() == (*cur).second.signed_flag))) {
|
||||
|
||||
verinum tmp (value, wid);
|
||||
tmp.has_sign ( (*cur).second.signed_flag );
|
||||
delete val;
|
||||
val = new NetEConst(tmp);
|
||||
(*cur).second.expr = val;
|
||||
}
|
||||
cerr << (*cur).second.get_fileline() << ": internal error: "
|
||||
<< "Unexpected expression type " << (*cur).second.type
|
||||
<< "." << endl;
|
||||
cerr << (*cur).second.get_fileline() << ": : "
|
||||
<< "Parameter name: " << (*cur).first << endl;
|
||||
cerr << (*cur).second.get_fileline() << ": : "
|
||||
<< "Expression is: " << *(*cur).second.expr << endl;
|
||||
ivl_assert((*cur).second, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,3 +677,14 @@ void Design::delete_process(NetProcTop*top)
|
||||
delete top;
|
||||
}
|
||||
|
||||
void Design::join_islands(void)
|
||||
{
|
||||
if (nodes_ == 0)
|
||||
return;
|
||||
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
do {
|
||||
join_island(cur);
|
||||
cur = cur->node_next_;
|
||||
} while (cur != nodes_->node_next_);
|
||||
}
|
||||
|
||||
+39
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2008 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
|
||||
@@ -20,6 +20,7 @@
|
||||
# include "config.h"
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
@@ -80,6 +81,7 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
|
||||
}
|
||||
|
||||
unsigned pad_width = lossless_flag? 1 : 0;
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
|
||||
/* Now that we have the operand sizes the way we like, or as
|
||||
good as we are going to get them, set the size of myself. */
|
||||
@@ -90,8 +92,6 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
|
||||
} else {
|
||||
expr_width(l->expr_width() + pad_width);
|
||||
}
|
||||
|
||||
cast_signed(l->has_sign() && r->has_sign());
|
||||
}
|
||||
|
||||
NetEBAdd::~NetEBAdd()
|
||||
@@ -218,6 +218,27 @@ ivl_variable_type_t NetEBDiv::expr_type() const
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBMinMax::NetEBMinMax(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
expr_width( max(l->expr_width(), r->expr_width()) );
|
||||
cast_signed(l->has_sign() || r->has_sign());
|
||||
}
|
||||
|
||||
NetEBMinMax::~NetEBMinMax()
|
||||
{
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEBMinMax::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
@@ -258,7 +279,8 @@ NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
assert(op == 'p');
|
||||
expr_width(l->expr_width());
|
||||
/* This is incorrect! a * (2^b - 1) is close. */
|
||||
expr_width(l->expr_width()+r->expr_width());
|
||||
cast_signed(l->has_sign() || r->has_sign());
|
||||
}
|
||||
|
||||
@@ -365,15 +387,7 @@ unsigned NetEConcat::repeat()
|
||||
if (repeat_calculated_)
|
||||
return repeat_value_;
|
||||
|
||||
assert(repeat_);
|
||||
|
||||
if (! dynamic_cast<NetEConst*>(repeat_)) {
|
||||
NetExpr*tmp = repeat_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete repeat_;
|
||||
repeat_ = tmp;
|
||||
}
|
||||
}
|
||||
eval_expr(repeat_);
|
||||
|
||||
NetEConst*repeat_const = dynamic_cast<NetEConst*>(repeat_);
|
||||
|
||||
@@ -462,7 +476,12 @@ NetEParam::NetEParam()
|
||||
}
|
||||
|
||||
NetEParam::NetEParam(Design*d, NetScope*s, perm_string n)
|
||||
: des_(d), scope_(s), name_(n)
|
||||
: des_(d), scope_(s), reference_(scope_->find_parameter(n))
|
||||
{
|
||||
}
|
||||
|
||||
NetEParam::NetEParam(Design*d, NetScope*s, ref_t ref)
|
||||
: des_(d), scope_(s), reference_(ref)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -475,9 +494,14 @@ bool NetEParam::has_width() const
|
||||
return false;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEParam::expr_type() const
|
||||
{
|
||||
return (*reference_).second.type;
|
||||
}
|
||||
|
||||
NetEParam* NetEParam::dup_expr() const
|
||||
{
|
||||
NetEParam*tmp = new NetEParam(des_, scope_, name_);
|
||||
NetEParam*tmp = new NetEParam(des_, scope_, reference_);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
+18
@@ -49,6 +49,24 @@ NetUserFunc::~NetUserFunc()
|
||||
{
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetUserFunc::data_type(unsigned port) const
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
|
||||
/* Port 0 is the return port. */
|
||||
if (port == 0) {
|
||||
const NetNet*sig = def->return_sig();
|
||||
assert(sig);
|
||||
return sig->data_type();
|
||||
}
|
||||
|
||||
port -= 1;
|
||||
assert(port < def->port_count());
|
||||
const NetNet*port_sig = def->port(port);
|
||||
|
||||
return port_sig->data_type();
|
||||
}
|
||||
|
||||
unsigned NetUserFunc::port_width(unsigned port) const
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
|
||||
+20
-85
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2008 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,9 +16,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_link.cc,v 1.21 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
@@ -101,6 +98,11 @@ Link::DIR Link::get_dir() const
|
||||
return dir_;
|
||||
}
|
||||
|
||||
void Link::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
|
||||
{
|
||||
nexus_->drivers_delays(rise, fall, decay);
|
||||
}
|
||||
|
||||
void Link::drive0(Link::strength_t str)
|
||||
{
|
||||
drive0_ = str;
|
||||
@@ -245,6 +247,19 @@ verinum::V Nexus::get_init() const
|
||||
return verinum::Vz;
|
||||
}
|
||||
|
||||
void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
|
||||
{
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() != Link::OUTPUT)
|
||||
continue;
|
||||
|
||||
NetObj*obj = cur->get_obj();
|
||||
obj->rise_time(rise);
|
||||
obj->fall_time(fall);
|
||||
obj->decay_time(decay);
|
||||
}
|
||||
}
|
||||
|
||||
void Nexus::unlink(Link*that)
|
||||
{
|
||||
if (name_) {
|
||||
@@ -413,7 +428,7 @@ NexusSet::~NexusSet()
|
||||
{
|
||||
if (nitems_ > 0) {
|
||||
assert(items_ != 0);
|
||||
delete[] items_;
|
||||
free(items_);
|
||||
} else {
|
||||
assert(items_ == 0);
|
||||
}
|
||||
@@ -523,83 +538,3 @@ bool NexusSet::intersect(const NexusSet&that) const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.21 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.20 2007/03/26 18:17:50 steve
|
||||
* Remove pretense of general use for t_cookie.
|
||||
*
|
||||
* Revision 1.19 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.18 2005/09/25 23:40:11 steve
|
||||
* Simplify NexusSet set handling.
|
||||
*
|
||||
* Revision 1.17 2005/06/13 23:22:37 steve
|
||||
* Fix compile errors.
|
||||
*
|
||||
* Revision 1.16 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.15 2005/01/09 20:16:01 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.14 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.13 2003/01/14 21:16:18 steve
|
||||
* Move strstream to ostringstream for compatibility.
|
||||
*
|
||||
* Revision 1.12 2002/10/21 01:42:08 steve
|
||||
* Synthesizer support for synchronous begin-end blocks.
|
||||
*
|
||||
* Revision 1.11 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
* Revision 1.10 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.9 2002/07/03 03:08:47 steve
|
||||
* Clear drive cache on link or unlink.
|
||||
*
|
||||
* Revision 1.8 2002/06/30 02:21:31 steve
|
||||
* Add structure for asynchronous logic synthesis.
|
||||
*
|
||||
* Revision 1.7 2002/06/24 01:49:39 steve
|
||||
* Make link_drive_constant cache its results in
|
||||
* the Nexus, to improve cprop performance.
|
||||
*
|
||||
* Revision 1.6 2002/04/21 04:59:08 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.5 2001/07/25 03:10:49 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.4 2000/10/06 23:46:50 steve
|
||||
* ivl_target updates, including more complete
|
||||
* handling of ivl_nexus_t objects. Much reduced
|
||||
* dependencies on pointers to netlist objects.
|
||||
*
|
||||
* Revision 1.3 2000/08/26 00:54:03 steve
|
||||
* Get at gate information for ivl_target interface.
|
||||
*
|
||||
* Revision 1.2 2000/07/14 06:12:57 steve
|
||||
* Move inital value handling from NetNet to Nexus
|
||||
* objects. This allows better propogation of inital
|
||||
* values.
|
||||
*
|
||||
* Clean up constant propagation a bit to account
|
||||
* for regs that are not really values.
|
||||
*
|
||||
* Revision 1.1 2000/06/25 19:59:42 steve
|
||||
* Redesign Links to include the Nexus class that
|
||||
* carries properties of the connected set of links.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1
-1
@@ -180,7 +180,7 @@ NexusSet* NetAssignBase::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result = rval_->nex_input(rem_out);
|
||||
|
||||
/* It is possible that the lval_ can hav nex_input values. In
|
||||
/* It is possible that the lval_ can have nex_input values. In
|
||||
particular, index expressions are statement inputs as well,
|
||||
so should be addressed here. */
|
||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ void NetPDelay::nex_output(NexusSet&out)
|
||||
|
||||
/*
|
||||
* For the purposes of synthesis, system task calls have no output at
|
||||
* all. This is OK because most system tasks are not synthesizeable in
|
||||
* all. This is OK because most system tasks are not synthesizable in
|
||||
* the first place.
|
||||
*/
|
||||
void NetSTask::nex_output(NexusSet&out)
|
||||
|
||||
+73
-22
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2008 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,16 +16,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_scope.cc,v 1.38 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
|
||||
# include "netlist.h"
|
||||
# include <cstring>
|
||||
# include <cstdlib>
|
||||
# include <sstream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* The NetScope class keeps a scope tree organized. Each node of the
|
||||
@@ -44,11 +43,13 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
|
||||
lcounter_ = 0;
|
||||
|
||||
if (up) {
|
||||
default_nettype_ = up->default_nettype();
|
||||
time_unit_ = up->time_unit();
|
||||
time_prec_ = up->time_precision();
|
||||
sib_ = up_->sub_;
|
||||
up_->sub_ = this;
|
||||
} else {
|
||||
default_nettype_ = NetNet::NONE;
|
||||
time_unit_ = 0;
|
||||
time_prec_ = 0;
|
||||
assert(t == MODULE);
|
||||
@@ -79,15 +80,50 @@ NetScope::~NetScope()
|
||||
/* name_ and module_name_ are perm-allocated. */
|
||||
}
|
||||
|
||||
void NetScope::set_line(const LineInfo*info)
|
||||
{
|
||||
file_ = info->get_file();
|
||||
def_file_ = file_;
|
||||
lineno_ = info->get_lineno();
|
||||
def_lineno_ = lineno_;
|
||||
}
|
||||
|
||||
void NetScope::set_line(perm_string file, unsigned lineno)
|
||||
{
|
||||
file_ = file;
|
||||
def_file_ = file;
|
||||
lineno_ = lineno;
|
||||
def_lineno_ = lineno;
|
||||
}
|
||||
|
||||
void NetScope::set_line(perm_string file, perm_string def_file,
|
||||
unsigned lineno, unsigned def_lineno)
|
||||
{
|
||||
file_ = file;
|
||||
def_file_ = def_file;
|
||||
lineno_ = lineno;
|
||||
def_lineno_ = def_lineno;
|
||||
}
|
||||
|
||||
NetExpr* NetScope::set_parameter(perm_string key, NetExpr*expr,
|
||||
NetExpr*msb, NetExpr*lsb, bool signed_flag)
|
||||
ivl_variable_type_t type,
|
||||
NetExpr*msb, NetExpr*lsb, bool signed_flag,
|
||||
NetScope::range_t*range_list,
|
||||
const LineInfo&file_line)
|
||||
{
|
||||
param_expr_t&ref = parameters[key];
|
||||
NetExpr* res = ref.expr;
|
||||
ref.expr = expr;
|
||||
ref.type = type;
|
||||
ref.msb = msb;
|
||||
ref.lsb = lsb;
|
||||
ref.signed_flag = signed_flag;
|
||||
ivl_assert(file_line, ref.range == 0);
|
||||
ref.range = range_list;
|
||||
ref.set_line(file_line);
|
||||
|
||||
ivl_assert(file_line, type != IVL_VT_NO_TYPE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -110,29 +146,30 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return false if this creates a new parameter.
|
||||
* Return false if the parameter does not already exist.
|
||||
* A parameter is not automatically created.
|
||||
*/
|
||||
bool NetScope::replace_parameter(perm_string key, NetExpr*expr)
|
||||
{
|
||||
bool flag = true;
|
||||
param_expr_t&ref = parameters[key];
|
||||
bool flag = false;
|
||||
|
||||
NetExpr* res = ref.expr;
|
||||
if (parameters.find(key) != parameters.end()) {
|
||||
param_expr_t&ref = parameters[key];
|
||||
|
||||
if (res) {
|
||||
delete res;
|
||||
} else {
|
||||
flag = false;
|
||||
ref.msb = 0;
|
||||
ref.lsb = 0;
|
||||
ref.signed_flag = false;
|
||||
delete ref.expr;
|
||||
ref.expr = expr;
|
||||
flag = true;
|
||||
}
|
||||
|
||||
ref.expr = expr;
|
||||
return flag;
|
||||
}
|
||||
|
||||
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
|
||||
/*
|
||||
* This is not really complete (msb, lsb, sign). It is currently only
|
||||
* used to add a genver to the local parameter list.
|
||||
*/
|
||||
NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr,
|
||||
const LineInfo&file_line)
|
||||
{
|
||||
param_expr_t&ref = localparams[key];
|
||||
NetExpr* res = ref.expr;
|
||||
@@ -140,6 +177,7 @@ NetExpr* NetScope::set_localparam(perm_string key, NetExpr*expr)
|
||||
ref.msb = 0;
|
||||
ref.lsb = 0;
|
||||
ref.signed_flag = false;
|
||||
ref.set_line(file_line);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -172,6 +210,20 @@ const NetExpr* NetScope::get_parameter(const char* key,
|
||||
|
||||
return 0;
|
||||
}
|
||||
map<perm_string,NetScope::param_expr_t>::iterator NetScope::find_parameter(perm_string key)
|
||||
{
|
||||
map<perm_string,param_expr_t>::iterator idx;
|
||||
|
||||
idx = parameters.find(key);
|
||||
if (idx != parameters.end())
|
||||
return idx;
|
||||
|
||||
idx = localparams.find(perm_string::literal(key));
|
||||
if (idx != localparams.end())
|
||||
return idx;
|
||||
|
||||
return (map<perm_string,param_expr_t>::iterator) 0;
|
||||
}
|
||||
|
||||
NetScope::TYPE NetScope::type() const
|
||||
{
|
||||
@@ -295,10 +347,10 @@ void NetScope::rem_event(NetEvent*ev)
|
||||
}
|
||||
|
||||
|
||||
NetEvent* NetScope::find_event(const char*name)
|
||||
NetEvent* NetScope::find_event(perm_string name)
|
||||
{
|
||||
for (NetEvent*cur = events_; cur ; cur = cur->snext_)
|
||||
if (strcmp(cur->name(), name) == 0)
|
||||
if (cur->name() == name)
|
||||
return cur;
|
||||
|
||||
return 0;
|
||||
@@ -337,7 +389,7 @@ void NetScope::rem_signal(NetNet*net)
|
||||
* is assumed to be the base name of the signal, so no sub-scopes are
|
||||
* searched.
|
||||
*/
|
||||
NetNet* NetScope::find_signal(const char*key)
|
||||
NetNet* NetScope::find_signal(perm_string key)
|
||||
{
|
||||
if (signals_ == 0)
|
||||
return 0;
|
||||
@@ -403,4 +455,3 @@ string NetScope::local_hsymbol()
|
||||
return string(name()) + "." + string(local_symbol());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include <typeinfo>
|
||||
# include <cstdlib>
|
||||
# include "compiler.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "ivl_target_priv.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
static bool has_enable(ivl_switch_type_t tt)
|
||||
{
|
||||
switch (tt) {
|
||||
case IVL_SW_TRANIF0:
|
||||
case IVL_SW_TRANIF1:
|
||||
case IVL_SW_RTRANIF0:
|
||||
case IVL_SW_RTRANIF1:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NetTran::NetTran(NetScope*scope, perm_string n, ivl_switch_type_t tt)
|
||||
: NetNode(scope, n, has_enable(tt)? 3 : 2), type_(tt)
|
||||
{
|
||||
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
|
||||
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
|
||||
if (pin_count() == 3) {
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("E"), 0);
|
||||
}
|
||||
}
|
||||
|
||||
NetTran::NetTran(NetScope*scope, perm_string n, unsigned wid, unsigned part, unsigned off)
|
||||
: NetNode(scope, n, 2), type_(IVL_SW_TRAN_VP), wid_(wid), part_(part), off_(off)
|
||||
{
|
||||
pin(0).set_dir(Link::PASSIVE); pin(0).set_name(perm_string::literal("A"), 0);
|
||||
pin(1).set_dir(Link::PASSIVE); pin(1).set_name(perm_string::literal("B"), 0);
|
||||
}
|
||||
|
||||
NetTran::~NetTran()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetTran::vector_width() const
|
||||
{
|
||||
return wid_;
|
||||
}
|
||||
|
||||
unsigned NetTran::part_width() const
|
||||
{
|
||||
return part_;
|
||||
}
|
||||
|
||||
unsigned NetTran::part_offset() const
|
||||
{
|
||||
return off_;
|
||||
}
|
||||
|
||||
void join_island(NetObj*obj)
|
||||
{
|
||||
IslandBranch*branch = dynamic_cast<IslandBranch*> (obj);
|
||||
|
||||
// If this is not even a branch, then stop now.
|
||||
if (branch == 0)
|
||||
return;
|
||||
|
||||
// If this is a branch, but already given to an island, then
|
||||
// stop.
|
||||
if (branch->island)
|
||||
return;
|
||||
|
||||
list<NetObj*> uncommitted_neighbors;
|
||||
|
||||
// Look for neighboring objects that might already be in
|
||||
// islands. If we find something, then join that island.
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
|
||||
Nexus*nex = obj->pin(idx).nexus();
|
||||
for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
unsigned pin;
|
||||
NetObj*tmp;
|
||||
cur->cur_link(tmp, pin);
|
||||
|
||||
// Skip self.
|
||||
if (tmp == obj)
|
||||
continue;
|
||||
|
||||
// If tmb is not a branch, then skip it.
|
||||
IslandBranch*tmp_branch = dynamic_cast<IslandBranch*> (tmp);
|
||||
if (tmp_branch == 0)
|
||||
continue;
|
||||
|
||||
// If that is an uncommitted branch, then save
|
||||
// it. When I finally choose an island for self,
|
||||
// these branches will be scanned so tha they join
|
||||
// this island as well.
|
||||
if (tmp_branch->island == 0) {
|
||||
uncommitted_neighbors.push_back(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
ivl_assert(*obj, branch->island==0 || branch->island==tmp_branch->island);
|
||||
|
||||
// We found an existing island to join. Join it
|
||||
// now. Keep scanning in order to find more neighbors.
|
||||
if (branch->island == 0) {
|
||||
if (debug_elaborate)
|
||||
cerr << obj->get_fileline() << ": debug: "
|
||||
<< "Join brach to existing island." << endl;
|
||||
branch->island = tmp_branch->island;
|
||||
|
||||
} else if (branch->island != tmp_branch->island) {
|
||||
cerr << obj->get_fileline() << ": internal error: "
|
||||
<< "Oops, Found 2 neighboring islands." << endl;
|
||||
ivl_assert(*obj, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If after all that we did not find an idland to join, then
|
||||
// start the island not and join it.
|
||||
if (branch->island == 0) {
|
||||
branch->island = new ivl_island_s;
|
||||
branch->island->discipline = 0;
|
||||
if (debug_elaborate)
|
||||
cerr << obj->get_fileline() << ": debug: "
|
||||
<< "Create new island for this branch" << endl;
|
||||
}
|
||||
|
||||
// Now scan all the uncommitted neighbors I found. Calling
|
||||
// join_island() on them will cause them to notice me in the
|
||||
// process, and thus they will join my island. This process
|
||||
// will recurse until all the connected branches join this island.
|
||||
for (list<NetObj*>::iterator cur = uncommitted_neighbors.begin()
|
||||
; cur != uncommitted_neighbors.end() ; cur ++ ) {
|
||||
join_island(*cur);
|
||||
}
|
||||
}
|
||||
+318
-169
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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
|
||||
@@ -235,11 +235,12 @@ NetBus::~NetBus()
|
||||
{
|
||||
}
|
||||
|
||||
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n,
|
||||
unsigned npins, bool condit_src)
|
||||
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins,
|
||||
bool condit_src, bool conditional)
|
||||
: NetObj(s, n, npins + (condit_src?1:0))
|
||||
{
|
||||
condit_flag_ = false;
|
||||
conditional_ = conditional;
|
||||
posedge_ = false;
|
||||
negedge_ = false;
|
||||
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
|
||||
@@ -379,6 +380,11 @@ const Link& NetDelaySrc::src_pin(unsigned idx) const
|
||||
}
|
||||
|
||||
bool NetDelaySrc::is_condit() const
|
||||
{
|
||||
return conditional_;
|
||||
}
|
||||
|
||||
bool NetDelaySrc::has_condit() const
|
||||
{
|
||||
return condit_flag_;
|
||||
}
|
||||
@@ -398,10 +404,11 @@ const Link& NetDelaySrc::condit_pin() const
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
|
||||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||
signed_(false), msb_(npins-1), lsb_(0), dimensions_(0), s0_(0), e0_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
signed_(false), isint_(false), msb_(npins-1), lsb_(0), dimensions_(0),
|
||||
s0_(0), e0_(0), local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
assert(npins>0);
|
||||
|
||||
verinum::V init_value = verinum::Vz;
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
@@ -437,7 +444,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
: NetObj(s, n, 1),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||
msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
|
||||
isint_(false), msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
@@ -483,8 +490,8 @@ static unsigned calculate_count(long s, long e)
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls, long array_s, long array_e)
|
||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||
sig_next_(0), sig_prev_(0), type_(t), port_type_(NOT_A_PORT),
|
||||
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
||||
msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
@@ -641,7 +648,7 @@ bool NetNet::sb_is_valid(long sb) const
|
||||
return (sb <= lsb_) && (sb >= msb_);
|
||||
}
|
||||
|
||||
unsigned NetNet::sb_to_idx(long sb) const
|
||||
long NetNet::sb_to_idx(long sb) const
|
||||
{
|
||||
if (msb_ >= lsb_)
|
||||
return sb - lsb_;
|
||||
@@ -754,10 +761,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
|
||||
pin(0).set_dir(Link::INPUT);
|
||||
pin(1).set_dir(Link::OUTPUT);
|
||||
break;
|
||||
case NetPartSelect::BI:
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(1).set_dir(Link::OUTPUT);
|
||||
break;
|
||||
}
|
||||
pin(0).set_name(perm_string::literal("Part"), 0);
|
||||
pin(1).set_name(perm_string::literal("Vect"), 0);
|
||||
@@ -780,10 +783,6 @@ NetPartSelect::NetPartSelect(NetNet*sig, NetNet*sel,
|
||||
pin(0).set_dir(Link::INPUT);
|
||||
pin(1).set_dir(Link::OUTPUT);
|
||||
break;
|
||||
case NetPartSelect::BI:
|
||||
pin(0).set_dir(Link::PASSIVE);
|
||||
pin(1).set_dir(Link::PASSIVE);
|
||||
break;
|
||||
}
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
|
||||
@@ -1039,6 +1038,24 @@ const verinum& NetFF::sset_value() const
|
||||
}
|
||||
|
||||
|
||||
NetAbs::NetAbs(NetScope*s, perm_string n, unsigned w)
|
||||
: NetNode(s, n, 2), width_(w)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
}
|
||||
|
||||
NetAbs::~NetAbs()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetAbs::width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetAddSub class represents an LPM_ADD_SUB device. The pinout is
|
||||
* assigned like so:
|
||||
@@ -1132,6 +1149,9 @@ NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Address"), 0);
|
||||
// Increment the expression reference count for the target
|
||||
// memory so that it is not deleted underneath me.
|
||||
mem->incr_eref();
|
||||
}
|
||||
|
||||
NetArrayDq::~NetArrayDq()
|
||||
@@ -1553,6 +1573,78 @@ const Link& NetMult::pin_DataB() const
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
NetPow::NetPow(NetScope*sc, perm_string n, unsigned wr,
|
||||
unsigned wa, unsigned wb)
|
||||
: NetNode(sc, n, 3),
|
||||
signed_(false), width_r_(wr), width_a_(wa), width_b_(wb)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("DataB"), 0);
|
||||
}
|
||||
|
||||
NetPow::~NetPow()
|
||||
{
|
||||
}
|
||||
|
||||
void NetPow::set_signed(bool flag)
|
||||
{
|
||||
signed_ = flag;
|
||||
}
|
||||
|
||||
bool NetPow::get_signed() const
|
||||
{
|
||||
return signed_;
|
||||
}
|
||||
|
||||
unsigned NetPow::width_r() const
|
||||
{
|
||||
return width_r_;
|
||||
}
|
||||
|
||||
unsigned NetPow::width_a() const
|
||||
{
|
||||
return width_a_;
|
||||
}
|
||||
|
||||
unsigned NetPow::width_b() const
|
||||
{
|
||||
return width_b_;
|
||||
}
|
||||
|
||||
Link& NetPow::pin_Result()
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetPow::pin_Result() const
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetPow::pin_DataA()
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetPow::pin_DataA() const
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
Link& NetPow::pin_DataB()
|
||||
{
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
const Link& NetPow::pin_DataB() const
|
||||
{
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* The NetMux class represents an LPM_MUX device. The pinout is assigned
|
||||
* like so:
|
||||
@@ -1842,8 +1934,9 @@ const NetExpr* NetSTask::parm(unsigned idx) const
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
NetEUFunc::NetEUFunc(NetScope*def, NetESignal*res, svector<NetExpr*>&p)
|
||||
: func_(def), result_sig_(res), parms_(p)
|
||||
NetEUFunc::NetEUFunc(NetScope*scope, NetScope*def, NetESignal*res,
|
||||
svector<NetExpr*>&p)
|
||||
: scope_(scope), func_(def), result_sig_(res), parms_(p)
|
||||
{
|
||||
expr_width(result_sig_->expr_width());
|
||||
}
|
||||
@@ -2186,6 +2279,11 @@ ivl_variable_type_t NetETernary::expr_type() const
|
||||
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
|
||||
return IVL_VT_LOGIC;
|
||||
|
||||
if (tru == IVL_VT_REAL && (fal == IVL_VT_LOGIC || fal == IVL_VT_BOOL))
|
||||
return IVL_VT_REAL;
|
||||
if (fal == IVL_VT_REAL && (tru == IVL_VT_LOGIC || tru == IVL_VT_BOOL))
|
||||
return IVL_VT_REAL;
|
||||
|
||||
if (tru != fal) {
|
||||
cerr << get_fileline() << ": internal error:"
|
||||
<< " Unexpected ?: type clash:"
|
||||
@@ -2206,6 +2304,7 @@ NetEUnary::NetEUnary(char op, NetExpr*ex)
|
||||
switch (op_) {
|
||||
case '-':
|
||||
case '+':
|
||||
case 'm': // abs()
|
||||
cast_signed(ex->has_sign());
|
||||
break;
|
||||
default:
|
||||
@@ -2337,155 +2436,205 @@ const NetProc*NetTaskDef::proc() const
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.258 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.257 2007/04/02 01:12:34 steve
|
||||
* Seperate arrayness from word count
|
||||
*
|
||||
* Revision 1.256 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.255 2007/03/01 06:19:38 steve
|
||||
* Add support for conditional specify delay paths.
|
||||
*
|
||||
* Revision 1.254 2007/02/20 05:58:36 steve
|
||||
* Handle unary minus of real valued expressions.
|
||||
*
|
||||
* Revision 1.253 2007/02/14 05:59:46 steve
|
||||
* Handle type of ternary expressions properly.
|
||||
*
|
||||
* Revision 1.252 2007/01/19 04:25:37 steve
|
||||
* Fix missing passive setting for array word pins.
|
||||
*
|
||||
* Revision 1.251 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.250 2006/11/10 04:54:26 steve
|
||||
* Add test_width methods for PETernary and PEString.
|
||||
*
|
||||
* Revision 1.249 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
* Revision 1.248 2005/09/14 02:53:14 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.247 2005/08/06 17:58:16 steve
|
||||
* Implement bi-directional part selects.
|
||||
*
|
||||
* Revision 1.246 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.245 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.244 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.243 2005/05/08 23:44:08 steve
|
||||
* Add support for variable part select.
|
||||
*
|
||||
* Revision 1.242 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.241 2005/04/08 04:51:16 steve
|
||||
* All memory addresses are signed.
|
||||
*
|
||||
* Revision 1.240 2005/04/06 05:29:08 steve
|
||||
* Rework NetRamDq and IVL_LPM_RAM nodes.
|
||||
*
|
||||
* Revision 1.239 2005/03/09 05:52:04 steve
|
||||
* Handle case inequality in netlists.
|
||||
*
|
||||
* Revision 1.238 2005/02/19 02:43:38 steve
|
||||
* Support shifts and divide.
|
||||
*
|
||||
* Revision 1.237 2005/02/12 06:25:40 steve
|
||||
* Restructure NetMux devices to pass vectors.
|
||||
* Generate NetMux devices from ternary expressions,
|
||||
* Reduce NetMux devices to bufif when appropriate.
|
||||
*
|
||||
* Revision 1.236 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.235 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.234 2005/01/28 05:39:33 steve
|
||||
* Simplified NetMult and IVL_LPM_MULT.
|
||||
*
|
||||
* Revision 1.233 2005/01/24 05:28:30 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.232 2005/01/22 18:16:01 steve
|
||||
* Remove obsolete NetSubnet class.
|
||||
*
|
||||
* Revision 1.231 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.230 2005/01/16 04:20:32 steve
|
||||
* Implement LPM_COMPARE nodes as two-input vector functors.
|
||||
*
|
||||
* Revision 1.229 2005/01/09 20:16:01 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.228 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.227 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.226 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.225 2004/06/30 02:16:26 steve
|
||||
* Implement signed divide and signed right shift in nets.
|
||||
*
|
||||
* Revision 1.224 2004/06/13 04:56:54 steve
|
||||
* Add support for the default_nettype directive.
|
||||
*
|
||||
* Revision 1.223 2004/05/31 23:34:37 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
* speed and more type support.
|
||||
*
|
||||
* Revision 1.222 2004/02/20 06:22:56 steve
|
||||
* parameter keys are per_strings.
|
||||
*
|
||||
* Revision 1.221 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.220 2003/11/10 19:44:30 steve
|
||||
* Fix return value warnings.
|
||||
*
|
||||
* Revision 1.219 2003/09/03 23:32:10 steve
|
||||
* Oops, missing pin_Sset implementation.
|
||||
*
|
||||
* Revision 1.218 2003/08/15 02:23:52 steve
|
||||
* Add synthesis support for synchronous reset.
|
||||
*
|
||||
* Revision 1.217 2003/07/05 20:42:08 steve
|
||||
* Fix some enumeration warnings.
|
||||
*
|
||||
* Revision 1.216 2003/06/18 03:55:18 steve
|
||||
* Add arithmetic shift operators.
|
||||
*
|
||||
* Revision 1.215 2003/05/01 01:13:57 steve
|
||||
* More complete bit range internal error message,
|
||||
* Better test of part select ranges on non-zero
|
||||
* signal ranges.
|
||||
* These are the delay_type() functions. They are used to determine
|
||||
* the type of delay for the given object.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function implements the following table:
|
||||
*
|
||||
* in_A in_B out
|
||||
* NO NO NO
|
||||
* NO ZERO ZERO
|
||||
* NO POS POS
|
||||
* NO DEF POS
|
||||
* ZERO NO ZERO
|
||||
* ZERO ZERO ZERO
|
||||
* ZERO POS POS
|
||||
* ZERO DEF POS
|
||||
* POS NO POS
|
||||
* POS ZERO POS
|
||||
* POS POS POS
|
||||
* POS DEF POS
|
||||
* DEF NO POS
|
||||
* DEF ZERO POS
|
||||
* DEF POS POS
|
||||
* DEF DEF DEF
|
||||
*
|
||||
* It is used to combine two delay values.
|
||||
*/
|
||||
static DelayType combine_delays(const DelayType a, const DelayType b)
|
||||
{
|
||||
/* The default is POSSIBLE_DELAY. */
|
||||
DelayType result = POSSIBLE_DELAY;
|
||||
|
||||
/* If both are no or zero delay then we return ZERO_DELAY. */
|
||||
if ((a == NO_DELAY || a == ZERO_DELAY) &&
|
||||
(b == NO_DELAY || b == ZERO_DELAY)) {
|
||||
result = ZERO_DELAY;
|
||||
}
|
||||
|
||||
/* Except if both are no delay then we return NO_DELAY. */
|
||||
if (a == NO_DELAY && b == NO_DELAY) {
|
||||
result = NO_DELAY;
|
||||
}
|
||||
|
||||
/* If both are definite delay then we return DEFINITE_DELAY. */
|
||||
if (a == DEFINITE_DELAY && b == DEFINITE_DELAY) {
|
||||
result = DEFINITE_DELAY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is used to see what we can find out about the delay when it
|
||||
* is given as an expression. We also use this for loop expressions.
|
||||
*/
|
||||
static DelayType delay_type_from_expr(const NetExpr*expr)
|
||||
{
|
||||
DelayType result = POSSIBLE_DELAY;
|
||||
|
||||
if (const NetEConst*e = dynamic_cast<const NetEConst*>(expr)) {
|
||||
if (e->value().is_zero()) result = ZERO_DELAY;
|
||||
else result = DEFINITE_DELAY;
|
||||
}
|
||||
|
||||
if (const NetECReal*e = dynamic_cast<const NetECReal*>(expr)) {
|
||||
if (e->value().as_double() == 0.0) result = ZERO_DELAY;
|
||||
else result = DEFINITE_DELAY;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* The looping structures can use the same basic code so put it here
|
||||
* instead of duplicating it for each one (repeat and while).
|
||||
*/
|
||||
static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc)
|
||||
{
|
||||
DelayType result;
|
||||
|
||||
switch (delay_type_from_expr(expr)) {
|
||||
/* We have a constant false expression so the body never runs. */
|
||||
case ZERO_DELAY:
|
||||
result = NO_DELAY;
|
||||
break;
|
||||
/* We have a constant true expression so the body always runs. */
|
||||
case DEFINITE_DELAY:
|
||||
result = proc->delay_type();
|
||||
break;
|
||||
/* We don't know if the body will run so reduce a DEFINITE_DELAY
|
||||
* to a POSSIBLE_DELAY. All other stay the same. */
|
||||
case POSSIBLE_DELAY:
|
||||
result = combine_delays(NO_DELAY, proc->delay_type());
|
||||
break;
|
||||
/* This should never happen since delay_type_from_expr() only
|
||||
* returns three different values. */
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The default object does not have any delay. */
|
||||
DelayType NetProc::delay_type() const
|
||||
{
|
||||
return NO_DELAY;
|
||||
}
|
||||
|
||||
DelayType NetBlock::delay_type() const
|
||||
{
|
||||
DelayType result = NO_DELAY;
|
||||
|
||||
for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) {
|
||||
DelayType dt = cur->delay_type();
|
||||
if (dt > result) result = dt;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DelayType NetCase::delay_type() const
|
||||
{
|
||||
DelayType result = NO_DELAY;
|
||||
bool def_stmt = false;
|
||||
unsigned nstmts = nitems();
|
||||
|
||||
for (unsigned idx = 0; idx < nstmts; idx += 1) {
|
||||
if (!expr(idx)) def_stmt = true;
|
||||
if (idx == 0) {
|
||||
result = stat(idx)->delay_type();
|
||||
} else {
|
||||
result = combine_delays(result, stat(idx)->delay_type());
|
||||
}
|
||||
}
|
||||
|
||||
/* If we don't have a default statement we don't know for sure
|
||||
* that we have a delay. */
|
||||
if (!def_stmt) result = combine_delays(NO_DELAY, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DelayType NetCondit::delay_type() const
|
||||
{
|
||||
DelayType result;
|
||||
|
||||
if (else_) {
|
||||
result = combine_delays(if_->delay_type(), else_->delay_type());
|
||||
} else {
|
||||
result = if_->delay_type();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DelayType NetEvWait::delay_type() const
|
||||
{
|
||||
return DEFINITE_DELAY;
|
||||
}
|
||||
|
||||
DelayType NetForever::delay_type() const
|
||||
{
|
||||
return statement_->delay_type();
|
||||
}
|
||||
|
||||
DelayType NetPDelay::delay_type() const
|
||||
{
|
||||
if (expr_) {
|
||||
return delay_type_from_expr(expr_);
|
||||
} else {
|
||||
if (delay() > 0) {
|
||||
return DEFINITE_DELAY;
|
||||
} else {
|
||||
if (statement_) {
|
||||
return statement_->delay_type();
|
||||
} else {
|
||||
return NO_DELAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DelayType NetRepeat::delay_type() const
|
||||
{
|
||||
return get_loop_delay_type(expr_, statement_);
|
||||
}
|
||||
|
||||
DelayType NetTaskDef::delay_type() const
|
||||
{
|
||||
return proc_->delay_type();
|
||||
}
|
||||
|
||||
DelayType NetUTask::delay_type() const
|
||||
{
|
||||
return task()->task_def()->delay_type();
|
||||
}
|
||||
|
||||
DelayType NetWhile::delay_type() const
|
||||
{
|
||||
return get_loop_delay_type(cond_, proc_);
|
||||
}
|
||||
|
||||
+128
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2008 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
|
||||
@@ -123,21 +123,57 @@ NetExpr* make_sub_expr(long val, NetExpr*expr)
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEConst* make_const_x(unsigned long wid)
|
||||
{
|
||||
verinum xxx (verinum::Vx, wid);
|
||||
NetEConst*resx = new NetEConst(xxx);
|
||||
return resx;
|
||||
}
|
||||
|
||||
NetExpr* condition_reduce(NetExpr*expr)
|
||||
{
|
||||
if (expr->expr_width() == 1)
|
||||
return expr;
|
||||
|
||||
verinum zero (verinum::V0, expr->expr_width());
|
||||
|
||||
NetEConst*ezero = new NetEConst(zero);
|
||||
ezero->cast_signed(expr->has_sign());
|
||||
ezero->set_line(*expr);
|
||||
ezero->set_width(expr->expr_width());
|
||||
|
||||
NetEBComp*cmp = new NetEBComp('n', expr, ezero);
|
||||
cmp->cast_signed(false);
|
||||
cmp->set_line(*expr);
|
||||
|
||||
return cmp;
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
const PExpr*pe, int expr_wid, int prune_width)
|
||||
{
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
if (NetExpr*tmp2 = tmp->eval_tree(prune_width)) {
|
||||
delete tmp;
|
||||
tmp = tmp2;
|
||||
}
|
||||
eval_expr(tmp, prune_width);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void eval_expr(NetExpr*&expr, int prune_width)
|
||||
{
|
||||
assert(expr);
|
||||
if (dynamic_cast<NetEConst*>(expr)) return;
|
||||
if (dynamic_cast<NetECReal*>(expr)) return;
|
||||
|
||||
NetExpr*tmp = expr->eval_tree(prune_width);
|
||||
if (tmp != 0) {
|
||||
tmp->set_line(*expr);
|
||||
delete expr;
|
||||
expr = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
bool eval_as_long(long&value, NetExpr*expr)
|
||||
{
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr) ) {
|
||||
@@ -153,6 +189,21 @@ bool eval_as_long(long&value, NetExpr*expr)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool eval_as_double(double&value, NetExpr*expr)
|
||||
{
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr) ) {
|
||||
value = tmp->value().as_long();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NetECReal*rtmp = dynamic_cast<NetECReal*>(expr)) {
|
||||
value = rtmp->value().as_double();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
const pform_name_t&path)
|
||||
{
|
||||
@@ -191,3 +242,73 @@ std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Human readable version of op. Used in elaboration error messages.
|
||||
*/
|
||||
const char *human_readable_op(const char op)
|
||||
{
|
||||
const char *type;
|
||||
switch (op) {
|
||||
case '~': type = "~"; break; // Negation
|
||||
|
||||
case '^': type = "^"; break; // XOR
|
||||
case 'X': type = "~^"; break; // XNOR
|
||||
case '&': type = "&"; break; // Bitwise AND
|
||||
case 'A': type = "~&"; break; // NAND (~&)
|
||||
case '|': type = "|"; break; // Bitwise OR
|
||||
case 'O': type = "~|"; break; // NOR
|
||||
|
||||
case 'a': type = "&&"; break; // Logical AND
|
||||
case 'o': type = "||"; break; // Logical OR
|
||||
|
||||
case 'E': type = "==="; break; // Case equality
|
||||
case 'N': type = "!=="; break; // Case inequality
|
||||
|
||||
case 'l': type = "<<(<)"; break; // Left shifts
|
||||
case 'r': type = ">>"; break; // Logical right shift
|
||||
case 'R': type = ">>>"; break; // Arithmetic right shift
|
||||
|
||||
default: assert(0);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
const_bool const_logical(const NetExpr*expr)
|
||||
{
|
||||
switch (expr->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
const NetECReal*val = dynamic_cast<const NetECReal*> (expr);
|
||||
if (val == 0) return C_NON;
|
||||
if (val->value().as_double() == 0.0) return C_0;
|
||||
else return C_1;
|
||||
}
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
const NetEConst*val = dynamic_cast<const NetEConst*> (expr);
|
||||
if (val == 0) return C_NON;
|
||||
verinum cval = val->value();
|
||||
const_bool res = C_0;
|
||||
for (unsigned idx = 0; idx < cval.len(); idx += 1) {
|
||||
switch (cval.get(idx)) {
|
||||
case verinum::V1:
|
||||
res = C_1;
|
||||
break;
|
||||
|
||||
case verinum::V0:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (res == C_0) res = C_X;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return C_NON;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __netmisc_H
|
||||
#define __netmisc_H
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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,9 +18,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.h,v 1.31 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
|
||||
@@ -67,6 +64,13 @@ extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
extern NetNet*pad_to_width_signed(Design*des, NetNet*n, unsigned w);
|
||||
|
||||
/*
|
||||
* Take the input expression and return a variation that assures that
|
||||
* the expression is 1-bit wide and logical. This reflects the needs
|
||||
* of conditions i.e. for "if" statements or logical operators.
|
||||
*/
|
||||
extern NetExpr*condition_reduce(NetExpr*expr);
|
||||
|
||||
/*
|
||||
* This function transforms an expression by cropping the high bits
|
||||
* off with a part select. The result has the width w passed in. This
|
||||
@@ -89,7 +93,7 @@ extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
|
||||
* make_add_expr
|
||||
* Make a NetEBAdd expression with <expr> the first argument and
|
||||
* <val> the second. This may get turned into a subtract if <val> is
|
||||
* less then zero. If val is exactly zero, then return <expr> as is.
|
||||
* less than zero. If val is exactly zero, then return <expr> as is.
|
||||
*
|
||||
* make_sub_expr
|
||||
* Make a NetEBAdd(subtract) node that subtracts the given
|
||||
@@ -98,6 +102,11 @@ extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
|
||||
extern NetExpr*make_add_expr(NetExpr*expr, long val);
|
||||
extern NetExpr*make_sub_expr(long val, NetExpr*expr);
|
||||
|
||||
/*
|
||||
* Make a NetEConst object that contains only X bits.
|
||||
*/
|
||||
extern NetEConst*make_const_x(unsigned long wid);
|
||||
|
||||
/*
|
||||
* In some cases the lval is accessible as a pointer to the head of
|
||||
* a list of NetAssign_ objects. This function returns the width of
|
||||
@@ -122,6 +131,11 @@ class PExpr;
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
const PExpr*pe, int expr_wid,
|
||||
int prune_width =-1);
|
||||
/*
|
||||
* This procedure elaborates an expression and if the elaboration is
|
||||
* successful the original expression is replaced with the new one.
|
||||
*/
|
||||
void eval_expr(NetExpr*&expr, int prune_width =-1);
|
||||
|
||||
/*
|
||||
* Get the long integer value for the passed in expression, if
|
||||
@@ -129,8 +143,26 @@ extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
* down to a constant) then return false and leave value unchanged.
|
||||
*/
|
||||
bool eval_as_long(long&value, NetExpr*expr);
|
||||
bool eval_as_double(double&value, NetExpr*expr);
|
||||
|
||||
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
const pform_name_t&path);
|
||||
|
||||
/*
|
||||
* Return a human readable version of the operator.
|
||||
*/
|
||||
const char *human_readable_op(const char op);
|
||||
|
||||
/*
|
||||
* Is the expression a constant value and if so what is its logical
|
||||
* value.
|
||||
*
|
||||
* C_NON - the expression is not a constant value.
|
||||
* C_0 - the expression is constant and it has a false value.
|
||||
* C_1 - the expression is constant and it has a true value.
|
||||
* C_X - the expression is constant and it has an 'bX value.
|
||||
*/
|
||||
enum const_bool { C_NON, C_0, C_1, C_X };
|
||||
const_bool const_logical(const NetExpr*expr);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class PUdp;
|
||||
/*
|
||||
* These are maps of the modules and primitives parsed from the
|
||||
* Verilog source into pform for elaboration. The parser adds modules
|
||||
* to these maps as it compiles modules in the verilog source.
|
||||
* to these maps as it compiles modules in the Verilog source.
|
||||
*/
|
||||
extern map<perm_string,Module*> pform_modules;
|
||||
extern map<perm_string,PUdp*> pform_primitives;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
# include "compiler.h"
|
||||
# include "pform.h"
|
||||
|
||||
/*
|
||||
@@ -39,6 +40,13 @@ struct vlltype {
|
||||
};
|
||||
# define YYLTYPE struct vlltype
|
||||
|
||||
class LineInfo;
|
||||
inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
|
||||
{
|
||||
tmp->set_lineno(where.first_line);
|
||||
tmp->set_file(filename_strings.make(where.text));
|
||||
}
|
||||
|
||||
/* This for compatibility with new and older bison versions. */
|
||||
#ifndef yylloc
|
||||
# define yylloc VLlloc
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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
|
||||
@@ -27,6 +27,7 @@
|
||||
# include "PUdp.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PSpec.h"
|
||||
# include "discipline.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include <assert.h>
|
||||
@@ -49,7 +50,7 @@ string vl_file = "";
|
||||
extern int VLparse();
|
||||
|
||||
/* This tracks the current module being processed. There can only be
|
||||
exactly one module currently being parsed, since verilog does not
|
||||
exactly one module currently being parsed, since Verilog does not
|
||||
allow nested module definitions. */
|
||||
static Module*pform_cur_module = 0;
|
||||
|
||||
@@ -81,47 +82,56 @@ static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno)
|
||||
obj->set_file(filename_strings.make(file));
|
||||
}
|
||||
|
||||
static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
|
||||
{
|
||||
tmp->set_lineno(where.first_line);
|
||||
tmp->set_file(filename_strings.make(where.text));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 pop function is called. Entering tasks, functions
|
||||
* and named blocks causes scope to be pushed and popped. The module
|
||||
* name is not included in this scope stack.
|
||||
* The lexical_scope keeps track of the current lexical scope that is
|
||||
* being parsed. The lexical scope may stack, so the current scope may
|
||||
* have a parent, that is restored when the current scope ends.
|
||||
*
|
||||
* The hier_name function, therefore, converts the name to the scoped
|
||||
* name within the module currently in progress. It never includes an
|
||||
* instance name.
|
||||
*
|
||||
* The scope stack does not include any scope created by a generate
|
||||
* scheme.
|
||||
* Items that have scoped names are put in the lexical_scope object.
|
||||
*/
|
||||
|
||||
static pform_name_t scope_stack;
|
||||
|
||||
void pform_push_scope(char*name)
|
||||
{
|
||||
scope_stack.push_back(name_component_t(lex_strings.make(name)));
|
||||
}
|
||||
static PScope* lexical_scope = 0;
|
||||
|
||||
void pform_pop_scope()
|
||||
{
|
||||
scope_stack.pop_back();
|
||||
lexical_scope = lexical_scope->pscope_parent();
|
||||
}
|
||||
|
||||
static pform_name_t hier_name(const char*tail)
|
||||
PTask* pform_push_task_scope(char*name)
|
||||
{
|
||||
pform_name_t name = scope_stack;
|
||||
name.push_back(name_component_t(lex_strings.make(tail)));
|
||||
return name;
|
||||
perm_string task_name = lex_strings.make(name);
|
||||
PTask*task = new PTask(task_name, pform_cur_module);
|
||||
|
||||
// Add the task to the current module
|
||||
pform_cur_module->add_task(task->pscope_name(), task);
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = task;
|
||||
return task;
|
||||
}
|
||||
|
||||
static PWire*get_wire_in_module(const pform_name_t&name)
|
||||
PFunction* pform_push_function_scope(char*name)
|
||||
{
|
||||
perm_string func_name = lex_strings.make(name);
|
||||
PFunction*func = new PFunction(func_name, lexical_scope);
|
||||
|
||||
// Add the task to the current module
|
||||
pform_cur_module->add_function(func->pscope_name(), func);
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = func;
|
||||
return func;
|
||||
}
|
||||
|
||||
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
|
||||
{
|
||||
perm_string block_name = lex_strings.make(name);
|
||||
PBlock*block = new PBlock(block_name, lexical_scope, bt);
|
||||
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = block;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
PWire*pform_get_wire_in_scope(perm_string name)
|
||||
{
|
||||
/* Note that if we are processing a generate, then the
|
||||
scope depth will be empty because generate schemes
|
||||
@@ -130,7 +140,7 @@ static PWire*get_wire_in_module(const pform_name_t&name)
|
||||
if (pform_cur_generate)
|
||||
return pform_cur_generate->get_wire(name);
|
||||
|
||||
return pform_cur_module->get_wire(name);
|
||||
return lexical_scope->wires_find(name);
|
||||
}
|
||||
|
||||
void pform_set_default_nettype(NetNet::Type type,
|
||||
@@ -259,6 +269,9 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||
FILE_NAME(pform_cur_module, file, lineno);
|
||||
pform_cur_module->library_flag = pform_library_flag;
|
||||
|
||||
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
||||
lexical_scope = pform_cur_module;
|
||||
|
||||
/* The generate scheme numbering starts with *1*, not
|
||||
zero. That's just the way it is, thanks to the standard. */
|
||||
scope_generate_counter = 1;
|
||||
@@ -285,14 +298,14 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||
* reference. This is a name without a .X(...), so the internal name
|
||||
* should be generated to be the same as the X.
|
||||
*/
|
||||
Module::port_t* pform_module_port_reference(char*name,
|
||||
Module::port_t* pform_module_port_reference(perm_string name,
|
||||
const char*file,
|
||||
unsigned lineno)
|
||||
{
|
||||
Module::port_t*ptmp = new Module::port_t;
|
||||
PEIdent*tmp = new PEIdent(lex_strings.make(name));
|
||||
PEIdent*tmp = new PEIdent(name);
|
||||
FILE_NAME(tmp, file, lineno);
|
||||
ptmp->name = lex_strings.make(name);
|
||||
ptmp->name = name;
|
||||
ptmp->expr = svector<PEIdent*>(1);
|
||||
ptmp->expr[0] = tmp;
|
||||
|
||||
@@ -331,18 +344,26 @@ void pform_endmodule(const char*name)
|
||||
msg << "Module " << name << " was already declared here: "
|
||||
<< (*test).second->get_fileline() << endl;
|
||||
VLerror(msg.str().c_str());
|
||||
pform_cur_module = 0;
|
||||
return;
|
||||
} else {
|
||||
pform_modules[mod_name] = pform_cur_module;
|
||||
}
|
||||
pform_modules[mod_name] = pform_cur_module;
|
||||
|
||||
// The current lexical scope should be this module by now, and
|
||||
// this module should not have a parent lexical scope.
|
||||
ivl_assert(*pform_cur_module, lexical_scope == pform_cur_module);
|
||||
lexical_scope = pform_cur_module->pscope_parent();
|
||||
ivl_assert(*pform_cur_module, lexical_scope == 0);
|
||||
|
||||
pform_cur_module = 0;
|
||||
}
|
||||
|
||||
void pform_genvars(list<perm_string>*names)
|
||||
void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
||||
{
|
||||
list<perm_string>::const_iterator cur;
|
||||
for (cur = names->begin(); cur != names->end() ; *cur++) {
|
||||
pform_cur_module->genvars.push_back( *cur );
|
||||
LineInfo*lni = new LineInfo();
|
||||
FILE_NAME(lni, li);
|
||||
pform_cur_module->genvars[*cur] = lni;
|
||||
}
|
||||
|
||||
delete names;
|
||||
@@ -412,6 +433,51 @@ void pform_start_generate_else(const struct vlltype&li)
|
||||
pform_cur_generate->loop_step = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The GS_CASE version of the PGenerate contains only case items. The
|
||||
* items in turn contain the generated items themselves.
|
||||
*/
|
||||
void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
|
||||
{
|
||||
PGenerate*gen = new PGenerate(scope_generate_counter++);
|
||||
|
||||
FILE_NAME(gen, li);
|
||||
|
||||
gen->parent = pform_cur_generate;
|
||||
pform_cur_generate = gen;
|
||||
|
||||
pform_cur_generate->scheme_type = PGenerate::GS_CASE;
|
||||
|
||||
pform_cur_generate->loop_init = 0;
|
||||
pform_cur_generate->loop_test = expr;
|
||||
pform_cur_generate->loop_step = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The generate case item is a special case schema that takes its id
|
||||
* from the case schema that it is a part of. The idea is that the
|
||||
* case schema can only instantiate exactly one item, so the items
|
||||
* need not have a unique number.
|
||||
*/
|
||||
void pform_generate_case_item(const struct vlltype&li, PExpr*expr)
|
||||
{
|
||||
assert(pform_cur_generate);
|
||||
assert(pform_cur_generate->scheme_type == PGenerate::GS_CASE);
|
||||
|
||||
PGenerate*gen = new PGenerate(pform_cur_generate->id_number);
|
||||
|
||||
FILE_NAME(gen, li);
|
||||
|
||||
gen->parent = pform_cur_generate;
|
||||
pform_cur_generate = gen;
|
||||
|
||||
pform_cur_generate->scheme_type = PGenerate::GS_CASE_ITEM;
|
||||
|
||||
pform_cur_generate->loop_init = 0;
|
||||
pform_cur_generate->loop_test = expr;
|
||||
pform_cur_generate->loop_step = 0;
|
||||
}
|
||||
|
||||
void pform_generate_block_name(char*name)
|
||||
{
|
||||
assert(pform_cur_generate != 0);
|
||||
@@ -439,10 +505,14 @@ void pform_endgenerate()
|
||||
PGenerate*cur = pform_cur_generate;
|
||||
pform_cur_generate = cur->parent;
|
||||
|
||||
if (pform_cur_generate != 0)
|
||||
if (pform_cur_generate != 0) {
|
||||
assert(cur->scheme_type == PGenerate::GS_CASE_ITEM
|
||||
|| pform_cur_generate->scheme_type != PGenerate::GS_CASE);
|
||||
pform_cur_generate->generates.push_back(cur);
|
||||
else
|
||||
} else {
|
||||
assert(cur->scheme_type != PGenerate::GS_CASE_ITEM);
|
||||
pform_cur_module->generate_schemes.push_back(cur);
|
||||
}
|
||||
}
|
||||
|
||||
bool pform_expression_is_constant(const PExpr*ex)
|
||||
@@ -496,6 +566,11 @@ PExpr* pform_select_mtm_expr(PExpr*min, PExpr*typ, PExpr*max)
|
||||
return res;
|
||||
}
|
||||
|
||||
template <> inline svector<perm_string>::svector(unsigned size)
|
||||
: nitems_(size), items_(new perm_string[size])
|
||||
{
|
||||
}
|
||||
|
||||
static void process_udp_table(PUdp*udp, list<string>*table,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
@@ -507,7 +582,7 @@ static void process_udp_table(PUdp*udp, list<string>*table,
|
||||
placed in the PUdp object.
|
||||
|
||||
The table strings are made up by the parser to be two or
|
||||
three substrings seperated by ';', i.e.:
|
||||
three substrings separated by ';', i.e.:
|
||||
|
||||
0101:1:1 (synchronous device entry)
|
||||
0101:0 (combinational device entry)
|
||||
@@ -563,7 +638,7 @@ static void process_udp_table(PUdp*udp, list<string>*table,
|
||||
udp->toutput = output;
|
||||
}
|
||||
|
||||
void pform_make_udp(perm_string name, list<string>*parms,
|
||||
void pform_make_udp(perm_string name, list<perm_string>*parms,
|
||||
svector<PWire*>*decl, list<string>*table,
|
||||
Statement*init_expr,
|
||||
const char*file, unsigned lineno)
|
||||
@@ -575,11 +650,10 @@ void pform_make_udp(perm_string name, list<string>*parms,
|
||||
off with the parameters in the list. If the port is already
|
||||
in the map, merge the port type. I will rebuild a list
|
||||
of parameters for the PUdp object. */
|
||||
map<string,PWire*> defs;
|
||||
map<perm_string,PWire*> defs;
|
||||
for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) {
|
||||
|
||||
pform_name_t pname = (*decl)[idx]->path();
|
||||
string port_name = peek_tail_name(pname).str();
|
||||
perm_string port_name = (*decl)[idx]->basename();
|
||||
|
||||
if (PWire*cur = defs[port_name]) {
|
||||
bool rc = true;
|
||||
@@ -605,8 +679,8 @@ void pform_make_udp(perm_string name, list<string>*parms,
|
||||
UDP declaration, and the defs map maps that name to a
|
||||
PWire* created by an input or output declaration. */
|
||||
svector<PWire*> pins (parms->size());
|
||||
svector<string> pin_names (parms->size());
|
||||
{ list<string>::iterator cur;
|
||||
svector<perm_string> pin_names (parms->size());
|
||||
{ list<perm_string>::iterator cur;
|
||||
unsigned idx;
|
||||
for (cur = parms->begin(), idx = 0
|
||||
; cur != parms->end()
|
||||
@@ -740,7 +814,7 @@ void pform_make_udp(perm_string name, list<string>*parms,
|
||||
|
||||
// Make the port list for the UDP
|
||||
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
|
||||
udp->ports[idx] = peek_tail_name(pins[idx]->path());
|
||||
udp->ports[idx] = pins[idx]->basename();
|
||||
|
||||
process_udp_table(udp, table, file, lineno);
|
||||
udp->initial = init;
|
||||
@@ -765,10 +839,9 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
||||
svector<PWire*> pins(parms->size() + 1);
|
||||
|
||||
/* Make the PWire for the output port. */
|
||||
pins[0] = new PWire(hier_name(out_name),
|
||||
pins[0] = new PWire(out_name,
|
||||
synchronous_flag? NetNet::REG : NetNet::WIRE,
|
||||
NetNet::POUTPUT,
|
||||
IVL_VT_LOGIC);
|
||||
NetNet::POUTPUT, IVL_VT_LOGIC);
|
||||
FILE_NAME(pins[0], file, lineno);
|
||||
|
||||
/* Make the PWire objects for the input ports. */
|
||||
@@ -778,10 +851,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
||||
; cur != parms->end()
|
||||
; idx += 1, cur++) {
|
||||
assert(idx < pins.count());
|
||||
pins[idx] = new PWire(hier_name(*cur),
|
||||
NetNet::WIRE,
|
||||
NetNet::PINPUT,
|
||||
IVL_VT_LOGIC);
|
||||
pins[idx] = new PWire(*cur, NetNet::WIRE,
|
||||
NetNet::PINPUT, IVL_VT_LOGIC);
|
||||
FILE_NAME(pins[idx], file, lineno);
|
||||
}
|
||||
assert(idx == pins.count());
|
||||
@@ -822,7 +893,7 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
||||
|
||||
// Make the port list for the UDP
|
||||
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
|
||||
udp->ports[idx] = peek_tail_name(pins[idx]->path());
|
||||
udp->ports[idx] = pins[idx]->basename();
|
||||
|
||||
assert(udp);
|
||||
assert(table);
|
||||
@@ -837,39 +908,18 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
||||
delete init_expr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to set the net range for a port that uses
|
||||
* the new (1364-2001) list_of_port_declarations, but omitted a
|
||||
* register/wire/etc. that would have triggered it to be set elsewhere.
|
||||
*/
|
||||
/*
|
||||
* Since implicitly defined list of port declarations are no longer
|
||||
* considered fully defined we no longer need this routine to force
|
||||
* them to be fully defined.
|
||||
*
|
||||
void pform_set_net_range(const char* name)
|
||||
{
|
||||
PWire*cur = get_wire_in_module(hier_name(name));
|
||||
if (cur == 0) {
|
||||
VLerror("error: name is not a valid net.");
|
||||
return;
|
||||
}
|
||||
cur->set_net_range();
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 char* name,
|
||||
static void pform_set_net_range(perm_string name,
|
||||
const svector<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt,
|
||||
PWSRType rt)
|
||||
{
|
||||
PWire*cur = get_wire_in_module(hier_name(name));
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
VLerror("error: name is not a valid net.");
|
||||
return;
|
||||
@@ -1184,24 +1234,23 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
* BTF-B14.
|
||||
*/
|
||||
void pform_make_reginit(const struct vlltype&li,
|
||||
const char*name, PExpr*expr)
|
||||
perm_string name, PExpr*expr)
|
||||
{
|
||||
const pform_name_t sname = hier_name(name);
|
||||
PWire*cur = pform_cur_module->get_wire(sname);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur == 0) {
|
||||
VLerror(li, "internal error: reginit to non-register?");
|
||||
delete expr;
|
||||
return;
|
||||
}
|
||||
|
||||
PEIdent*lval = new PEIdent(sname);
|
||||
PEIdent*lval = new PEIdent(name);
|
||||
FILE_NAME(lval, li);
|
||||
PAssign*ass = new PAssign(lval, expr);
|
||||
FILE_NAME(ass, li);
|
||||
PProcess*top = new PProcess(PProcess::PR_INITIAL, ass);
|
||||
FILE_NAME(top, li);
|
||||
|
||||
pform_cur_module->add_behavior(top);
|
||||
lexical_scope->behaviors.push_back(top);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1215,18 +1264,17 @@ void pform_make_reginit(const struct vlltype&li,
|
||||
* as is done for the old method.
|
||||
*/
|
||||
void pform_module_define_port(const struct vlltype&li,
|
||||
const char*nm,
|
||||
perm_string name,
|
||||
NetNet::PortType port_type,
|
||||
NetNet::Type type,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur) {
|
||||
ostringstream msg;
|
||||
msg << nm << " definition conflicts with "
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_fileline()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
@@ -1257,7 +1305,7 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
cur->attributes[tmp->name] = tmp->parm;
|
||||
}
|
||||
}
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1280,27 +1328,25 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
*/
|
||||
|
||||
/*
|
||||
* this is the basic form of pform_makwire. This takes a single simple
|
||||
* this is the basic form of pform_makewire. This takes a single simple
|
||||
* name, port type, net type, data type, and attributes, and creates
|
||||
* the variable/net. Other forms of pform_makewire ultimately call
|
||||
* this one to create the wire and stash it.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li, const char*nm,
|
||||
void pform_makewire(const vlltype&li, perm_string name,
|
||||
NetNet::Type type, NetNet::PortType pt,
|
||||
ivl_variable_type_t dt,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
|
||||
// If this is not implicit ("implicit" meaning we don't know
|
||||
// what the type is yet) then set thay type now.
|
||||
// what the type is yet) then set the type now.
|
||||
if (cur && type != NetNet::IMPLICIT) {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
if (rc == false) {
|
||||
ostringstream msg;
|
||||
msg << nm << " definition conflicts with "
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_fileline()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
@@ -1344,9 +1390,9 @@ void pform_makewire(const vlltype&li, const char*nm,
|
||||
|
||||
if (new_wire_flag) {
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_wire(cur);
|
||||
pform_cur_generate->wires[name] = cur;
|
||||
else
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1406,32 +1452,28 @@ void pform_makewire(const vlltype&li,
|
||||
SR_NET);
|
||||
}
|
||||
|
||||
perm_string first_name = lex_strings.make(first->name);
|
||||
pform_name_t name = hier_name(first_name);
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
PWire*cur = pform_get_wire_in_scope(first->name);
|
||||
if (cur != 0) {
|
||||
PEIdent*lval = new PEIdent(first_name);
|
||||
PEIdent*lval = new PEIdent(first->name);
|
||||
FILE_NAME(lval, li.text, li.first_line);
|
||||
PGAssign*ass = pform_make_pgassign(lval, first->expr,
|
||||
delay, str);
|
||||
FILE_NAME(ass, li.text, li.first_line);
|
||||
}
|
||||
|
||||
free(first->name);
|
||||
delete first;
|
||||
first = next;
|
||||
}
|
||||
}
|
||||
|
||||
void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
|
||||
FILE_NAME(cur, file, lineno);
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
}
|
||||
|
||||
switch (cur->get_port_type()) {
|
||||
@@ -1442,14 +1484,14 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
|
||||
case NetNet::NOT_A_PORT:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << nm << " is not in the port list."
|
||||
<< "port " << name << " is not in the port list."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << nm << " already has a port declaration."
|
||||
<< "port " << name << " already has a port declaration."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
@@ -1509,18 +1551,17 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; cur ++ ) {
|
||||
|
||||
perm_string txt = *cur;
|
||||
pform_name_t name = hier_name(txt);
|
||||
perm_string name = *cur;
|
||||
|
||||
/* Look for a preexisting wire. If it exists, set the
|
||||
port direction. If not, create it. */
|
||||
PWire*curw = pform_cur_module->get_wire(name);
|
||||
PWire*curw = lexical_scope->wires_find(name);
|
||||
if (curw) {
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
|
||||
FILE_NAME(curw, file, lineno);
|
||||
pform_cur_module->add_wire(curw);
|
||||
lexical_scope->wires[name] = curw;
|
||||
}
|
||||
|
||||
curw->set_signed(signed_flag);
|
||||
@@ -1541,22 +1582,9 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
return res;
|
||||
}
|
||||
|
||||
void pform_set_task(perm_string name, PTask*task)
|
||||
{
|
||||
pform_cur_module->add_task(name, task);
|
||||
}
|
||||
|
||||
|
||||
void pform_set_function(perm_string name, PFunction*func)
|
||||
{
|
||||
pform_cur_module->add_function(name, func);
|
||||
}
|
||||
|
||||
void pform_set_attrib(perm_string name, perm_string key, char*value)
|
||||
{
|
||||
pform_name_t path = hier_name(name);
|
||||
|
||||
if (PWire*cur = pform_cur_module->get_wire(path)) {
|
||||
if (PWire*cur = lexical_scope->wires_find(name)) {
|
||||
cur->attributes[key] = new PEString(value);
|
||||
|
||||
} else if (PGate*cur = pform_cur_module->get_gate(name)) {
|
||||
@@ -1590,13 +1618,13 @@ void pform_set_type_attrib(perm_string name, const string&key,
|
||||
* This function attaches a memory index range to an existing
|
||||
* register. (The named wire must be a register.
|
||||
*/
|
||||
void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r)
|
||||
void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r)
|
||||
{
|
||||
PWire*cur = 0;
|
||||
if (pform_cur_generate) {
|
||||
cur = pform_cur_generate->get_wire(hier_name(name));
|
||||
cur = pform_cur_generate->get_wire(name);
|
||||
} else {
|
||||
cur = pform_cur_module->get_wire(hier_name(name));
|
||||
cur = lexical_scope->wires_find(name);
|
||||
}
|
||||
if (cur == 0) {
|
||||
VLerror("internal error: name is not a valid memory for index.");
|
||||
@@ -1606,44 +1634,76 @@ void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r)
|
||||
cur->set_memory_idx(l, r);
|
||||
}
|
||||
|
||||
void pform_set_parameter(perm_string name, bool signed_flag,
|
||||
svector<PExpr*>*range, PExpr*expr)
|
||||
Module::range_t* pform_parameter_value_range(bool exclude_flag,
|
||||
bool low_open, PExpr*low_expr,
|
||||
bool hig_open, PExpr*hig_expr)
|
||||
{
|
||||
// Detect +-inf and make the the *_open flags false to force
|
||||
// the range interpretation as inf.
|
||||
if (low_expr == 0) low_open = false;
|
||||
if (hig_expr == 0) hig_open = false;
|
||||
|
||||
Module::range_t*tmp = new Module::range_t;
|
||||
tmp->exclude_flag = exclude_flag;
|
||||
tmp->low_open_flag = low_open;
|
||||
tmp->low_expr = low_expr;
|
||||
tmp->high_open_flag = hig_open;
|
||||
tmp->high_expr = hig_expr;
|
||||
tmp->next = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void pform_set_parameter(const struct vlltype&loc,
|
||||
perm_string name, ivl_variable_type_t type,
|
||||
bool signed_flag, svector<PExpr*>*range, PExpr*expr,
|
||||
Module::range_t*value_range)
|
||||
{
|
||||
assert(expr);
|
||||
pform_cur_module->parameters[name].expr = expr;
|
||||
Module::param_expr_t&parm = pform_cur_module->parameters[name];
|
||||
FILE_NAME(&parm, loc);
|
||||
|
||||
parm.expr = expr;
|
||||
|
||||
parm.type = type;
|
||||
if (range) {
|
||||
assert(range->count() == 2);
|
||||
assert((*range)[0]);
|
||||
assert((*range)[1]);
|
||||
pform_cur_module->parameters[name].msb = (*range)[0];
|
||||
pform_cur_module->parameters[name].lsb = (*range)[1];
|
||||
parm.msb = (*range)[0];
|
||||
parm.lsb = (*range)[1];
|
||||
} else {
|
||||
pform_cur_module->parameters[name].msb = 0;
|
||||
pform_cur_module->parameters[name].lsb = 0;
|
||||
parm.msb = 0;
|
||||
parm.lsb = 0;
|
||||
}
|
||||
pform_cur_module->parameters[name].signed_flag = signed_flag;
|
||||
parm.signed_flag = signed_flag;
|
||||
parm.range = value_range;
|
||||
|
||||
pform_cur_module->param_names.push_back(name);
|
||||
}
|
||||
|
||||
void pform_set_localparam(perm_string name, bool signed_flag,
|
||||
svector<PExpr*>*range, PExpr*expr)
|
||||
void pform_set_localparam(const struct vlltype&loc,
|
||||
perm_string name, ivl_variable_type_t type,
|
||||
bool signed_flag, svector<PExpr*>*range, PExpr*expr)
|
||||
{
|
||||
assert(expr);
|
||||
pform_cur_module->localparams[name].expr = expr;
|
||||
Module::param_expr_t&parm = pform_cur_module->localparams[name];
|
||||
FILE_NAME(&parm, loc);
|
||||
|
||||
parm.expr = expr;
|
||||
|
||||
parm.type = type;
|
||||
if (range) {
|
||||
assert(range->count() == 2);
|
||||
assert((*range)[0]);
|
||||
assert((*range)[1]);
|
||||
pform_cur_module->localparams[name].msb = (*range)[0];
|
||||
pform_cur_module->localparams[name].lsb = (*range)[1];
|
||||
parm.msb = (*range)[0];
|
||||
parm.lsb = (*range)[1];
|
||||
} else {
|
||||
pform_cur_module->localparams[name].msb = 0;
|
||||
pform_cur_module->localparams[name].lsb = 0;
|
||||
parm.msb = 0;
|
||||
parm.lsb = 0;
|
||||
}
|
||||
pform_cur_module->localparams[name].signed_flag = signed_flag;
|
||||
parm.signed_flag = signed_flag;
|
||||
parm.range = 0;
|
||||
}
|
||||
|
||||
void pform_set_specparam(perm_string name, PExpr*expr)
|
||||
@@ -1743,16 +1803,15 @@ void pform_set_port_type(const struct vlltype&li,
|
||||
delete range;
|
||||
}
|
||||
|
||||
static void pform_set_reg_integer(const char*nm)
|
||||
static void pform_set_reg_integer(perm_string name)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::INTEGER,
|
||||
NetNet::NOT_A_PORT,
|
||||
IVL_VT_LOGIC);
|
||||
cur->set_signed(true);
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::INTEGER);
|
||||
assert(rc);
|
||||
@@ -1778,13 +1837,12 @@ void pform_set_reg_integer(list<perm_string>*names)
|
||||
delete names;
|
||||
}
|
||||
|
||||
static void pform_set_reg_time(const char*nm)
|
||||
static void pform_set_reg_time(perm_string name)
|
||||
{
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
pform_cur_module->add_wire(cur);
|
||||
lexical_scope->wires[name] = cur;
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::REG);
|
||||
assert(rc);
|
||||
@@ -1818,9 +1876,7 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||
; cur != names->end()
|
||||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
pform_name_t tmp;
|
||||
tmp.push_back(name_component_t(txt));
|
||||
PWire*pp = new PWire(tmp,
|
||||
PWire*pp = new PWire(txt,
|
||||
NetNet::IMPLICIT,
|
||||
NetNet::PINPUT,
|
||||
IVL_VT_LOGIC);
|
||||
@@ -1848,7 +1904,7 @@ PProcess* pform_make_behavior(PProcess::Type type, Statement*st,
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_behavior(pp);
|
||||
else
|
||||
pform_cur_module->add_behavior(pp);
|
||||
pform_cur_module->behaviors.push_back(pp);
|
||||
|
||||
return pp;
|
||||
}
|
||||
@@ -1897,4 +1953,3 @@ void pform_error_nested_modules()
|
||||
cerr << pform_cur_module->get_fileline() << ": error: original module "
|
||||
"(" << pform_cur_module->mod_name() << ") defined here." << endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __pform_H
|
||||
#define __pform_H
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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,9 +18,6 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.h,v 1.91 2007/05/24 04:07:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "HName.h"
|
||||
@@ -33,6 +30,7 @@
|
||||
# include "PUdp.h"
|
||||
# include "PWire.h"
|
||||
# include "verinum.h"
|
||||
# include "discipline.h"
|
||||
# include <iostream>
|
||||
# include <string>
|
||||
# include <list>
|
||||
@@ -40,7 +38,7 @@
|
||||
|
||||
/*
|
||||
* These classes implement the parsed form (P-form for short) of the
|
||||
* original verilog source. the parser generates the pform for the
|
||||
* original Verilog source. the parser generates the pform for the
|
||||
* convenience of later processing steps.
|
||||
*/
|
||||
|
||||
@@ -95,7 +93,7 @@ struct parmvalue_t {
|
||||
struct str_pair_t { PGate::strength_t str0, str1; };
|
||||
|
||||
struct net_decl_assign_t {
|
||||
char*name;
|
||||
perm_string name;
|
||||
PExpr*expr;
|
||||
struct net_decl_assign_t*next;
|
||||
};
|
||||
@@ -118,11 +116,19 @@ struct lgate {
|
||||
unsigned lineno;
|
||||
};
|
||||
|
||||
|
||||
/* The lexor calls this function to change the default nettype. */
|
||||
extern void pform_set_default_nettype(NetNet::Type net,
|
||||
const char*file,
|
||||
unsigned lineno);
|
||||
|
||||
/*
|
||||
* Look for the given wire in the current lexical scope. If the wire
|
||||
* (including variables of any type) cannot be found in the current
|
||||
* scope, then return 0.
|
||||
*/
|
||||
extern PWire* pform_get_wire_in_scope(perm_string name);
|
||||
|
||||
/*
|
||||
* The parser uses startmodule and endmodule together to build up a
|
||||
* module as it parses it. The startmodule tells the pform code that a
|
||||
@@ -138,19 +144,19 @@ extern void pform_module_set_ports(svector<Module::port_t*>*);
|
||||
port_definition_list. In this case, we have everything needed to
|
||||
define the port, all in one place. */
|
||||
extern void pform_module_define_port(const struct vlltype&li,
|
||||
const char*name,
|
||||
perm_string name,
|
||||
NetNet::PortType,
|
||||
NetNet::Type type,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
svector<named_pexpr_t*>*attr);
|
||||
|
||||
extern Module::port_t* pform_module_port_reference(char*name,
|
||||
extern Module::port_t* pform_module_port_reference(perm_string name,
|
||||
const char*file,
|
||||
unsigned lineno);
|
||||
extern void pform_endmodule(const char*);
|
||||
|
||||
extern void pform_make_udp(perm_string name, list<string>*parms,
|
||||
extern void pform_make_udp(perm_string name, list<perm_string>*parms,
|
||||
svector<PWire*>*decl, list<string>*table,
|
||||
Statement*init,
|
||||
const char*file, unsigned lineno);
|
||||
@@ -167,18 +173,21 @@ extern void pform_make_udp(perm_string name,
|
||||
* name string onto the scope hierarchy. The pop pulls it off and
|
||||
* deletes it. Thus, the string pushed must be allocated.
|
||||
*/
|
||||
extern void pform_push_scope(char*name);
|
||||
extern void pform_pop_scope();
|
||||
|
||||
extern PTask*pform_push_task_scope(char*name);
|
||||
extern PFunction*pform_push_function_scope(char*name);
|
||||
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
||||
|
||||
|
||||
extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
|
||||
const char*file, unsigned loneno);
|
||||
const char*file, unsigned lineno);
|
||||
|
||||
/*
|
||||
* This function takes the list of names as new genvars to declare in
|
||||
* the current module scope.
|
||||
*/
|
||||
extern void pform_genvars(list<perm_string>*names);
|
||||
extern void pform_genvars(const struct vlltype&li, list<perm_string>*names);
|
||||
|
||||
extern void pform_start_generate_for(const struct vlltype&li,
|
||||
char*ident1,
|
||||
@@ -188,6 +197,8 @@ extern void pform_start_generate_for(const struct vlltype&li,
|
||||
PExpr*next);
|
||||
extern void pform_start_generate_if(const struct vlltype&li, PExpr*test);
|
||||
extern void pform_start_generate_else(const struct vlltype&li);
|
||||
extern void pform_start_generate_case(const struct vlltype&lp, PExpr*test);
|
||||
extern void pform_generate_case_item(const struct vlltype&lp, PExpr*test);
|
||||
extern void pform_generate_block_name(char*name);
|
||||
extern void pform_endgenerate();
|
||||
|
||||
@@ -196,7 +207,7 @@ extern void pform_endgenerate();
|
||||
* The makewire functions announce to the pform code new wires. These
|
||||
* go into a module that is currently opened.
|
||||
*/
|
||||
extern void pform_makewire(const struct vlltype&li, const char*name,
|
||||
extern void pform_makewire(const struct vlltype&li, perm_string name,
|
||||
NetNet::Type type,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t,
|
||||
@@ -224,7 +235,7 @@ extern void pform_makewire(const struct vlltype&li,
|
||||
ivl_variable_type_t);
|
||||
|
||||
extern void pform_make_reginit(const struct vlltype&li,
|
||||
const char*name, PExpr*expr);
|
||||
perm_string name, PExpr*expr);
|
||||
|
||||
/* Look up the names of the wires, and set the port type,
|
||||
i.e. input, output or inout. If the wire does not exist, create
|
||||
@@ -237,17 +248,14 @@ extern void pform_set_port_type(const struct vlltype&li,
|
||||
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno);
|
||||
|
||||
extern void pform_set_net_range(const char* name);
|
||||
extern void pform_set_net_range(list<perm_string>*names,
|
||||
svector<PExpr*>*,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t,
|
||||
PWSRType rt = SR_NET);
|
||||
extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_integer(list<perm_string>*names);
|
||||
extern void pform_set_reg_time(list<perm_string>*names);
|
||||
extern void pform_set_task(perm_string name, PTask*);
|
||||
extern void pform_set_function(perm_string name, PFunction*);
|
||||
|
||||
/* pform_set_attrib and pform_set_type_attrib exist to support the
|
||||
$attribute syntax, which can only set string values to
|
||||
@@ -258,13 +266,21 @@ extern void pform_set_attrib(perm_string name, perm_string key,
|
||||
extern void pform_set_type_attrib(perm_string name, const string&key,
|
||||
char*value);
|
||||
|
||||
extern void pform_set_parameter(perm_string name,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
PExpr*expr);
|
||||
extern void pform_set_localparam(perm_string name,
|
||||
extern Module::range_t* pform_parameter_value_range(bool exclude_flag,
|
||||
bool low_open, PExpr*low_expr,
|
||||
bool hig_open, PExpr*hig_expr);
|
||||
|
||||
extern void pform_set_parameter(const struct vlltype&loc,
|
||||
perm_string name,
|
||||
ivl_variable_type_t type,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
PExpr*expr, Module::range_t*value_range);
|
||||
extern void pform_set_localparam(const struct vlltype&loc,
|
||||
perm_string name,
|
||||
ivl_variable_type_t type,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
PExpr*expr);
|
||||
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
|
||||
|
||||
@@ -337,7 +353,7 @@ extern svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
|
||||
/*
|
||||
* These are functions that the outside-the-parser code uses the do
|
||||
* interesting things to the verilog. The parse function reads and
|
||||
* interesting things to the Verilog. The parse function reads and
|
||||
* parses the source file and places all the modules it finds into the
|
||||
* mod list. The dump function dumps a module to the output stream.
|
||||
*/
|
||||
@@ -349,4 +365,28 @@ extern void pform_dump(ostream&out, Module*mod);
|
||||
*/
|
||||
extern void pform_error_nested_modules();
|
||||
|
||||
/* ** pform_discipline.cc
|
||||
* Functions for handling the parse of natures and disciplines. These
|
||||
* functions are in pform_disciplines.cc
|
||||
*/
|
||||
class discipline_t;
|
||||
|
||||
extern void pform_start_nature(const char*name);
|
||||
extern void pform_end_nature(const struct vlltype&loc);
|
||||
|
||||
extern void pform_nature_access(const struct vlltype&loc, const char*name);
|
||||
|
||||
extern void pform_start_discipline(const char*name);
|
||||
extern void pform_end_discipline(const struct vlltype&loc);
|
||||
|
||||
extern void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain);
|
||||
extern void pform_discipline_potential(const struct vlltype&loc, const char*name);
|
||||
extern void pform_discipline_flow(const struct vlltype&loc, const char*name);
|
||||
|
||||
extern void pform_attach_discipline(const struct vlltype&loc,
|
||||
discipline_t*discipline, list<perm_string>*names);
|
||||
|
||||
extern void pform_dump(ostream&out, const nature_t*);
|
||||
extern void pform_dump(ostream&out, const discipline_t*);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2008 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
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
# include "pform.h"
|
||||
# include "parse_misc.h"
|
||||
# include "discipline.h"
|
||||
|
||||
map<perm_string,nature_t*> natures;
|
||||
map<perm_string,discipline_t*> disciplines;
|
||||
|
||||
static perm_string nature_name = perm_string::perm_string();
|
||||
static perm_string nature_access = perm_string::perm_string();
|
||||
|
||||
void pform_start_nature(const char*name)
|
||||
{
|
||||
nature_name = lex_strings.make(name);
|
||||
}
|
||||
|
||||
void pform_nature_access(const struct vlltype&loc, const char*name)
|
||||
{
|
||||
if (nature_access) {
|
||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||
<< "Too many access names for nature "
|
||||
<< nature_name << "." << endl;
|
||||
error_count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
nature_access = lex_strings.make(name);
|
||||
}
|
||||
|
||||
void pform_end_nature(const struct vlltype&loc)
|
||||
{
|
||||
// The nature access function is required. If it is missing,
|
||||
// then signal an error. For a temporary expedient, we can set
|
||||
// the nature name as the access function, but don't expect it
|
||||
// to work.
|
||||
if (! nature_access) {
|
||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||
<< "Missing access name for nature "
|
||||
<< nature_name << "." << endl;
|
||||
error_count += 1;
|
||||
nature_access = nature_name;
|
||||
}
|
||||
|
||||
nature_t*tmp = new nature_t(nature_name, nature_access);
|
||||
natures[nature_name] = tmp;
|
||||
|
||||
FILE_NAME(tmp, loc);
|
||||
|
||||
nature_name = perm_string::perm_string();
|
||||
nature_access = perm_string::perm_string();
|
||||
}
|
||||
|
||||
|
||||
static perm_string discipline_name;
|
||||
static ddomain_t discipline_domain = DD_NONE;
|
||||
static nature_t* discipline_potential = 0;
|
||||
static nature_t* discipline_flow = 0;
|
||||
|
||||
void pform_start_discipline(const char*name)
|
||||
{
|
||||
discipline_name = lex_strings.make(name);
|
||||
discipline_domain = DD_NONE;
|
||||
}
|
||||
|
||||
void pform_discipline_domain(const struct vlltype&loc, ddomain_t use_domain)
|
||||
{
|
||||
assert(use_domain != DD_NONE);
|
||||
|
||||
if (discipline_domain != DD_NONE) {
|
||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||
<< "Too many domain attributes for discipline "
|
||||
<< discipline_name << "." << endl;
|
||||
error_count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
discipline_domain = use_domain;
|
||||
}
|
||||
|
||||
void pform_discipline_potential(const struct vlltype&loc, const char*name)
|
||||
{
|
||||
if (discipline_potential) {
|
||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||
<< "Too many potential natures for discipline "
|
||||
<< discipline_name << "." << endl;
|
||||
error_count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
perm_string key = lex_strings.make(name);
|
||||
discipline_potential = natures[key];
|
||||
|
||||
if (discipline_potential == 0) {
|
||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||
<< "nature " << key << " is not declared." << endl;
|
||||
error_count += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void pform_discipline_flow(const struct vlltype&loc, const char*name)
|
||||
{
|
||||
if (discipline_flow) {
|
||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||
<< "Too many flow natures for discipline "
|
||||
<< discipline_name << "." << endl;
|
||||
error_count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
perm_string key = lex_strings.make(name);
|
||||
discipline_flow = natures[key];
|
||||
|
||||
if (discipline_flow == 0) {
|
||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||
<< "nature " << key << " is not declared." << endl;
|
||||
error_count += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void pform_end_discipline(const struct vlltype&loc)
|
||||
{
|
||||
// If the domain is not otherwise specified, then take it to
|
||||
// be continuous if potential or flow natures are given.
|
||||
if (discipline_domain == DD_NONE && (discipline_potential||discipline_flow))
|
||||
discipline_domain = DD_CONTINUOUS;
|
||||
|
||||
discipline_t*tmp = new discipline_t(discipline_name, discipline_domain,
|
||||
discipline_potential, discipline_flow);
|
||||
disciplines[discipline_name] = tmp;
|
||||
|
||||
FILE_NAME(tmp, loc);
|
||||
|
||||
/* Clear the static variables for the next item. */
|
||||
discipline_name = perm_string::perm_string();
|
||||
discipline_domain = DD_NONE;
|
||||
discipline_potential = 0;
|
||||
discipline_flow = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The parser uses this function to attach a discipline to a wire. The
|
||||
* wire may be declared by now, or will be declared further later. If
|
||||
* it is already declared, we just attach the discipline. If it is not
|
||||
* declared yet, then this is the declaration and we create the signal
|
||||
* in the current lexical scope.
|
||||
*/
|
||||
void pform_attach_discipline(const struct vlltype&loc,
|
||||
discipline_t*discipline, list<perm_string>*names)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; cur ++ ) {
|
||||
|
||||
PWire* cur_net = pform_get_wire_in_scope(*cur);
|
||||
if (cur_net == 0) {
|
||||
/* Not declared yet, declare it now. */
|
||||
pform_makewire(loc, *cur, NetNet::WIRE,
|
||||
NetNet::NOT_A_PORT, IVL_VT_REAL, 0);
|
||||
cur_net = pform_get_wire_in_scope(*cur);
|
||||
assert(cur_net);
|
||||
}
|
||||
|
||||
if (discipline_t*tmp = cur_net->get_discipline()) {
|
||||
cerr << loc.text << ":" << loc.first_line << ": error: "
|
||||
<< "discipline " << discipline->name()
|
||||
<< " cannot override existing discipline " << tmp->name()
|
||||
<< " on net " << cur_net->basename() << endl;
|
||||
error_count += 1;
|
||||
|
||||
} else {
|
||||
cur_net->set_discipline(discipline);
|
||||
}
|
||||
}
|
||||
}
|
||||
+136
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2006 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2008 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
|
||||
@@ -29,6 +29,7 @@
|
||||
# include "PEvent.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PSpec.h"
|
||||
# include "discipline.h"
|
||||
# include <iostream>
|
||||
# include <iomanip>
|
||||
# include <typeinfo>
|
||||
@@ -97,7 +98,7 @@ ostream& operator<< (ostream&out, const index_component_t&that)
|
||||
}
|
||||
out << "]";
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&out, const name_component_t&that)
|
||||
{
|
||||
@@ -128,6 +129,26 @@ ostream& operator<< (ostream&o, const pform_name_t&that)
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& operator << (std::ostream&out, ddomain_t dom)
|
||||
{
|
||||
switch (dom) {
|
||||
case DD_NONE:
|
||||
out << "no-domain";
|
||||
break;
|
||||
case DD_DISCRETE:
|
||||
out << "discrete";
|
||||
break;
|
||||
case DD_CONTINUOUS:
|
||||
out << "continuous";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void PExpr::dump(ostream&out) const
|
||||
{
|
||||
out << typeid(*this).name();
|
||||
@@ -215,11 +236,30 @@ void PETernary::dump(ostream&out) const
|
||||
|
||||
void PEUnary::dump(ostream&out) const
|
||||
{
|
||||
out << op_ << "(" << *expr_ << ")";
|
||||
switch (op_) {
|
||||
case 'm':
|
||||
out << "abs";
|
||||
break;
|
||||
default:
|
||||
out << op_;
|
||||
break;
|
||||
}
|
||||
out << "(" << *expr_ << ")";
|
||||
}
|
||||
|
||||
void PEBinary::dump(ostream&out) const
|
||||
{
|
||||
/* Handle some special cases, where the operators are written
|
||||
in function notation. */
|
||||
if (op_ == 'm') {
|
||||
out << "min(" << *left_ << "," << *right_ << ")";
|
||||
return;
|
||||
}
|
||||
if (op_ == 'M') {
|
||||
out << "min(" << *left_ << "," << *right_ << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
out << "(" << *left_ << ")";
|
||||
switch (op_) {
|
||||
case 'a':
|
||||
@@ -281,6 +321,10 @@ void PWire::dump(ostream&out, unsigned ind) const
|
||||
out << " signed";
|
||||
}
|
||||
|
||||
if (discipline_) {
|
||||
out << " discipline<" << discipline_->name() << ">";
|
||||
}
|
||||
|
||||
if (port_set_) {
|
||||
if (port_msb_ == 0) {
|
||||
out << " port<scalar>";
|
||||
@@ -296,7 +340,7 @@ void PWire::dump(ostream&out, unsigned ind) const
|
||||
}
|
||||
}
|
||||
|
||||
out << " " << hname_;
|
||||
out << " " << name_;
|
||||
|
||||
// If the wire has indices, dump them.
|
||||
if (lidx_ || ridx_) {
|
||||
@@ -504,10 +548,13 @@ void PAssignNB::dump(ostream&out, unsigned ind) const
|
||||
void PBlock::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "begin";
|
||||
if (name_ != 0)
|
||||
out << " : " << name_;
|
||||
if (pscope_name() != 0)
|
||||
out << " : " << pscope_name();
|
||||
out << endl;
|
||||
|
||||
if (pscope_name() != 0)
|
||||
dump_wires_(out, ind+2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {
|
||||
if (list_[idx])
|
||||
list_[idx]->dump(out, ind+2);
|
||||
@@ -697,15 +744,17 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
||||
out << "] ";
|
||||
}
|
||||
|
||||
out << name_ << ";" << endl;
|
||||
out << pscope_name() << ";" << endl;
|
||||
|
||||
if (ports_)
|
||||
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
||||
out << setw(ind) << "";
|
||||
out << "input ";
|
||||
out << (*ports_)[idx]->path() << ";" << endl;
|
||||
out << (*ports_)[idx]->basename() << ";" << endl;
|
||||
}
|
||||
|
||||
dump_wires_(out, ind);
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(out, ind);
|
||||
else
|
||||
@@ -743,9 +792,11 @@ void PTask::dump(ostream&out, unsigned ind) const
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
out << (*ports_)[idx]->path() << ";" << endl;
|
||||
out << (*ports_)[idx]->basename() << ";" << endl;
|
||||
}
|
||||
|
||||
dump_wires_(out, ind);
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(out, ind);
|
||||
else
|
||||
@@ -854,6 +905,15 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
||||
case GS_ELSE:
|
||||
out << " else !(" << *loop_test << ")";
|
||||
break;
|
||||
case GS_CASE:
|
||||
out << " case (" << *loop_test << ")";
|
||||
break;
|
||||
case GS_CASE_ITEM:
|
||||
if (loop_test)
|
||||
out << " (" << *loop_test << ") == (" << *parent->loop_test << ")";
|
||||
else
|
||||
out << " default:";
|
||||
break;
|
||||
}
|
||||
|
||||
if (scope_name)
|
||||
@@ -861,7 +921,7 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
||||
|
||||
out << endl;
|
||||
|
||||
for (map<pform_name_t,PWire*>::const_iterator idx = wires.begin()
|
||||
for (map<perm_string,PWire*>::const_iterator idx = wires.begin()
|
||||
; idx != wires.end() ; idx++) {
|
||||
|
||||
(*idx).second->dump(out, indent+2);
|
||||
@@ -882,7 +942,17 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
||||
(*idx)->dump(out, indent+2);
|
||||
}
|
||||
|
||||
out << " endgenerate" << endl;
|
||||
out << setw(indent) << "" << "endgenerate" << endl;
|
||||
}
|
||||
|
||||
void PScope::dump_wires_(ostream&out, unsigned indent) const
|
||||
{
|
||||
// Iterate through and display all the wires.
|
||||
for (map<perm_string,PWire*>::const_iterator wire = wires.begin()
|
||||
; wire != wires.end() ; wire ++ ) {
|
||||
|
||||
(*wire).second->dump(out, indent);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::dump(ostream&out) const
|
||||
@@ -902,7 +972,7 @@ void Module::dump(ostream&out) const
|
||||
out << " *) ";
|
||||
}
|
||||
|
||||
out << "module " << name_ << ";" << endl;
|
||||
out << "module " << mod_name() << ";" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
port_t*cur = ports[idx];
|
||||
@@ -924,7 +994,7 @@ void Module::dump(ostream&out) const
|
||||
typedef map<pform_name_t,PExpr*>::const_iterator parm_hiter_t;
|
||||
for (parm_iter_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
out << " parameter ";
|
||||
out << " parameter " << (*cur).second.type << " ";
|
||||
if ((*cur).second.signed_flag)
|
||||
out << "signed ";
|
||||
if ((*cur).second.msb)
|
||||
@@ -932,9 +1002,38 @@ void Module::dump(ostream&out) const
|
||||
<< *(*cur).second.lsb << "] ";
|
||||
out << (*cur).first << " = ";
|
||||
if ((*cur).second.expr)
|
||||
out << *(*cur).second.expr << ";" << endl;
|
||||
out << *(*cur).second.expr;
|
||||
else
|
||||
out << "/* ERROR */;" << endl;
|
||||
out << "/* ERROR */";
|
||||
for (Module::range_t*tmp = (*cur).second.range
|
||||
; tmp ; tmp = tmp->next) {
|
||||
if (tmp->exclude_flag)
|
||||
out << " exclude ";
|
||||
else
|
||||
out << " from ";
|
||||
if (tmp->low_open_flag)
|
||||
out << "(";
|
||||
else
|
||||
out << "[";
|
||||
if (tmp->low_expr)
|
||||
out << *(tmp->low_expr);
|
||||
else if (tmp->low_open_flag==false)
|
||||
out << "-inf";
|
||||
else
|
||||
out << "<nil>";
|
||||
out << ":";
|
||||
if (tmp->high_expr)
|
||||
out << *(tmp->high_expr);
|
||||
else if (tmp->high_open_flag==false)
|
||||
out << "inf";
|
||||
else
|
||||
out << "<nil>";
|
||||
if (tmp->high_open_flag)
|
||||
out << ")";
|
||||
else
|
||||
out << "]";
|
||||
}
|
||||
out << ";" << endl;
|
||||
}
|
||||
|
||||
for (parm_iter_t cur = localparams.begin()
|
||||
@@ -950,10 +1049,10 @@ void Module::dump(ostream&out) const
|
||||
out << "/* ERROR */;" << endl;
|
||||
}
|
||||
|
||||
typedef list<perm_string>::const_iterator genvar_iter_t;
|
||||
typedef map<perm_string,LineInfo*>::const_iterator genvar_iter_t;
|
||||
for (genvar_iter_t cur = genvars.begin()
|
||||
; cur != genvars.end() ; cur++) {
|
||||
out << " genvar " << (*cur) << ";" << endl;
|
||||
out << " genvar " << ((*cur).first) << ";" << endl;
|
||||
}
|
||||
|
||||
typedef list<PGenerate*>::const_iterator genscheme_iter_t;
|
||||
@@ -986,12 +1085,7 @@ void Module::dump(ostream&out) const
|
||||
}
|
||||
|
||||
// Iterate through and display all the wires.
|
||||
for (map<pform_name_t,PWire*>::const_iterator wire = wires_.begin()
|
||||
; wire != wires_.end()
|
||||
; wire ++ ) {
|
||||
|
||||
(*wire).second->dump(out);
|
||||
}
|
||||
dump_wires_(out, 4);
|
||||
|
||||
// Dump the task definitions.
|
||||
typedef map<perm_string,PTask*>::const_iterator task_iter_t;
|
||||
@@ -1021,8 +1115,8 @@ void Module::dump(ostream&out) const
|
||||
}
|
||||
|
||||
|
||||
for (list<PProcess*>::const_iterator behav = behaviors_.begin()
|
||||
; behav != behaviors_.end()
|
||||
for (list<PProcess*>::const_iterator behav = behaviors.begin()
|
||||
; behav != behaviors.end()
|
||||
; behav ++ ) {
|
||||
|
||||
(*behav)->dump(out, 4);
|
||||
@@ -1084,3 +1178,20 @@ void PUdp::dump(ostream&out) const
|
||||
out << "endprimitive" << endl;
|
||||
}
|
||||
|
||||
void pform_dump(std::ostream&out, const nature_t*nat)
|
||||
{
|
||||
out << "nature " << nat->name() << endl;
|
||||
out << " access " << nat->access() << ";" << endl;
|
||||
out << "endnature" << endl;
|
||||
}
|
||||
|
||||
void pform_dump(std::ostream&out, const discipline_t*dis)
|
||||
{
|
||||
out << "discipline " << dis->name() << endl;
|
||||
out << " domain " << dis->domain() << ";" << endl;
|
||||
if (const nature_t*tmp = dis->potential())
|
||||
out << " potential " << tmp->name() << ";" << endl;
|
||||
if (const nature_t*tmp = dis->flow())
|
||||
out << " flow " << tmp->name() << ";" << endl;
|
||||
out << "enddiscipline" << endl;
|
||||
}
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ struct name_component_t {
|
||||
extern bool operator < (const name_component_t&lef, const name_component_t&rig);
|
||||
|
||||
/*
|
||||
* The pform_name_t is the general form for a heirarchical identifier.
|
||||
* The pform_name_t is the general form for a hierarchical identifier.
|
||||
*/
|
||||
typedef std::list<name_component_t> pform_name_t;
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script makes snapshots from a git repository. The input is
|
||||
# the number for a snapshot and the path to a temporary directory.
|
||||
# for example:
|
||||
#
|
||||
# sh scripts/MAKE_SNAPSHOT.sh 20080428 ~/tmp
|
||||
#
|
||||
# The above assumes that there is a tag "s20080428" at the point
|
||||
# to be snaphot. (The tag has the "s", but the argument to this
|
||||
# script does not have the "s"). This script extracts based on the
|
||||
# tag, uses the temporary directory to stage intermediate results,
|
||||
# and finally creates a file called verilog-20080428.tar.gz that
|
||||
# contains the snapshot ready to go.
|
||||
#
|
||||
# The complete steps to make a snapshot YYYYMMDD generally are:
|
||||
#
|
||||
# git tag -a sYYYYMMDD
|
||||
# (Make the tag in the local git repository.)
|
||||
#
|
||||
# sh scripts/MAKE_SNAPSHOT.sh YYYYMMDD ~/tmp
|
||||
# (Make the snapshot bundle verilog-YYYYMMDD.tar.gz)
|
||||
#
|
||||
# git push --tags
|
||||
# (Publish the tag to the repository.)
|
||||
#
|
||||
id=$1
|
||||
destdir=$2
|
||||
|
||||
# The git tag to use is the snapshot id with a prepended "s".
|
||||
tag="s$id"
|
||||
|
||||
# The prefix is the directory that contains the extracted files
|
||||
# of the bundle. This is also the name of the bundle file itself.
|
||||
prefix="verilog-$id"
|
||||
|
||||
if [ ! -d $destdir ]; then
|
||||
echo "ERROR: Directory $destdir does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e $destdir/$prefix ]; then
|
||||
echo "ERROR: $destdir/$prefix already exists."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Exporting $tag to $destdir/$prefix..."
|
||||
git-archive --prefix="$prefix/" $tag | ( cd "$destdir" && tar xf - )
|
||||
|
||||
versionh="$destdir/$prefix/version.h"
|
||||
echo "Create $versionh ..."
|
||||
echo "#define VERSION_TAG \"$tag\"" > $versionh
|
||||
|
||||
echo "Running autoconf.sh..."
|
||||
( cd $destdir/$prefix && sh autoconf.sh )
|
||||
|
||||
echo "Making bundle $prefix.tar.gz..."
|
||||
tar czf $prefix.tar.gz --exclude=autom4te.cache -C "$destdir" $prefix
|
||||
|
||||
echo "Removing temporary $destdir/$prefix..."
|
||||
rm -rf "$destdir/$prefix"
|
||||
|
||||
echo done
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2008 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
|
||||
@@ -185,8 +185,7 @@ bool NetEBMult::set_width(unsigned w, bool)
|
||||
|
||||
bool NetEBPow::set_width(unsigned w, bool last_chance)
|
||||
{
|
||||
bool flag = left_->set_width(w, last_chance);
|
||||
return flag;
|
||||
return w == expr_width();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -414,8 +413,10 @@ bool NetETernary::set_width(unsigned w, bool last_chance)
|
||||
*/
|
||||
bool NetEUFunc::set_width(unsigned wid, bool)
|
||||
{
|
||||
expr_width(wid);
|
||||
return true;
|
||||
if (result_sig_->expr_width() == wid)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetEUnary::set_width(unsigned w, bool)
|
||||
@@ -445,4 +446,3 @@ bool NetEUReduce::set_width(unsigned w, bool)
|
||||
{
|
||||
return w == 1;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2000-2005 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2007 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
|
||||
@@ -263,6 +263,9 @@ struct tokenize : public proc_match_t {
|
||||
last_->next_ = cur;
|
||||
last_ = cur;
|
||||
|
||||
/* Because synthesis is broken this is needed to prevent
|
||||
* a seg. fault. */
|
||||
if (!dev->if_clause()) return 0;
|
||||
dev -> if_clause() -> match_proc(this);
|
||||
|
||||
if (dev->else_clause()) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user