mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcc7045fc9 | ||
|
|
3b1929259a | ||
|
|
cdd6ea8e60 | ||
|
|
4b8927af75 | ||
|
|
0fba25c1b3 | ||
|
|
f19ba9d54d | ||
|
|
8e9a0121ac | ||
|
|
bd6e8d808c | ||
|
|
11b9a631d4 | ||
|
|
f197dd29cb | ||
|
|
daf7f42138 | ||
|
|
dd487d4184 | ||
|
|
d90071637d | ||
|
|
d8efae2aba | ||
|
|
22543f3e19 | ||
|
|
6aaef67e73 | ||
|
|
82a934d6fb | ||
|
|
eca6f2ca05 | ||
|
|
ef69f36403 | ||
|
|
99cf981c2f | ||
|
|
fc7a449f6d | ||
|
|
b7fafdafaa | ||
|
|
8e180cfcde | ||
|
|
4770fd39d2 | ||
|
|
df107628c6 | ||
|
|
3463080a71 | ||
|
|
500dc2170f | ||
|
|
a76ae67a81 | ||
|
|
1d091e49e1 | ||
|
|
2b63219cc6 | ||
|
|
f1b7762bef | ||
|
|
043ad86482 | ||
|
|
74ca9578ed | ||
|
|
d499161446 | ||
|
|
34e8de56bc | ||
|
|
8a7864ebaa | ||
|
|
9e5fb5467f | ||
|
|
fb34bf7222 | ||
|
|
4591f35b7c | ||
|
|
f0a06182ca | ||
|
|
d9e47a6293 | ||
|
|
a555f87705 | ||
|
|
826b997166 | ||
|
|
d34bc6f304 | ||
|
|
5771ea48ef | ||
|
|
a4f3199427 | ||
|
|
e6a43fc127 | ||
|
|
701bd38d01 | ||
|
|
1a8c8bec0d | ||
|
|
20aa21d4b6 | ||
|
|
8c6adeb85a | ||
|
|
09b7ba1317 | ||
|
|
0703843ac1 | ||
|
|
d962dfe48c | ||
|
|
d6884db439 | ||
|
|
fdcbedef8f | ||
|
|
8afd19648f | ||
|
|
3017f12238 | ||
|
|
23ee0342c6 | ||
|
|
499f98a51c | ||
|
|
3073db4e81 | ||
|
|
5703377a5f | ||
|
|
b85aa872cc | ||
|
|
5a1a5a7d97 | ||
|
|
52912c6329 | ||
|
|
056f72f27f | ||
|
|
bb038e86a2 | ||
|
|
cc6c71eb37 | ||
|
|
de4358f8d8 | ||
|
|
d6e9c72424 | ||
|
|
96608fb18d | ||
|
|
280b826d6d | ||
|
|
538d3d46f4 | ||
|
|
66b8ec8935 | ||
|
|
4f30025aa0 | ||
|
|
faad36a3ef | ||
|
|
0b461599d1 | ||
|
|
0cbab84143 | ||
|
|
a4e2a770f6 | ||
|
|
36e84973ec | ||
|
|
f6c8888ee2 | ||
|
|
f2bf6a037b | ||
|
|
9dade8fbd9 | ||
|
|
d2d38edf06 | ||
|
|
e0abd238e3 | ||
|
|
7edcc08886 | ||
|
|
0c73b547f1 | ||
|
|
73c3d4bb50 | ||
|
|
77f063367a | ||
|
|
8e812058cb | ||
|
|
506c36beed | ||
|
|
0110f0193e | ||
|
|
7b870f4b2a | ||
|
|
aa2630f837 | ||
|
|
e137e93f94 | ||
|
|
215bdfccc2 | ||
|
|
956a0a9c99 | ||
|
|
ab83717b7d | ||
|
|
61e876e4bf | ||
|
|
9ca3dbc140 | ||
|
|
a02e2e25bb | ||
|
|
a9281f2c37 | ||
|
|
95395a8b87 | ||
|
|
ecdbd72fa1 | ||
|
|
3a2f8224e4 | ||
|
|
15841fe5f6 | ||
|
|
7e5a7b65a0 | ||
|
|
549bf876e4 | ||
|
|
bd60cf12f8 | ||
|
|
61fbab1910 | ||
|
|
957f495314 | ||
|
|
280eb48ba4 | ||
|
|
ebe5711b40 | ||
|
|
a16477d84f | ||
|
|
f6fb2362c6 | ||
|
|
170427bba1 | ||
|
|
93531e520a | ||
|
|
aa2db8fdde | ||
|
|
7c3c2af90b | ||
|
|
6dca9b4ba4 | ||
|
|
ede37bb9d8 | ||
|
|
4a1729eaab | ||
|
|
b1565f5b89 | ||
|
|
4fb8dcfd4e | ||
|
|
16d1f2b835 | ||
|
|
73594e5aa5 | ||
|
|
c0a365bd34 | ||
|
|
45940ff820 | ||
|
|
d545ae242c | ||
|
|
e862aaf2e1 | ||
|
|
30c3540086 | ||
|
|
663a084ca4 | ||
|
|
b4d9ccd9af | ||
|
|
98fff6a4ce | ||
|
|
4977a5e1d9 | ||
|
|
e4297486ef | ||
|
|
ad591767c9 | ||
|
|
8bc1e75d9f | ||
|
|
a1c7adcffc | ||
|
|
8867169957 | ||
|
|
79eac1e6b0 | ||
|
|
87533b13e1 | ||
|
|
a2ffe86a36 | ||
|
|
22bde7d461 | ||
|
|
f23203dc96 | ||
|
|
a94f1c779b | ||
|
|
6412aff82d | ||
|
|
99bc1f92c9 | ||
|
|
891edad53a | ||
|
|
98e35b02ad | ||
|
|
8075372675 | ||
|
|
10e34ca48e | ||
|
|
329808afff | ||
|
|
7fc3e6c168 | ||
|
|
199b32709c | ||
|
|
1775da5f43 | ||
|
|
45c202f78f | ||
|
|
a77b58dba9 | ||
|
|
c300ab6dd9 | ||
|
|
9ac0f1accb | ||
|
|
7990e5d4b1 | ||
|
|
fb2cb3c49d | ||
|
|
c4b1bc2506 | ||
|
|
551393d443 | ||
|
|
79d305f3e8 | ||
|
|
822956e769 | ||
|
|
a681a6a6d5 | ||
|
|
5f6d69affd | ||
|
|
4a9bea6980 | ||
|
|
bfddd80f43 | ||
|
|
84a778719a | ||
|
|
829d80d5b5 | ||
|
|
d6a5c97f3a | ||
|
|
4ba00bd256 | ||
|
|
c18f9da400 | ||
|
|
5b620a8dc5 | ||
|
|
9c968c590c | ||
|
|
dff5d5c4e4 | ||
|
|
1265e8cce8 | ||
|
|
2b5d7eeb50 | ||
|
|
bb9ae89049 | ||
|
|
72832a2810 | ||
|
|
18cb210eac | ||
|
|
2c5a183368 | ||
|
|
386f0a75df | ||
|
|
ea26482154 | ||
|
|
3aee7f918a | ||
|
|
b3dd18b215 | ||
|
|
a77e331e89 | ||
|
|
6f414ee9e2 | ||
|
|
8d56b498d1 | ||
|
|
871c1853bf | ||
|
|
f8cd3a785c | ||
|
|
6a6995187e | ||
|
|
a216c1e7e4 | ||
|
|
ea8445d187 | ||
|
|
77261cce5b | ||
|
|
78db712438 | ||
|
|
749302acb8 | ||
|
|
cbf52bb5d0 | ||
|
|
d2ce499b59 | ||
|
|
01e9bc4855 | ||
|
|
28d5e425a9 | ||
|
|
eae1f380cd | ||
|
|
e7280d7237 | ||
|
|
78997ee13c | ||
|
|
79ab50d84f | ||
|
|
98282114c9 | ||
|
|
d6cb175f96 | ||
|
|
b4d9eb6ec4 | ||
|
|
fabbfbc46e | ||
|
|
c7d80f8cf8 | ||
|
|
c70add7d0f | ||
|
|
44fe8741f3 | ||
|
|
f8680cf5c2 | ||
|
|
24c3424e51 | ||
|
|
bd264006ef | ||
|
|
bec3daa79f | ||
|
|
ead01ba0b9 | ||
|
|
8e7267f0e2 | ||
|
|
5dbae27f01 | ||
|
|
ecb938f20e | ||
|
|
f1a2ee3273 | ||
|
|
eb2eb14297 | ||
|
|
da07cc6ed1 | ||
|
|
3ff10b40d6 | ||
|
|
7f515e6033 | ||
|
|
a583592cd4 | ||
|
|
b6f2b5b46a | ||
|
|
895a3264a3 | ||
|
|
8738a51449 | ||
|
|
8ca6901f1f | ||
|
|
c14818ebb3 | ||
|
|
58dc91605b | ||
|
|
b5b1d94d4a | ||
|
|
5a65f6debb | ||
|
|
58b1ad1439 | ||
|
|
94d0aa2058 | ||
|
|
1d6495e2dc | ||
|
|
42883e7b6a | ||
|
|
dc6a164e01 | ||
|
|
26bab12257 | ||
|
|
8714ee591f | ||
|
|
11335fae5f | ||
|
|
ce531c5a67 | ||
|
|
52e36fb434 | ||
|
|
100d5b386c | ||
|
|
699563c9bd | ||
|
|
a599fbea18 | ||
|
|
c5f0ed9c99 | ||
|
|
2ce30e78a1 | ||
|
|
3b554f4c5b | ||
|
|
cf40fd356f | ||
|
|
8848469bf9 | ||
|
|
4100417f83 | ||
|
|
bd6d743f9c | ||
|
|
857ac24ba7 | ||
|
|
5672b99203 | ||
|
|
3d8de3194c | ||
|
|
8b91a9f898 | ||
|
|
038ee69a96 | ||
|
|
8986d1f16f | ||
|
|
86c8e7b3e6 | ||
|
|
9026118a7c | ||
|
|
58fc922737 | ||
|
|
3b5c791332 | ||
|
|
6e16bc1b7b | ||
|
|
1aba0f6379 | ||
|
|
11cfa3c072 | ||
|
|
59141b1678 | ||
|
|
2083c071ce | ||
|
|
3ad5872d30 | ||
|
|
ea6bb21cdc | ||
|
|
3d4fe0364a | ||
|
|
710d7c0ee5 | ||
|
|
1c8fd37745 | ||
|
|
956c854662 | ||
|
|
318a6e348c | ||
|
|
e471a34323 | ||
|
|
95c5b85e88 | ||
|
|
a46a556a64 | ||
|
|
fa3e03e071 | ||
|
|
74d7c55f1b | ||
|
|
79e02858cb | ||
|
|
7738b202ac | ||
|
|
b4d4917c6c | ||
|
|
5c93520b27 | ||
|
|
94f0809d33 | ||
|
|
ca4e3c1737 | ||
|
|
ba7b4f261a | ||
|
|
4f42c25c7c | ||
|
|
621ef70c31 | ||
|
|
e3f17e7853 | ||
|
|
73c897ac69 | ||
|
|
a4db880809 | ||
|
|
f9697463cc | ||
|
|
f283076570 | ||
|
|
e15228498d | ||
|
|
53155b3a36 | ||
|
|
12ae70ba95 | ||
|
|
88809587f9 |
@@ -7,7 +7,7 @@
|
|||||||
*.1
|
*.1
|
||||||
*.tmp
|
*.tmp
|
||||||
*.tex
|
*.tex
|
||||||
Makefile
|
/Makefile
|
||||||
README
|
README
|
||||||
config.cache
|
config.cache
|
||||||
config.status
|
config.status
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
^CVS/
|
||||||
|
/CVS/
|
||||||
|
\.git/
|
||||||
|
\.svn/
|
||||||
|
\.(bak|old)/
|
||||||
|
\.(bak|old)$
|
||||||
|
\bMakefile$
|
||||||
|
\.tar\.
|
||||||
|
.*\.tgz
|
||||||
|
.*\.log
|
||||||
|
.*\.tmp
|
||||||
|
.*\.tex
|
||||||
|
.*\.key
|
||||||
|
.*\.vcd
|
||||||
|
/obj_dir/
|
||||||
|
/obj_dbg/
|
||||||
|
/obj_opt/
|
||||||
|
/INCA_libs/
|
||||||
|
/cov_work/
|
||||||
|
/logs/
|
||||||
|
Makefile
|
||||||
|
src/Makefile_obj
|
||||||
|
include/verilated.mk
|
||||||
|
config.cache
|
||||||
|
config.status
|
||||||
|
verilator_bin.*
|
||||||
|
autom4te\.cache/
|
||||||
|
nodist/
|
||||||
+93
-54
@@ -1,24 +1,23 @@
|
|||||||
# $Id$
|
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
# DESCRIPTION: Verilator top level: Makefile pre-configure version
|
# DESCRIPTION: Verilator top level: Makefile pre-configure version
|
||||||
#
|
#
|
||||||
# This file is part of Verilator.
|
# This file is part of Verilator.
|
||||||
#
|
#
|
||||||
# Author: Wilson Snyder <[email protected]> or <[email protected]>
|
# Author: Wilson Snyder <[email protected]>
|
||||||
#
|
#
|
||||||
# Code available from: http://www.veripool.com/verilator
|
# Code available from: http://www.veripool.org/verilator
|
||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# General Public License or the Perl Artistic License.
|
# General Public License or the Perl Artistic License.
|
||||||
#
|
#
|
||||||
# Verilator is distributed in the hope that it will be useful,
|
# Verilator is distributed in the hope that it will be useful,
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
# GNU General Public License for more details.
|
# GNU General Public License for more details.
|
||||||
#
|
#
|
||||||
#****************************************************************************/
|
#****************************************************************************/
|
||||||
#
|
#
|
||||||
# make all to compile and build Verilator.
|
# make all to compile and build Verilator.
|
||||||
@@ -38,7 +37,7 @@
|
|||||||
# source and built the program without creating any other files,
|
# source and built the program without creating any other files,
|
||||||
# `make distclean' should leave only the files that were in the
|
# `make distclean' should leave only the files that were in the
|
||||||
# distribution.
|
# distribution.
|
||||||
#
|
#
|
||||||
# make maintainer-clean
|
# make maintainer-clean
|
||||||
# Delete everything from the current directory that can be
|
# Delete everything from the current directory that can be
|
||||||
# reconstructed with this Makefile. This typically includes
|
# reconstructed with this Makefile. This typically includes
|
||||||
@@ -61,6 +60,9 @@ MAKEINFO = makeinfo
|
|||||||
TEXI2DVI = texi2dvi
|
TEXI2DVI = texi2dvi
|
||||||
PERL = @PERL@
|
PERL = @PERL@
|
||||||
|
|
||||||
|
# Destination prefix for RPMs
|
||||||
|
DESTDIR =
|
||||||
|
|
||||||
#### Don't edit: You're much better using configure switches to set these
|
#### Don't edit: You're much better using configure switches to set these
|
||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
exec_prefix = @exec_prefix@
|
exec_prefix = @exec_prefix@
|
||||||
@@ -78,9 +80,12 @@ datadir = @datadir@
|
|||||||
infodir = @infodir@
|
infodir = @infodir@
|
||||||
|
|
||||||
# Directory in which to install package specific files
|
# Directory in which to install package specific files
|
||||||
# Note this gets coded into v3c/config.h also
|
# Generally ${prefix}/share/verilator
|
||||||
pkgdatadir = @pkgdatadir@
|
pkgdatadir = @pkgdatadir@
|
||||||
|
|
||||||
|
# Directory in which to install data across multiple architectures
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
@@ -91,30 +96,38 @@ SUBDIRS = src test_verilated test_c test_sc test_sp test_regress test_vcs
|
|||||||
INFOS = README verilator.txt verilator.html verilator.1 verilator.pdf
|
INFOS = README verilator.txt verilator.html verilator.1 verilator.pdf
|
||||||
|
|
||||||
# Files that can be generated, but should be up to date for a distribution.
|
# Files that can be generated, but should be up to date for a distribution.
|
||||||
DISTDEP = $(INFOS) Makefile
|
DISTDEP = info Makefile
|
||||||
# Files to distribute.
|
# Files to distribute.
|
||||||
DISTBIN = $(wildcard bin/verilator-*)
|
DISTBIN = $(wildcard bin/verilator-*)
|
||||||
|
|
||||||
DISTFILES_INC = $(INFOS) .cvsignore COPYING *.in \
|
DISTFILES_INC = $(INFOS) .gitignore COPYING *.in *.ac \
|
||||||
Changes README TODO \
|
Changes README TODO \
|
||||||
|
MANIFEST.SKIP \
|
||||||
bin/* \
|
bin/* \
|
||||||
install-sh configure mkinstalldirs *.texi \
|
install-sh configure mkinstalldirs *.texi \
|
||||||
include/verilated.[chv]* \
|
include/verilated.[chv]* \
|
||||||
include/verilatedos.[chv]* \
|
include/verilatedos.[chv]* \
|
||||||
include/*.in \
|
include/*.in \
|
||||||
src/.cvsignore src/*.in src/*.cpp src/*.[chly] src/astgen src/flexfix \
|
include/.*ignore \
|
||||||
|
.*attributes */.*attributes */*/.*attributes \
|
||||||
|
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
|
||||||
src/*.pl \
|
src/*.pl \
|
||||||
test_*/.cvsignore test_*/Makefile* test_*/*.cpp \
|
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
||||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
|
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
|
||||||
test_verilated/vgen*.pl \
|
test_verilated/vgen*.pl \
|
||||||
test_regress/t/*.v* \
|
test_regress/t/*.cpp \
|
||||||
test_regress/t/*.pl \
|
test_regress/t/*.h \
|
||||||
|
test_regress/t/*.dat \
|
||||||
|
test_regress/t/*.mem \
|
||||||
test_regress/t/*.out \
|
test_regress/t/*.out \
|
||||||
|
test_regress/t/*.pl \
|
||||||
|
test_regress/t/*.v* \
|
||||||
verilator.* \
|
verilator.* \
|
||||||
|
|
||||||
INST_PROJ_FILES = \
|
INST_PROJ_FILES = \
|
||||||
bin/verilator \
|
bin/verilator \
|
||||||
bin/verilator_includer \
|
bin/verilator_includer \
|
||||||
|
bin/verilator_profcfunc \
|
||||||
include/verilated.[chv]* \
|
include/verilated.[chv]* \
|
||||||
include/verilated.mk \
|
include/verilated.mk \
|
||||||
include/verilatedos.[chv]* \
|
include/verilatedos.[chv]* \
|
||||||
@@ -125,8 +138,10 @@ INST_PROJ_BIN_FILES = \
|
|||||||
|
|
||||||
DISTFILES := $(DISTFILES_INC)
|
DISTFILES := $(DISTFILES_INC)
|
||||||
|
|
||||||
|
VL_INST_MAN_FILES = verilator.1
|
||||||
|
|
||||||
all: all_nomsg msg_test
|
all: all_nomsg msg_test
|
||||||
all_nomsg: verilator_exe info
|
all_nomsg: verilator_exe $(VL_INST_MAN_FILES)
|
||||||
|
|
||||||
.PHONY:verilator_exe
|
.PHONY:verilator_exe
|
||||||
verilator_exe verilator_bin verilator_bin_dbg:
|
verilator_exe verilator_bin verilator_bin_dbg:
|
||||||
@@ -141,6 +156,7 @@ msg_test:
|
|||||||
@echo "Type 'make test' to test."
|
@echo "Type 'make test' to test."
|
||||||
@echo
|
@echo
|
||||||
|
|
||||||
|
.PHONY:test
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||||
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
||||||
else
|
else
|
||||||
@@ -156,15 +172,15 @@ test_vcs: all_nomsg
|
|||||||
test_c: all_nomsg
|
test_c: all_nomsg
|
||||||
@(cd test_c && $(MAKE))
|
@(cd test_c && $(MAKE))
|
||||||
test_c_debug: all_nomsg
|
test_c_debug: all_nomsg
|
||||||
@(cd test_c && $(MAKE) debug)
|
@(cd test_c && $(MAKE) test_debug)
|
||||||
test_sc: all_nomsg
|
test_sc: all_nomsg
|
||||||
@(cd test_sc && $(MAKE))
|
@(cd test_sc && $(MAKE))
|
||||||
test_sc_debug: all_nomsg
|
test_sc_debug: all_nomsg
|
||||||
@(cd test_sc && $(MAKE) debug)
|
@(cd test_sc && $(MAKE) test_debug)
|
||||||
test_sp: all_nomsg
|
test_sp: all_nomsg
|
||||||
@(cd test_sp && $(MAKE))
|
@(cd test_sp && $(MAKE))
|
||||||
test_sp_debug: all_nomsg
|
test_sp_debug: all_nomsg
|
||||||
@(cd test_sp && $(MAKE) debug)
|
@(cd test_sp && $(MAKE) test_debug)
|
||||||
test_verilated: all_nomsg
|
test_verilated: all_nomsg
|
||||||
@(cd test_verilated && $(MAKE))
|
@(cd test_verilated && $(MAKE))
|
||||||
test_regress: all_nomsg
|
test_regress: all_nomsg
|
||||||
@@ -185,16 +201,18 @@ verilator.html: bin/verilator
|
|||||||
verilator.pdf: bin/verilator $(DISTCONFIG)
|
verilator.pdf: bin/verilator $(DISTCONFIG)
|
||||||
pod2latex --full --out verilator.tex bin/verilator
|
pod2latex --full --out verilator.tex bin/verilator
|
||||||
cat < verilator.tex \
|
cat < verilator.tex \
|
||||||
|
| sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \
|
||||||
|
| sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \
|
||||||
| sed 's/\\begin{document}/\\usepackage{fancyhdr} \\pagestyle{fancy}\n\\begin{document}/' \
|
| sed 's/\\begin{document}/\\usepackage{fancyhdr} \\pagestyle{fancy}\n\\begin{document}/' \
|
||||||
| sed 's/\\begin{document}/\\setlength{\\parindent}{0pt} \\setlength{\\parskip}{\\baselineskip}\n\\begin{document}/' \
|
| sed 's/\\begin{document}/\\setlength{\\parindent}{0pt} \\setlength{\\parskip}{\\baselineskip}\n\\begin{document}/' \
|
||||||
| sed 's/\\begin{document}/\\title{$(DISTTITLE)} \\date{${DISTDATE}} \\author{Wilson Snyder\\\\ http:\/\/www.veripool.com}\n\\begin{document}/' \
|
| sed 's/\\begin{document}/\\title{$(DISTTITLE)} \\date{${DISTDATE}} \\author{Wilson Snyder\\\\ http:\/\/www.veripool.org}\n\\begin{document}/' \
|
||||||
| sed 's/\\begin{document}/\\lhead[$(DISTTITLE)]{$(DISTTITLE)}\n\\begin{document}/' \
|
| sed 's/\\begin{document}/\\lhead[$(DISTTITLE)]{$(DISTTITLE)}\n\\begin{document}/' \
|
||||||
| sed 's/\\tableofcontents/\\begin{titlepage} \\maketitle \\end{titlepage}\n\\tableofcontents/' \
|
| sed 's/\\tableofcontents/\\begin{titlepage} \\maketitle \\end{titlepage}\n\\tableofcontents/' \
|
||||||
> verilator2.tex
|
> verilator2.tex
|
||||||
mv verilator2.tex verilator.tex
|
mv verilator2.tex verilator.tex
|
||||||
pdflatex verilator.tex
|
pdflatex verilator.tex
|
||||||
pdflatex verilator.tex
|
pdflatex verilator.tex
|
||||||
-rm -f verilator.toc verilator.aux verilator.idx
|
-rm -f verilator.toc verilator.aux verilator.idx verilator.out
|
||||||
|
|
||||||
INSTALL: install.texi
|
INSTALL: install.texi
|
||||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/install.texi --output=$@ \
|
$(MAKEINFO) -I$(srcdir) $(srcdir)/install.texi --output=$@ \
|
||||||
@@ -204,21 +222,37 @@ README: readme.texi
|
|||||||
$(MAKEINFO) -I$(srcdir) $(srcdir)/readme.texi --output=$@ \
|
$(MAKEINFO) -I$(srcdir) $(srcdir)/readme.texi --output=$@ \
|
||||||
--no-headers --no-validate
|
--no-headers --no-validate
|
||||||
|
|
||||||
installdirs:
|
|
||||||
$(SHELL) ${srcdir}/mkinstalldirs $(bindir) $(infodir)
|
|
||||||
|
|
||||||
# See uninstall also
|
# See uninstall also
|
||||||
VL_INST_BIN_FILES = verilator
|
VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
|
||||||
|
verilator_includer verilator_profcfunc
|
||||||
|
# Some scripts go into both the search path and pkgdatadir,
|
||||||
|
# so they can be found by the user, and under $VERILATOR_ROOT.
|
||||||
installbin:
|
installbin:
|
||||||
( cd bin ; $(INSTALL_PROGRAM) verilator $(bindir)/verilator )
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
|
||||||
|
( cd bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
|
||||||
|
( cd bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(bindir)/verilator_includer )
|
||||||
|
( cd bin ; $(INSTALL_PROGRAM) verilator_profcfunc $(DESTDIR)$(bindir)/verilator_profcfunc )
|
||||||
|
( $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin )
|
||||||
|
( $(INSTALL_PROGRAM) verilator_bin_dbg $(DESTDIR)$(bindir)/verilator_bin_dbg )
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
|
||||||
|
( cd bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
||||||
|
|
||||||
VL_INST_MAN_FILES = verilator.1
|
|
||||||
installman:
|
installman:
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||||
for p in $(VL_INST_MAN_FILES) ; do \
|
for p in $(VL_INST_MAN_FILES) ; do \
|
||||||
$(INSTALL_PROGRAM) $$p $(mandir)/man1/$$p; \
|
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||||
done
|
done
|
||||||
|
|
||||||
install: all_nomsg info installdirs installbin installman install-msg
|
installdata:
|
||||||
|
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
cp -r include $(DESTDIR)$(pkgdatadir)
|
||||||
|
cp -r test_c $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
cp -r test_sc $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
cp -r test_sp $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
cp -r test_v $(DESTDIR)$(pkgdatadir)/examples
|
||||||
|
|
||||||
|
VL_INST_DATA_FILES = verilator.1
|
||||||
|
install: all_nomsg installbin installman installdata install-msg
|
||||||
|
|
||||||
install-here: installman ftp
|
install-here: installman ftp
|
||||||
|
|
||||||
@@ -233,8 +267,8 @@ install-project: dist
|
|||||||
for p in verilator.1 ; do \
|
for p in verilator.1 ; do \
|
||||||
$(INSTALL_PROGRAM) -m 0666 $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
$(INSTALL_PROGRAM) -m 0666 $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
||||||
done
|
done
|
||||||
$(INST_PROJ_CVS) $(DISTNAME).tar.gz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
|
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
|
||||||
rm $(DISTNAME).tar.gz
|
rm $(DISTNAME).tgz
|
||||||
|
|
||||||
install-project-quick:
|
install-project-quick:
|
||||||
@echo "Install-project-quick (no strip) to $(DIRPROJECT)"
|
@echo "Install-project-quick (no strip) to $(DIRPROJECT)"
|
||||||
@@ -247,9 +281,6 @@ install-project-quick:
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ftp: info
|
ftp: info
|
||||||
echo "http://www.veripool.com/verilator3.html"
|
|
||||||
cp verilator.html verilator_man.html
|
|
||||||
ftp_tree --password $(VERIPOOL_PW) --user $(VERIPOOL_USER) verilator_man.html webftp.veripool.com:/web
|
|
||||||
|
|
||||||
install-msg:
|
install-msg:
|
||||||
@echo "Installed!"
|
@echo "Installed!"
|
||||||
@@ -262,19 +293,20 @@ install-msg:
|
|||||||
@echo
|
@echo
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
-cd $(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
||||||
-cd $(bindir) && rm -f $(VL_INST_BIN_FILES)
|
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
|
||||||
|
-rm -f $(DESTDIR)$(pkgdatadir)
|
||||||
|
|
||||||
# autoheader might not change config.h.in, so touch a stamp file.
|
# autoheader might not change config_build.h.in, so touch a stamp file.
|
||||||
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
|
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in ${srcdir}/*/*/*.in \
|
||||||
*.in */*.in */*.in
|
*.in */*.in */*.in
|
||||||
|
|
||||||
${srcdir}/config.h.in: stamp-h.in
|
${srcdir}/config_build.h.in: stamp-h.in
|
||||||
${srcdir}/stamp-h.in: configure.in $(wildcard $(IN_WILD))
|
${srcdir}/stamp-h.in: configure.ac $(wildcard $(IN_WILD))
|
||||||
cd ${srcdir} && autoheader
|
cd ${srcdir} && autoheader
|
||||||
echo timestamp > ${srcdir}/stamp-h.in
|
echo timestamp > ${srcdir}/stamp-h.in
|
||||||
config.h: stamp-h
|
config_build.h: stamp-h
|
||||||
stamp-h: config.h.in config.status
|
stamp-h: config_build.h.in config.status
|
||||||
./config.status
|
./config.status
|
||||||
Makefile: Makefile.in config.status
|
Makefile: Makefile.in config.status
|
||||||
./config.status
|
./config.status
|
||||||
@@ -282,13 +314,13 @@ src/Makefile: src/Makefile.in config.status
|
|||||||
./config.status
|
./config.status
|
||||||
config.status: configure
|
config.status: configure
|
||||||
./config.status --recheck
|
./config.status --recheck
|
||||||
configure: configure.in
|
configure: configure.ac
|
||||||
autoconf
|
autoconf
|
||||||
|
|
||||||
maintainer-clean::
|
maintainer-clean::
|
||||||
@echo "This command is intended for maintainers to use;"
|
@echo "This command is intended for maintainers to use;"
|
||||||
@echo "rebuilding the deleted files requires makeinfo."
|
@echo "rebuilding the deleted files requires makeinfo."
|
||||||
rm -f *.info* $(INFOS) faq.html verilator.html configure bin/*
|
rm -f *.info* $(INFOS) faq.html verilator.html configure
|
||||||
|
|
||||||
clean mostlyclean distclean maintainer-clean maintainer-copy::
|
clean mostlyclean distclean maintainer-clean maintainer-copy::
|
||||||
for dir in $(SUBDIRS); do \
|
for dir in $(SUBDIRS); do \
|
||||||
@@ -297,7 +329,7 @@ clean mostlyclean distclean maintainer-clean maintainer-copy::
|
|||||||
done
|
done
|
||||||
|
|
||||||
clean mostlyclean distclean maintainer-clean::
|
clean mostlyclean distclean maintainer-clean::
|
||||||
rm -f $(SCRIPTS) *.tmp
|
rm -f $(SCRIPTS) *.tmp
|
||||||
rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
|
rm -f *.aux *.cp *.cps *.dvi *.fn *.fns *.ky *.kys *.log
|
||||||
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
||||||
rm -f *.ev *.evs *.ov *.ovs *.cv *.cvs *.ma *.mas
|
rm -f *.ev *.evs *.ov *.ovs *.cv *.cvs *.ma *.mas
|
||||||
@@ -313,15 +345,22 @@ TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/[a-z]*.in \
|
|||||||
TAGS: $(TAGFILES)
|
TAGS: $(TAGFILES)
|
||||||
etags $(TAGFILES)
|
etags $(TAGFILES)
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# Test targets
|
||||||
|
|
||||||
|
dist-file-list:
|
||||||
|
@echo "begin-dist-file-list:"; # Scripts look for this
|
||||||
|
@echo $(wildcard $(DISTFILES))
|
||||||
|
@echo "end-dist-file-list:"; # Scripts look for this
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Distributions
|
# Distributions
|
||||||
|
|
||||||
DISTCONFIG = src/config.h.in
|
DISTCONFIG = src/config_build.h.in
|
||||||
|
|
||||||
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG))
|
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG))
|
||||||
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG))
|
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG))
|
||||||
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([0-3]\?[0-9].[0-3]\?[0-9].[1-2][0-9][0-9][0-9]\).*/\1/' -e q $(DISTCONFIG))
|
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([1-2][0-9][0-9][0-9].[0-9]*[0-9].[0-9]*[0-9]\).*/\1/' -e q $(DISTCONFIG))
|
||||||
|
|
||||||
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
||||||
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
||||||
@@ -340,14 +379,14 @@ dist: $(DISTDEP) maintainer-copy
|
|||||||
chmod -R a+r $(DISTNAME)
|
chmod -R a+r $(DISTNAME)
|
||||||
tar chf $(DISTNAME).tar $(DISTNAME)
|
tar chf $(DISTNAME).tar $(DISTNAME)
|
||||||
gzip --force --best $(DISTNAME).tar
|
gzip --force --best $(DISTNAME).tar
|
||||||
|
mv $(DISTNAME).tar.gz $(DISTNAME).tgz
|
||||||
rm -fr $(DISTNAME)
|
rm -fr $(DISTNAME)
|
||||||
|
|
||||||
maintainer-diff:
|
maintainer-diff:
|
||||||
svnorcvs diff $(DISTTAGNAME)
|
svnorcvs diff $(DISTTAGNAME)
|
||||||
|
|
||||||
preexist:
|
preexist:
|
||||||
test ! -r ~/src/kits/$(DISTNAME).tar.gz
|
svnorcvs nexists $(DISTTAGNAME)
|
||||||
|
|
||||||
maintainer-dist: preexist dist tag
|
maintainer-dist: preexist dist tag
|
||||||
cp *.gz ~/backpack
|
svnorcvs release $(DISTNAME).tgz
|
||||||
cp *.gz ~/src/kits
|
|
||||||
|
|||||||
@@ -1,167 +0,0 @@
|
|||||||
1 Verilator
|
|
||||||
***********
|
|
||||||
|
|
||||||
This is the Verilator Package.
|
|
||||||
|
|
||||||
1.1 Copyright
|
|
||||||
=============
|
|
||||||
|
|
||||||
This package is Copyright 2003-2006 by Wilson Snyder
|
|
||||||
<[email protected]>.
|
|
||||||
|
|
||||||
You may distribute under the terms of either the GNU General Public
|
|
||||||
License or the Artistic License, as specified in the Perl README file.
|
|
||||||
|
|
||||||
This code is provided with no warranty of any kind, and is used
|
|
||||||
entirely at your own risk.
|
|
||||||
|
|
||||||
1.2 Description
|
|
||||||
===============
|
|
||||||
|
|
||||||
Verilator converts synthesizable (not behavioral) Verilog code into C++
|
|
||||||
or SystemC code. It is not a complete simulator, just a translator.
|
|
||||||
|
|
||||||
Verilator is invoked with parameters similar to GCC or Synopsys's
|
|
||||||
VCS. It reads the specified Verilog code, lints it, and optionally
|
|
||||||
adds coverage code. For C++ format, it outputs .cpp and .h files. For
|
|
||||||
SystemC format, it outputs .sp files for the SystemPerl preprocessor
|
|
||||||
available at http://veripool.com.
|
|
||||||
|
|
||||||
The resulting files are then compiled with C++. The user writes a
|
|
||||||
little C++ wrapper file, which instantiates the top level module. This
|
|
||||||
is compiled in C++, and linked with the Verilated files.
|
|
||||||
|
|
||||||
The resulting executable will perform the actual simulation.
|
|
||||||
|
|
||||||
1.3 Obtaining Distribution
|
|
||||||
==========================
|
|
||||||
|
|
||||||
The latest version is available at `http://veripool.com/verilator.htm'
|
|
||||||
|
|
||||||
Download the latest package from that site, and decompress. `gunzip
|
|
||||||
verilator_version.tar.gz ; tar xvf verilator_version.tar'
|
|
||||||
|
|
||||||
1.4 Directory Structure
|
|
||||||
=======================
|
|
||||||
|
|
||||||
The directories after de-taring are as follows:
|
|
||||||
|
|
||||||
* bin/verilator => Compiler Wrapper invoked on user Verilog code
|
|
||||||
|
|
||||||
* include/ => Files that should be in your -I compiler
|
|
||||||
path
|
|
||||||
|
|
||||||
* include/verilated.cpp => Global routines to link into your
|
|
||||||
simulator
|
|
||||||
|
|
||||||
* include/verilated.h => Global headers
|
|
||||||
|
|
||||||
* include/verilated.v => Stub defines for linting
|
|
||||||
|
|
||||||
* include/verilated.mk => Common makefile
|
|
||||||
|
|
||||||
* src/ => Translator source code
|
|
||||||
|
|
||||||
* test_v => Example Verilog code for other test dirs
|
|
||||||
|
|
||||||
* test_c => Example Verilog->C++ conversion
|
|
||||||
|
|
||||||
* test_sc => Example Verilog->SystemC conversion
|
|
||||||
|
|
||||||
* test_sp => Example Verilog->SystemPerl conversion
|
|
||||||
|
|
||||||
* test_vcs => Example Verilog->VCS conversion (test the
|
|
||||||
test)
|
|
||||||
|
|
||||||
* test_verilated => Internal tests
|
|
||||||
|
|
||||||
* test_regress => Internal tests
|
|
||||||
|
|
||||||
1.5 Supported Systems
|
|
||||||
=====================
|
|
||||||
|
|
||||||
This version of verilator has been built and tested on:
|
|
||||||
|
|
||||||
* SuSE AMD64 i686-linux-2.6.5
|
|
||||||
|
|
||||||
Other users report success with Redhat Linux 2.4, Windows under
|
|
||||||
Cygwin, HPUX and Solaris. It should run with minor porting on any Unix
|
|
||||||
system.
|
|
||||||
|
|
||||||
1.6 Installation
|
|
||||||
================
|
|
||||||
|
|
||||||
1. If you will be using SystemC (vs straight C++ output), download
|
|
||||||
SystemC 2.0.1 from `http://www.systemc.org'. Follow their
|
|
||||||
installation instructions. As described in the System-Perl README,
|
|
||||||
you will need to set SYSTEMC and/or SYSTEMC_KIT to point to this
|
|
||||||
download. Also, set SYSTEMC_ARCH to the architecture name you used
|
|
||||||
with SystemC, generally 'linux' or 'cygwin'.
|
|
||||||
|
|
||||||
2. If you will be using SystemC, download and install Verilog-Perl,
|
|
||||||
`http://search.cpan.org/search?module=Verilog::Language'.
|
|
||||||
|
|
||||||
3. If you will be using SystemC, download and install System-Perl,
|
|
||||||
`http://search.cpan.org/search?module=SystemC::Netlist'. Note
|
|
||||||
you'll need to set a `SYSTEMPERL' environment variable to point to
|
|
||||||
the downloaded kit (not the installed files.) Also, make sure to
|
|
||||||
do a `make sc_patch'.
|
|
||||||
|
|
||||||
4. `cd' to the Verilator directory containing this README.
|
|
||||||
|
|
||||||
5. Type `./configure' to configure Verilator for your system.
|
|
||||||
|
|
||||||
6. Type `make' to compile Verilator.
|
|
||||||
|
|
||||||
On Cygwin (Windows) you may get a error about libperl.a not being
|
|
||||||
found. You need to copy your perl libraries as follows.
|
|
||||||
|
|
||||||
1. Type `perl -MExtUtils::Embed -e ldopts'
|
|
||||||
|
|
||||||
2. It will show a directory name ending in /CORE. cd to that
|
|
||||||
directory.
|
|
||||||
|
|
||||||
3. `cp libperl5_6_1.a libperl.a'
|
|
||||||
|
|
||||||
4. `cp libperl5_6_1.dll libperl.dll'
|
|
||||||
|
|
||||||
5. `cp libperl5_6_1.def libperl.def'
|
|
||||||
|
|
||||||
7. Type `make test' to check the compilation.
|
|
||||||
|
|
||||||
You may get a error about the Bit::Vector perl package. You will
|
|
||||||
need to install it if you want the tests to pass. (Try `make
|
|
||||||
test_c' for a smaller test that doesn't require it.)
|
|
||||||
|
|
||||||
You may get a error about a typedef conflict for uint32_t. Edit
|
|
||||||
verilated.h to change the typedef to work, probably to `typedef
|
|
||||||
unsigned long uint32_t;'.
|
|
||||||
|
|
||||||
If you get warnings, you might want to edit `include/verilated.mk'
|
|
||||||
to delete the lines that define VK_CPPFLAGS_WALL.
|
|
||||||
|
|
||||||
8. There is no installation at present; this package runs from the
|
|
||||||
distribution directory. Programs should set the environment
|
|
||||||
variable VERILATOR_ROOT to point to this distribution, then execute
|
|
||||||
$VERILATOR_ROOT/bin/verilator, which will find the path to all
|
|
||||||
needed files.
|
|
||||||
|
|
||||||
Verilator assumes you did a make in the SystemC kit directory. If
|
|
||||||
not, you will need to populate `$SYSTEMC/include' and
|
|
||||||
`$SYSTEMC/lib-linux' appropriately.
|
|
||||||
|
|
||||||
If you will be modifying Verilator, you will probably want a second
|
|
||||||
stable copy of this kit for others to use while you experiment.
|
|
||||||
|
|
||||||
9. Detailed documentation and the man page can be seen by running:
|
|
||||||
|
|
||||||
bin/verilator -help
|
|
||||||
|
|
||||||
or reading verilator.txt in the same directory as this README.
|
|
||||||
|
|
||||||
|
|
||||||
1.7 Limitations
|
|
||||||
===============
|
|
||||||
|
|
||||||
See verilator.txt (or execute `bin/verilator --help') for limitations.
|
|
||||||
|
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
// $Id$
|
|
||||||
// DESCRIPTION: Verilator: List of To Do issues.
|
// DESCRIPTION: Verilator: List of To Do issues.
|
||||||
//
|
//
|
||||||
// Copyright 2004-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
Finish 3.400 new ordering fixes
|
Finish 3.400 new ordering fixes
|
||||||
Latch optimizations {Need here}
|
Latch optimizations {Need here}
|
||||||
Task I/Os connecting to non-simple variables.
|
Task I/Os connecting to non-simple variables.
|
||||||
Fix nested casez statements expanding into to huge C++. [JeanPaul Vanitegem]
|
Fix nested casez statements expanding into to huge C++. [JeanPaul Vanitegem]
|
||||||
@@ -25,12 +24,13 @@ Features:
|
|||||||
Coverage
|
Coverage
|
||||||
Points should be per-scope like everything else rather then per-module
|
Points should be per-scope like everything else rather then per-module
|
||||||
Expression coverage (see notes)
|
Expression coverage (see notes)
|
||||||
|
Constant functions for widths, etc, IE "input [log2(PARAM):0] xx;"
|
||||||
More Verilog 2001 Support
|
More Verilog 2001 Support
|
||||||
C-style function and task arguments. [Wim Michiels]
|
|
||||||
(* *) Attributes (just ignore -- preprocessor?)
|
(* *) Attributes (just ignore -- preprocessor?)
|
||||||
Real numbers (NEVER)
|
Real numbers (NEVER)
|
||||||
Recursive functions (NEVER)
|
Recursive functions (NEVER)
|
||||||
Verilog configuration files (NEVER)
|
Verilog configuration files (NEVER)
|
||||||
|
DPI to define C/C++ calls from Verilog
|
||||||
|
|
||||||
Long-term Features
|
Long-term Features
|
||||||
Assertions
|
Assertions
|
||||||
@@ -47,6 +47,14 @@ Testing:
|
|||||||
Better graph viewer with search and zoom
|
Better graph viewer with search and zoom
|
||||||
Port and test against opencores.org code
|
Port and test against opencores.org code
|
||||||
|
|
||||||
|
Usability:
|
||||||
|
Better reporting of unopt problems, including what lines of code
|
||||||
|
Report more errors (all of them?) before exiting [Eugene Weber]
|
||||||
|
|
||||||
|
Internal Code:
|
||||||
|
Eliminate the AstNUser* passed to all visitors; its only needed in V3Width,
|
||||||
|
and removing it will speed up and simplify all the other code.
|
||||||
|
|
||||||
Performance:
|
Performance:
|
||||||
Constant propagation
|
Constant propagation
|
||||||
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
|
Extra cleaning AND: 1 & ((VARREF >> 1) | ((&VARREF >> 1) & VARREF))
|
||||||
@@ -60,7 +68,7 @@ Performance:
|
|||||||
Multithreaded execution
|
Multithreaded execution
|
||||||
Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
|
Bit-multiply for faster bit swapping and a=b[1,3,2] random bit reorderings.
|
||||||
Move _last sets and all other combo logic inside master
|
Move _last sets and all other combo logic inside master
|
||||||
if() that triggers on all possible sense items
|
if() that triggers on all possible sense items
|
||||||
Rewrite and combine V3Life, V3Subst
|
Rewrite and combine V3Life, V3Subst
|
||||||
If block temp only ever set in one place to constant, propagate it
|
If block temp only ever set in one place to constant, propagate it
|
||||||
Used in t_mem for array delayed assignments
|
Used in t_mem for array delayed assignments
|
||||||
@@ -97,6 +105,13 @@ Performance:
|
|||||||
Track recirculation and convert into clock-enables
|
Track recirculation and convert into clock-enables
|
||||||
Clock enables should become new clocking domains for speed
|
Clock enables should become new clocking domains for speed
|
||||||
If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
|
If floped(a) & flopped(b) and no other a&b, then instead flop(a&b).
|
||||||
|
Sort by output bitselects so can combine more assignments (see DDP example dx_dm signal)
|
||||||
|
|
||||||
|
All of the temp vars that get set, exp pre_ vars and never feedback
|
||||||
|
(not flops) don't need to be stored in the structs, but instead can
|
||||||
|
be per-invocation, and even better register-colored-like to reuse
|
||||||
|
the space. This will greatly reduce the data footprint.
|
||||||
|
|
||||||
|
|
||||||
//**********************************************************************
|
//**********************************************************************
|
||||||
//* Detailed notes on 'todo' features
|
//* Detailed notes on 'todo' features
|
||||||
@@ -123,15 +138,15 @@ Selectable SystemC types based on widths (see notes below)
|
|||||||
c) a conditional whose possible values are (a) or (b)
|
c) a conditional whose possible values are (a) or (b)
|
||||||
|
|
||||||
2) One can lose that fact that a node is a tristate node. This happens
|
2) One can lose that fact that a node is a tristate node. This happens
|
||||||
if a tristate node is assigned to a 'standard' node, or is used on
|
if a tristate node is assigned to a 'standard' node, or is used on
|
||||||
RHS of a conditional. The following infer tristate signals:
|
RHS of a conditional. The following infer tristate signals:
|
||||||
a) inout <SIGNAL>
|
a) inout <SIGNAL>
|
||||||
b) tri <SIGNAL>
|
b) tri <SIGNAL>
|
||||||
c) assigning to 'Z' (maybe through a conditional)
|
c) assigning to 'Z' (maybe through a conditional)
|
||||||
Note: tristate-ness of an output port determined only by
|
Note: tristate-ness of an output port determined only by
|
||||||
statements in the module (not the instances it calls)
|
statements in the module (not the instances it calls)
|
||||||
|
|
||||||
4) Tristate variables can't be multidimensional arrays
|
4) Tristate variables can't be multidimensional arrays
|
||||||
5) Only check tristate contention between modules (not within!)
|
5) Only check tristate contention between modules (not within!)
|
||||||
6) Only simple compares with 'Z' are allowed (===)
|
6) Only simple compares with 'Z' are allowed (===)
|
||||||
|
|
||||||
|
|||||||
+998
-256
File diff suppressed because it is too large
Load Diff
+10
-8
@@ -1,10 +1,9 @@
|
|||||||
: # -*-Mode: perl;-*- use perl, wherever it is
|
: # -*-Mode: perl;-*- use perl, wherever it is
|
||||||
eval 'exec perl -wS $0 ${1+"$@"}'
|
eval 'exec perl -wS $0 ${1+"$@"}'
|
||||||
if 0;
|
if 0;
|
||||||
# $Id$
|
|
||||||
######################################################################
|
######################################################################
|
||||||
#
|
#
|
||||||
# Copyright 2005-2006 by Wilson Snyder <[email protected]>. This
|
# Copyright 2005-2008 by Wilson Snyder <[email protected]>. This
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
# program is free software; you can redistribute it and/or modify it under
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
# the terms of either the GNU Lesser General Public License or the Perl
|
||||||
# Artistic License.
|
# Artistic License.
|
||||||
@@ -35,17 +34,21 @@ my $Opt_A;
|
|||||||
my $Opt_B;
|
my $Opt_B;
|
||||||
autoflush STDOUT 1;
|
autoflush STDOUT 1;
|
||||||
autoflush STDERR 1;
|
autoflush STDERR 1;
|
||||||
|
Getopt::Long::config ("no_auto_abbrev");
|
||||||
if (! GetOptions (
|
if (! GetOptions (
|
||||||
"help" => \&usage,
|
"help" => \&usage,
|
||||||
"debug" => \&debug,
|
"debug" => \&debug,
|
||||||
"<>" => \¶meter,
|
"<>" => \¶meter,
|
||||||
)) {
|
)) {
|
||||||
usage();
|
die "%Error: Bad usage, try 'verilator_difftree --help'\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
defined $Opt_A or die "%Error: No old diff filename\n";
|
defined $Opt_A or die "%Error: No old diff filename\n";
|
||||||
defined $Opt_B or die "%Error: No new diff filename\n";
|
defined $Opt_B or die "%Error: No new diff filename\n";
|
||||||
|
|
||||||
|
-e $Opt_A or die "%Error: No old diff filename found: $Opt_A\n";
|
||||||
|
-e $Opt_B or die "%Error: No new diff filename found: $Opt_B\n";
|
||||||
|
|
||||||
if (-d $Opt_A && -d $Opt_B) {
|
if (-d $Opt_A && -d $Opt_B) {
|
||||||
diff_dir ($Opt_A, $Opt_B);
|
diff_dir ($Opt_A, $Opt_B);
|
||||||
} elsif (-f $Opt_A && -f $Opt_B) {
|
} elsif (-f $Opt_A && -f $Opt_B) {
|
||||||
@@ -111,7 +114,6 @@ sub filter {
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print '$Id$ ', "\n";
|
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
@@ -126,7 +128,7 @@ sub parameter {
|
|||||||
$Opt_A = $param;
|
$Opt_A = $param;
|
||||||
} elsif (!defined $Opt_B) {
|
} elsif (!defined $Opt_B) {
|
||||||
$Opt_B = $param;
|
$Opt_B = $param;
|
||||||
} else {
|
} else {
|
||||||
die "%Error: Unknown parameter: $param\n";
|
die "%Error: Unknown parameter: $param\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,9 +176,9 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
The latest version is available from L<http://www.veripool.com/>.
|
The latest version is available from L<http://www.veripool.org/verilator>.
|
||||||
|
|
||||||
Copyright 2005-2006 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2008 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License or the Perl Artistic License.
|
Lesser General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
@@ -192,5 +194,5 @@ C<verilator>
|
|||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
### Local Variables:
|
### Local Variables:
|
||||||
### compile-command: "$V4/bin/verilator_difftree ~/SandBox/workwsnyder/verilator/test_c/obj_dir/V*_03_*.tree $V4/test_c/obj_dir/V*_03_*.tree"
|
### compile-command: "$V4/bin/verilator_difftree $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree"
|
||||||
### End:
|
### End:
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
: # -*-Mode: perl;-*- use perl, wherever it is
|
: # -*-Mode: perl;-*- use perl, wherever it is
|
||||||
eval 'exec perl -wS $0 ${1+"$@"}'
|
eval 'exec perl -wS $0 ${1+"$@"}'
|
||||||
if 0;
|
if 0;
|
||||||
# $Id$
|
|
||||||
# DESCRIPTION: Print include statements for each ARGV
|
# DESCRIPTION: Print include statements for each ARGV
|
||||||
#
|
#
|
||||||
# Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# General Public License or the Perl Artistic License.
|
# General Public License or the Perl Artistic License.
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|||||||
Executable
+228
@@ -0,0 +1,228 @@
|
|||||||
|
: # -*-Mode: perl;-*- use perl, wherever it is
|
||||||
|
eval 'exec perl -wS $0 ${1+"$@"}'
|
||||||
|
if 0;
|
||||||
|
# See copyright, etc in below POD section.
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
require 5.006_001;
|
||||||
|
use warnings;
|
||||||
|
use Getopt::Long;
|
||||||
|
use IO::File;
|
||||||
|
use Pod::Usage;
|
||||||
|
eval { use Data::Dumper; $Data::Dumper::Indent = 1; }; # Debug, ok if missing
|
||||||
|
use strict;
|
||||||
|
use vars qw ($Debug);
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
# main
|
||||||
|
|
||||||
|
$Debug = 0;
|
||||||
|
my $Opt_File;
|
||||||
|
autoflush STDOUT 1;
|
||||||
|
autoflush STDERR 1;
|
||||||
|
Getopt::Long::config ("no_auto_abbrev");
|
||||||
|
if (! GetOptions (
|
||||||
|
"help" => \&usage,
|
||||||
|
"debug" => \&debug,
|
||||||
|
"<>" => \¶meter,
|
||||||
|
)) {
|
||||||
|
die "%Error: Bad usage, try 'verilator_profcfunc --help'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
defined $Opt_File or die "%Error: No filename given\n";
|
||||||
|
|
||||||
|
profcfunc($Opt_File);
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub debug {
|
||||||
|
$Debug = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub parameter {
|
||||||
|
my $param = shift;
|
||||||
|
if (!defined $Opt_File) {
|
||||||
|
$Opt_File = $param;
|
||||||
|
} else {
|
||||||
|
die "%Error: Unknown parameter: $param\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
sub profcfunc {
|
||||||
|
my $filename = shift;
|
||||||
|
# Remove hex numbers before diffing
|
||||||
|
my $fh = IO::File->new ($filename) or die "%Error: $! $filename,";
|
||||||
|
|
||||||
|
my %funcs;
|
||||||
|
|
||||||
|
while (defined (my $line=$fh->getline())) {
|
||||||
|
# %time cumesec selfsec calls {stuff} name
|
||||||
|
if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+[^a-zA-Z_]*([a-zA-Z_].*)$/) {
|
||||||
|
my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4;
|
||||||
|
$funcs{$func}{pct} += $pct;
|
||||||
|
$funcs{$func}{sec} += $sec;
|
||||||
|
$funcs{$func}{calls} += $calls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$fh->close;
|
||||||
|
|
||||||
|
# Find modules
|
||||||
|
my %pointer_mods;
|
||||||
|
my %verilated_mods;
|
||||||
|
foreach my $func (keys %funcs) {
|
||||||
|
if ($func =~ /(.*)::_eval\(([a-zA-Z_0-9]+__Syms).*\)$/) {
|
||||||
|
$verilated_mods{$1} = qr/^$1/;
|
||||||
|
$pointer_mods{$2} = $1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#print Dumper(\%pointer_mods, \%verilated_mods);
|
||||||
|
|
||||||
|
# Resort by Verilog name
|
||||||
|
my %vfuncs;
|
||||||
|
my %groups;
|
||||||
|
foreach my $func (keys %funcs) {
|
||||||
|
my $pct = $funcs{$func}{pct};
|
||||||
|
my $vfunc = $func;
|
||||||
|
my $design;
|
||||||
|
|
||||||
|
if ($func =~ /\(([a-zA-Z_0-9]+__Syms)/) {
|
||||||
|
$design = $pointer_mods{$1};
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $vde (keys %verilated_mods) {
|
||||||
|
last if $design;
|
||||||
|
if ($func =~ /$verilated_mods{$vde}/) {
|
||||||
|
$design=$vde;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__([0-9]+)\(/) {
|
||||||
|
$vfunc = sprintf("VBlock %s:%d", $1, $2);
|
||||||
|
$groups{type}{"Verilog Blocks under $design"} += $pct;
|
||||||
|
$groups{design}{$design} += $pct;
|
||||||
|
$groups{module}{$1} += $pct;
|
||||||
|
} else {
|
||||||
|
if ($design) {
|
||||||
|
$vfunc = sprintf("VCommon %s", $func);
|
||||||
|
$groups{type}{"Common code under $design"} += $pct;
|
||||||
|
$groups{design}{$design} += $pct;
|
||||||
|
$groups{module}{$design." common code"} += $pct;
|
||||||
|
} else {
|
||||||
|
$vfunc = sprintf("C++ %s", $func);
|
||||||
|
$groups{type}{'C++'} += $pct;
|
||||||
|
$groups{design}{'C++'} += $pct;
|
||||||
|
$groups{module}{'C++'} += $pct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$vfuncs{$vfunc} = $funcs{$func};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach my $type qw(type design module) {
|
||||||
|
my $missing = 100;
|
||||||
|
foreach (sort (keys %{$groups{$type}})) {
|
||||||
|
$missing -= $groups{$type}{$_};
|
||||||
|
}
|
||||||
|
if ($missing) {
|
||||||
|
$groups{$type}{"\377Unaccounted for/rounding error"} = $missing;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Overall summary by $type:\n");
|
||||||
|
printf(" %-6s %s\n","% time",$type);
|
||||||
|
foreach my $what (sort (keys %{$groups{$type}})) {
|
||||||
|
(my $pwhat = $what) =~ s/^\377//; # Just used to establish sort order
|
||||||
|
printf(" %6.2f %s\n", $groups{$type}{$what}, $pwhat);
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Verilog code profile:\n");
|
||||||
|
print(" These are split into three categories:\n");
|
||||||
|
print(" C++: Time in non-Verilated C++ code\n");
|
||||||
|
print(" VBlock: Time attributable to a block in a Verilog file and line\n");
|
||||||
|
print(" VCommon: Time in a Verilated module, due to all parts of the design\n");
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print(" % cumulative self \n");
|
||||||
|
print(" time seconds seconds calls type filename and line number\n");
|
||||||
|
|
||||||
|
my $cume = 0;
|
||||||
|
foreach my $func (sort {$vfuncs{$b}{sec} <=> $vfuncs{$a}{sec}
|
||||||
|
|| $a cmp $b}
|
||||||
|
(keys %vfuncs)) {
|
||||||
|
$cume += $vfuncs{$func}{sec};
|
||||||
|
printf +("%6.2f %9.2f %8.2f %8d %s\n",
|
||||||
|
$vfuncs{$func}{pct},
|
||||||
|
$cume, $vfuncs{$func}{sec},
|
||||||
|
$vfuncs{$func}{calls},
|
||||||
|
$func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
verilator_profcfunc - Read gprof report created with --profile-cfuncs
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
verilator --profile-cfuncs ....
|
||||||
|
gcc --ggdb -pg ....
|
||||||
|
{run executable}
|
||||||
|
gprof
|
||||||
|
verilator_profcfuncs gprof.out
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
Verilator_profcfunc reads a profile report created by gprof. The names of
|
||||||
|
the functions are then transformed, assuming the user used verilator's
|
||||||
|
--profile-cfuncs, and a report printed showing the percentage of time, etc,
|
||||||
|
in each Verilog block.
|
||||||
|
|
||||||
|
=head1 ARGUMENTS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item --help
|
||||||
|
|
||||||
|
Displays this message and program version and exits.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
|
The latest version is available from L<http://www.veripool.org/>.
|
||||||
|
|
||||||
|
Copyright 2007-2008 by Wilson Snyder. This package is free software; you
|
||||||
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
Lesser General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
Wilson Snyder <[email protected]>
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
C<verilator>
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
### Local Variables:
|
||||||
|
### compile-command: "$V4/bin/verilator_profcfunc $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree"
|
||||||
|
### End:
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
dnl DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||||
|
dnl Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
|
dnl redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
dnl General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
AC_INIT(src/Verilator.cpp)
|
||||||
|
AC_CONFIG_HEADER(src/config_build.h)
|
||||||
|
|
||||||
|
dnl Special Substitutions
|
||||||
|
AC_ARG_ENABLE(defenv,
|
||||||
|
[AS_HELP_STRING([--disable-defenv], [disable hardcoded default environment variables])],
|
||||||
|
CFG_WITH_DEFENV=$enableval,
|
||||||
|
CFG_WITH_DEFENV=yes)
|
||||||
|
AC_SUBST(CFG_WITH_DEFENV)
|
||||||
|
|
||||||
|
dnl Compiler flags
|
||||||
|
CXX=g++
|
||||||
|
CFLAGS=-I${includedir}
|
||||||
|
CPPFLAGS=-I${includedir}
|
||||||
|
CXXFLAGS=-I${includedir}
|
||||||
|
LDFLAGS=-L${libdir}
|
||||||
|
|
||||||
|
dnl Checks for programs.
|
||||||
|
AC_PROG_CC
|
||||||
|
AC_PROG_CXX
|
||||||
|
AC_PROG_INSTALL
|
||||||
|
|
||||||
|
AC_LANG_PUSH(C++)
|
||||||
|
AC_MSG_CHECKING([that C++ compiler can compile simple program])
|
||||||
|
AC_TRY_RUN([int main() { return 0; }],
|
||||||
|
AC_MSG_RESULT(yes),
|
||||||
|
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]))
|
||||||
|
|
||||||
|
AC_PATH_PROG(PERL,perl)
|
||||||
|
if test "x$PERL" = "x" ; then
|
||||||
|
AC_MSG_ERROR([Cannot find "perl" in your PATH, please install it])
|
||||||
|
fi
|
||||||
|
AC_PATH_PROG(LEX,flex)
|
||||||
|
if test "x$LEX" = "x" ; then
|
||||||
|
AC_MSG_ERROR([Cannot find "flex" in your PATH, please install it])
|
||||||
|
fi
|
||||||
|
AC_PATH_PROG(YACC,bison)
|
||||||
|
if test "x$YACC" = "x" ; then
|
||||||
|
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
|
||||||
|
fi
|
||||||
|
|
||||||
|
dnl Checks for libraries.
|
||||||
|
|
||||||
|
dnl Checks for header files.
|
||||||
|
AC_HEADER_STDC
|
||||||
|
AC_HEADER_SYS_WAIT
|
||||||
|
AC_CHECK_HEADERS(fcntl.h unistd.h inttypes.h sys/file.h sys/time.h sys/un.h math.h stdint.h mingw/stdint.h)
|
||||||
|
|
||||||
|
dnl Checks for typedefs, structures
|
||||||
|
AC_CHECK_TYPE(size_t,unsigned int)
|
||||||
|
AC_CHECK_TYPE(uint_t,unsigned int)
|
||||||
|
AC_CHECK_TYPE(ulong_t,unsigned long)
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_STRUCT_TM
|
||||||
|
|
||||||
|
dnl Checks for compiler characteristics.
|
||||||
|
AC_C_INLINE
|
||||||
|
|
||||||
|
dnl Checks for library functions.
|
||||||
|
|
||||||
|
dnl Checks for system services
|
||||||
|
|
||||||
|
dnl Other install directories
|
||||||
|
pkgdatadir=${datadir}/verilator
|
||||||
|
AC_SUBST(pkgdatadir)
|
||||||
|
|
||||||
|
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||||
|
|
||||||
|
AC_MSG_RESULT([])
|
||||||
|
AC_MSG_RESULT([Now type 'make'])
|
||||||
|
AC_MSG_RESULT([])
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
dnl $Id$
|
|
||||||
dnl DESCRIPTION: Process this file with autoconf to produce a configure script.
|
|
||||||
dnl Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
|
||||||
dnl redistribute it and/or modify it under the terms of either the GNU
|
|
||||||
dnl General Public License or the Perl Artistic License.
|
|
||||||
|
|
||||||
AC_REVISION($Revision$)dnl
|
|
||||||
AC_INIT(src/Verilator.cpp)
|
|
||||||
AC_CONFIG_HEADER(src/config.h)
|
|
||||||
|
|
||||||
dnl Special Substitutions
|
|
||||||
|
|
||||||
dnl Checks for programs.
|
|
||||||
CXX=g++
|
|
||||||
AC_PROG_CC
|
|
||||||
AC_PROG_CXX
|
|
||||||
AC_PROG_INSTALL
|
|
||||||
AC_PATH_PROG(PERL,perl)
|
|
||||||
|
|
||||||
dnl Checks for libraries.
|
|
||||||
|
|
||||||
dnl Checks for header files.
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_HEADER_SYS_WAIT
|
|
||||||
AC_CHECK_HEADERS(fcntl.h unistd.h sys/file.h sys/time.h sys/un.h math.h stdint.h mingw/stdint.h)
|
|
||||||
|
|
||||||
dnl Checks for typedefs, structures
|
|
||||||
AC_CHECK_TYPE(size_t,unsigned int)
|
|
||||||
AC_CHECK_TYPE(uint_t,unsigned int)
|
|
||||||
AC_CHECK_TYPE(ulong_t,unsigned long)
|
|
||||||
AC_TYPE_SIZE_T
|
|
||||||
AC_STRUCT_TM
|
|
||||||
|
|
||||||
dnl Checks for compiler characteristics.
|
|
||||||
AC_C_INLINE
|
|
||||||
|
|
||||||
dnl Checks for library functions.
|
|
||||||
|
|
||||||
dnl Checks for system services
|
|
||||||
|
|
||||||
dnl Other install directories
|
|
||||||
pkgdatadir=${datadir}/verilator
|
|
||||||
AC_SUBST(pkgdatadir)
|
|
||||||
|
|
||||||
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
|
||||||
|
|
||||||
AC_MSG_RESULT([])
|
|
||||||
AC_MSG_RESULT([Now type 'make'])
|
|
||||||
AC_MSG_RESULT([])
|
|
||||||
+595
-98
@@ -1,15 +1,15 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// Lesser General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
// Verilator is distributed in the hope that it will be useful,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
///
|
///
|
||||||
/// \file
|
/// \file
|
||||||
@@ -18,19 +18,19 @@
|
|||||||
/// This file must be compiled and linked against all objects
|
/// This file must be compiled and linked against all objects
|
||||||
/// created from Verilator.
|
/// created from Verilator.
|
||||||
///
|
///
|
||||||
/// Code available from: http://www.veripool.com/verilator
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
///
|
///
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
|
|
||||||
#include "verilated.h"
|
#include "verilated.h"
|
||||||
#include <string.h>
|
#include <cctype>
|
||||||
|
|
||||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Global variables
|
// Global variables
|
||||||
|
|
||||||
int Verilated::s_randReset = false;
|
int Verilated::s_randReset = 0;
|
||||||
int Verilated::s_debug = 1;
|
int Verilated::s_debug = 1;
|
||||||
bool Verilated::s_calcUnusedSigs = false;
|
bool Verilated::s_calcUnusedSigs = false;
|
||||||
bool Verilated::s_gotFinish = false;
|
bool Verilated::s_gotFinish = false;
|
||||||
@@ -71,30 +71,51 @@ void vl_fatal (const char* filename, int linenum, const char* hier, const char*
|
|||||||
// Random reset -- Only called at init time, so don't inline.
|
// Random reset -- Only called at init time, so don't inline.
|
||||||
|
|
||||||
IData VL_RAND32() {
|
IData VL_RAND32() {
|
||||||
#ifdef _MSC_VER
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
// Windows doesn't have lrand48(), although Cygwin does.
|
||||||
return (rand()<<16) | rand();
|
return (rand()<<16) | rand();
|
||||||
#else
|
#else
|
||||||
return (lrand48()<<16) | lrand48();
|
return (lrand48()<<16) | lrand48();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
IData VL_RAND_RESET_I(int outBits) {
|
IData VL_RANDOM_I(int obits) {
|
||||||
|
return VL_RAND32() & VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
|
||||||
|
QData VL_RANDOM_Q(int obits) {
|
||||||
|
QData data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
|
||||||
|
return data & VL_MASK_Q(obits);
|
||||||
|
}
|
||||||
|
|
||||||
|
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) {
|
||||||
|
for (int i=0; i<VL_WORDS_I(obits); i++) {
|
||||||
|
if (i<(VL_WORDS_I(obits)-1)) {
|
||||||
|
outwp[i] = VL_RAND32();
|
||||||
|
} else {
|
||||||
|
outwp[i] = VL_RAND32() & VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return outwp;
|
||||||
|
}
|
||||||
|
|
||||||
|
IData VL_RAND_RESET_I(int obits) {
|
||||||
if (Verilated::randReset()==0) return 0;
|
if (Verilated::randReset()==0) return 0;
|
||||||
IData data = ~0;
|
IData data = ~0;
|
||||||
if (Verilated::randReset()!=1) { // if 2, randomize
|
if (Verilated::randReset()!=1) { // if 2, randomize
|
||||||
data = VL_RAND32();
|
data = VL_RANDOM_I(obits);
|
||||||
}
|
}
|
||||||
if (outBits<32) data &= VL_MASK_I(outBits);
|
if (obits<32) data &= VL_MASK_I(obits);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
QData VL_RAND_RESET_Q(int outBits) {
|
QData VL_RAND_RESET_Q(int obits) {
|
||||||
if (Verilated::randReset()==0) return 0;
|
if (Verilated::randReset()==0) return 0;
|
||||||
QData data = VL_ULL(~0);
|
QData data = VL_ULL(~0);
|
||||||
if (Verilated::randReset()!=1) { // if 2, randomize
|
if (Verilated::randReset()!=1) { // if 2, randomize
|
||||||
data = ((QData)VL_RAND32()<<VL_ULL(32)) | (QData)VL_RAND32();
|
data = VL_RANDOM_Q(obits);
|
||||||
}
|
}
|
||||||
if (outBits<64) data &= VL_MASK_Q(outBits);
|
if (obits<64) data &= VL_MASK_Q(obits);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,94 +138,368 @@ WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) {
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Formatting
|
// Formatting
|
||||||
|
|
||||||
const char* VL_VALUE_FORMATTED_Q(int obits, char fmt, bool drop0, QData ld) {
|
// Do a va_arg returning a quad, assuming input argument is anything less than wide
|
||||||
// Convert value into %b/%o/%x/%s/%u/%d formatted string
|
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap,IData) : va_arg(ap,QData))
|
||||||
// Note uses a single buffer; presumes only one call per printf
|
|
||||||
static VL_THREAD char str[VL_VALUE_STRING_MAX_WIDTH];
|
void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||||
char* strp = &str[0];
|
// Format a Verilog $write style format into the output list
|
||||||
int lsb=obits-1;
|
// The format must be pre-processed (and lower cased) by Verilator
|
||||||
if (drop0) while (lsb && !VL_BITISSET_Q(ld,lsb)) lsb--;
|
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||||
switch (fmt) {
|
//
|
||||||
case 'd':
|
// Note uses a single buffer internally; presumes only one usage per printf
|
||||||
sprintf(str,"%lld",(vlsint64_t)(VL_EXTENDS_QQ(obits,obits,ld)));
|
// Note also assumes variables < 64 are not wide, this assumption is
|
||||||
return str;
|
// sometimes not true in low-level routines written here in verilated.cpp
|
||||||
case 'u':
|
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||||
sprintf(str,"%llu",ld);
|
bool inPct = false;
|
||||||
return str;
|
bool widthSet = false;
|
||||||
case 's':
|
int width = 0;
|
||||||
for (; lsb>=0; lsb--) {
|
const char* pos = formatp;
|
||||||
lsb = (lsb / 8) * 8; // Next digit
|
for (; *pos; ++pos) {
|
||||||
IData charval = (ld>>VL_BITBIT_Q(lsb)) & 0xff;
|
if (!inPct && pos[0]=='%') {
|
||||||
*strp++ = (charval==0)?' ':charval;
|
inPct = true;
|
||||||
|
widthSet = false;
|
||||||
|
width = 0;
|
||||||
|
} else if (!inPct) { // Normal text
|
||||||
|
// Fast-forward to next escape and add to output
|
||||||
|
const char *ep = pos;
|
||||||
|
while (ep[0] && ep[0]!='%') ep++;
|
||||||
|
if (ep != pos) {
|
||||||
|
output += string(pos, ep-pos);
|
||||||
|
pos += ep-pos-1;
|
||||||
|
}
|
||||||
|
} else { // Format character
|
||||||
|
inPct = false;
|
||||||
|
char fmt = pos[0];
|
||||||
|
switch (fmt) {
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
inPct = true; // Get more digits
|
||||||
|
widthSet = true;
|
||||||
|
width = width*10 + (fmt - '0');
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
output += '%';
|
||||||
|
break;
|
||||||
|
case 'S': { // "C" string
|
||||||
|
const char* cstrp = va_arg(ap, const char*);
|
||||||
|
output += cstrp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// Deal with all read-and-print somethings
|
||||||
|
const int lbits = va_arg(ap, int);
|
||||||
|
QData ld = 0;
|
||||||
|
WDataInP lwp;
|
||||||
|
if (lbits <= VL_QUADSIZE) {
|
||||||
|
WData qlwp[2];
|
||||||
|
ld = _VL_VA_ARG_Q(ap, lbits);
|
||||||
|
VL_SET_WQ(qlwp,ld);
|
||||||
|
lwp = qlwp;
|
||||||
|
} else {
|
||||||
|
lwp = va_arg(ap,WDataInP);
|
||||||
|
ld = lwp[0];
|
||||||
|
if (fmt == 'u' || fmt == 'd') fmt = 'x'; // Not supported, but show something
|
||||||
|
}
|
||||||
|
int lsb=lbits-1;
|
||||||
|
if (widthSet && width==0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
|
||||||
|
switch (fmt) {
|
||||||
|
case 'c': {
|
||||||
|
IData charval = ld & 0xff;
|
||||||
|
output += charval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
for (; lsb>=0; lsb--) {
|
||||||
|
lsb = (lsb / 8) * 8; // Next digit
|
||||||
|
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
||||||
|
output += (charval==0)?' ':charval;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'd': { // Signed decimal
|
||||||
|
int digits=sprintf(tmp,"%lld",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||||
|
int needmore = width-digits;
|
||||||
|
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||||
|
output += tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u': { // Unsigned decimal
|
||||||
|
int digits=sprintf(tmp,"%llu",ld);
|
||||||
|
int needmore = width-digits;
|
||||||
|
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||||
|
output += tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 't': { // Time
|
||||||
|
int digits;
|
||||||
|
if (VL_TIME_MULTIPLIER==1) {
|
||||||
|
digits=sprintf(tmp,"%llu",ld);
|
||||||
|
} else if (VL_TIME_MULTIPLIER==1000) {
|
||||||
|
digits=sprintf(tmp,"%llu.%03llu",
|
||||||
|
(QData)(ld/VL_TIME_MULTIPLIER),
|
||||||
|
(QData)(ld%VL_TIME_MULTIPLIER));
|
||||||
|
} else {
|
||||||
|
vl_fatal(__FILE__,__LINE__,"","%%Error: Unsupported VL_TIME_MULTIPLIER");
|
||||||
|
}
|
||||||
|
int needmore = width-digits;
|
||||||
|
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||||
|
output += tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b':
|
||||||
|
for (; lsb>=0; lsb--) {
|
||||||
|
output += ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
for (; lsb>=0; lsb--) {
|
||||||
|
lsb = (lsb / 3) * 3; // Next digit
|
||||||
|
// Octal numbers may span more than one wide word,
|
||||||
|
// so we need to grab each bit separately and check for overrun
|
||||||
|
// Octal is rare, so we'll do it a slow simple way
|
||||||
|
output += ('0'
|
||||||
|
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+0)) ? 1 : 0)
|
||||||
|
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+1)) ? 2 : 0)
|
||||||
|
+ ((VL_BITISSETLIMIT_W(lwp, lbits, lsb+2)) ? 4 : 0));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
for (; lsb>=0; lsb--) {
|
||||||
|
lsb = (lsb / 4) * 4; // Next digit
|
||||||
|
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
|
||||||
|
output += "0123456789abcdef"[charval];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
string msg = string("%%Error: Unknown _vl_vsformat code: ")+pos[0]+"\n";
|
||||||
|
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
}
|
||||||
|
} // switch
|
||||||
}
|
}
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
case 'b':
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
*strp++ = ((ld>>VL_BITBIT_Q(lsb)) & 1) + '0';
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
case 'o':
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
lsb = (lsb / 3) * 3; // Next digit
|
|
||||||
*strp++ = ((ld>>VL_BITBIT_Q(lsb)) & 7) + '0';
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
default:
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
lsb = (lsb / 4) * 4; // Next digit
|
|
||||||
IData charval = (ld>>VL_BITBIT_Q(lsb)) & 0xf;
|
|
||||||
*strp++ = (charval + ((charval < 10) ? '0':('a'-10)));
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* VL_VALUE_FORMATTED_W(int obits, char fmt, bool drop0, WDataInP lwp) {
|
static inline bool _vl_vsss_eof(FILE* fp, int& floc) {
|
||||||
// Convert value into %b/%o/%x/%s/%u/%d formatted string
|
return fp ? feof(fp) : (floc<0);
|
||||||
// Note uses a single buffer; presumes only one call per printf
|
}
|
||||||
static VL_THREAD char str[VL_VALUE_STRING_MAX_WIDTH];
|
static inline void _vl_vsss_advance(FILE* fp, int& floc) {
|
||||||
char* strp = &str[0];
|
if (fp) fgetc(fp);
|
||||||
int lsb=obits-1;
|
else floc -= 8;
|
||||||
if (drop0) while (lsb && !VL_BITISSET_W(lwp,lsb)) lsb--;
|
}
|
||||||
switch (fmt) {
|
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp) {
|
||||||
case 's':
|
// Get a character without advancing
|
||||||
for (; lsb>=0; lsb--) {
|
if (fp) {
|
||||||
lsb = (lsb / 8) * 8; // Next digit
|
int data = fgetc(fp);
|
||||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xff;
|
if (data == EOF) return EOF;
|
||||||
*strp++ = (charval==0)?' ':charval;
|
ungetc(data,fp);
|
||||||
}
|
return data;
|
||||||
*strp++ = '\0';
|
} else {
|
||||||
return str;
|
if (floc < 0) return EOF;
|
||||||
case 'b':
|
floc = floc & ~7; // Align to closest character
|
||||||
for (; lsb>=0; lsb--) {
|
int data = (fromp[VL_BITWORD_I(floc)] >> VL_BITBIT_I(floc)) & 0xff;
|
||||||
*strp++ = ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 1) + '0';
|
return data;
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
case 'o':
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
lsb = (lsb / 3) * 3; // Next digit
|
|
||||||
*strp++ = ((lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 7) + '0';
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
default:
|
|
||||||
for (; lsb>=0; lsb--) {
|
|
||||||
lsb = (lsb / 4) * 4; // Next digit
|
|
||||||
IData charval = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb)) & 0xf;
|
|
||||||
*strp++ = (charval + ((charval < 10) ? '0':('a'-10)));
|
|
||||||
}
|
|
||||||
*strp++ = '\0';
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
*strp++ = '\0';
|
}
|
||||||
return str;
|
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp) {
|
||||||
|
while (1) {
|
||||||
|
int c = _vl_vsss_peek(fp, floc, fromp);
|
||||||
|
if (c==EOF || !isspace(c)) return;
|
||||||
|
_vl_vsss_advance(fp, floc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp,
|
||||||
|
char* tmpp, const char* acceptp) {
|
||||||
|
// Read into tmp, consisting of characters from acceptp list
|
||||||
|
char* cp = tmpp;
|
||||||
|
while (1) {
|
||||||
|
int c = _vl_vsss_peek(fp, floc, fromp);
|
||||||
|
if (c==EOF || isspace(c)) break;
|
||||||
|
if (acceptp!=NULL // String - allow anything
|
||||||
|
&& NULL==strchr(acceptp, c)) break;
|
||||||
|
if (acceptp!=NULL) c = tolower(c); // Non-strings we'll simplify
|
||||||
|
*cp++ = c;
|
||||||
|
_vl_vsss_advance(fp, floc);
|
||||||
|
}
|
||||||
|
*cp++ = '\0';
|
||||||
|
//VL_PRINTF("\t_read got='%s'\n", tmpp);
|
||||||
|
}
|
||||||
|
static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits, IData ld) {
|
||||||
|
for (; nbits && lsb<obits; nbits--, lsb++, ld>>=1) {
|
||||||
|
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||||
|
int fbits, WDataInP fromp, // Else if a sscanf
|
||||||
|
const char* formatp, va_list ap) {
|
||||||
|
// Read a Verilog $sscanf/$fscanf style format into the output list
|
||||||
|
// The format must be pre-processed (and lower cased) by Verilator
|
||||||
|
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||||
|
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||||
|
int floc = fbits - 1;
|
||||||
|
IData got = 0;
|
||||||
|
bool inPct = false;
|
||||||
|
const char* pos = formatp;
|
||||||
|
for (; *pos && !_vl_vsss_eof(fp,floc); ++pos) {
|
||||||
|
//VL_PRINTF("_vlscan fmt='%c' floc=%d file='%c'\n", pos[0], floc, _vl_vsss_peek(fp,floc,fromp));
|
||||||
|
if (!inPct && pos[0]=='%') {
|
||||||
|
inPct = true;
|
||||||
|
} else if (!inPct && isspace(pos[0])) { // Format spaces
|
||||||
|
while (isspace(pos[1])) pos++;
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
} else if (!inPct) { // Expected Format
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||||
|
if (c != pos[0]) goto done;
|
||||||
|
else _vl_vsss_advance(fp,floc);
|
||||||
|
} else { // Format character
|
||||||
|
// Skip loading spaces
|
||||||
|
inPct = false;
|
||||||
|
char fmt = pos[0];
|
||||||
|
switch (fmt) {
|
||||||
|
case '%': {
|
||||||
|
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||||
|
if (c != '%') goto done;
|
||||||
|
else _vl_vsss_advance(fp,floc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// Deal with all read-and-scan somethings
|
||||||
|
// Note LSBs are preserved if there's an overflow
|
||||||
|
const int obits = va_arg(ap, int);
|
||||||
|
int lsb = 0;
|
||||||
|
WData qowp[2];
|
||||||
|
WDataOutP owp = qowp;
|
||||||
|
if (obits > VL_QUADSIZE) {
|
||||||
|
owp = va_arg(ap,WDataOutP);
|
||||||
|
}
|
||||||
|
for (int i=0; i<VL_WORDS_I(obits); i++) owp[i] = 0;
|
||||||
|
switch (fmt) {
|
||||||
|
case 'c': {
|
||||||
|
int c = _vl_vsss_peek(fp,floc,fromp);
|
||||||
|
if (c==EOF) goto done;
|
||||||
|
else _vl_vsss_advance(fp,floc);
|
||||||
|
owp[0] = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's': {
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, NULL);
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
int pos = strlen(tmp)-1;
|
||||||
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
|
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd': { // Signed decimal
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
vlsint64_t ld;
|
||||||
|
sscanf(tmp,"%lld",&ld);
|
||||||
|
VL_SET_WQ(owp,ld);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 't': // FALLTHRU // Time
|
||||||
|
case 'u': { // Unsigned decimal
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789+-xz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
QData ld;
|
||||||
|
sscanf(tmp,"%llu",&ld);
|
||||||
|
VL_SET_WQ(owp,ld);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b': {
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "01xz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
int pos = strlen(tmp)-1;
|
||||||
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
|
switch(tmp[pos]) {
|
||||||
|
case 'x': case 'z': case '?': //FALLTHRU
|
||||||
|
case '0': lsb++; break;
|
||||||
|
case '1': _vl_vsss_setbit(owp,obits,lsb, 1, 1); lsb++; break;
|
||||||
|
case '_': break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'o': {
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "01234567xz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
int pos = strlen(tmp)-1;
|
||||||
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
|
switch(tmp[pos]) {
|
||||||
|
case 'x': case 'z': case '?': //FALLTHRU
|
||||||
|
case '0': lsb+=3; break;
|
||||||
|
case '1': _vl_vsss_setbit(owp,obits,lsb, 3, 1); lsb+=3; break;
|
||||||
|
case '2': _vl_vsss_setbit(owp,obits,lsb, 3, 2); lsb+=3; break;
|
||||||
|
case '3': _vl_vsss_setbit(owp,obits,lsb, 3, 3); lsb+=3; break;
|
||||||
|
case '4': _vl_vsss_setbit(owp,obits,lsb, 3, 4); lsb+=3; break;
|
||||||
|
case '5': _vl_vsss_setbit(owp,obits,lsb, 3, 5); lsb+=3; break;
|
||||||
|
case '6': _vl_vsss_setbit(owp,obits,lsb, 3, 6); lsb+=3; break;
|
||||||
|
case '7': _vl_vsss_setbit(owp,obits,lsb, 3, 7); lsb+=3; break;
|
||||||
|
case '_': break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'x': {
|
||||||
|
_vl_vsss_skipspace(fp,floc,fromp);
|
||||||
|
_vl_vsss_read(fp,floc,fromp, tmp, "0123456789abcdefxz?_");
|
||||||
|
if (!tmp[0]) goto done;
|
||||||
|
int pos = strlen(tmp)-1;
|
||||||
|
for (int i=0; i<obits && pos>=0; pos--) {
|
||||||
|
switch(tmp[pos]) {
|
||||||
|
case 'x': case 'z': case '?': //FALLTHRU
|
||||||
|
case '0': lsb+=4; break;
|
||||||
|
case '1': _vl_vsss_setbit(owp,obits,lsb, 4, 1); lsb+=4; break;
|
||||||
|
case '2': _vl_vsss_setbit(owp,obits,lsb, 4, 2); lsb+=4; break;
|
||||||
|
case '3': _vl_vsss_setbit(owp,obits,lsb, 4, 3); lsb+=4; break;
|
||||||
|
case '4': _vl_vsss_setbit(owp,obits,lsb, 4, 4); lsb+=4; break;
|
||||||
|
case '5': _vl_vsss_setbit(owp,obits,lsb, 4, 5); lsb+=4; break;
|
||||||
|
case '6': _vl_vsss_setbit(owp,obits,lsb, 4, 6); lsb+=4; break;
|
||||||
|
case '7': _vl_vsss_setbit(owp,obits,lsb, 4, 7); lsb+=4; break;
|
||||||
|
case '8': _vl_vsss_setbit(owp,obits,lsb, 4, 8); lsb+=4; break;
|
||||||
|
case '9': _vl_vsss_setbit(owp,obits,lsb, 4, 9); lsb+=4; break;
|
||||||
|
case 'a': _vl_vsss_setbit(owp,obits,lsb, 4, 10); lsb+=4; break;
|
||||||
|
case 'b': _vl_vsss_setbit(owp,obits,lsb, 4, 11); lsb+=4; break;
|
||||||
|
case 'c': _vl_vsss_setbit(owp,obits,lsb, 4, 12); lsb+=4; break;
|
||||||
|
case 'd': _vl_vsss_setbit(owp,obits,lsb, 4, 13); lsb+=4; break;
|
||||||
|
case 'e': _vl_vsss_setbit(owp,obits,lsb, 4, 14); lsb+=4; break;
|
||||||
|
case 'f': _vl_vsss_setbit(owp,obits,lsb, 4, 15); lsb+=4; break;
|
||||||
|
case '_': break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
string msg = string("%%Error: Unknown _vl_vsscanf code: ")+pos[0]+"\n";
|
||||||
|
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
|
||||||
|
got++;
|
||||||
|
// Reload data if non-wide (if wide, we put it in the right place directly)
|
||||||
|
if (obits <= VL_BYTESIZE) {
|
||||||
|
CData* p = va_arg(ap,CData*); *p = owp[0];
|
||||||
|
} else if (obits <= VL_SHORTSIZE) {
|
||||||
|
SData* p = va_arg(ap,SData*); *p = owp[0];
|
||||||
|
} else if (obits <= VL_WORDSIZE) {
|
||||||
|
IData* p = va_arg(ap,IData*); *p = owp[0];
|
||||||
|
} else if (obits <= VL_QUADSIZE) {
|
||||||
|
QData* p = va_arg(ap,QData*); *p = VL_SET_QW(owp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // switch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@@ -226,6 +521,40 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
|||||||
while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||||
|
// Convert C string to Verilog format
|
||||||
|
int bytes = VL_BYTES_I(obits);
|
||||||
|
char* op = ((char*)(destp));
|
||||||
|
if (srclen > bytes) srclen = bytes; // Don't overflow destination
|
||||||
|
int i;
|
||||||
|
for (i=0; i<srclen; i++) { *op++ = srcp[srclen-1-i]; }
|
||||||
|
for (; i<bytes; i++) { *op++ = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||||
|
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||||
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
|
|
||||||
|
// The string needs to be padded with 0's in unused spaces in front of
|
||||||
|
// any read data. This means we can't know in what location the first
|
||||||
|
// character will finally live, so we need to copy. Yuk.
|
||||||
|
IData bytes = VL_BYTES_I(obits);
|
||||||
|
char buffer[bytes];
|
||||||
|
|
||||||
|
// We don't use fgets, as we must read \0s.
|
||||||
|
IData got = 0;
|
||||||
|
char* cp = buffer;
|
||||||
|
while (got < bytes) {
|
||||||
|
int c = getc(fp);
|
||||||
|
if (c==EOF) break;
|
||||||
|
*cp++ = c; got++;
|
||||||
|
if (c=='\n') break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_VL_STRING_TO_VINT(obits, destp, got, buffer);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
QData VL_FOPEN_QI(QData filename, IData mode) {
|
QData VL_FOPEN_QI(QData filename, IData mode) {
|
||||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||||
return VL_FOPEN_WI(2, fnw, mode);
|
return VL_FOPEN_WI(2, fnw, mode);
|
||||||
@@ -238,6 +567,174 @@ QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
|||||||
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VL_WRITEF(const char* formatp, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
string output;
|
||||||
|
_vl_vsformat(output, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
// Users can redefine VL_PRINTF if they wish.
|
||||||
|
VL_PRINTF("%s", output.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||||
|
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||||
|
if (VL_UNLIKELY(!fp)) return;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
string output;
|
||||||
|
_vl_vsformat(output, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
fputs(output.c_str(), fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
|
||||||
|
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||||
|
if (VL_UNLIKELY(!fp)) return 0;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
IData got = _vl_vsscanf(fp, 0, NULL, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
|
IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) {
|
||||||
|
IData fnw[2]; VL_SET_WI(fnw, ld);
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) {
|
||||||
|
IData fnw[2]; VL_SET_WQ(fnw, ld);
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
IData got = _vl_vsscanf(NULL, lbits, fnw, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap,formatp);
|
||||||
|
IData got = _vl_vsscanf(NULL, lbits, lwp, formatp, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return got;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||||
|
QData ofilename, void* memp, IData start, IData end) {
|
||||||
|
IData fnw[2]; VL_SET_WQ(fnw, ofilename);
|
||||||
|
return VL_READMEM_W(hex,width,depth,array_lsb,2, fnw,memp,start,end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
|
WDataInP ofilenamep, void* memp, IData start, IData end) {
|
||||||
|
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||||
|
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
|
||||||
|
FILE* fp = fopen(ofilenamez, "r");
|
||||||
|
if (!fp) {
|
||||||
|
// We don't report the Verilog source filename as it slow to have to pass it down
|
||||||
|
vl_fatal (ofilenamez, 0, "", "$readmem file not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Prep for reading
|
||||||
|
IData addr = start;
|
||||||
|
int linenum = 1;
|
||||||
|
bool innum = false;
|
||||||
|
bool ignore_to_eol = false;
|
||||||
|
bool ignore_to_cmt = false;
|
||||||
|
bool needinc = false;
|
||||||
|
bool reading_addr = false;
|
||||||
|
int lastc = ' ';
|
||||||
|
// Read the data
|
||||||
|
// We process a character at a time, as then we don't need to deal
|
||||||
|
// with changing buffer sizes dynamically, etc.
|
||||||
|
while (1) {
|
||||||
|
int c = fgetc(fp);
|
||||||
|
if (c==EOF) break;
|
||||||
|
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
|
||||||
|
if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; }
|
||||||
|
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; }
|
||||||
|
// Skip // comments and detect /* comments
|
||||||
|
else if (ignore_to_cmt && lastc=='*' && c=='/') {
|
||||||
|
ignore_to_cmt = false; if (innum) reading_addr=false; innum=false;
|
||||||
|
} else if (!ignore_to_eol && !ignore_to_cmt) {
|
||||||
|
if (lastc=='/' && c=='*') { ignore_to_cmt = true; }
|
||||||
|
else if (lastc=='/' && c=='/') { ignore_to_eol = true; }
|
||||||
|
else if (c=='/') {} // Part of /* or //
|
||||||
|
else if (c=='_') {}
|
||||||
|
else if (c=='@') { reading_addr = true; innum=false; needinc=false; }
|
||||||
|
// Check for hex or binary digits as file format requests
|
||||||
|
else if (isxdigit(c)) {
|
||||||
|
c = tolower(c);
|
||||||
|
int value = (c >= 'a' ? (c-'a'+10) : (c-'0'));
|
||||||
|
if (!innum) { // Prep for next number
|
||||||
|
if (needinc) { addr++; needinc=false; }
|
||||||
|
}
|
||||||
|
if (reading_addr) {
|
||||||
|
// Decode @ addresses
|
||||||
|
if (!innum) addr=0;
|
||||||
|
addr = (addr<<4) + value;
|
||||||
|
} else {
|
||||||
|
needinc = true;
|
||||||
|
//printf(" Value width=%d @%x = %c\n", width, addr, c);
|
||||||
|
if (addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb)) {
|
||||||
|
vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array");
|
||||||
|
} else {
|
||||||
|
int entry = addr - array_lsb;
|
||||||
|
QData shift = hex ? VL_ULL(4) : VL_ULL(1);
|
||||||
|
// Shift value in
|
||||||
|
if (width<=8) {
|
||||||
|
CData* datap = &((CData*)(memp))[entry];
|
||||||
|
if (!innum) { *datap = 0; }
|
||||||
|
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||||
|
} else if (width<=16) {
|
||||||
|
SData* datap = &((SData*)(memp))[entry];
|
||||||
|
if (!innum) { *datap = 0; }
|
||||||
|
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||||
|
} else if (width<=VL_WORDSIZE) {
|
||||||
|
IData* datap = &((IData*)(memp))[entry];
|
||||||
|
if (!innum) { *datap = 0; }
|
||||||
|
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||||
|
} else if (width<=VL_QUADSIZE) {
|
||||||
|
QData* datap = &((QData*)(memp))[entry];
|
||||||
|
if (!innum) { *datap = 0; }
|
||||||
|
*datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width);
|
||||||
|
} else {
|
||||||
|
WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ];
|
||||||
|
if (!innum) { VL_ZERO_RESET_W(width, datap); }
|
||||||
|
_VL_SHIFTL_INPLACE_W(width, datap, shift);
|
||||||
|
datap[0] |= value;
|
||||||
|
}
|
||||||
|
if (value>=(1<<shift)) {
|
||||||
|
vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
innum = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vl_fatal (ofilenamez, linenum, "", "$readmem file syntax error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastc = c;
|
||||||
|
}
|
||||||
|
if (needinc) { addr++; needinc=false; }
|
||||||
|
|
||||||
|
// Final checks
|
||||||
|
fclose(fp);
|
||||||
|
if (end != (IData)(~ VL_ULL(0)) && addr != (end+1)) {
|
||||||
|
vl_fatal (ofilenamez, linenum, "", "$readmem file ended before specified ending-address");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
// Verilated:: Methods
|
// Verilated:: Methods
|
||||||
|
|
||||||
@@ -246,7 +743,7 @@ const char* Verilated::catName(const char* n1, const char* n2) {
|
|||||||
// Used by symbol table creation to make module names
|
// Used by symbol table creation to make module names
|
||||||
static char* strp = NULL;
|
static char* strp = NULL;
|
||||||
static int len = -1;
|
static int len = -1;
|
||||||
int newlen = strlen(n1)+strlen(n2)+2;
|
int newlen = strlen(n1)+strlen(n2)+2;
|
||||||
if (newlen > len) {
|
if (newlen > len) {
|
||||||
if (strp) delete [] strp;
|
if (strp) delete [] strp;
|
||||||
strp = new char[newlen];
|
strp = new char[newlen];
|
||||||
|
|||||||
+183
-116
@@ -1,15 +1,15 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// Lesser General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
// Verilator is distributed in the hope that it will be useful,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
///
|
///
|
||||||
/// \file
|
/// \file
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
/// all C++ files it generates. It contains standard macros and
|
/// all C++ files it generates. It contains standard macros and
|
||||||
/// classes required by the Verilated code.
|
/// classes required by the Verilated code.
|
||||||
///
|
///
|
||||||
/// Code available from: http://www.veripool.com/verilator
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
///
|
///
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
@@ -29,22 +29,22 @@
|
|||||||
|
|
||||||
#include "verilatedos.h"
|
#include "verilatedos.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <cassert>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Basic types
|
// Basic types
|
||||||
|
|
||||||
typedef uint8_t CData; ///< Verilated data, 1-8 bits
|
typedef vluint8_t CData; ///< Verilated data, 1-8 bits
|
||||||
typedef uint16_t SData; ///< Verilated data, 9-16 bits
|
typedef vluint16_t SData; ///< Verilated data, 9-16 bits
|
||||||
typedef uint32_t IData; ///< Verilated data, 17-32 bits
|
typedef vluint32_t IData; ///< Verilated data, 17-32 bits
|
||||||
typedef vluint64_t QData; ///< Verilated data, 33-64 bits
|
typedef vluint64_t QData; ///< Verilated data, 33-64 bits
|
||||||
typedef uint32_t WData; ///< Verilated data, >64 bits, as an array
|
typedef vluint32_t WData; ///< Verilated data, >64 bits, as an array
|
||||||
|
|
||||||
typedef const WData* WDataInP; ///< Array input to a function
|
typedef const WData* WDataInP; ///< Array input to a function
|
||||||
typedef WData* WDataOutP; ///< Array output from a function
|
typedef WData* WDataOutP; ///< Array output from a function
|
||||||
@@ -115,6 +115,13 @@ public:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
// Functions overridable by user defines
|
||||||
|
|
||||||
|
#ifndef VL_PRINTF
|
||||||
|
# define VL_PRINTF printf ///< Print ala printf; may redefine if desired
|
||||||
|
#endif
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
/// Verilator global static information class
|
/// Verilator global static information class
|
||||||
|
|
||||||
@@ -122,7 +129,7 @@ struct Verilated {
|
|||||||
// Extern Vars
|
// Extern Vars
|
||||||
// Below two are used as bool, but having as uint32_t avoids conversion time
|
// Below two are used as bool, but having as uint32_t avoids conversion time
|
||||||
private:
|
private:
|
||||||
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
static int s_randReset; ///< Random reset: 0=all 0s, 1=all 1s, 2=random
|
||||||
static int s_debug; ///< See accessors... only when VL_DEBUG set
|
static int s_debug; ///< See accessors... only when VL_DEBUG set
|
||||||
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
static bool s_calcUnusedSigs; ///< Waves file on, need all signals calculated
|
||||||
static bool s_gotFinish; ///< A $finish statement executed
|
static bool s_gotFinish; ///< A $finish statement executed
|
||||||
@@ -145,7 +152,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
/// Internal: Create a new module name by concatenating two strings
|
/// Internal: Create a new module name by concatenating two strings
|
||||||
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
||||||
/// Enable calculation of unused signals
|
/// Enable calculation of unused signals
|
||||||
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
|
static void calcUnusedSigs(bool flag) { s_calcUnusedSigs=flag; }
|
||||||
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
static bool calcUnusedSigs() { return s_calcUnusedSigs; } ///< Return calcUnusedSigs value
|
||||||
/// Did the simulation $finish?
|
/// Did the simulation $finish?
|
||||||
@@ -158,7 +165,7 @@ public:
|
|||||||
/// Enable/disable assertions
|
/// Enable/disable assertions
|
||||||
static void assertOn(bool flag) { s_assertOn=flag; }
|
static void assertOn(bool flag) { s_assertOn=flag; }
|
||||||
static bool assertOn() { return s_assertOn; }
|
static bool assertOn() { return s_assertOn; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Extern functions -- User may override -- See verilated.cpp
|
// Extern functions -- User may override -- See verilated.cpp
|
||||||
@@ -172,35 +179,54 @@ extern void vl_fatal (const char* filename, int linenum, const char* hier,
|
|||||||
const char* msg);
|
const char* msg);
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Extern functions -- Init time only, so slow is fine
|
// Extern functions -- Slow path
|
||||||
|
|
||||||
|
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
|
||||||
|
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
|
||||||
|
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
||||||
|
|
||||||
|
/// Init time only, so slow is fine
|
||||||
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
||||||
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
|
extern QData VL_RAND_RESET_Q(int obits); ///< Random reset a signal
|
||||||
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
|
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp); ///< Random reset a signal
|
||||||
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal
|
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a signal
|
||||||
|
|
||||||
/// Return string with formated Verilog value
|
|
||||||
extern const char* VL_VALUE_FORMATTED_W(int obits, char fmt, bool drop0, WDataInP lwp);
|
|
||||||
extern const char* VL_VALUE_FORMATTED_Q(int obits, char fmt, bool drop0, QData ld);
|
|
||||||
inline const char* VL_VALUE_FORMATTED_I(int obits, char fmt, bool drop0, IData ld) {
|
|
||||||
return VL_VALUE_FORMATTED_Q(obits,fmt,drop0,ld);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// File I/O
|
/// File I/O
|
||||||
extern QData VL_FOPEN_WI(int fnwords, WDataInP filename, IData mode);
|
extern IData VL_FGETS_IXQ(int sbits, void* strgp, QData fpq);
|
||||||
extern QData VL_FOPEN_QI(QData filename, IData mode);
|
|
||||||
inline QData VL_FOPEN_II(IData filename, IData mode) { return VL_FOPEN_QI(filename,mode); }
|
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||||
|
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||||
|
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||||
|
|
||||||
|
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
|
WDataInP ofilename, void* memp, IData start, IData end);
|
||||||
|
extern void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
|
QData ofilename, void* memp, IData start, IData end);
|
||||||
|
inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||||
|
IData ofilename, void* memp, IData start, IData end) {
|
||||||
|
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||||
|
|
||||||
|
extern void VL_WRITEF(const char* formatp, ...);
|
||||||
|
extern void VL_FWRITEF(QData fpq, const char* formatp, ...);
|
||||||
|
|
||||||
|
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
|
||||||
|
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
|
||||||
|
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
|
||||||
|
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Base macros
|
// Base macros
|
||||||
|
|
||||||
/// Return true if data[bit] set
|
/// Return true if data[bit] set
|
||||||
#define VL_BITISSET_I(data,bit) (data & (1UL<<VL_BITBIT_I(bit)))
|
#define VL_BITISSET_I(data,bit) (data & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
|
#define VL_BITISSET_Q(data,bit) (data & (VL_ULL(1)<<VL_BITBIT_Q(bit)))
|
||||||
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (1UL<<VL_BITBIT_I(bit)))
|
#define VL_BITISSET_W(data,bit) (data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
|
#define VL_BITISSETLIMIT_W(data,width,bit) (((bit)<(width)) && data[VL_BITWORD_I(bit)] & (VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
|
|
||||||
/// Create two 32-bit words from quadword
|
/// Create two 32-bit words from quadword
|
||||||
#define VL_SET_WQ(decl,data) { decl[0]=(data); decl[1]=((data)>>VL_WORDSIZE); }
|
#define VL_SET_WQ(owp,data) { owp[0]=(data); owp[1]=((data)>>VL_WORDSIZE); }
|
||||||
|
#define VL_SET_WI(owp,data) { owp[0]=(data); owp[1]=0; }
|
||||||
|
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
|
||||||
|
|
||||||
// Use a union to avoid cast-to-different-size warnings
|
// Use a union to avoid cast-to-different-size warnings
|
||||||
/// Return FILE* from QData
|
/// Return FILE* from QData
|
||||||
@@ -210,25 +236,36 @@ static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q
|
|||||||
|
|
||||||
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
||||||
// (Requires clean input)
|
// (Requires clean input)
|
||||||
#define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - 1UL))
|
#define VL_SIGN_I(nbits,lhs) ((lhs) >> VL_BITBIT_I((nbits) - VL_UL(1)))
|
||||||
#define VL_SIGN_Q(nbits,lhs) ((lhs) >> VL_BITBIT_Q((nbits) - VL_ULL(1)))
|
#define VL_SIGN_Q(nbits,lhs) ((lhs) >> VL_BITBIT_Q((nbits) - VL_ULL(1)))
|
||||||
#define VL_SIGNONES_I(nbits,lhs) (-(VL_SIGN_I(nbits,lhs)))
|
#define VL_SIGNONES_I(nbits,lhs) (-(VL_SIGN_I(nbits,lhs)))
|
||||||
|
|
||||||
// Sign bit extended up to MSB, doesn't include unsigned portion
|
// Sign bit extended up to MSB, doesn't include unsigned portion
|
||||||
// Optimization bug in GCC 3.3 returns different bitmasks to later states for
|
// Optimization bug in GCC 3.3 returns different bitmasks to later states for
|
||||||
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) { return (-((lhs)&(1UL<<(lbits-1)))); }
|
static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
|
||||||
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) { return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
|
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) { return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
|
||||||
|
|
||||||
|
// Debugging prints
|
||||||
|
static inline void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp) {
|
||||||
|
printf(" Data: w%d: ", lbits);
|
||||||
|
for (int i=VL_WORDS_I(lbits)-1; i>=0; i--) { printf("%08x ",iwp[i]); }
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Pli macros
|
// Pli macros
|
||||||
|
|
||||||
|
#ifndef VL_TIME_MULTIPLIER
|
||||||
|
# define VL_TIME_MULTIPLIER 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Return current simulation time
|
/// Return current simulation time
|
||||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
||||||
# define VL_TIME_I(ign) ((IData)sc_time_stamp().to_default_time_units())
|
# define VL_TIME_I(ign) ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||||
# define VL_TIME_Q(ign) ((QData)sc_time_stamp().to_default_time_units())
|
# define VL_TIME_Q(ign) ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||||
#else
|
#else
|
||||||
# define VL_TIME_I(ign) ((IData)sc_time_stamp())
|
# define VL_TIME_I(ign) ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||||
# define VL_TIME_Q(ign) ((QData)sc_time_stamp())
|
# define VL_TIME_Q(ign) ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||||
extern double sc_time_stamp();
|
extern double sc_time_stamp();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -282,15 +319,15 @@ static inline WDataOutP VL_ASSIGN_W(int obits, WDataOutP owp,WDataInP lwp){
|
|||||||
|
|
||||||
// EMIT_RULE: VL_ASSIGNBIT: rclean=clean;
|
// EMIT_RULE: VL_ASSIGNBIT: rclean=clean;
|
||||||
static inline void VL_ASSIGNBIT_II(int, int bit, CData& lhsr, IData rhs) {
|
static inline void VL_ASSIGNBIT_II(int, int bit, CData& lhsr, IData rhs) {
|
||||||
lhsr = ((lhsr & ~(1UL<<VL_BITBIT_I(bit)))
|
lhsr = ((lhsr & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
| (rhs<<VL_BITBIT_I(bit)));
|
| (rhs<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_II(int, int bit, SData& lhsr, IData rhs) {
|
static inline void VL_ASSIGNBIT_II(int, int bit, SData& lhsr, IData rhs) {
|
||||||
lhsr = ((lhsr & ~(1UL<<VL_BITBIT_I(bit)))
|
lhsr = ((lhsr & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
| (rhs<<VL_BITBIT_I(bit)));
|
| (rhs<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_II(int, int bit, IData& lhsr, IData rhs) {
|
static inline void VL_ASSIGNBIT_II(int, int bit, IData& lhsr, IData rhs) {
|
||||||
lhsr = ((lhsr & ~(1UL<<VL_BITBIT_I(bit)))
|
lhsr = ((lhsr & ~(VL_UL(1)<<VL_BITBIT_I(bit)))
|
||||||
| (rhs<<VL_BITBIT_I(bit)));
|
| (rhs<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) {
|
static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) {
|
||||||
@@ -299,25 +336,25 @@ static inline void VL_ASSIGNBIT_QI(int, int bit, QData& lhsr, QData rhs) {
|
|||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) {
|
static inline void VL_ASSIGNBIT_WI(int, int bit, WDataOutP owp, IData rhs) {
|
||||||
IData orig = owp[VL_BITWORD_I(bit)];
|
IData orig = owp[VL_BITWORD_I(bit)];
|
||||||
owp[VL_BITWORD_I(bit)] = (orig & ~(1UL<<VL_BITBIT_I(bit))
|
owp[VL_BITWORD_I(bit)] = (orig & ~(VL_UL(1)<<VL_BITBIT_I(bit))
|
||||||
| (rhs<<VL_BITBIT_I(bit)));
|
| (rhs<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
// Alternative form that is an instruction faster when rhs is constant one.
|
// Alternative form that is an instruction faster when rhs is constant one.
|
||||||
static inline void VL_ASSIGNBIT_IO(int, int bit, CData& lhsr, IData) {
|
static inline void VL_ASSIGNBIT_IO(int, int bit, CData& lhsr, IData) {
|
||||||
lhsr = (lhsr | (1UL<<VL_BITBIT_I(bit)));
|
lhsr = (lhsr | (VL_UL(1)<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_IO(int, int bit, SData& lhsr, IData) {
|
static inline void VL_ASSIGNBIT_IO(int, int bit, SData& lhsr, IData) {
|
||||||
lhsr = (lhsr | (1UL<<VL_BITBIT_I(bit)));
|
lhsr = (lhsr | (VL_UL(1)<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_IO(int, int bit, IData& lhsr, IData) {
|
static inline void VL_ASSIGNBIT_IO(int, int bit, IData& lhsr, IData) {
|
||||||
lhsr = (lhsr | (1UL<<VL_BITBIT_I(bit)));
|
lhsr = (lhsr | (VL_UL(1)<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_QO(int, int bit, QData& lhsr, IData) {
|
static inline void VL_ASSIGNBIT_QO(int, int bit, QData& lhsr, IData) {
|
||||||
lhsr = (lhsr | (VL_ULL(1)<<VL_BITBIT_Q(bit)));
|
lhsr = (lhsr | (VL_ULL(1)<<VL_BITBIT_Q(bit)));
|
||||||
}
|
}
|
||||||
static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||||
IData orig = owp[VL_BITWORD_I(bit)];
|
IData orig = owp[VL_BITWORD_I(bit)];
|
||||||
owp[VL_BITWORD_I(bit)] = (orig | (1UL<<VL_BITBIT_I(bit)));
|
owp[VL_BITWORD_I(bit)] = (orig | (VL_UL(1)<<VL_BITBIT_I(bit)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//===================================================================
|
//===================================================================
|
||||||
@@ -438,43 +475,92 @@ static inline IData VL_REDOR_W(int words, WDataInP lwp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_RULE: VL_REDXOR: oclean=dirty; obits=1;
|
// EMIT_RULE: VL_REDXOR: oclean=dirty; obits=1;
|
||||||
static inline IData VL_REDXOR_W(int words, WDataInP lwp) {
|
|
||||||
IData r = lwp[0];
|
|
||||||
for (int i=1; i < words; i++) r ^= lwp[i];
|
|
||||||
r=(r^(r>>1));
|
|
||||||
r=(r^(r>>2));
|
|
||||||
r=(r^(r>>4));
|
|
||||||
r=(r^(r>>8));
|
|
||||||
r=(r^(r>>16));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
static inline IData VL_REDXOR_2(IData r) {
|
static inline IData VL_REDXOR_2(IData r) {
|
||||||
|
// Experiments show VL_REDXOR_2 is faster than __builtin_parityl
|
||||||
r=(r^(r>>1));
|
r=(r^(r>>1));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_4(IData r) {
|
static inline IData VL_REDXOR_4(IData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityl(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2));
|
r=(r^(r>>1)); r=(r^(r>>2));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_8(IData r) {
|
static inline IData VL_REDXOR_8(IData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityl(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4));
|
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_16(IData r) {
|
static inline IData VL_REDXOR_16(IData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityl(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8));
|
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_32(IData r) {
|
static inline IData VL_REDXOR_32(IData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityl(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16));
|
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
static inline IData VL_REDXOR_64(QData r) {
|
static inline IData VL_REDXOR_64(QData r) {
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(VL_NO_BUILTINS)
|
||||||
|
return __builtin_parityll(r);
|
||||||
|
#else
|
||||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16)); r=(r^(r>>32));
|
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16)); r=(r^(r>>32));
|
||||||
return r;
|
return r;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
static inline IData VL_REDXOR_W(int words, WDataInP lwp) {
|
||||||
|
IData r = lwp[0];
|
||||||
|
for (int i=1; i < words; i++) r ^= lwp[i];
|
||||||
|
return VL_REDXOR_32(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline IData VL_CLOG2_I(IData lhs) {
|
||||||
|
// Perhaps can do better using fls GCC4 builtins
|
||||||
|
int n=1;
|
||||||
|
IData chk;
|
||||||
|
if (!lhs) return 0;
|
||||||
|
chk = lhs >> VL_UL(16); if (chk) { n += 16; lhs = chk; }
|
||||||
|
chk = lhs >> VL_UL(8); if (chk) { n += 8; lhs = chk; }
|
||||||
|
chk = lhs >> VL_UL(4); if (chk) { n += 4; lhs = chk; }
|
||||||
|
chk = lhs >> VL_UL(2); if (chk) { n += 2; lhs = chk; }
|
||||||
|
chk = lhs >> VL_UL(1); if (chk) { n += 1; lhs = chk; }
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
static inline IData VL_CLOG2_Q(QData lhs) {
|
||||||
|
// Perhaps can do better using fls GCC4 builtins
|
||||||
|
int n=1;
|
||||||
|
QData chk;
|
||||||
|
if (!lhs) return 0;
|
||||||
|
chk = lhs >> VL_ULL(32); if (chk) { n += 32; lhs = chk; }
|
||||||
|
chk = lhs >> VL_ULL(16); if (chk) { n += 16; lhs = chk; }
|
||||||
|
chk = lhs >> VL_ULL(8); if (chk) { n += 8; lhs = chk; }
|
||||||
|
chk = lhs >> VL_ULL(4); if (chk) { n += 4; lhs = chk; }
|
||||||
|
chk = lhs >> VL_ULL(2); if (chk) { n += 2; lhs = chk; }
|
||||||
|
chk = lhs >> VL_ULL(1); if (chk) { n += 1; lhs = chk; }
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
static inline IData VL_CLOG2_W(int words, WDataInP lwp) {
|
||||||
|
for (int i=words-1; i>=0; i--) {
|
||||||
|
if (lwp[i]) return VL_CLOG2_I(lwp[i])+i*VL_WORDSIZE;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_RULE: VL_COUNTONES_II: oclean = false; lhs clean
|
// EMIT_RULE: VL_COUNTONES_II: oclean = false; lhs clean
|
||||||
static inline IData VL_COUNTONES_I(IData lhs) {
|
static inline IData VL_COUNTONES_I(IData lhs) {
|
||||||
|
// This is faster than __builtin_popcountl
|
||||||
IData r = lhs - ((lhs >> 1) & 033333333333) - ((lhs >> 2) & 011111111111);
|
IData r = lhs - ((lhs >> 1) & 033333333333) - ((lhs >> 2) & 011111111111);
|
||||||
r = (r + (r>>3)) & 030707070707;
|
r = (r + (r>>3)) & 030707070707;
|
||||||
r = (r + (r>>6));
|
r = (r + (r>>6));
|
||||||
@@ -491,10 +577,10 @@ static inline IData VL_COUNTONES_W(int words, WDataInP lwp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline IData VL_ONEHOT_I(IData lhs) {
|
static inline IData VL_ONEHOT_I(IData lhs) {
|
||||||
return ((lhs & (lhs-1))==0 & lhs!=0);
|
return (((lhs & (lhs-1))==0) & (lhs!=0));
|
||||||
}
|
}
|
||||||
static inline IData VL_ONEHOT_Q(QData lhs) {
|
static inline IData VL_ONEHOT_Q(QData lhs) {
|
||||||
return ((lhs & (lhs-1))==0 & lhs!=0);
|
return (((lhs & (lhs-1))==0) & (lhs!=0));
|
||||||
}
|
}
|
||||||
static inline IData VL_ONEHOT_W(int words, WDataInP lwp) {
|
static inline IData VL_ONEHOT_W(int words, WDataInP lwp) {
|
||||||
IData one=0;
|
IData one=0;
|
||||||
@@ -807,7 +893,7 @@ static inline IData VL_POW_III(int, int, int rbits, IData lhs, IData rhs) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
|
#define VL_POW_QQI(obits,lbits,rbits,lhs,rhs) VL_POW_QQQ(obits,lbits,rbits,lhs,rhs)
|
||||||
|
|
||||||
static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
||||||
if (lhs==0) return 0;
|
if (lhs==0) return 0;
|
||||||
@@ -825,23 +911,23 @@ static inline QData VL_POW_QQQ(int, int, int rbits, QData lhs, QData rhs) {
|
|||||||
|
|
||||||
// INTERNAL: Stuff LHS bit 0++ into OUTPUT at specified offset
|
// INTERNAL: Stuff LHS bit 0++ into OUTPUT at specified offset
|
||||||
// ld may be "dirty", output is clean
|
// ld may be "dirty", output is clean
|
||||||
static inline void _VL_INSERT_II(int, CData& lhsr, IData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_II(int, CData& lhsr, IData ld, int hbit, int lbit) {
|
||||||
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
||||||
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
||||||
}
|
}
|
||||||
static inline void _VL_INSERT_II(int, SData& lhsr, IData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_II(int, SData& lhsr, IData ld, int hbit, int lbit) {
|
||||||
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
||||||
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
||||||
}
|
}
|
||||||
static inline void _VL_INSERT_II(int, IData& lhsr, IData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_II(int, IData& lhsr, IData ld, int hbit, int lbit) {
|
||||||
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
IData insmask = (VL_MASK_I(hbit-lbit+1))<<lbit;
|
||||||
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
||||||
}
|
}
|
||||||
static inline void _VL_INSERT_QQ(int, QData& lhsr, QData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_QQ(int, QData& lhsr, QData ld, int hbit, int lbit) {
|
||||||
QData insmask = (VL_MASK_Q(hbit-lbit+1))<<lbit;
|
QData insmask = (VL_MASK_Q(hbit-lbit+1))<<lbit;
|
||||||
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
lhsr = (lhsr & ~insmask) | ((ld<<lbit) & insmask);
|
||||||
}
|
}
|
||||||
static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbit) {
|
||||||
int hoffset = VL_BITBIT_I(hbit);
|
int hoffset = VL_BITBIT_I(hbit);
|
||||||
int loffset = VL_BITBIT_I(lbit);
|
int loffset = VL_BITBIT_I(lbit);
|
||||||
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
if (hoffset==VL_SIZEBITS_I && loffset==0) {
|
||||||
@@ -866,7 +952,7 @@ static inline void _VL_INSERT_WI(int, WDataOutP owp, IData ld, int hbit, int lbi
|
|||||||
|
|
||||||
// INTERNAL: Stuff large LHS bit 0++ into OUTPUT at specified offset
|
// INTERNAL: Stuff large LHS bit 0++ into OUTPUT at specified offset
|
||||||
// lwp may be "dirty"
|
// lwp may be "dirty"
|
||||||
static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int lbit) {
|
static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int lbit) {
|
||||||
int hoffset = hbit & VL_SIZEBITS_I;
|
int hoffset = hbit & VL_SIZEBITS_I;
|
||||||
int loffset = lbit & VL_SIZEBITS_I;
|
int loffset = lbit & VL_SIZEBITS_I;
|
||||||
int lword = VL_BITWORD_I(lbit);
|
int lword = VL_BITWORD_I(lbit);
|
||||||
@@ -912,7 +998,7 @@ static inline void _VL_INSERT_WW(int, WDataOutP owp, WDataInP lwp, int hbit, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, int lbit) {
|
static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, int lbit) {
|
||||||
WData lwp[2]; VL_SET_WQ(lwp,ld);
|
WData lwp[2]; VL_SET_WQ(lwp,ld);
|
||||||
_VL_INSERT_WW(obits,owp,lwp,hbit,lbit);
|
_VL_INSERT_WW(obits,owp,lwp,hbit,lbit);
|
||||||
}
|
}
|
||||||
@@ -1028,6 +1114,18 @@ static inline WDataOutP VL_CONCAT_WWW(int obits,int lbits,int rbits,WDataOutP ow
|
|||||||
//===================================================================
|
//===================================================================
|
||||||
// Shifts
|
// Shifts
|
||||||
|
|
||||||
|
// Static shift, used by internal functions
|
||||||
|
// The output is the same as the input - it overlaps!
|
||||||
|
static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or 4*/) {
|
||||||
|
int words = VL_WORDS_I(obits);
|
||||||
|
IData linsmask = VL_MASK_I(rd);
|
||||||
|
for (int i=words-1; i>=1; i--) {
|
||||||
|
iowp[i] = ((iowp[i]<<rd) & ~linsmask) | ((iowp[i-1] >> (32-rd)) & linsmask);
|
||||||
|
}
|
||||||
|
iowp[0] = ((iowp[0]<<rd) & ~linsmask);
|
||||||
|
iowp[VL_WORDS_I(obits)-1] &= VL_MASK_I(obits);
|
||||||
|
}
|
||||||
|
|
||||||
// EMIT_RULE: VL_SHIFTL: oclean=lclean; rclean==clean;
|
// EMIT_RULE: VL_SHIFTL: oclean=lclean; rclean==clean;
|
||||||
// Important: Unlike most other funcs, the shift might well be a computed
|
// Important: Unlike most other funcs, the shift might well be a computed
|
||||||
// expression. Thus consider this when optimizing. (And perhaps have 2 funcs?)
|
// expression. Thus consider this when optimizing. (And perhaps have 2 funcs?)
|
||||||
@@ -1130,7 +1228,7 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData
|
|||||||
int word = VL_BITWORD_I(rd);
|
int word = VL_BITWORD_I(rd);
|
||||||
if ((int)rd>lbits) {
|
if ((int)rd>lbits) {
|
||||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||||
// We return all 1's as that's more likely to find bugs (?) then 0's.
|
// We return all 1's as that's more likely to find bugs (?) than 0's.
|
||||||
} else {
|
} else {
|
||||||
return (lwp[word]>>VL_BITBIT_I(rd));
|
return (lwp[word]>>VL_BITBIT_I(rd));
|
||||||
}
|
}
|
||||||
@@ -1180,7 +1278,7 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData ls
|
|||||||
static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WDataInP lwp, IData lsb, IData width) {
|
static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WDataInP lwp, IData lsb, IData width) {
|
||||||
int msb = lsb+width-1;
|
int msb = lsb+width-1;
|
||||||
int word_shift = VL_BITWORD_I(lsb);
|
int word_shift = VL_BITWORD_I(lsb);
|
||||||
if (msb>lbits) { // Outside bounds,
|
if (msb>lbits) { // Outside bounds,
|
||||||
for (int i=0; i<VL_WORDS_I(obits)-1; i++) owp[i] = ~0;
|
for (int i=0; i<VL_WORDS_I(obits)-1; i++) owp[i] = ~0;
|
||||||
owp[VL_WORDS_I(obits)-1] = VL_MASK_I(obits);
|
owp[VL_WORDS_I(obits)-1] = VL_MASK_I(obits);
|
||||||
} else if (VL_BITBIT_I(lsb)==0) {
|
} else if (VL_BITBIT_I(lsb)==0) {
|
||||||
@@ -1254,91 +1352,60 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
|
|||||||
// VL_CONST_W_#X(int obits, WDataOutP owp, IData data0, .... IData data(#-1))
|
// VL_CONST_W_#X(int obits, WDataOutP owp, IData data0, .... IData data(#-1))
|
||||||
// Sets wide vector words to specified constant words, zeros upper data.
|
// Sets wide vector words to specified constant words, zeros upper data.
|
||||||
|
|
||||||
|
// If changing the number of functions here, also change EMITCINLINES_NUM_CONSTW
|
||||||
|
|
||||||
#define I IData
|
#define I IData
|
||||||
#define _END(obits,wordsSet) \
|
#define _END(obits,wordsSet) \
|
||||||
for(int i=(wordsSet);i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0; \
|
for(int i=(wordsSet);i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0; \
|
||||||
return o
|
return o
|
||||||
|
|
||||||
|
#define VL_HAVE_CONST_W_1X
|
||||||
static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o,
|
||||||
I d0) {
|
I d0) {
|
||||||
o[0]=d0;
|
o[0]=d0;
|
||||||
_END(obits,1); }
|
_END(obits,1); }
|
||||||
|
#define VL_HAVE_CONST_W_2X
|
||||||
static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o,
|
||||||
I d1,I d0) {
|
I d1,I d0) {
|
||||||
o[0]=d0; o[1]=d1;
|
o[0]=d0; o[1]=d1;
|
||||||
_END(obits,2); }
|
_END(obits,2); }
|
||||||
|
#define VL_HAVE_CONST_W_3X
|
||||||
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o,
|
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o,
|
||||||
I d2,I d1,I d0) {
|
I d2,I d1,I d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2;
|
o[0]=d0; o[1]=d1; o[2]=d2;
|
||||||
_END(obits,3); }
|
_END(obits,3); }
|
||||||
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
|
#define VL_HAVE_CONST_W_4X
|
||||||
|
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
|
||||||
I d3,I d2,I d1,I d0) {
|
I d3,I d2,I d1,I d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
|
||||||
_END(obits,4); }
|
_END(obits,4); }
|
||||||
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
|
#define VL_HAVE_CONST_W_5X
|
||||||
|
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
|
||||||
I d4,I d3,I d2,I d1,I d0) {
|
I d4,I d3,I d2,I d1,I d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
|
||||||
_END(obits,5); }
|
_END(obits,5); }
|
||||||
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
|
#define VL_HAVE_CONST_W_6X
|
||||||
|
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
|
||||||
I d5,I d4,I d3,I d2,I d1,I d0) {
|
I d5,I d4,I d3,I d2,I d1,I d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
|
||||||
_END(obits,6); }
|
_END(obits,6); }
|
||||||
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
|
#define VL_HAVE_CONST_W_7X
|
||||||
|
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
|
||||||
I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
|
||||||
_END(obits,7); }
|
_END(obits,7); }
|
||||||
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
|
#define VL_HAVE_CONST_W_8X
|
||||||
|
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
||||||
_END(obits,8); }
|
_END(obits,8); }
|
||||||
static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
#define VL_HAVE_CONST_W_9X
|
||||||
|
static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
||||||
I d8,
|
I d8,
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
||||||
o[8]=d8;
|
o[8]=d8;
|
||||||
_END(obits,9); }
|
_END(obits,9); }
|
||||||
static inline WDataOutP VL_CONST_W_10X(int obits, WDataOutP o,
|
|
||||||
I d9,I d8,
|
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
|
||||||
o[8]=d8; o[9]=d9;
|
|
||||||
_END(obits,10); }
|
|
||||||
static inline WDataOutP VL_CONST_W_11X(int obits, WDataOutP o,
|
|
||||||
I d10,I d9,I d8,
|
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
|
||||||
o[8]=d8; o[9]=d9; o[10]=d10;
|
|
||||||
_END(obits,11); }
|
|
||||||
static inline WDataOutP VL_CONST_W_12X(int obits, WDataOutP o,
|
|
||||||
I d11,I d10,I d9,I d8,
|
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
|
||||||
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11;
|
|
||||||
_END(obits,12); }
|
|
||||||
static inline WDataOutP VL_CONST_W_16X(int obits, WDataOutP o,
|
|
||||||
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
|
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
|
||||||
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
|
|
||||||
_END(obits,16); }
|
|
||||||
static inline WDataOutP VL_CONST_W_24X(int obits, WDataOutP o,
|
|
||||||
I d23,I d22,I d21,I d20,I d19,I d18,I d17,I d16,
|
|
||||||
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
|
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
|
||||||
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
|
|
||||||
o[16]=d16; o[17]=d17; o[18]=d18; o[19]=d19; o[20]=d20; o[21]=d21; o[22]=d22; o[23]=d23;
|
|
||||||
_END(obits,24); }
|
|
||||||
static inline WDataOutP VL_CONST_W_28X(int obits, WDataOutP o,
|
|
||||||
I d27,I d26,I d25,I d24,
|
|
||||||
I d23,I d22,I d21,I d20,I d19,I d18,I d17,I d16,
|
|
||||||
I d15,I d14,I d13,I d12,I d11,I d10,I d9,I d8,
|
|
||||||
I d7,I d6,I d5,I d4,I d3,I d2,I d1,I d0) {
|
|
||||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
|
||||||
o[8]=d8; o[9]=d9; o[10]=d10; o[11]=d11; o[12]=d12; o[13]=d13; o[14]=d14; o[15]=d15;
|
|
||||||
o[16]=d16; o[17]=d17; o[18]=d18; o[19]=d19; o[20]=d20; o[21]=d21; o[22]=d22; o[23]=d23;
|
|
||||||
o[24]=d24; o[25]=d25; o[26]=d26; o[27]=d27;
|
|
||||||
_END(obits,28); }
|
|
||||||
|
|
||||||
#undef _END
|
#undef _END
|
||||||
#undef I
|
#undef I
|
||||||
|
|||||||
+31
-11
@@ -1,10 +1,10 @@
|
|||||||
# $Id$ -*- Makefile -*-
|
# -*- Makefile -*-
|
||||||
######################################################################
|
######################################################################
|
||||||
# DESCRIPTION: Makefile commands for all verilated target files
|
# DESCRIPTION: Makefile commands for all verilated target files
|
||||||
#
|
#
|
||||||
# Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# General Public License or the Perl Artistic License.
|
# Lesser General Public License or the Perl Artistic License.
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
PERL = @PERL@
|
PERL = @PERL@
|
||||||
@@ -28,6 +28,7 @@ VK_CPPFLAGS_ALWAYS += \
|
|||||||
-I$(VERILATOR_ROOT)/include \
|
-I$(VERILATOR_ROOT)/include \
|
||||||
-DVL_PRINTF=printf \
|
-DVL_PRINTF=printf \
|
||||||
-DVM_TRACE=$(VM_TRACE) \
|
-DVM_TRACE=$(VM_TRACE) \
|
||||||
|
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||||
|
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||||
VK_CPPFLAGS_WALL += -Wall \
|
VK_CPPFLAGS_WALL += -Wall \
|
||||||
@@ -44,18 +45,26 @@ CPPFLAGS += -I. $(VK_CPPFLAGS_ALWAYS) $(VK_CPPFLAGS_WALL)
|
|||||||
VPATH += ..
|
VPATH += ..
|
||||||
VPATH += $(VERILATOR_ROOT)/include
|
VPATH += $(VERILATOR_ROOT)/include
|
||||||
|
|
||||||
#OPT = -ggdb -DPRINTINITSTR -DDETECTCHANGE
|
#OPT = -ggdb -DPRINTINITSTR -DDETECTCHANGE
|
||||||
#OPT = -ggdb -DPRINTINITSTR
|
#OPT = -ggdb -DPRINTINITSTR
|
||||||
CPPFLAGS += $(OPT)
|
CPPFLAGS += $(OPT)
|
||||||
|
|
||||||
|
CPPFLAGS += $(M32)
|
||||||
|
LDFLAGS += $(M32)
|
||||||
|
|
||||||
|
# Allow upper level user makefiles to specify flags they want.
|
||||||
|
# These aren't ever set by Verilator, so users are free to override them.
|
||||||
|
CPPFLAGS += $(USER_CPPFLAGS)
|
||||||
|
LDFLAGS += $(USER_LDFLAGS)
|
||||||
|
|
||||||
# See the benchmarking section of bin/verilator.
|
# See the benchmarking section of bin/verilator.
|
||||||
# Support class optimizations. This includes the tracing and symbol table.
|
# Support class optimizations. This includes the tracing and symbol table.
|
||||||
# SystemC takes minutes to optimize, thus it is off by default.
|
# SystemC takes minutes to optimize, thus it is off by default.
|
||||||
#OPT_SLOW =
|
#OPT_SLOW =
|
||||||
# Fast path optimizations. Most time is spent in these classes.
|
# Fast path optimizations. Most time is spent in these classes.
|
||||||
#OPT_FAST = -O2 -fstrict-aliasing
|
#OPT_FAST = -O2 -fstrict-aliasing
|
||||||
#OPT_FAST = -O
|
#OPT_FAST = -O
|
||||||
#OPT_FAST =
|
#OPT_FAST =
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##### Aggregates
|
##### Aggregates
|
||||||
@@ -69,7 +78,6 @@ VM_SUPPORT += $(VM_SUPPORT_FAST) $(VM_SUPPORT_SLOW)
|
|||||||
ifeq ($(VM_SP_OR_SC),1)
|
ifeq ($(VM_SP_OR_SC),1)
|
||||||
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC)/include
|
CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC)/include
|
||||||
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)
|
LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)
|
||||||
LIBS += -lm -lstdc++
|
|
||||||
SC_LIBS = -lsystemc
|
SC_LIBS = -lsystemc
|
||||||
ifneq ($(wildcard $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/*numeric_bit*),)
|
ifneq ($(wildcard $(SYSTEMC)/lib-$(VM_SC_TARGET_ARCH)/*numeric_bit*),)
|
||||||
# Systemc 1.2.1beta
|
# Systemc 1.2.1beta
|
||||||
@@ -81,8 +89,9 @@ endif
|
|||||||
##### SystemPerl builds
|
##### SystemPerl builds
|
||||||
|
|
||||||
ifeq ($(VM_SP),1)
|
ifeq ($(VM_SP),1)
|
||||||
CPPFLAGS += -I$(SYSTEMPERL) -I$(SYSTEMPERL)/src -DSYSTEMPERL
|
CPPFLAGS += -I$(SYSTEMPERL)/src -DSYSTEMPERL
|
||||||
VPATH += $(SYSTEMPERL) $(SYSTEMPERL)/src
|
VPATH += $(SYSTEMPERL)/src
|
||||||
|
LIBS += -lm -lstdc++
|
||||||
|
|
||||||
VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES))
|
VK_CLASSES_SP = $(addsuffix .sp, $(VM_CLASSES))
|
||||||
|
|
||||||
@@ -95,14 +104,25 @@ else
|
|||||||
preproc:
|
preproc:
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
##### SystemC w/o SystemPerl builds
|
||||||
|
|
||||||
|
ifeq ($(VM_SC),1)
|
||||||
|
LIBS += -lm -lstdc++
|
||||||
|
ifeq ($(VM_TRACE),1)
|
||||||
|
CPPFLAGS += -I$(SYSTEMPERL)/src
|
||||||
|
VPATH += $(SYSTEMPERL)/src
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
##### C/H builds
|
##### C/H builds
|
||||||
|
|
||||||
ifeq ($(VM_PCLI),1)
|
ifeq ($(VM_PCLI),1)
|
||||||
LIBS += -lm -lstdc++
|
LIBS += -lm -lstdc++
|
||||||
ifeq ($(VM_TRACE),1)
|
ifeq ($(VM_TRACE),1)
|
||||||
CPPFLAGS += -I$(SYSTEMPERL) -I$(SYSTEMPERL)/src
|
CPPFLAGS += -I$(SYSTEMPERL)/src
|
||||||
VPATH += $(SYSTEMPERL) $(SYSTEMPERL)/src
|
VPATH += $(SYSTEMPERL)/src
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -1,19 +1,19 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// Lesser General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
// This is distributed in the hope that it will be useful,
|
// This is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
//
|
//
|
||||||
// DESCRIPTION: Verilator: Include in verilog files to hide verilator defines
|
// DESCRIPTION: Verilator: Include in verilog files to hide verilator defines
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
`ifdef verilator `else
|
`ifdef verilator `else
|
||||||
`define coverage_block_off
|
`define coverage_block_off
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
// Hide file descriptor difference
|
// Hide file descriptor difference
|
||||||
`ifdef verilator
|
`ifdef verilator
|
||||||
`define verilator_file_descriptor reg [63:0]
|
`define verilator_file_descriptor reg [63:0]
|
||||||
|
|||||||
+50
-27
@@ -1,25 +1,27 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// Lesser General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
// Verilator is distributed in the hope that it will be useful,
|
// Verilator is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
///
|
///
|
||||||
/// \file
|
/// \file
|
||||||
/// \brief Verilator: Common include for OS portability (verilated & verilator)
|
/// \brief Verilator: Common include for OS portability (verilated & verilator)
|
||||||
///
|
///
|
||||||
/// This header is used by both verilated code, and the verilator
|
/// This header is used by both the Verilator source code (run on the
|
||||||
/// program itself Code needed by only one goes into verilated.h or
|
/// build and host system), and the Verilated output (run on the target
|
||||||
/// config.h.in respectively.
|
/// system). Code needed by only the host system goes into
|
||||||
|
/// config_build.h.in, code needed by Verilated code only goes into
|
||||||
|
/// verilated.h, and code needed by both goes here (verilatedos.h).
|
||||||
///
|
///
|
||||||
/// Code available from: http://www.veripool.com/verilator
|
/// Code available from: http://www.veripool.org/verilator
|
||||||
///
|
///
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
@@ -37,13 +39,17 @@
|
|||||||
# define VL_ATTR_UNUSED __attribute__ ((unused))
|
# define VL_ATTR_UNUSED __attribute__ ((unused))
|
||||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||||
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||||
|
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
|
||||||
|
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
|
||||||
#else
|
#else
|
||||||
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
# define VL_ATTR_PRINTF(fmtArgNum) ///< Function with printf format checking
|
||||||
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
# define VL_ATTR_ALIGNED(alignment) ///< Align structure to specified byte alignment
|
||||||
# define VL_ATTR_NORETURN ///< Function does not ever return
|
# define VL_ATTR_NORETURN ///< Function does not ever return
|
||||||
# define VL_ATTR_UNUSED ///< Function that may be never used
|
# define VL_ATTR_UNUSED ///< Function that may be never used
|
||||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true then false
|
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false then true
|
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||||
|
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||||
|
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VL_THREADED
|
#ifdef VL_THREADED
|
||||||
@@ -62,39 +68,56 @@
|
|||||||
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
# define VL_ULL(c) (c##ULL) ///< Add appropriate suffix to 64-bit constant
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
||||||
|
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Basic integer types
|
// Basic integer types
|
||||||
|
|
||||||
#ifdef VL_UINTS_DEFINED
|
#ifdef VL_UINTS_DEFINED
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
typedef unsigned char uint8_t; ///< 8-bit basic type
|
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned short int uint16_t; ///< 16-bit basic type
|
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned long uint32_t; ///< 32-bit basic type
|
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned long long vluint64_t; ///< 64-bit basic type
|
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||||
|
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||||
typedef long vlsint32_t; ///< 32-bit signed type
|
typedef long vlsint32_t; ///< 32-bit signed type
|
||||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||||
#elif defined(_WIN32)
|
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||||
typedef unsigned char uint8_t; ///< 8-bit basic type
|
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
typedef unsigned short int uint16_t; ///< 16-bit basic type
|
#elif defined(_WIN32) && !defined(__MINGW32__)
|
||||||
typedef unsigned int uint32_t; ///< 32-bit basic type
|
typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward compatibility)
|
||||||
typedef unsigned __int64 vluint64_t; ///< 64-bit basic type
|
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||||
typedef int vlsint32_t; ///< 32-bit signed type
|
typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibility)
|
||||||
typedef __int64 vlsint64_t; ///< 64-bit signed type
|
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||||
#else // Linux or compliant Unix flavors
|
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||||
# include <stdint.h>
|
typedef int vlsint32_t; ///< 32-bit signed type
|
||||||
typedef unsigned long long vluint64_t; ///< 64-bit basic type
|
typedef unsigned int vluint32_t; ///< 32-bit unsigned type
|
||||||
typedef long vlsint32_t; ///< 32-bit signed type
|
typedef __int64 vlsint64_t; ///< 64-bit signed type
|
||||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||||
|
#else // Linux or compliant Unix flavors, -m64
|
||||||
|
# include <stdint.h> // Linux and most flavors
|
||||||
|
# include <inttypes.h> // Solaris
|
||||||
|
typedef uint8_t vluint8_t; ///< 32-bit unsigned type
|
||||||
|
typedef uint16_t vluint16_t; ///< 32-bit unsigned type
|
||||||
|
typedef int vlsint32_t; ///< 32-bit signed type
|
||||||
|
typedef uint32_t vluint32_t; ///< 32-bit signed type
|
||||||
|
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||||
|
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//=========================================================================
|
//=========================================================================
|
||||||
// Integer size macros
|
// Integer size macros
|
||||||
|
|
||||||
|
#define VL_BYTESIZE 8 ///< Bits in a byte
|
||||||
|
#define VL_SHORTSIZE 16 ///< Bits in a short
|
||||||
#define VL_WORDSIZE 32 ///< Bits in a word
|
#define VL_WORDSIZE 32 ///< Bits in a word
|
||||||
#define VL_QUADSIZE 64 ///< Bits in a quadword
|
#define VL_QUADSIZE 64 ///< Bits in a quadword
|
||||||
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
|
#define VL_WORDSIZE_LOG2 5 ///< log2(VL_WORDSIZE)
|
||||||
|
|
||||||
|
/// Bytes this number of bits needs (1 bit=1 byte)
|
||||||
|
#define VL_BYTES_I(nbits) (((nbits)+(VL_BYTESIZE-1))/VL_BYTESIZE)
|
||||||
/// Words this number of bits needs (1 bit=1 word)
|
/// Words this number of bits needs (1 bit=1 word)
|
||||||
#define VL_WORDS_I(nbits) (((nbits)+(VL_WORDSIZE-1))/VL_WORDSIZE)
|
#define VL_WORDS_I(nbits) (((nbits)+(VL_WORDSIZE-1))/VL_WORDSIZE)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -115,7 +115,7 @@ fi
|
|||||||
if [ x"$dir_arg" != x ]; then
|
if [ x"$dir_arg" != x ]; then
|
||||||
dst=$src
|
dst=$src
|
||||||
src=""
|
src=""
|
||||||
|
|
||||||
if [ -d $dst ]; then
|
if [ -d $dst ]; then
|
||||||
instcmd=:
|
instcmd=:
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
# Created: 1993-05-16
|
# Created: 1993-05-16
|
||||||
# Public domain
|
# Public domain
|
||||||
|
|
||||||
# $Id:$
|
|
||||||
|
|
||||||
errstatus=0
|
errstatus=0
|
||||||
|
|
||||||
for file
|
for file
|
||||||
|
|||||||
Executable
+66
@@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
######################################################################
|
||||||
|
#
|
||||||
|
# Copyright 2007-2008 by Wilson Snyder.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of either the GNU General Public License or the
|
||||||
|
# Perl Artistic License.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the Perl Artistic License
|
||||||
|
# along with this module; see the file COPYING. If not, see
|
||||||
|
# www.cpan.org
|
||||||
|
#
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# DESCRIPTION: Debugging of bison output
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
my $Debug;
|
||||||
|
|
||||||
|
my %declared;
|
||||||
|
my %used;
|
||||||
|
|
||||||
|
my $body = 0;
|
||||||
|
my $rule = "";
|
||||||
|
my $lineno = 0;
|
||||||
|
foreach my $line (<STDIN>) {
|
||||||
|
$lineno++;
|
||||||
|
chomp $line;
|
||||||
|
$line =~ s!//.*$!!g;
|
||||||
|
$line =~ s!\s+! !g;
|
||||||
|
next if $line eq '';
|
||||||
|
if ($line =~ m!^\%\%!) {
|
||||||
|
$body++;
|
||||||
|
} elsif ($body == 1) {
|
||||||
|
$rule .= $line;
|
||||||
|
if ($line =~ m!^\s*;\s*$!) {
|
||||||
|
#print "Rule: $rule\n";
|
||||||
|
($rule =~ /^([a-zA-Z0-9_]+):(.*)$/) or die "%Error: No rule name: $1\n";
|
||||||
|
my $rulename = $1; my $preaction = $2;
|
||||||
|
$declared{$rulename} = $lineno;
|
||||||
|
$preaction =~ s/\{[^\}]*\}/ /g;
|
||||||
|
#print "RULEN $rulename PA $preaction\n" if $Debug;
|
||||||
|
$rule = '';
|
||||||
|
foreach my $ref (split /\s+/, $preaction) {
|
||||||
|
next if $ref !~ /^[a-zA-Z]/;
|
||||||
|
next if $ref eq $rulename;
|
||||||
|
if (!$used{$ref} && $declared{$ref}) {
|
||||||
|
print " %Warning: $lineno: $ref used by $rulename after declaration\n";
|
||||||
|
}
|
||||||
|
$used{$ref} = $lineno;
|
||||||
|
print " ref $ref\n" if $Debug;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# compile-command: "./bisonreader < verilog.y"
|
||||||
|
# End:
|
||||||
Executable
+161
@@ -0,0 +1,161 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
# See copyright, etc in below POD section.
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
require 5.006_001;
|
||||||
|
use Getopt::Long;
|
||||||
|
use IO::File;
|
||||||
|
use Pod::Usage;
|
||||||
|
use Data::Dumper; $Data::Dumper::Indent=1;
|
||||||
|
use strict;
|
||||||
|
use vars qw ($Debug);
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
|
||||||
|
our @Header;
|
||||||
|
our %Vertexes;
|
||||||
|
our @Edges;
|
||||||
|
our %Edges;
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
# main
|
||||||
|
|
||||||
|
$Debug = 0;
|
||||||
|
my $opt_filename;
|
||||||
|
autoflush STDOUT 1;
|
||||||
|
autoflush STDERR 1;
|
||||||
|
if (! GetOptions (
|
||||||
|
"help" => \&usage,
|
||||||
|
"debug" => \&debug,
|
||||||
|
"<>" => \¶meter,
|
||||||
|
)) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
dotread ($opt_filename);
|
||||||
|
cwrite ("graph_export.cpp");
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub debug {
|
||||||
|
$Debug = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub parameter {
|
||||||
|
my $param = shift;
|
||||||
|
if (!$opt_filename) {
|
||||||
|
$opt_filename = $param;
|
||||||
|
} else {
|
||||||
|
die "%Error: Unknown parameter: $param\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
sub dotread {
|
||||||
|
my $filename = shift;
|
||||||
|
|
||||||
|
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
|
||||||
|
my $header = 1;
|
||||||
|
my $vnum = 0;
|
||||||
|
while (defined (my $line = $fh->getline)) {
|
||||||
|
if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) {
|
||||||
|
next if $1 eq 'nTITLE';
|
||||||
|
$header = 0;
|
||||||
|
$Vertexes{$1} = {num => $vnum++,
|
||||||
|
line => $line,
|
||||||
|
name => $1,};
|
||||||
|
}
|
||||||
|
elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) {
|
||||||
|
my $from=$1; my $to=$2;
|
||||||
|
my $weight = 1; $weight = $1 if $line =~ /weight=(\d+)/;
|
||||||
|
my $cutable = undef; $cutable = $1 if $line =~ /style=(\S+)/;
|
||||||
|
my $edge = {num => $vnum++,
|
||||||
|
line => $line,
|
||||||
|
weight => $weight,
|
||||||
|
cutable => $cutable,
|
||||||
|
from => $from,
|
||||||
|
to => $to,};
|
||||||
|
push @Edges, $edge;
|
||||||
|
$Edges{$from}{$to} = $edge;
|
||||||
|
}
|
||||||
|
elsif ($header) {
|
||||||
|
push @Header, $line;
|
||||||
|
print "IGNORE: $line";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
|
||||||
|
sub cwrite {
|
||||||
|
my $filename = shift;
|
||||||
|
|
||||||
|
my $fh = IO::File->new(">$filename") or die "%Error: $! $filename,";
|
||||||
|
$fh->print("void V3GraphTestImport::dotImport() {\n");
|
||||||
|
$fh->print(" DfaGraph* gp = &m_graph;\n");
|
||||||
|
foreach my $ver (sort {$a->{num} <=> $b->{num}} (values %Vertexes)) {
|
||||||
|
$fh->printf(" V3GraphTestVertex* %s = new V3GraphTestVertex(gp, \"%s\"); if (%s) {}\n",
|
||||||
|
$ver->{name}, $ver->{name}, $ver->{name});
|
||||||
|
}
|
||||||
|
$fh->print("\n");
|
||||||
|
foreach my $edge (@Edges) {
|
||||||
|
$fh->printf(" new V3GraphEdge(gp, %s, %s, %s, %s);\n",
|
||||||
|
$edge->{from}, $edge->{to},
|
||||||
|
$edge->{weight}, $edge->{cutable}?"true":"false");
|
||||||
|
}
|
||||||
|
$fh->print("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
dot_importer - Take graph .dot file and convert into .cpp file
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
dot_importer a.dot
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
Dot_importer takes a graphvis .dot file and converts into .cpp file. This
|
||||||
|
.cpp file is then manually included in V3GraphTest.cpp to verify various
|
||||||
|
sub-algorithms.
|
||||||
|
|
||||||
|
=head1 ARGUMENTS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item --help
|
||||||
|
|
||||||
|
Displays this message and program version and exits.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
|
Copyright 2005-2008 by Wilson Snyder. This package is free software; you
|
||||||
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
Lesser General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
Wilson Snyder <[email protected]>
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
### Local Variables:
|
||||||
|
### compile-command: "./dot_importer | tee ~/d/a.dot"
|
||||||
|
### End:
|
||||||
+3
-16
@@ -1,17 +1,5 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
# $Id$
|
# See copyright, etc in below POD section.
|
||||||
######################################################################
|
|
||||||
#
|
|
||||||
# Copyright 2005-2006 by Wilson Snyder <[email protected]>. This
|
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
|
||||||
# Artistic License.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.006_001;
|
require 5.006_001;
|
||||||
@@ -55,7 +43,6 @@ dotwrite();
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print '$Id$ ', "\n";
|
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
@@ -175,7 +162,7 @@ __END__
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
dot_pruner -
|
dot_pruner -
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
@@ -197,7 +184,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2006 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2008 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License or the Perl Artistic License.
|
Lesser General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
|||||||
Executable
+58
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
# See copyright, etc in below POD section.
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
require 5.006_001;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
# main
|
||||||
|
|
||||||
|
delete $ENV{MODULE_VERSION};
|
||||||
|
_setup_modules();
|
||||||
|
module('add','cadence_verif');
|
||||||
|
exec('iccr',@ARGV);
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Modules package
|
||||||
|
|
||||||
|
sub _setup_modules {
|
||||||
|
# Load the 'module' command into the environment
|
||||||
|
my $init = "/sicortex/$ENV{DIRPROJECT_ARCH}/lib/Modules/default/init/perl";
|
||||||
|
(-f $init) or die "%Error: Script not found: $init,";
|
||||||
|
require $init;
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
invoke_iccr - Invoke tool under "modules" command
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
invoke_iccr {ncv arguments}
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
|
Copyright 2007-2008 by Wilson Snyder. This package is free software; you
|
||||||
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
Lesser General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
Wilson Snyder <[email protected]>
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
### Local Variables:
|
||||||
|
### compile-command: "./invoke_iccr -help"
|
||||||
|
### End:
|
||||||
Executable
+58
@@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
# See copyright, etc in below POD section.
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
require 5.006_001;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
#======================================================================
|
||||||
|
# main
|
||||||
|
|
||||||
|
delete $ENV{MODULE_VERSION};
|
||||||
|
_setup_modules();
|
||||||
|
module('add','cadence_verif');
|
||||||
|
exec('ncverilog',@ARGV);
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Modules package
|
||||||
|
|
||||||
|
sub _setup_modules {
|
||||||
|
# Load the 'module' command into the environment
|
||||||
|
my $init = "/sicortex/$ENV{DIRPROJECT_ARCH}/lib/Modules/default/init/perl";
|
||||||
|
(-f $init) or die "%Error: Script not found: $init,";
|
||||||
|
require $init;
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
__END__
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
invoke_ncverilog - Invoke tool under "modules" command
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
invoke_ncverilog {ncv arguments}
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
|
Copyright 2007-2008 by Wilson Snyder. This package is free software; you
|
||||||
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
Lesser General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
=head1 AUTHORS
|
||||||
|
|
||||||
|
Wilson Snyder <[email protected]>
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
### Local Variables:
|
||||||
|
### compile-command: "./invoke_ncverilog -help"
|
||||||
|
### End:
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export GLIBCPP_FORCE_NEW=1
|
||||||
|
compile with -DVL_LEAK_CHECKS
|
||||||
|
valgrind --tool=memcheck --leak-check=yes /home/wsnyder/src/verilator/v4/verilator/verilator_bin_dbg -MMD --bin /home/wsnyder/src/verilator/v4/verilator/verilator_bin_dbg --cc -f /home/wsnyder/src/verilator/v4/verilator/test_c/../test_v/input.vc top.v --no-skip-identical 2>&1 | tee ~/d/aa
|
||||||
|
valgrind --tool=memcheck --leak-check=yes /home/wsnyder/src/verilator/v4/verilator/verilator_bin_dbg -MMD --bin /home/wsnyder/src/verilator/v4/verilator/verilator_bin_dbg --cc /home/wsnyder/src/verilator/v4/verilator/test_regress/t/t_case_huge.v --no-skip-identical -I/home/wsnyder/src/verilator/v4/verilator/test_regress/t 2>&1 | tee ~/d/aa
|
||||||
+4
-17
@@ -1,17 +1,5 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
# $Id$
|
# See copyright, etc in below POD section.
|
||||||
######################################################################
|
|
||||||
#
|
|
||||||
# Copyright 2005-2006 by Wilson Snyder <[email protected]>. This
|
|
||||||
# program is free software; you can redistribute it and/or modify it under
|
|
||||||
# the terms of either the GNU Lesser General Public License or the Perl
|
|
||||||
# Artistic License.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
require 5.006_001;
|
require 5.006_001;
|
||||||
@@ -52,7 +40,6 @@ print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print '$Id$ ', "\n";
|
|
||||||
pod2usage(-verbose=>2, -exitval => 2);
|
pod2usage(-verbose=>2, -exitval => 2);
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
@@ -292,7 +279,7 @@ sub p_var {
|
|||||||
}
|
}
|
||||||
p "\t";
|
p "\t";
|
||||||
{
|
{
|
||||||
local $Avoid_Hex=1;
|
local $Avoid_Hex=1;
|
||||||
t1;
|
t1;
|
||||||
}
|
}
|
||||||
p "\t";
|
p "\t";
|
||||||
@@ -322,7 +309,7 @@ __END__
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
vtree_importer -
|
vtree_importer -
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
@@ -344,7 +331,7 @@ Displays this message and program version and exits.
|
|||||||
|
|
||||||
=head1 DISTRIBUTION
|
=head1 DISTRIBUTION
|
||||||
|
|
||||||
Copyright 2005-2006 by Wilson Snyder. This package is free software; you
|
Copyright 2005-2008 by Wilson Snyder. This package is free software; you
|
||||||
can redistribute it and/or modify it under the terms of either the GNU
|
can redistribute it and/or modify it under the terms of either the GNU
|
||||||
Lesser General Public License or the Perl Artistic License.
|
Lesser General Public License or the Perl Artistic License.
|
||||||
|
|
||||||
|
|||||||
+18
-13
@@ -1,6 +1,5 @@
|
|||||||
\input texinfo @c -*-texinfo-*-
|
\input texinfo @c -*-texinfo-*-
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
$c $Id$
|
|
||||||
@setfilename readme.info
|
@setfilename readme.info
|
||||||
@settitle Verilator Installation
|
@settitle Verilator Installation
|
||||||
@c %**end of header
|
@c %**end of header
|
||||||
@@ -15,19 +14,19 @@ $c $Id$
|
|||||||
This is the Verilator Package.
|
This is the Verilator Package.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Copyright::
|
* Copyright::
|
||||||
* Description::
|
* Description::
|
||||||
* Obtaining Distribution::
|
* Obtaining Distribution::
|
||||||
* Directory Structure::
|
* Directory Structure::
|
||||||
* Supported Systems::
|
* Supported Systems::
|
||||||
* Installation::
|
* Installation::
|
||||||
* Limitations::
|
* Limitations::
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Copyright, Description, Top, Top
|
@node Copyright, Description, Top, Top
|
||||||
@section Copyright
|
@section Copyright
|
||||||
|
|
||||||
This package is Copyright 2003-2006 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
This package is Copyright 2003-2008 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
||||||
|
|
||||||
You may distribute under the terms of either the GNU General Public License
|
You may distribute under the terms of either the GNU General Public License
|
||||||
or the Artistic License, as specified in the Perl README file.
|
or the Artistic License, as specified in the Perl README file.
|
||||||
@@ -45,7 +44,7 @@ Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
|
|||||||
reads the specified Verilog code, lints it, and optionally adds coverage
|
reads the specified Verilog code, lints it, and optionally adds coverage
|
||||||
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
|
code. For C++ format, it outputs .cpp and .h files. For SystemC format,
|
||||||
it outputs .sp files for the SystemPerl preprocessor available at
|
it outputs .sp files for the SystemPerl preprocessor available at
|
||||||
http://veripool.com.
|
http://www.veripool.org.
|
||||||
|
|
||||||
The resulting files are then compiled with C++. The user writes a little
|
The resulting files are then compiled with C++. The user writes a little
|
||||||
C++ wrapper file, which instantiates the top level module. This is
|
C++ wrapper file, which instantiates the top level module. This is
|
||||||
@@ -56,11 +55,11 @@ The resulting executable will perform the actual simulation.
|
|||||||
@node Obtaining Distribution, Directory Structure, Description, Top
|
@node Obtaining Distribution, Directory Structure, Description, Top
|
||||||
@section Obtaining Distribution
|
@section Obtaining Distribution
|
||||||
|
|
||||||
The latest version is available at
|
The latest version is available at
|
||||||
@uref{http://veripool.com/verilator.htm}
|
@uref{http://www.veripool.org/verilator}
|
||||||
|
|
||||||
Download the latest package from that site, and decompress.
|
Download the latest package from that site, and decompress.
|
||||||
@samp{gunzip verilator_version.tar.gz ; tar xvf verilator_version.tar}
|
@samp{tar xvzf verilator_version.tgz}
|
||||||
|
|
||||||
@node Directory Structure, Supported Systems, Obtaining Distribution, Top
|
@node Directory Structure, Supported Systems, Obtaining Distribution, Top
|
||||||
@section Directory Structure
|
@section Directory Structure
|
||||||
@@ -126,6 +125,12 @@ do a @code{make sc_patch}.
|
|||||||
@item
|
@item
|
||||||
Type @samp{./configure} to configure Verilator for your system.
|
Type @samp{./configure} to configure Verilator for your system.
|
||||||
|
|
||||||
|
If you are configuring Verilator to be part of a RPM or other
|
||||||
|
distribution package system, you may want to use the --enable-defenv
|
||||||
|
configure flag. This will take the current value of VERILATOR_ROOT,
|
||||||
|
SYSTEMC, SYSTEMC_ARCH, and SYSTEMPERL and build them as defaults into
|
||||||
|
the executable.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
Type @samp{make} to compile Verilator.
|
Type @samp{make} to compile Verilator.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
*.old
|
*.old
|
||||||
config.h
|
config_build.h
|
||||||
Makefile
|
Makefile
|
||||||
Makefile_obj
|
Makefile_obj
|
||||||
.objcache*
|
.objcache*
|
||||||
+13
-6
@@ -1,13 +1,13 @@
|
|||||||
# $Id$ */
|
# -*- Makefile -*-
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# DESCRIPTION: Verilator: Makefile for verilog source
|
# DESCRIPTION: Verilator: Makefile for verilog source
|
||||||
#
|
#
|
||||||
# Code available from: http://www.veripool.com/verilator
|
# Code available from: http://www.veripool.org/verilator
|
||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# General Public License or the Perl Artistic License.
|
# General Public License or the Perl Artistic License.
|
||||||
#
|
#
|
||||||
@@ -40,12 +40,16 @@ export OBJCACHE_HOSTS := $(shell rschedule --no-allow-reserved --similar hostnam
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OBJCACHE_HOSTS),)
|
ifeq ($(OBJCACHE_HOSTS),)
|
||||||
export OBJCACHE :=
|
export OBJCACHE :=
|
||||||
else
|
else
|
||||||
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
||||||
export OBJCACHE := @objcache --read --write
|
export OBJCACHE := @objcache --read --write
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
UNDER_GIT = $(wildcard ../.git)
|
||||||
|
|
||||||
|
#*********************************************************************
|
||||||
|
|
||||||
obj_opt:
|
obj_opt:
|
||||||
mkdir $@
|
mkdir $@
|
||||||
obj_dbg:
|
obj_dbg:
|
||||||
@@ -71,10 +75,10 @@ dbg: ../verilator_bin_dbg
|
|||||||
|
|
||||||
prefiles::
|
prefiles::
|
||||||
|
|
||||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||||
prefiles:: config_rev.h
|
prefiles:: config_rev.h
|
||||||
# This output goes into srcdir, as we need to distribute it as part of the kit.
|
# This output goes into srcdir, as we need to distribute it as part of the kit.
|
||||||
config_rev.h: config_rev.pl .svn/entries
|
config_rev.h: config_rev.pl ../.git/index
|
||||||
$(PERL) config_rev.pl . >$@
|
$(PERL) config_rev.pl . >$@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -85,3 +89,6 @@ clean mostlyclean distclean maintainer-clean::
|
|||||||
-rm -f *__gen*
|
-rm -f *__gen*
|
||||||
-rm -f *.yy.* y.output y.tab.[cho] *_test
|
-rm -f *.yy.* y.output y.tab.[cho] *_test
|
||||||
-rm -f .objcache*
|
-rm -f .objcache*
|
||||||
|
|
||||||
|
distclean maintainer-clean::
|
||||||
|
-rm -f Makefile Makefile_obj config_build.h
|
||||||
|
|||||||
+49
-17
@@ -1,13 +1,13 @@
|
|||||||
# $Id$ -*- Makefile -*-
|
# -*- Makefile -*-
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# DESCRIPTION: Verilator: Makefile for verilog source
|
# DESCRIPTION: Verilator: Makefile for verilog source
|
||||||
#
|
#
|
||||||
# Code available from: http://www.veripool.com/verilator
|
# Code available from: http://www.veripool.org/verilator
|
||||||
#
|
#
|
||||||
#*****************************************************************************
|
#*****************************************************************************
|
||||||
#
|
#
|
||||||
# Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
# Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
# redistribute it and/or modify it under the terms of either the GNU
|
# redistribute it and/or modify it under the terms of either the GNU
|
||||||
# General Public License or the Perl Artistic License.
|
# General Public License or the Perl Artistic License.
|
||||||
#
|
#
|
||||||
@@ -23,10 +23,28 @@
|
|||||||
srcdir = ..
|
srcdir = ..
|
||||||
incdir = ../../include
|
incdir = ../../include
|
||||||
|
|
||||||
PERL = @PERL@
|
# Programs
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
CXX = @CXX@
|
CXX = @CXX@
|
||||||
LINK = @CXX@
|
LINK = @CXX@
|
||||||
|
LEX = @LEX@
|
||||||
|
LFLAGS = -d
|
||||||
|
PERL = @PERL@
|
||||||
|
YACC = @YACC@
|
||||||
|
|
||||||
|
prefix = @prefix@
|
||||||
|
|
||||||
|
# Directory in which to install data across multiple architectures
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
|
||||||
|
# Directory in which to install package specific files
|
||||||
|
# Generally ${prefix}/share/verilator
|
||||||
|
pkgdatadir = @pkgdatadir@
|
||||||
|
|
||||||
|
# Compile options
|
||||||
|
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||||
|
CPPFLAGSNOWALL += @CPPFLAGS@
|
||||||
|
LDFLAGS += @LDFLAGS@
|
||||||
|
|
||||||
#### End of system configuration section. ####
|
#### End of system configuration section. ####
|
||||||
|
|
||||||
@@ -36,29 +54,22 @@ TGT = ../../verilator_bin
|
|||||||
#################
|
#################
|
||||||
ifeq ($(VL_DEBUG),)
|
ifeq ($(VL_DEBUG),)
|
||||||
# Optimize
|
# Optimize
|
||||||
LDFLAGS =
|
|
||||||
COPT = -O
|
COPT = -O
|
||||||
else
|
else
|
||||||
# Debug
|
# Debug
|
||||||
LDFLAGS =
|
|
||||||
COPT = -ggdb -DVL_DEBUG
|
COPT = -ggdb -DVL_DEBUG
|
||||||
# Debug & Profile:
|
# Debug & Profile:
|
||||||
#LDFLAGS = -pg -g
|
#LDFLAGS += -pg -g
|
||||||
#COPT = -ggdb -pg -g
|
#COPT = -ggdb -pg -g
|
||||||
endif
|
endif
|
||||||
#################
|
#################
|
||||||
|
|
||||||
LEX = flex
|
|
||||||
LFLAGS = -d
|
|
||||||
YACC = bison -y
|
|
||||||
YFLAGS = -d -v
|
|
||||||
|
|
||||||
#LIBS += -ldl
|
#LIBS += -ldl
|
||||||
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl
|
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl
|
||||||
|
|
||||||
LIBS = -lm -lfl
|
LIBS = -lm -lfl
|
||||||
|
|
||||||
CPPFLAGSNOWALL = -MMD
|
CPPFLAGSNOWALL += -MMD
|
||||||
CPPFLAGSNOWALL += -I. -I$(srcdir) -I$(incdir)
|
CPPFLAGSNOWALL += -I. -I$(srcdir) -I$(incdir)
|
||||||
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages
|
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages
|
||||||
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
||||||
@@ -70,9 +81,23 @@ CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
|
|||||||
#CPPFLAGS += -pedantic-errors
|
#CPPFLAGS += -pedantic-errors
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Allow RPM builds to specify hardcoded data directories
|
||||||
|
# To do this:
|
||||||
|
ifeq ($(CFG_WITH_DEFENV),yes)
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMC=\"$(SYSTEMC)\"
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMC_ARCH=\"$(SYSTEMC_ARCH)\"
|
||||||
|
CPPFLAGS += -DDEFENV_SYSTEMPERL=\"$(SYSTEMPERL)\"
|
||||||
|
ifeq ($(VERILATOR_ROOT),) # Use what we're given, or intuit
|
||||||
|
CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(pkgdatadir)\"
|
||||||
|
else
|
||||||
|
CPPFLAGS += -DDEFENV_VERILATOR_ROOT=\"$(VERILATOR_ROOT)\"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
HEADERS = $(wildcard V*.h v*.h)
|
HEADERS = $(wildcard V*.h v*.h)
|
||||||
|
|
||||||
ASTGEN = $(srcdir)/astgen
|
ASTGEN = $(srcdir)/astgen
|
||||||
|
BISONPRE = $(srcdir)/bisonpre
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
#### Top level
|
#### Top level
|
||||||
@@ -89,7 +114,6 @@ clean mostlyclean distclean maintainer-clean::
|
|||||||
-rm -f obj_* .objcache*
|
-rm -f obj_* .objcache*
|
||||||
|
|
||||||
distclean maintainer-clean:: clean
|
distclean maintainer-clean:: clean
|
||||||
rm -f Makefile config.h
|
|
||||||
|
|
||||||
maintainer-clean::
|
maintainer-clean::
|
||||||
|
|
||||||
@@ -119,8 +143,10 @@ RAW_OBJS = \
|
|||||||
V3Dead.o \
|
V3Dead.o \
|
||||||
V3Delayed.o \
|
V3Delayed.o \
|
||||||
V3Depth.o \
|
V3Depth.o \
|
||||||
|
V3DepthBlock.o \
|
||||||
V3Descope.o \
|
V3Descope.o \
|
||||||
V3EmitC.o \
|
V3EmitC.o \
|
||||||
|
V3EmitCInlines.o \
|
||||||
V3EmitCSyms.o \
|
V3EmitCSyms.o \
|
||||||
V3EmitMk.o \
|
V3EmitMk.o \
|
||||||
V3EmitV.o \
|
V3EmitV.o \
|
||||||
@@ -143,6 +169,8 @@ RAW_OBJS = \
|
|||||||
V3LinkCells.o \
|
V3LinkCells.o \
|
||||||
V3LinkDot.o \
|
V3LinkDot.o \
|
||||||
V3LinkLevel.o \
|
V3LinkLevel.o \
|
||||||
|
V3LinkLValue.o \
|
||||||
|
V3LinkParse.o \
|
||||||
V3LinkResolve.o \
|
V3LinkResolve.o \
|
||||||
V3Localize.o \
|
V3Localize.o \
|
||||||
V3Name.o \
|
V3Name.o \
|
||||||
@@ -155,6 +183,7 @@ RAW_OBJS = \
|
|||||||
V3Scope.o \
|
V3Scope.o \
|
||||||
V3Signed.o \
|
V3Signed.o \
|
||||||
V3Split.o \
|
V3Split.o \
|
||||||
|
V3SplitAs.o \
|
||||||
V3Stats.o \
|
V3Stats.o \
|
||||||
V3StatsReport.o \
|
V3StatsReport.o \
|
||||||
V3Subst.o \
|
V3Subst.o \
|
||||||
@@ -217,14 +246,17 @@ V3PreProc.o: V3PreProc.cpp V3PreLex.yy.cpp
|
|||||||
#### Generated files
|
#### Generated files
|
||||||
|
|
||||||
# Target rule called before parallel build to make generated files
|
# Target rule called before parallel build to make generated files
|
||||||
serial:: V3Ast__gen_classes.h
|
serial:: V3Ast__gen_classes.h y.tab.c
|
||||||
|
|
||||||
V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h
|
V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h
|
||||||
$(PERL) $(ASTGEN) -I$(srcdir) --classes
|
$(PERL) $(ASTGEN) -I$(srcdir) --classes
|
||||||
|
|
||||||
y.tab.c y.tab.h: verilog.y $(HEADERS)
|
y.tab.h: y.tab.c
|
||||||
|
|
||||||
|
# Have only one output file in this rule to prevent parallel make issues
|
||||||
|
y.tab.c: verilog.y $(HEADERS) bisonpre
|
||||||
@echo "If you get errors from verilog.y below, try upgrading bison to version 1.875 or newer."
|
@echo "If you get errors from verilog.y below, try upgrading bison to version 1.875 or newer."
|
||||||
${YACC} ${YFLAGS} $<
|
$(PERL) $(BISONPRE) --yacc ${YACC} -d -v -o y.tab.c $<
|
||||||
|
|
||||||
V3Lexer_pregen.yy.cpp: verilog.l y.tab.h $(HEADERS)
|
V3Lexer_pregen.yy.cpp: verilog.l y.tab.h $(HEADERS)
|
||||||
${LEX} ${LFLAGS} -o$@ $<
|
${LEX} ${LFLAGS} -o$@ $<
|
||||||
|
|||||||
+9
-7
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Active's Transformations:
|
// V3Active's Transformations:
|
||||||
//
|
//
|
||||||
// Note this can be called multiple times.
|
// Note this can be called multiple times.
|
||||||
// Create a IACTIVE(initial), SACTIVE(combo)
|
// Create a IACTIVE(initial), SACTIVE(combo)
|
||||||
// ALWAYS: Remove any-edges from sense list
|
// ALWAYS: Remove any-edges from sense list
|
||||||
@@ -31,9 +30,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -298,8 +298,10 @@ private:
|
|||||||
// OPTIMIZE: We could substitute a constant for things in the sense list, for example
|
// OPTIMIZE: We could substitute a constant for things in the sense list, for example
|
||||||
// always (posedge RESET) { if (RESET).... } we know RESET is true.
|
// always (posedge RESET) { if (RESET).... } we know RESET is true.
|
||||||
// Summarize a long list of combo inputs as just "combo"
|
// Summarize a long list of combo inputs as just "combo"
|
||||||
|
#ifndef __COVERITY__ // Else dead code on next line.
|
||||||
if (combo) nodep->sensesp()->addSensesp
|
if (combo) nodep->sensesp()->addSensesp
|
||||||
(new AstSenItem(nodep->fileline(),AstSenItem::Combo()));
|
(new AstSenItem(nodep->fileline(),AstSenItem::Combo()));
|
||||||
|
#endif
|
||||||
wantactivep = m_namer.getActive(nodep->fileline(), nodep->sensesp());
|
wantactivep = m_namer.getActive(nodep->fileline(), nodep->sensesp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3ACTIVE_H_
|
#ifndef _V3ACTIVE_H_
|
||||||
#define _V3ACTIVE_H_ 1
|
#define _V3ACTIVE_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
// DESCRIPTION: Verilator: Break always into sensitivity active domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Active's Transformations:
|
// V3Active's Transformations:
|
||||||
//
|
//
|
||||||
// Note this can be called multiple times.
|
// Note this can be called multiple times.
|
||||||
// Across all ACTIVES
|
// Across all ACTIVES
|
||||||
// SenTrees are now under each ACTIVE statement, we want them global:
|
// SenTrees are now under each ACTIVE statement, we want them global:
|
||||||
@@ -28,9 +27,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3ACTIVETOP_H_
|
#ifndef _V3ACTIVETOP_H_
|
||||||
#define _V3ACTIVETOP_H_ 1
|
#define _V3ACTIVETOP_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+116
-24
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Collect and print statistics
|
// DESCRIPTION: Verilator: Collect and print statistics
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,9 +18,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -43,36 +43,72 @@ private:
|
|||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
AstModule* m_modp; // Last module
|
AstModule* m_modp; // Last module
|
||||||
|
AstBegin* m_beginp; // Last begin
|
||||||
V3Double0 m_statAsCover; // Statistic tracking
|
V3Double0 m_statAsCover; // Statistic tracking
|
||||||
V3Double0 m_statAsPsl; // Statistic tracking
|
V3Double0 m_statAsPsl; // Statistic tracking
|
||||||
V3Double0 m_statAsFull; // Statistic tracking
|
V3Double0 m_statAsFull; // Statistic tracking
|
||||||
|
V3Double0 m_statAsSV; // Statistic tracking
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
string assertDisplayMessage(AstNode* nodep, const string& prefix, const string& message) {
|
||||||
AstNode* bodysp = new AstDisplay
|
return (string("[%0t] "+prefix+": ")+nodep->fileline()->filebasename()
|
||||||
(nodep->fileline(), '\0',
|
+":"+cvtToStr(nodep->fileline()->lineno())
|
||||||
(string("[%0t] %%Error: ")+nodep->fileline()->filebasename()
|
+": Assertion failed in %m"
|
||||||
+":"+cvtToStr(nodep->fileline()->lineno())
|
+((message != "")?": ":"")+message
|
||||||
+": Assertion failed in %m"
|
+"\\n");
|
||||||
+((message != "")?": ":"")+message
|
}
|
||||||
+"\\n"),
|
void replaceDisplay(AstDisplay* nodep, const string& prefix) {
|
||||||
NULL,
|
nodep->displayType(AstDisplayType::WRITE);
|
||||||
new AstTime(nodep->fileline()));
|
nodep->text(assertDisplayMessage(nodep, prefix, nodep->text()));
|
||||||
bodysp->addNext(new AstStop (nodep->fileline()));
|
AstNode* timesp = nodep->exprsp(); if (timesp) timesp->unlinkFrBack();
|
||||||
|
timesp = timesp->addNext(new AstTime(nodep->fileline()));
|
||||||
|
nodep->exprsp(timesp);
|
||||||
|
if (!nodep->scopeNamep() && nodep->name().find("%m") != string::npos) {
|
||||||
|
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode* newIfAssertOn(AstNode* nodep) {
|
||||||
// Add a internal if to check assertions are on.
|
// Add a internal if to check assertions are on.
|
||||||
// Don't make this a AND term, as it's unlikely to need to test this.
|
// Don't make this a AND term, as it's unlikely to need to test this.
|
||||||
bodysp = new AstIf (nodep->fileline(),
|
return new AstIf (nodep->fileline(),
|
||||||
new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1),
|
// If assertions are off, have constant propagation rip them out later
|
||||||
bodysp, NULL);
|
// This allows syntax errors and such to be detected normally.
|
||||||
|
(v3Global.opt.assertOn()
|
||||||
|
? (AstNode*)(new AstCMath(nodep->fileline(), "Verilated::assertOn()", 1))
|
||||||
|
: (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 0)))),
|
||||||
|
nodep, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode* newIfCoverageOn(AstNode* nodep) {
|
||||||
|
// Add a internal if to check coverage is on
|
||||||
|
// Don't make this a AND term, as it's unlikely to need to test this.
|
||||||
|
return new AstIf (nodep->fileline(),
|
||||||
|
// If assertions are off, have constant propagation rip them out later
|
||||||
|
// This allows syntax errors and such to be detected normally.
|
||||||
|
(v3Global.opt.coverage()
|
||||||
|
? (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 1)))
|
||||||
|
: (AstNode*)(new AstConst(nodep->fileline(), V3Number(nodep->fileline(), 1, 0)))),
|
||||||
|
nodep, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode* newFireAssert(AstNode* nodep, const string& message) {
|
||||||
|
AstDisplay* dispp = new AstDisplay (nodep->fileline(), AstDisplayType::ERROR, message, NULL, NULL);
|
||||||
|
AstNode* bodysp = dispp;
|
||||||
|
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
|
||||||
|
bodysp->addNext(new AstStop (nodep->fileline()));
|
||||||
|
bodysp = newIfAssertOn(bodysp);
|
||||||
return bodysp;
|
return bodysp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void newAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep, const string& message) {
|
void newPslAssertion(AstNode* nodep, AstNode* propp, AstSenTree* sentreep,
|
||||||
|
AstNode* stmtsp, const string& message) {
|
||||||
propp->unlinkFrBack();
|
propp->unlinkFrBack();
|
||||||
sentreep->unlinkFrBack();
|
sentreep->unlinkFrBack();
|
||||||
|
if (stmtsp) stmtsp->unlinkFrBack();
|
||||||
//
|
//
|
||||||
AstNode* bodysp = NULL;
|
AstNode* bodysp = NULL;
|
||||||
bool selfDestruct = false;
|
bool selfDestruct = false;
|
||||||
if (AstPslCover* snodep = nodep->castPslCover()) {
|
if (AstPslCover* snodep = nodep->castPslCover()) {
|
||||||
if (!v3Global.opt.coverageUser()) {
|
if (!v3Global.opt.coverageUser()) {
|
||||||
selfDestruct = true;
|
selfDestruct = true;
|
||||||
@@ -93,6 +129,7 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
nodep->v3fatalSrc("Unknown node type");
|
nodep->v3fatalSrc("Unknown node type");
|
||||||
}
|
}
|
||||||
|
if (stmtsp) bodysp = bodysp->addNext(stmtsp);
|
||||||
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
|
AstIf* ifp = new AstIf (nodep->fileline(), propp, bodysp, NULL);
|
||||||
bodysp = ifp;
|
bodysp = ifp;
|
||||||
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::UNLIKELY);
|
if (nodep->castPslAssert()) ifp->branchPred(AstBranchPred::UNLIKELY);
|
||||||
@@ -113,6 +150,28 @@ private:
|
|||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void newVAssertion(AstVAssert* nodep, AstNode* propp) {
|
||||||
|
propp->unlinkFrBackWithNext();
|
||||||
|
AstNode* passsp = nodep->passsp(); if (passsp) passsp->unlinkFrBackWithNext();
|
||||||
|
AstNode* failsp = nodep->failsp(); if (failsp) failsp->unlinkFrBackWithNext();
|
||||||
|
//
|
||||||
|
if (nodep->castVAssert()) {
|
||||||
|
if (passsp) passsp = newIfAssertOn(passsp);
|
||||||
|
if (failsp) failsp = newIfAssertOn(failsp);
|
||||||
|
} else {
|
||||||
|
nodep->v3fatalSrc("Unknown node type");
|
||||||
|
}
|
||||||
|
|
||||||
|
AstIf* ifp = new AstIf (nodep->fileline(), propp, passsp, failsp);
|
||||||
|
AstNode* newp = ifp;
|
||||||
|
if (nodep->castVAssert()) ifp->branchPred(AstBranchPred::UNLIKELY);
|
||||||
|
//
|
||||||
|
// Install it
|
||||||
|
nodep->replaceWith(newp);
|
||||||
|
// Bye
|
||||||
|
pushDeletep(nodep); nodep=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS //========== Case assertions
|
// VISITORS //========== Case assertions
|
||||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -162,16 +221,37 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// VISITORS //========== Statements
|
// VISITORS //========== Statements
|
||||||
|
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
// Replace the special types with standard text
|
||||||
|
if (nodep->displayType()==AstDisplayType::INFO) {
|
||||||
|
replaceDisplay(nodep, "-Info");
|
||||||
|
} else if (nodep->displayType()==AstDisplayType::WARNING) {
|
||||||
|
replaceDisplay(nodep, "%%Warning");
|
||||||
|
} else if (nodep->displayType()==AstDisplayType::ERROR
|
||||||
|
|| nodep->displayType()==AstDisplayType::FATAL) {
|
||||||
|
replaceDisplay(nodep, "%%Error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
newAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
|
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
||||||
|
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||||
|
nodep->stmtsp(), nodep->name()); nodep=NULL;
|
||||||
m_statAsCover++;
|
m_statAsCover++;
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
newAssertion(nodep, nodep->propp(), nodep->sentreep(), nodep->name()); nodep=NULL;
|
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||||
|
NULL, nodep->name()); nodep=NULL;
|
||||||
m_statAsPsl++;
|
m_statAsPsl++;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
newVAssertion(nodep, nodep->propp()); nodep=NULL;
|
||||||
|
m_statAsSV++;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
@@ -180,6 +260,16 @@ private:
|
|||||||
// Reset defaults
|
// Reset defaults
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstBegin* nodep, AstNUser*) {
|
||||||
|
// This code is needed rather than a visitor in V3Begin,
|
||||||
|
// because V3Assert is called before V3Begin
|
||||||
|
AstBegin* lastp = m_beginp;
|
||||||
|
{
|
||||||
|
m_beginp = nodep;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
m_beginp = lastp;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS //========== Temporal Layer
|
// VISITORS //========== Temporal Layer
|
||||||
|
|
||||||
@@ -195,6 +285,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
AssertVisitor(AstNetlist* nodep) {
|
AssertVisitor(AstNetlist* nodep) {
|
||||||
|
m_beginp = NULL;
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
// Process
|
// Process
|
||||||
AstNode::userClearTree(); // userp() used on entire tree
|
AstNode::userClearTree(); // userp() used on entire tree
|
||||||
@@ -202,6 +293,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual ~AssertVisitor() {
|
virtual ~AssertVisitor() {
|
||||||
V3Stats::addStat("Assertions, PSL asserts", m_statAsPsl);
|
V3Stats::addStat("Assertions, PSL asserts", m_statAsPsl);
|
||||||
|
V3Stats::addStat("Assertions, SystemVerilog asserts", m_statAsSV);
|
||||||
V3Stats::addStat("Assertions, cover statements", m_statAsCover);
|
V3Stats::addStat("Assertions, cover statements", m_statAsCover);
|
||||||
V3Stats::addStat("Assertions, full/parallel case", m_statAsFull);
|
V3Stats::addStat("Assertions, full/parallel case", m_statAsFull);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Assertion expansion
|
// DESCRIPTION: Verilator: Assertion expansion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3ASSERT_H_
|
#ifndef _V3ASSERT_H_
|
||||||
#define _V3ASSERT_H_ 1
|
#define _V3ASSERT_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+42
-16
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Collect and print statistics
|
// DESCRIPTION: Verilator: Collect and print statistics
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -22,9 +21,10 @@
|
|||||||
// Attach clocks to each assertion
|
// Attach clocks to each assertion
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -56,10 +56,17 @@ private:
|
|||||||
// Return NULL for always
|
// Return NULL for always
|
||||||
AstSenTree* newp = NULL;
|
AstSenTree* newp = NULL;
|
||||||
AstSenItem* senip = m_senip ? m_senip : m_seniDefaultp;
|
AstSenItem* senip = m_senip ? m_senip : m_seniDefaultp;
|
||||||
if (senip) newp = new AstSenTree(nodep->fileline(), senip->cloneTree(true));
|
if (!senip) {
|
||||||
if (!senip) nodep->v3error("Unsupported: Unclocked assertion");
|
nodep->v3error("Unsupported: Unclocked assertion");
|
||||||
|
newp = new AstSenTree(nodep->fileline(), NULL);
|
||||||
|
} else {
|
||||||
|
newp = new AstSenTree(nodep->fileline(), senip->cloneTree(true));
|
||||||
|
}
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
void clearAssertInfo() {
|
||||||
|
m_senip = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS //========== Statements
|
// VISITORS //========== Statements
|
||||||
virtual void visit(AstPslDefClock* nodep, AstNUser*) {
|
virtual void visit(AstPslDefClock* nodep, AstNUser*) {
|
||||||
@@ -70,28 +77,47 @@ private:
|
|||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstClocking* nodep, AstNUser*) {
|
||||||
|
UINFO(8," CLOCKING"<<nodep<<endl);
|
||||||
|
// Store the new default clock, reset on new module
|
||||||
|
m_seniDefaultp = nodep->sensesp();
|
||||||
|
// Trash it, keeping children
|
||||||
|
if (nodep->bodysp()) {
|
||||||
|
nodep->replaceWith(nodep->bodysp()->unlinkFrBack());
|
||||||
|
} else {
|
||||||
|
nodep->unlinkFrBack();
|
||||||
|
}
|
||||||
|
pushDeletep(nodep); nodep=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
virtual void visit(AstPslCover* nodep, AstNUser*) {
|
||||||
// Prep
|
if (nodep->sentreep()) return; // Already processed
|
||||||
m_senip = NULL;
|
clearAssertInfo();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->sentreep(newSenTree(nodep));
|
nodep->sentreep(newSenTree(nodep));
|
||||||
m_senip = NULL;
|
clearAssertInfo();
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
||||||
// Prep
|
if (nodep->sentreep()) return; // Already processed
|
||||||
m_senip = NULL;
|
clearAssertInfo();
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
nodep->sentreep(newSenTree(nodep));
|
nodep->sentreep(newSenTree(nodep));
|
||||||
m_senip = NULL;
|
clearAssertInfo();
|
||||||
}
|
}
|
||||||
virtual void visit(AstPslClocked* nodep, AstNUser*) {
|
virtual void visit(AstPslClocked* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (m_senip) {
|
if (m_senip) {
|
||||||
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion\n");
|
nodep->v3error("Unsupported: Only one PSL clock allowed per assertion\n");
|
||||||
}
|
}
|
||||||
// Unlink and just keep a pointer to it, convert to sentree as needed
|
// Block is the new expression to evaluate
|
||||||
AstNode* blockp = nodep->propp()->unlinkFrBack();
|
AstNode* blockp = nodep->propp()->unlinkFrBack();
|
||||||
|
if (nodep->disablep()) {
|
||||||
|
blockp = new AstAnd(nodep->disablep()->fileline(),
|
||||||
|
new AstNot(nodep->disablep()->fileline(),
|
||||||
|
nodep->disablep()->unlinkFrBack()),
|
||||||
|
blockp);
|
||||||
|
}
|
||||||
|
// Unlink and just keep a pointer to it, convert to sentree as needed
|
||||||
m_senip = nodep->sensesp();
|
m_senip = nodep->sensesp();
|
||||||
nodep->replaceWith(blockp);
|
nodep->replaceWith(blockp);
|
||||||
pushDeletep(nodep); nodep=NULL;
|
pushDeletep(nodep); nodep=NULL;
|
||||||
@@ -108,8 +134,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
AssertPreVisitor(AstNetlist* nodep) {
|
AssertPreVisitor(AstNetlist* nodep) {
|
||||||
m_senip = NULL;
|
|
||||||
m_seniDefaultp = NULL;
|
m_seniDefaultp = NULL;
|
||||||
|
clearAssertInfo();
|
||||||
// Process
|
// Process
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Assertion pre-expansion
|
// DESCRIPTION: Verilator: Assertion pre-expansion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2005-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2005-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3ASSERTPRE_H_
|
#ifndef _V3ASSERTPRE_H_
|
||||||
#define _V3ASSERTPRE_H_ 1
|
#define _V3ASSERTPRE_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+117
-27
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Ast node structures
|
// DESCRIPTION: Verilator: Ast node structures
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,8 +18,8 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -33,8 +32,8 @@
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
// Statics
|
// Statics
|
||||||
|
|
||||||
uint64_t AstNode::s_editCntGbl=0;
|
vluint64_t AstNode::s_editCntGbl=0;
|
||||||
uint64_t AstNode::s_editCntLast=0;
|
vluint64_t AstNode::s_editCntLast=0;
|
||||||
|
|
||||||
// To allow for fast clearing of all user pointers, we keep a "timestamp"
|
// To allow for fast clearing of all user pointers, we keep a "timestamp"
|
||||||
// along with each userp, and thus by bumping this count we can make it look
|
// along with each userp, and thus by bumping this count we can make it look
|
||||||
@@ -83,6 +82,43 @@ void AstNode::init() {
|
|||||||
m_user5Cnt = 0;
|
m_user5Cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AstNode::encodeName(const string& namein) {
|
||||||
|
string name2 = namein;
|
||||||
|
string out;
|
||||||
|
const char* start = name2.c_str();
|
||||||
|
for (const char* pos = start; *pos; pos++) {
|
||||||
|
if ((pos==start) ? isalpha(pos[0]) // digits can't lead identifiers
|
||||||
|
: isalnum(pos[0])) {
|
||||||
|
out += pos[0];
|
||||||
|
} else if (pos[0]=='_') {
|
||||||
|
if (pos[1]=='_') {
|
||||||
|
out += "_"; out += "__5F"; // hex(_) = 0x5F
|
||||||
|
pos++;
|
||||||
|
} else {
|
||||||
|
out += pos[0];
|
||||||
|
}
|
||||||
|
} else if (pos[0]=='.') {
|
||||||
|
out += "__DOT__";
|
||||||
|
} else if (pos[0]=='[') {
|
||||||
|
out += "__BRA__";
|
||||||
|
} else if (pos[0]==']') {
|
||||||
|
out += "__KET__";
|
||||||
|
} else {
|
||||||
|
char hex[10]; sprintf(hex,"%02X",pos[0]);
|
||||||
|
out += "__"; out += hex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AstNode::encodeNumber(vlsint64_t num) {
|
||||||
|
if (num < 0) {
|
||||||
|
return "__2D"+cvtToStr(-num); // 2D=-
|
||||||
|
} else {
|
||||||
|
return cvtToStr(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string AstNode::shortName() const {
|
string AstNode::shortName() const {
|
||||||
string pretty = name();
|
string pretty = name();
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
@@ -92,19 +128,52 @@ string AstNode::shortName() const {
|
|||||||
return pretty;
|
return pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
string AstNode::prettyName(const string& namein) {
|
string AstNode::dedotName(const string& namein) {
|
||||||
string pretty = namein;
|
string pretty = namein;
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
while ((pos=pretty.find("__DOT__")) != string::npos) {
|
while ((pos=pretty.find("__DOT__")) != string::npos) {
|
||||||
pretty.replace(pos, 7, ".");
|
pretty.replace(pos, 7, ".");
|
||||||
}
|
}
|
||||||
while ((pos=pretty.find("__PVT__")) != string::npos) {
|
|
||||||
pretty.replace(pos, 7, "");
|
|
||||||
}
|
|
||||||
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
||||||
return pretty;
|
return pretty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string AstNode::prettyName(const string& namein) {
|
||||||
|
string pretty;
|
||||||
|
string name2 = namein;
|
||||||
|
pretty = "";
|
||||||
|
for (const char* pos = name2.c_str(); *pos; ) {
|
||||||
|
if (0==strncmp(pos,"__BRA__",7)) {
|
||||||
|
pretty += "[";
|
||||||
|
pos += 7;
|
||||||
|
}
|
||||||
|
else if (0==strncmp(pos,"__KET__",7)) {
|
||||||
|
pretty += "]";
|
||||||
|
pos += 7;
|
||||||
|
}
|
||||||
|
else if (0==strncmp(pos,"__DOT__",7)) {
|
||||||
|
pretty += ".";
|
||||||
|
pos += 7;
|
||||||
|
}
|
||||||
|
else if (0==strncmp(pos,"__PVT__",7)) {
|
||||||
|
pretty += "";
|
||||||
|
pos += 7;
|
||||||
|
}
|
||||||
|
else if (pos[0]=='_' && pos[1]=='_' && isxdigit(pos[2]) && isxdigit(pos[3])) {
|
||||||
|
char value = 0;
|
||||||
|
value += 16*(isdigit(pos[2]) ? (pos[2]-'0') : (tolower(pos[2])-'a'+10));
|
||||||
|
value += (isdigit(pos[3]) ? (pos[3]-'0') : (tolower(pos[3])-'a'+10));
|
||||||
|
pretty += value;
|
||||||
|
pos += 4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pretty += pos[0];
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AstNode::dedotName(pretty);
|
||||||
|
}
|
||||||
|
|
||||||
int AstNode::widthPow2() const {
|
int AstNode::widthPow2() const {
|
||||||
// I.e. width 30 returns 32, width 32 returns 32.
|
// I.e. width 30 returns 32, width 32 returns 32.
|
||||||
uint32_t width = this->width();
|
uint32_t width = this->width();
|
||||||
@@ -122,6 +191,7 @@ inline void AstNode::debugTreeChange(const char* prefix, int lineno, bool next)
|
|||||||
// Called on all major tree changers.
|
// Called on all major tree changers.
|
||||||
// Only for use for those really nasty bugs relating to internals
|
// Only for use for those really nasty bugs relating to internals
|
||||||
// Note this may be null.
|
// Note this may be null.
|
||||||
|
//if (debug()) cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<": "<<(void*)this<<endl;
|
||||||
//if (debug()) {
|
//if (debug()) {
|
||||||
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
|
// cout<<"-treeChange: V3Ast.cpp:"<<lineno<<" Tree Change for "<<prefix<<endl;
|
||||||
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
|
// v3Global.rootp()->dumpTree(cout,"-treeChange: ");
|
||||||
@@ -225,8 +295,8 @@ void AstNode::addNextHere(AstNode* newp) {
|
|||||||
void AstNode::setOp1p(AstNode* newp) {
|
void AstNode::setOp1p(AstNode* newp) {
|
||||||
UASSERT(newp,"Null item passed to setOp1p\n");
|
UASSERT(newp,"Null item passed to setOp1p\n");
|
||||||
UDEBUGONLY(if (m_op1p) this->v3fatalSrc("Adding to non-empty, non-list op1"););
|
UDEBUGONLY(if (m_op1p) this->v3fatalSrc("Adding to non-empty, non-list op1"););
|
||||||
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op1"););
|
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op1"););
|
||||||
this->debugTreeChange("-setOp1pThs: ", __LINE__, false);
|
this->debugTreeChange("-setOp1pThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-setOp1pNew: ", __LINE__, true);
|
newp->debugTreeChange("-setOp1pNew: ", __LINE__, true);
|
||||||
m_op1p = newp;
|
m_op1p = newp;
|
||||||
@@ -238,8 +308,8 @@ void AstNode::setOp1p(AstNode* newp) {
|
|||||||
void AstNode::setOp2p(AstNode* newp) {
|
void AstNode::setOp2p(AstNode* newp) {
|
||||||
UASSERT(newp,"Null item passed to setOp2p\n");
|
UASSERT(newp,"Null item passed to setOp2p\n");
|
||||||
UDEBUGONLY(if (m_op2p) this->v3fatalSrc("Adding to non-empty, non-list op2"););
|
UDEBUGONLY(if (m_op2p) this->v3fatalSrc("Adding to non-empty, non-list op2"););
|
||||||
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op2"););
|
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op2"););
|
||||||
this->debugTreeChange("-setOp2pThs: ", __LINE__, false);
|
this->debugTreeChange("-setOp2pThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-setOp2pNew: ", __LINE__, true);
|
newp->debugTreeChange("-setOp2pNew: ", __LINE__, true);
|
||||||
m_op2p = newp;
|
m_op2p = newp;
|
||||||
@@ -251,8 +321,8 @@ void AstNode::setOp2p(AstNode* newp) {
|
|||||||
void AstNode::setOp3p(AstNode* newp) {
|
void AstNode::setOp3p(AstNode* newp) {
|
||||||
UASSERT(newp,"Null item passed to setOp3p\n");
|
UASSERT(newp,"Null item passed to setOp3p\n");
|
||||||
UDEBUGONLY(if (m_op3p) this->v3fatalSrc("Adding to non-empty, non-list op3"););
|
UDEBUGONLY(if (m_op3p) this->v3fatalSrc("Adding to non-empty, non-list op3"););
|
||||||
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op3"););
|
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op3"););
|
||||||
this->debugTreeChange("-setOp3pThs: ", __LINE__, false);
|
this->debugTreeChange("-setOp3pThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-setOp3pNew: ", __LINE__, true);
|
newp->debugTreeChange("-setOp3pNew: ", __LINE__, true);
|
||||||
m_op3p = newp;
|
m_op3p = newp;
|
||||||
@@ -264,8 +334,8 @@ void AstNode::setOp3p(AstNode* newp) {
|
|||||||
void AstNode::setOp4p(AstNode* newp) {
|
void AstNode::setOp4p(AstNode* newp) {
|
||||||
UASSERT(newp,"Null item passed to setOp4p\n");
|
UASSERT(newp,"Null item passed to setOp4p\n");
|
||||||
UDEBUGONLY(if (m_op4p) this->v3fatalSrc("Adding to non-empty, non-list op4"););
|
UDEBUGONLY(if (m_op4p) this->v3fatalSrc("Adding to non-empty, non-list op4"););
|
||||||
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
UDEBUGONLY(if (newp->m_backp) newp->v3fatalSrc("Adding already linked node"););
|
||||||
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op4"););
|
UDEBUGONLY(if (newp->m_nextp) newp->v3fatalSrc("Adding list to non-list op4"););
|
||||||
this->debugTreeChange("-setOp4pThs: ", __LINE__, false);
|
this->debugTreeChange("-setOp4pThs: ", __LINE__, false);
|
||||||
newp->debugTreeChange("-setOp4pNew: ", __LINE__, true);
|
newp->debugTreeChange("-setOp4pNew: ", __LINE__, true);
|
||||||
m_op4p = newp;
|
m_op4p = newp;
|
||||||
@@ -446,7 +516,7 @@ void AstNode::relink(AstNRelinker* linkerp) {
|
|||||||
if (linkerp->m_iterpp) {
|
if (linkerp->m_iterpp) {
|
||||||
// If we're iterating over a next() link, we need to follow links off the
|
// If we're iterating over a next() link, we need to follow links off the
|
||||||
// NEW node. Thus we pass iteration information via a pointer in the node.
|
// NEW node. Thus we pass iteration information via a pointer in the node.
|
||||||
// This adds a unfortunate 4 bytes to every AstNode, but is faster then passing
|
// This adds a unfortunate 4 bytes to every AstNode, but is faster than passing
|
||||||
// across every function.
|
// across every function.
|
||||||
// If anyone has a cleaner way, I'd be grateful.
|
// If anyone has a cleaner way, I'd be grateful.
|
||||||
*(linkerp->m_iterpp) = newp;
|
*(linkerp->m_iterpp) = newp;
|
||||||
@@ -574,11 +644,29 @@ void AstNode::deleteTree() {
|
|||||||
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
|
// unlinkFromBack or unlinkFromBackWithNext as appropriate before calling this.
|
||||||
if (!this) return;
|
if (!this) return;
|
||||||
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
UASSERT(m_backp==NULL,"Delete called on node with backlink still set\n");
|
||||||
this->debugTreeChange("-delete: ", __LINE__, true);
|
this->debugTreeChange("-delTree: ", __LINE__, true);
|
||||||
// MUST be depth first!
|
// MUST be depth first!
|
||||||
deleteTreeIter();
|
deleteTreeIter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
// Memory checks
|
||||||
|
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
void* AstNode::operator new(size_t size) {
|
||||||
|
AstNode* objp = static_cast<AstNode*>(::operator new(size));
|
||||||
|
V3Broken::addNewed(objp);
|
||||||
|
return objp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AstNode::operator delete(void* objp, size_t size) {
|
||||||
|
if (!objp) return;
|
||||||
|
AstNode* nodep = static_cast<AstNode*>(objp);
|
||||||
|
V3Broken::deleted(nodep);
|
||||||
|
::operator delete(objp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//======================================================================
|
//======================================================================
|
||||||
// Iterators
|
// Iterators
|
||||||
|
|
||||||
@@ -596,7 +684,7 @@ void AstNode::iterateListBackwards(AstNVisitor& v, AstNUser* vup) {
|
|||||||
while (nodep->m_nextp) nodep=nodep->m_nextp;
|
while (nodep->m_nextp) nodep=nodep->m_nextp;
|
||||||
while (nodep) {
|
while (nodep) {
|
||||||
// Edits not supported: nodep->m_iterpp = &nodep;
|
// Edits not supported: nodep->m_iterpp = &nodep;
|
||||||
nodep->accept(v, vup);
|
nodep->accept(v, vup);
|
||||||
if (nodep->backp()->m_nextp == nodep) nodep=nodep->backp();
|
if (nodep->backp()->m_nextp == nodep) nodep=nodep->backp();
|
||||||
else nodep = NULL; // else: backp points up the tree.
|
else nodep = NULL; // else: backp points up the tree.
|
||||||
}
|
}
|
||||||
@@ -617,7 +705,7 @@ void AstNode::iterateAndNext(AstNVisitor& v, AstNUser* vup) {
|
|||||||
for (AstNode* nodep=this; nodep;) {
|
for (AstNode* nodep=this; nodep;) {
|
||||||
AstNode* niterp = nodep;
|
AstNode* niterp = nodep;
|
||||||
niterp->m_iterpp = &niterp;
|
niterp->m_iterpp = &niterp;
|
||||||
niterp->accept(v, vup);
|
niterp->accept(v, vup);
|
||||||
// accept may do a replaceNode and change niterp on us...
|
// accept may do a replaceNode and change niterp on us...
|
||||||
if (!niterp) return;
|
if (!niterp) return;
|
||||||
niterp->m_iterpp = NULL;
|
niterp->m_iterpp = NULL;
|
||||||
@@ -634,7 +722,7 @@ void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
|
|||||||
if (!this) return;
|
if (!this) return;
|
||||||
for (AstNode* nodep=this; nodep; ) {
|
for (AstNode* nodep=this; nodep; ) {
|
||||||
AstNode* nnextp = nodep->m_nextp;
|
AstNode* nnextp = nodep->m_nextp;
|
||||||
nodep->accept(v, vup);
|
nodep->accept(v, vup);
|
||||||
nodep = nnextp;
|
nodep = nnextp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -777,21 +865,23 @@ void AstNode::dumpTreeFile(const string& filename, bool append) {
|
|||||||
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
if (logsp->fail()) v3fatalSrc("Can't write "<<filename);
|
||||||
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
|
*logsp<<"Tree Dump from <e"<<dec<<editCountLast()<<">";
|
||||||
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
*logsp<<" to <e"<<dec<<editCountGbl()<<">"<<endl;
|
||||||
if (editCountGbl()==editCountLast() && 0) { // Off, as messes up tree diffing
|
if (editCountGbl()==editCountLast() && 1) { // Off, as messes up tree diffing
|
||||||
*logsp<<endl;
|
*logsp<<endl;
|
||||||
*logsp<<"No changes since last dump!\n";
|
*logsp<<"No changes since last dump!\n";
|
||||||
} else {
|
} else {
|
||||||
dumpTree(*logsp);
|
dumpTree(*logsp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (v3Global.opt.debugCheck() || v3Global.opt.dumpTree()) {
|
||||||
// Error check
|
// Error check
|
||||||
checkTree();
|
checkTree();
|
||||||
// Broken isn't part of check tree because it can munge iterp's
|
// Broken isn't part of check tree because it can munge iterp's
|
||||||
// set by other steps if it is called in the middle of other operations
|
// set by other steps if it is called in the middle of other operations
|
||||||
if (AstNetlist* netp=this->castNetlist()) V3Broken::brokenAll(netp);
|
if (AstNetlist* netp=this->castNetlist()) V3Broken::brokenAll(netp);
|
||||||
// Next dump can indicate start from here
|
|
||||||
editCountSetLast();
|
|
||||||
}
|
}
|
||||||
|
// Next dump can indicate start from here
|
||||||
|
editCountSetLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstNode::v3errorEnd(ostringstream& str) {
|
void AstNode::v3errorEnd(ostringstream& str) {
|
||||||
|
|||||||
+113
-22
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Ast node structure
|
// DESCRIPTION: Verilator: Ast node structure
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3AST_H_
|
#ifndef _V3AST_H_
|
||||||
#define _V3AST_H_ 1
|
#define _V3AST_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Number.h"
|
#include "V3Number.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -57,6 +58,7 @@ public:
|
|||||||
COVERAGE_BLOCK_OFF,
|
COVERAGE_BLOCK_OFF,
|
||||||
INLINE_MODULE,
|
INLINE_MODULE,
|
||||||
NO_INLINE_MODULE,
|
NO_INLINE_MODULE,
|
||||||
|
NO_INLINE_TASK,
|
||||||
PUBLIC_MODULE,
|
PUBLIC_MODULE,
|
||||||
PUBLIC_TASK
|
PUBLIC_TASK
|
||||||
};
|
};
|
||||||
@@ -195,7 +197,8 @@ public:
|
|||||||
TRIWIRE,
|
TRIWIRE,
|
||||||
BLOCKTEMP,
|
BLOCKTEMP,
|
||||||
MODULETEMP,
|
MODULETEMP,
|
||||||
STMTTEMP
|
STMTTEMP,
|
||||||
|
XTEMP
|
||||||
};
|
};
|
||||||
enum en m_e;
|
enum en m_e;
|
||||||
inline AstVarType () {};
|
inline AstVarType () {};
|
||||||
@@ -207,7 +210,7 @@ public:
|
|||||||
"?","GPARAM","LPARAM","GENVAR",
|
"?","GPARAM","LPARAM","GENVAR",
|
||||||
"INTEGER","INPUT","OUTPUT","INOUT",
|
"INTEGER","INPUT","OUTPUT","INOUT",
|
||||||
"SUPPLY0","SUPPLY1","WIRE","IMPLICIT","REG","TRIWIRE",
|
"SUPPLY0","SUPPLY1","WIRE","IMPLICIT","REG","TRIWIRE",
|
||||||
"BLOCKTEMP","MODULETEMP","STMTTEMP"};
|
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP"};
|
||||||
return names[m_e];};
|
return names[m_e];};
|
||||||
};
|
};
|
||||||
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
@@ -246,6 +249,80 @@ public:
|
|||||||
inline bool operator== (AstBranchPred::en lhs, AstBranchPred rhs) { return (lhs == rhs.m_e); }
|
inline bool operator== (AstBranchPred::en lhs, AstBranchPred rhs) { return (lhs == rhs.m_e); }
|
||||||
inline ostream& operator<<(ostream& os, AstBranchPred rhs) { return os<<rhs.ascii(); }
|
inline ostream& operator<<(ostream& os, AstBranchPred rhs) { return os<<rhs.ascii(); }
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
class AstCaseType {
|
||||||
|
public:
|
||||||
|
enum en {
|
||||||
|
CASE,
|
||||||
|
CASEX,
|
||||||
|
CASEZ
|
||||||
|
};
|
||||||
|
enum en m_e;
|
||||||
|
inline AstCaseType () {};
|
||||||
|
inline AstCaseType (en _e) : m_e(_e) {};
|
||||||
|
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {};
|
||||||
|
operator en () const { return m_e; };
|
||||||
|
};
|
||||||
|
inline bool operator== (AstCaseType lhs, AstCaseType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
|
inline bool operator== (AstCaseType lhs, AstCaseType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
|
inline bool operator== (AstCaseType::en lhs, AstCaseType rhs) { return (lhs == rhs.m_e); }
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
class AstDisplayType {
|
||||||
|
public:
|
||||||
|
enum en {
|
||||||
|
DISPLAY,
|
||||||
|
WRITE,
|
||||||
|
INFO,
|
||||||
|
ERROR,
|
||||||
|
WARNING,
|
||||||
|
FATAL
|
||||||
|
};
|
||||||
|
enum en m_e;
|
||||||
|
inline AstDisplayType () {};
|
||||||
|
inline AstDisplayType (en _e) : m_e(_e) {};
|
||||||
|
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {};
|
||||||
|
operator en () const { return m_e; };
|
||||||
|
bool addNewline() const { return m_e!=WRITE; }
|
||||||
|
bool needScopeTracking() const { return m_e!=DISPLAY && m_e!=WRITE; }
|
||||||
|
const char* ascii() const {
|
||||||
|
static const char* names[] = {
|
||||||
|
"display","write","info","error","warning","fatal"};
|
||||||
|
return names[m_e];};
|
||||||
|
};
|
||||||
|
inline bool operator== (AstDisplayType lhs, AstDisplayType rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
|
inline bool operator== (AstDisplayType lhs, AstDisplayType::en rhs) { return (lhs.m_e == rhs); }
|
||||||
|
inline bool operator== (AstDisplayType::en lhs, AstDisplayType rhs) { return (lhs == rhs.m_e); }
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
class AstParseRefExp {
|
||||||
|
public:
|
||||||
|
enum en {
|
||||||
|
NONE, // Used in V3LinkParse only
|
||||||
|
VAR_MEM,
|
||||||
|
VAR_ANY,
|
||||||
|
TASK,
|
||||||
|
FUNC,
|
||||||
|
_ENUM_END
|
||||||
|
};
|
||||||
|
enum en m_e;
|
||||||
|
inline AstParseRefExp() : m_e(NONE) {};
|
||||||
|
inline AstParseRefExp (en _e) : m_e(_e) {};
|
||||||
|
explicit inline AstParseRefExp (int _e) : m_e(static_cast<en>(_e)) {};
|
||||||
|
operator en () const { return m_e; };
|
||||||
|
const char* ascii() const {
|
||||||
|
static const char* names[] = {
|
||||||
|
"","VAR_MEM","VAR_ANY","TASK","FUNC"};
|
||||||
|
return names[m_e];};
|
||||||
|
};
|
||||||
|
inline bool operator== (AstParseRefExp lhs, AstParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
|
inline bool operator== (AstParseRefExp lhs, AstParseRefExp::en rhs) { return (lhs.m_e == rhs); }
|
||||||
|
inline bool operator== (AstParseRefExp::en lhs, AstParseRefExp rhs) { return (lhs == rhs.m_e); }
|
||||||
|
inline ostream& operator<<(ostream& os, AstParseRefExp rhs) { return os<<rhs.ascii(); }
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// AstNUser - Generic pointer base class for AST User nodes.
|
// AstNUser - Generic pointer base class for AST User nodes.
|
||||||
// - Also used to allow parameter passing up/down iterate calls
|
// - Also used to allow parameter passing up/down iterate calls
|
||||||
@@ -391,9 +468,9 @@ private:
|
|||||||
static int s_cloneCntGbl; // Count of which userp is set
|
static int s_cloneCntGbl; // Count of which userp is set
|
||||||
|
|
||||||
FileLine* m_fileline; // Where it was declared
|
FileLine* m_fileline; // Where it was declared
|
||||||
uint64_t m_editCount; // When it was last edited
|
vluint64_t m_editCount; // When it was last edited
|
||||||
static uint64_t s_editCntGbl;// Global edit counter
|
static vluint64_t s_editCntGbl; // Global edit counter
|
||||||
static uint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
|
static vluint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
bool m_signed; // Node is signed
|
bool m_signed; // Node is signed
|
||||||
@@ -476,10 +553,15 @@ public:
|
|||||||
AstNode* op3p() const { return m_op3p; }
|
AstNode* op3p() const { return m_op3p; }
|
||||||
AstNode* op4p() const { return m_op4p; }
|
AstNode* op4p() const { return m_op4p; }
|
||||||
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
|
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
|
||||||
|
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
|
||||||
bool brokeExists() const;
|
bool brokeExists() const;
|
||||||
|
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
virtual ~AstNode();
|
virtual ~AstNode();
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
static void* operator new(size_t size);
|
||||||
|
static void operator delete(void* obj, size_t size);
|
||||||
|
#endif
|
||||||
|
|
||||||
// CONSTANT ACCESSORS
|
// CONSTANT ACCESSORS
|
||||||
static int instrCountBranch() { return 4; } ///< Instruction cycles to branch
|
static int instrCountBranch() { return 4; } ///< Instruction cycles to branch
|
||||||
@@ -494,7 +576,10 @@ public:
|
|||||||
virtual string name() const { return ""; }
|
virtual string name() const { return ""; }
|
||||||
virtual string verilogKwd() const { return ""; }
|
virtual string verilogKwd() const { return ""; }
|
||||||
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
||||||
|
static string dedotName(const string& namein); // Name with dots removed
|
||||||
static string prettyName(const string& namein); // Name for printing out to the user
|
static string prettyName(const string& namein); // Name for printing out to the user
|
||||||
|
static string encodeName(const string& namein); // Encode user name into internal C representation
|
||||||
|
static string encodeNumber(vlsint64_t numin); // Encode number into internal C representation
|
||||||
string prettyName() const { return prettyName(name()); }
|
string prettyName() const { return prettyName(name()); }
|
||||||
FileLine* fileline() const { return m_fileline; }
|
FileLine* fileline() const { return m_fileline; }
|
||||||
int width() const { return m_width; }
|
int width() const { return m_width; }
|
||||||
@@ -539,10 +624,10 @@ public:
|
|||||||
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
||||||
static void user5ClearTree() { s_user5CntGbl++; } // Clear userp()'s across the entire tree
|
static void user5ClearTree() { s_user5CntGbl++; } // Clear userp()'s across the entire tree
|
||||||
|
|
||||||
uint64_t editCount() const { return m_editCount; }
|
vluint64_t editCount() const { return m_editCount; }
|
||||||
void editCountInc() { m_editCount = s_editCntGbl++; }
|
void editCountInc() { m_editCount = s_editCntGbl++; }
|
||||||
static uint64_t editCountLast() { return s_editCntLast; }
|
static vluint64_t editCountLast() { return s_editCntLast; }
|
||||||
static uint64_t editCountGbl() { return s_editCntGbl; }
|
static vluint64_t editCountGbl() { return s_editCntGbl; }
|
||||||
static void editCountSetLast() { s_editCntLast = editCountGbl(); }
|
static void editCountSetLast() { s_editCntLast = editCountGbl(); }
|
||||||
|
|
||||||
// ACCESSORS for specific types
|
// ACCESSORS for specific types
|
||||||
@@ -585,8 +670,8 @@ public:
|
|||||||
virtual int instrCount() const { return 0; }
|
virtual int instrCount() const { return 0; }
|
||||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
|
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
|
||||||
virtual bool same(AstNode* otherp) const { return true; }
|
virtual bool same(AstNode* otherp) const { return true; }
|
||||||
|
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
||||||
virtual bool broken() const { return false; }
|
virtual bool broken() const { return false; }
|
||||||
virtual bool emitWordForm() { return false; }
|
|
||||||
|
|
||||||
// INVOKERS
|
// INVOKERS
|
||||||
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
|
virtual void accept(AstNVisitor& v, AstNUser* vup=NULL) = 0;
|
||||||
@@ -617,7 +702,7 @@ struct AstNodeMath : public AstNode {
|
|||||||
virtual ~AstNodeMath() {}
|
virtual ~AstNodeMath() {}
|
||||||
// METHODS
|
// METHODS
|
||||||
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
||||||
virtual string emitOperator() = 0;
|
virtual string emitC() = 0;
|
||||||
virtual string emitSimpleOperator() { return ""; }
|
virtual string emitSimpleOperator() { return ""; }
|
||||||
virtual bool cleanOut() = 0; // True if output has extra upper bits zero
|
virtual bool cleanOut() = 0; // True if output has extra upper bits zero
|
||||||
};
|
};
|
||||||
@@ -719,7 +804,7 @@ struct AstNodeCond : public AstNodeTriop {
|
|||||||
AstNode* expr1p() const { return op2p()->castNode(); } // op2 = If true...
|
AstNode* expr1p() const { return op2p()->castNode(); } // op2 = If true...
|
||||||
AstNode* expr2p() const { return op3p()->castNode(); } // op3 = If false...
|
AstNode* expr2p() const { return op3p()->castNode(); } // op3 = If false...
|
||||||
virtual string emitVerilog() { return "%k(%l %k? %r %k: %t)"; }
|
virtual string emitVerilog() { return "%k(%l %k? %r %k: %t)"; }
|
||||||
virtual string emitOperator() { return "VL_COND"; }
|
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
|
||||||
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
|
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
|
||||||
virtual bool cleanLhs() { return true; }
|
virtual bool cleanLhs() { return true; }
|
||||||
virtual bool cleanRhs() { return false; } virtual bool cleanThs() { return false; } // Propagates up
|
virtual bool cleanRhs() { return false; } virtual bool cleanThs() { return false; } // Propagates up
|
||||||
@@ -874,6 +959,7 @@ public:
|
|||||||
virtual ~AstNodePli() {}
|
virtual ~AstNodePli() {}
|
||||||
virtual string name() const { return m_text; }
|
virtual string name() const { return m_text; }
|
||||||
virtual int instrCount() const { return instrCountPli(); }
|
virtual int instrCount() const { return instrCountPli(); }
|
||||||
|
void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output
|
||||||
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
|
AstNode* exprsp() const { return op1p()->castNode(); } // op1 = Expressions to output
|
||||||
string text() const { return m_text; } // * = Text to display
|
string text() const { return m_text; } // * = Text to display
|
||||||
void text(const string& text) { m_text=text; }
|
void text(const string& text) { m_text=text; }
|
||||||
@@ -922,6 +1008,7 @@ public:
|
|||||||
virtual ~AstNodeFTask() {}
|
virtual ~AstNodeFTask() {}
|
||||||
virtual void dump(ostream& str=cout);
|
virtual void dump(ostream& str=cout);
|
||||||
virtual string name() const { return m_name; } // * = Var name
|
virtual string name() const { return m_name; } // * = Var name
|
||||||
|
virtual bool maybePointedTo() const { return true; }
|
||||||
// {AstFunc only} op1 = Range output variable
|
// {AstFunc only} op1 = Range output variable
|
||||||
// op3 = Statements/Ports/Vars
|
// op3 = Statements/Ports/Vars
|
||||||
void name(const string& name) { m_name = name; }
|
void name(const string& name) { m_name = name; }
|
||||||
@@ -937,12 +1024,12 @@ private:
|
|||||||
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
|
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
|
||||||
string m_name; // Name of variable
|
string m_name; // Name of variable
|
||||||
string m_dotted; // Dotted part of scope to task or ""
|
string m_dotted; // Dotted part of scope to task or ""
|
||||||
string m_inlinedDots; // Dotted hiearchy flattened out
|
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||||
public:
|
public:
|
||||||
AstNodeFTaskRef(FileLine* fl, const string& name, const string& dotted, AstNode* pinsp)
|
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
|
||||||
:AstNode(fl)
|
:AstNode(fl)
|
||||||
, m_taskp(NULL), m_name(name), m_dotted(dotted) {
|
, m_taskp(NULL) {
|
||||||
addNOp1p(pinsp);
|
setOp1p(namep); addNOp2p(pinsp);
|
||||||
}
|
}
|
||||||
virtual ~AstNodeFTaskRef() {}
|
virtual ~AstNodeFTaskRef() {}
|
||||||
virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); }
|
virtual bool broken() const { return m_taskp && !m_taskp->brokeExists(); }
|
||||||
@@ -957,9 +1044,13 @@ public:
|
|||||||
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
||||||
AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable
|
AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable
|
||||||
void taskp(AstNodeFTask* taskp) { m_taskp=taskp; }
|
void taskp(AstNodeFTask* taskp) { m_taskp=taskp; }
|
||||||
// op1 = Pin interconnection list
|
void name(const string& name) { m_name = name; }
|
||||||
AstNode* pinsp() const { return op1p()->castNode(); }
|
void dotted(const string& name) { m_dotted = name; }
|
||||||
void addPinsp(AstNode* nodep) { addOp1p(nodep); }
|
// op1 = namep
|
||||||
|
AstNode* namep() const { return op1p(); }
|
||||||
|
// op2 = Pin interconnection list
|
||||||
|
AstNode* pinsp() const { return op2p()->castNode(); }
|
||||||
|
void addPinsp(AstNode* nodep) { addOp2p(nodep); }
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|||||||
+49
-14
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Ast node structures
|
// DESCRIPTION: Verilator: Ast node structures
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,8 +18,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "config_build.h"
|
||||||
#include <stdarg.h>
|
#include "verilatedos.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -42,11 +43,11 @@ void AstNodeVarRef::cloneRelink() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int AstNodeSel::bitConst() const {
|
int AstNodeSel::bitConst() const {
|
||||||
AstConst* constp=bitp()->castConst(); return (constp?constp->asInt():0);
|
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstVar::isSigPublic() const {
|
bool AstVar::isSigPublic() const {
|
||||||
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp()));
|
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AstVar::isScQuad() const {
|
bool AstVar::isScQuad() const {
|
||||||
@@ -85,7 +86,7 @@ int AstVar::widthTotalBytes() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string AstVar::verilogKwd() const {
|
string AstVar::verilogKwd() const {
|
||||||
if (isTristate()) {
|
if (isInout()) {
|
||||||
return "inout";
|
return "inout";
|
||||||
} else if (isInput()) {
|
} else if (isInput()) {
|
||||||
return "input";
|
return "input";
|
||||||
@@ -93,6 +94,8 @@ string AstVar::verilogKwd() const {
|
|||||||
return "output";
|
return "output";
|
||||||
} else if (isInteger()) {
|
} else if (isInteger()) {
|
||||||
return "integer";
|
return "integer";
|
||||||
|
} else if (isTristate()) {
|
||||||
|
return "tri";
|
||||||
} else if (varType()==AstVarType::WIRE) {
|
} else if (varType()==AstVarType::WIRE) {
|
||||||
return "wire";
|
return "wire";
|
||||||
} else {
|
} else {
|
||||||
@@ -101,6 +104,18 @@ string AstVar::verilogKwd() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string AstVar::cType() const {
|
string AstVar::cType() const {
|
||||||
|
if (widthMin() == 1) {
|
||||||
|
return "bool";
|
||||||
|
} else if (widthMin() <= VL_WORDSIZE) {
|
||||||
|
return "uint32_t";
|
||||||
|
} else if (isScWide()) {
|
||||||
|
return "uint32_t"; // []'s added later
|
||||||
|
} else {
|
||||||
|
return "uint64_t";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string AstVar::scType() const {
|
||||||
if (widthMin() == 1) {
|
if (widthMin() == 1) {
|
||||||
return "bool";
|
return "bool";
|
||||||
} else if (widthMin() <= VL_WORDSIZE) {
|
} else if (widthMin() <= VL_WORDSIZE) {
|
||||||
@@ -130,7 +145,7 @@ uint32_t AstVar::arrayElements() const {
|
|||||||
bool AstScope::broken() const {
|
bool AstScope::broken() const {
|
||||||
return ((m_aboveScopep && !m_aboveScopep->brokeExists())
|
return ((m_aboveScopep && !m_aboveScopep->brokeExists())
|
||||||
|| (m_aboveCellp && !m_aboveCellp->brokeExists())
|
|| (m_aboveCellp && !m_aboveCellp->brokeExists())
|
||||||
|| !m_modp || !((AstNode*)m_modp)->brokeExists());
|
|| !m_modp || !m_modp->brokeExists());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AstScope::cloneRelink() {
|
void AstScope::cloneRelink() {
|
||||||
@@ -282,15 +297,21 @@ void AstCell::dump(ostream& str) {
|
|||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (modp()) { str<<" -> "; modp()->dump(str); }
|
if (modp()) { str<<" -> "; modp()->dump(str); }
|
||||||
else { str<<" ->UNLINKED:"<<modName(); }
|
else { str<<" ->UNLINKED:"<<modName(); }
|
||||||
|
if (pinStar()) str<<" [.*]";
|
||||||
}
|
}
|
||||||
void AstCellInline::dump(ostream& str) {
|
void AstCellInline::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" -> "<<origModName();
|
str<<" -> "<<origModName();
|
||||||
}
|
}
|
||||||
|
void AstDisplay::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
//str<<" "<<displayType().ascii();
|
||||||
|
}
|
||||||
void AstPin::dump(ostream& str) {
|
void AstPin::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
|
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
|
||||||
else { str<<" ->UNLINKED"; }
|
else { str<<" ->UNLINKED"; }
|
||||||
|
if (svImplicit()) str<<" [.SV]";
|
||||||
}
|
}
|
||||||
void AstVarXRef::dump(ostream& str) {
|
void AstVarXRef::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
@@ -325,14 +346,19 @@ void AstVarRef::dump(ostream& str) {
|
|||||||
void AstVar::dump(ostream& str) {
|
void AstVar::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
if (isSc()) str<<" [SC]";
|
if (isSc()) str<<" [SC]";
|
||||||
if (isInput()) str<<" [I]";
|
if (isPrimaryIO()) str<<(isInout()?" [PIO]":(isInput()?" [PI]":" [PO]"));
|
||||||
if (isPrimaryIO()) str<<(isInput()?" [PI]":" [PO]");
|
else {
|
||||||
if (isOutput()) str<<" [O]";
|
if (isInout()) str<<" [IO]";
|
||||||
|
else if (isInput()) str<<" [I]";
|
||||||
|
else if (isOutput()) str<<" [O]";
|
||||||
|
}
|
||||||
if (isUsedClock()) str<<" [C]";
|
if (isUsedClock()) str<<" [C]";
|
||||||
if (isSigPublic()) str<<" [P]";
|
if (isSigPublic()) str<<" [P]";
|
||||||
if (attrClockEn()) str<<" [aCLKEN]";
|
if (attrClockEn()) str<<" [aCLKEN]";
|
||||||
|
if (attrIsolateAssign()) str<<" [aISO]";
|
||||||
if (attrFileDescr()) str<<" [aFD]";
|
if (attrFileDescr()) str<<" [aFD]";
|
||||||
if (isFuncLocal() || isFuncReturn()) str<<" [FUNC]";
|
if (isFuncReturn()) str<<" [FUNCRTN]";
|
||||||
|
else if (isFuncLocal()) str<<" [FUNC]";
|
||||||
str<<" "<<varType();
|
str<<" "<<varType();
|
||||||
}
|
}
|
||||||
void AstSenTree::dump(ostream& str) {
|
void AstSenTree::dump(ostream& str) {
|
||||||
@@ -341,7 +367,11 @@ void AstSenTree::dump(ostream& str) {
|
|||||||
}
|
}
|
||||||
void AstSenItem::dump(ostream& str) {
|
void AstSenItem::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
str<<" ["<<m_edgeType.ascii()<<"]";
|
str<<" ["<<edgeType().ascii()<<"]";
|
||||||
|
}
|
||||||
|
void AstParseRef::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
str<<" ["<<expect().ascii()<<"]";
|
||||||
}
|
}
|
||||||
void AstActive::dump(ostream& str) {
|
void AstActive::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
@@ -358,6 +388,7 @@ void AstNodeFTaskRef::dump(ostream& str) {
|
|||||||
}
|
}
|
||||||
void AstNodeFTask::dump(ostream& str) {
|
void AstNodeFTask::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
|
if (taskPublic()) str<<" [PUBLIC]";
|
||||||
}
|
}
|
||||||
void AstCoverDecl::dump(ostream& str) {
|
void AstCoverDecl::dump(ostream& str) {
|
||||||
this->AstNode::dump(str);
|
this->AstNode::dump(str);
|
||||||
@@ -386,3 +417,7 @@ void AstCCall::dump(ostream& str) {
|
|||||||
funcp()->dump(str);
|
funcp()->dump(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void AstCFunc::dump(ostream& str) {
|
||||||
|
this->AstNode::dump(str);
|
||||||
|
if (slow()) str<<" [SLOW]";
|
||||||
|
}
|
||||||
|
|||||||
+518
-164
File diff suppressed because it is too large
Load Diff
+21
-36
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Removal of named begin blocks
|
// DESCRIPTION: Verilator: Removal of named begin blocks
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Begin's Transformations:
|
// V3Begin's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// Look for BEGINs
|
// Look for BEGINs
|
||||||
// BEGIN(VAR...) -> VAR ... {renamed}
|
// BEGIN(VAR...) -> VAR ... {renamed}
|
||||||
@@ -27,10 +26,12 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -49,25 +50,6 @@ private:
|
|||||||
string m_beginScope; // Name of begin blocks above us
|
string m_beginScope; // Name of begin blocks above us
|
||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
bool nameMatchesGen(const char* namep, string& numr) {
|
|
||||||
numr = "";
|
|
||||||
bool needbar = false;
|
|
||||||
for (const char* cp=namep; *cp; ) {
|
|
||||||
if (0==strncmp(cp,"genblk",6) || 0==strncmp(cp,"genfor",6)) {
|
|
||||||
cp += 6;
|
|
||||||
} else if (isdigit(*cp)) {
|
|
||||||
if (needbar) { numr += '_'; needbar = false; }
|
|
||||||
numr += *cp++;
|
|
||||||
} else if (*cp=='_') {
|
|
||||||
cp++;
|
|
||||||
needbar = true;
|
|
||||||
} else {
|
|
||||||
return false; // Not exact match
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
@@ -84,15 +66,6 @@ private:
|
|||||||
UINFO(8," "<<nodep<<endl);
|
UINFO(8," "<<nodep<<endl);
|
||||||
string oldScope = m_beginScope;
|
string oldScope = m_beginScope;
|
||||||
{
|
{
|
||||||
//string nameNum;
|
|
||||||
//string oldNum;
|
|
||||||
//if (nameMatchesGen(oldScope.c_str(), oldNum/*ref*/)
|
|
||||||
// && nameMatchesGen(nodep->name().c_str(), nameNum/*ref*/)
|
|
||||||
// && 0) { // Messes up V3Link
|
|
||||||
// // Need to leave the dot or we mess up later V3LinkDot
|
|
||||||
// // gen[blk|for]##_gen[blk|for]## -> gen[blk|for]##__DOT__##...
|
|
||||||
// m_beginScope = oldScope + "__DOT__"+nameNum;
|
|
||||||
|
|
||||||
//UINFO(8,"nname "<<m_beginScope<<endl);
|
//UINFO(8,"nname "<<m_beginScope<<endl);
|
||||||
// Create data for dotted variable resolution
|
// Create data for dotted variable resolution
|
||||||
string dottedname = nodep->name() + "__DOT__"; // So always found
|
string dottedname = nodep->name() + "__DOT__"; // So always found
|
||||||
@@ -100,7 +73,7 @@ private:
|
|||||||
while ((pos=dottedname.find("__DOT__")) != string::npos) {
|
while ((pos=dottedname.find("__DOT__")) != string::npos) {
|
||||||
string ident = dottedname.substr(0,pos);
|
string ident = dottedname.substr(0,pos);
|
||||||
dottedname = dottedname.substr(pos+strlen("__DOT__"));
|
dottedname = dottedname.substr(pos+strlen("__DOT__"));
|
||||||
if (m_beginScope=="") m_beginScope = nodep->name();
|
if (m_beginScope=="") m_beginScope = ident;
|
||||||
else m_beginScope = m_beginScope + "__DOT__"+ident;
|
else m_beginScope = m_beginScope + "__DOT__"+ident;
|
||||||
// Create CellInline for dotted resolution
|
// Create CellInline for dotted resolution
|
||||||
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
AstCellInline* inlinep = new AstCellInline(nodep->fileline(),
|
||||||
@@ -158,6 +131,18 @@ private:
|
|||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||||
|
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||||
|
// Similar code in V3Inline
|
||||||
|
if (m_beginScope != "") {
|
||||||
|
// To keep correct visual order, must add before other Text's
|
||||||
|
AstNode* afterp = nodep->scopeAttrp();
|
||||||
|
if (afterp) afterp->unlinkFrBackWithNext();
|
||||||
|
nodep->scopeAttrp(new AstText(nodep->fileline(), (string)"."+AstNode::prettyName(m_beginScope)));
|
||||||
|
if (afterp) nodep->scopeAttrp(afterp);
|
||||||
|
}
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Removal of named begin blocks
|
// DESCRIPTION: Verilator: Removal of named begin blocks
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3BEGIN_H_
|
#ifndef _V3BEGIN_H_
|
||||||
#define _V3BEGIN_H_ 1
|
#define _V3BEGIN_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Branch prediction
|
// DESCRIPTION: Verilator: Branch prediction
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,13 +20,14 @@
|
|||||||
// BRANCH TRANSFORMATIONS:
|
// BRANCH TRANSFORMATIONS:
|
||||||
// At each IF/(IF else).
|
// At each IF/(IF else).
|
||||||
// Count underneath $display/$stop statements.
|
// Count underneath $display/$stop statements.
|
||||||
// If more on if then else, this branch is unlikely, or vice-versa.
|
// If more on if than else, this branch is unlikely, or vice-versa.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Branch prediction
|
// DESCRIPTION: Verilator: Branch prediction
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3BRANCH_H_
|
#ifndef _V3BRANCH_H_
|
||||||
#define _V3BRANCH_H_ 1
|
#define _V3BRANCH_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+112
-24
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Find broken links in tree
|
// DESCRIPTION: Verilator: Find broken links in tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,19 +18,20 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Broken's Transformations:
|
// V3Broken's Transformations:
|
||||||
//
|
//
|
||||||
// Entire netlist
|
// Entire netlist
|
||||||
// Mark all nodes
|
// Mark all nodes
|
||||||
// Check all links point to marked nodes
|
// Check all links point to marked nodes
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <set>
|
#include <map>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Broken.h"
|
#include "V3Broken.h"
|
||||||
@@ -44,19 +44,100 @@ class BrokenTable : public AstNVisitor {
|
|||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
// For each node, we keep if it exists or not.
|
// For each node, we keep if it exists or not.
|
||||||
typedef set<const AstNode*> NodeSet;
|
typedef map<const AstNode*,int> NodeMap;
|
||||||
static NodeSet s_nodes; // Set of all nodes that exist
|
static NodeMap s_nodes; // Set of all nodes that exist
|
||||||
|
// BITMASK
|
||||||
|
static const int FLAG_ALLOCATED = 0x01; // new() and not delete()ed
|
||||||
|
static const int FLAG_IN_TREE = 0x02; // Is in netlist tree
|
||||||
|
static const int FLAG_LINKABLE = 0x04; // Is in netlist tree, can be linked to
|
||||||
|
static const int FLAG_LEAKED = 0x08; // Known to have been leaked
|
||||||
public:
|
public:
|
||||||
// METHODS
|
// METHODS
|
||||||
static void add(const AstNode* nodep) {
|
static void deleted(const AstNode* nodep) {
|
||||||
s_nodes.insert(nodep);
|
// Called by operator delete on any node - only if VL_LEAK_CHECKS
|
||||||
|
if (debug()) cout<<"-nodeDel: "<<(void*)(nodep)<<endl;
|
||||||
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
|
if (iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED)) {
|
||||||
|
((AstNode*)(nodep))->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted\n");
|
||||||
|
}
|
||||||
|
if (iter!=s_nodes.end()) s_nodes.erase(iter);
|
||||||
}
|
}
|
||||||
static bool exists(const AstNode* nodep) {
|
static void addNewed(const AstNode* nodep) {
|
||||||
NodeSet::iterator iter = s_nodes.find(nodep);
|
// Called by operator new on any node - only if VL_LEAK_CHECKS
|
||||||
return (iter != s_nodes.end());
|
if (debug()) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
|
||||||
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
|
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
|
||||||
|
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated\n");
|
||||||
|
}
|
||||||
|
if (iter == s_nodes.end()) {
|
||||||
|
s_nodes.insert(make_pair(nodep,FLAG_ALLOCATED));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static void clear() {
|
static void addInTree(AstNode* nodep, bool linkable) {
|
||||||
|
#ifndef VL_LEAK_CHECKS
|
||||||
|
if (!linkable) return; // save some time, else the map will get huge!
|
||||||
|
#endif
|
||||||
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
|
if (iter == s_nodes.end()) {
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (!(iter->second & FLAG_ALLOCATED)) {
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
nodep->v3fatalSrc("AstNode is in tree, but not allocated\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (iter->second & FLAG_IN_TREE) {
|
||||||
|
nodep->v3fatalSrc("AstNode is already in tree at another location\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int or_flags = FLAG_IN_TREE | (linkable?FLAG_LINKABLE:0);
|
||||||
|
if (iter == s_nodes.end()) {
|
||||||
|
s_nodes.insert(make_pair(nodep,or_flags));
|
||||||
|
} else {
|
||||||
|
iter->second |= or_flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static bool okIfLinkedTo(const AstNode* nodep) {
|
||||||
|
// Someone has a pointer to this node. Is it kosher?
|
||||||
|
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||||
|
if (iter == s_nodes.end()) return false;
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
if (!(iter->second & FLAG_ALLOCATED)) return false;
|
||||||
|
#endif
|
||||||
|
if (!(iter->second & FLAG_IN_TREE)) return false;
|
||||||
|
if (!(iter->second & FLAG_LINKABLE)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static void prepForTree() {
|
||||||
|
#ifndef VL_LEAK_CHECKS
|
||||||
s_nodes.clear();
|
s_nodes.clear();
|
||||||
|
#endif
|
||||||
|
for (NodeMap::iterator it = s_nodes.begin(); it != s_nodes.end(); ++it) {
|
||||||
|
it->second &= ~FLAG_IN_TREE;
|
||||||
|
it->second &= ~FLAG_LINKABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void doneWithTree() {
|
||||||
|
for (int backs=0; backs<2; backs++) { // Those with backp() are probably under one leaking without
|
||||||
|
for (NodeMap::iterator it = s_nodes.begin(); it != s_nodes.end(); ++it) {
|
||||||
|
if ((it->second & FLAG_ALLOCATED)
|
||||||
|
&& !(it->second & FLAG_IN_TREE)
|
||||||
|
&& !(it->second & FLAG_LEAKED)
|
||||||
|
&& (it->first->backp() ? backs==1 : backs==0)) {
|
||||||
|
// Use only AstNode::dump instead of the virtual one, as there
|
||||||
|
// may be varp() and other cross links that are bad.
|
||||||
|
if (debug()) {
|
||||||
|
cout<<"%Error: LeakedNode"<<(it->first->backp()?"Back: ":": ");
|
||||||
|
((AstNode*)(it->first))->AstNode::dump(cout);
|
||||||
|
cout<<endl;
|
||||||
|
V3Error::incErrors();
|
||||||
|
}
|
||||||
|
it->second |= FLAG_LEAKED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
@@ -64,11 +145,11 @@ public:
|
|||||||
virtual ~BrokenTable() {}
|
virtual ~BrokenTable() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
BrokenTable::NodeSet BrokenTable::s_nodes;
|
BrokenTable::NodeMap BrokenTable::s_nodes;
|
||||||
|
|
||||||
bool AstNode::brokeExists() const {
|
bool AstNode::brokeExists() const {
|
||||||
// Called by node->broken() routines to do table lookup
|
// Called by node->broken() routines to do table lookup
|
||||||
return BrokenTable::exists(this);
|
return BrokenTable::okIfLinkedTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -81,13 +162,13 @@ private:
|
|||||||
// // so userp and friends may not be used
|
// // so userp and friends may not be used
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
BrokenTable::add(nodep);
|
BrokenTable::addInTree(nodep, nodep->maybePointedTo());
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
BrokenMarkVisitor(AstNode* nodep) {
|
BrokenMarkVisitor(AstNetlist* nodep) {
|
||||||
nodep->iterateAndNext(*this, NULL);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~BrokenMarkVisitor() {}
|
virtual ~BrokenMarkVisitor() {}
|
||||||
};
|
};
|
||||||
@@ -99,7 +180,7 @@ class BrokenCheckVisitor : public AstNVisitor {
|
|||||||
private:
|
private:
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
if (nodep->broken()) {
|
if (nodep->broken()) {
|
||||||
nodep->v3fatalSrc("Broken link in node\n");
|
nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo)\n");
|
||||||
}
|
}
|
||||||
if (v3Global.assertWidthsSame()) {
|
if (v3Global.assertWidthsSame()) {
|
||||||
if (nodep->width() != nodep->widthMin()) {
|
if (nodep->width() != nodep->widthMin()) {
|
||||||
@@ -124,8 +205,15 @@ public:
|
|||||||
|
|
||||||
void V3Broken::brokenAll(AstNetlist* nodep) {
|
void V3Broken::brokenAll(AstNetlist* nodep) {
|
||||||
//UINFO(9,__FUNCTION__<<": "<<endl);
|
//UINFO(9,__FUNCTION__<<": "<<endl);
|
||||||
BrokenTable::clear();
|
BrokenTable::prepForTree();
|
||||||
BrokenMarkVisitor mvisitor (nodep);
|
BrokenMarkVisitor mvisitor (nodep);
|
||||||
BrokenCheckVisitor cvisitor (nodep);
|
BrokenCheckVisitor cvisitor (nodep);
|
||||||
BrokenTable::clear();
|
BrokenTable::doneWithTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
void V3Broken::addNewed(AstNode* nodep) {
|
||||||
|
BrokenTable::addNewed(nodep);
|
||||||
|
}
|
||||||
|
void V3Broken::deleted(AstNode* nodep) {
|
||||||
|
BrokenTable::deleted(nodep);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Find broken links in tree
|
// DESCRIPTION: Verilator: Find broken links in tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3BROKEN_H_
|
#ifndef _V3BROKEN_H_
|
||||||
#define _V3BROKEN_H_ 1
|
#define _V3BROKEN_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
@@ -30,6 +31,8 @@
|
|||||||
class V3Broken {
|
class V3Broken {
|
||||||
public:
|
public:
|
||||||
static void brokenAll(AstNetlist* nodep);
|
static void brokenAll(AstNetlist* nodep);
|
||||||
|
static void addNewed(AstNode* nodep);
|
||||||
|
static void deleted(AstNode* nodep);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Guard
|
#endif // Guard
|
||||||
|
|||||||
+145
-74
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Case's Transformations:
|
// V3Case's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// TBD: Eliminate tristates by adding __in, __inen, __en wires in parallel
|
// TBD: Eliminate tristates by adding __in, __inen, __en wires in parallel
|
||||||
// Need __en in changed list if a signal is on the LHS of a assign
|
// Need __en in changed list if a signal is on the LHS of a assign
|
||||||
@@ -29,18 +28,19 @@
|
|||||||
// (other items))
|
// (other items))
|
||||||
// body
|
// body
|
||||||
// Or, converts to a if/else tree.
|
// Or, converts to a if/else tree.
|
||||||
// Constants:
|
// FUTURES:
|
||||||
// RHS, Replace 5'bx_1_x with a module global we init to a random value
|
// Large 16+ bit tables with constants and no masking (address muxes)
|
||||||
// CONST(5'bx_1_x) -> VARREF(_{numberedtemp})
|
// Enter all into multimap, sort by value and use a tree of < and == compares.
|
||||||
// -> VAR(_{numberedtemp})
|
// "Diagonal" find of {rightmost,leftmost} bit {set,clear}
|
||||||
// -> INITIAL(VARREF(_{numberedtemp}), OR(5'bx_1_x,AND(random,5'b0_1_x))
|
// Ignoring mask, check each value is unique (using multimap as above?)
|
||||||
// OPTIMIZE: Must not collapse this initial back into the equation.
|
// Each branch is then mask-and-compare operation (IE <000000001_000000000 at midpoint.)
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -49,7 +49,9 @@
|
|||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
#include "V3Stats.h"
|
#include "V3Stats.h"
|
||||||
|
|
||||||
#define CASE_OVERLAP_WIDTH 12 // Maximum width we can check for overlaps in
|
#define CASE_OVERLAP_WIDTH 12 // Maximum width we can check for overlaps in
|
||||||
|
#define CASE_BARF 999999 // Magic width when non-constant
|
||||||
|
#define CASE_ENCODER_GROUP_DEPTH 8 // Levels of priority to be ORed together in top IF tree
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
|
|
||||||
@@ -59,9 +61,6 @@ private:
|
|||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
virtual void visit(AstNodeCase* nodep, AstNUser*) {
|
||||||
// We report a syntax error on empty "case (x) endcase" blocks, so never no items at all
|
|
||||||
if (!nodep->itemsp()) nodep->v3fatalSrc("No items (not even default) under case statement?\n");
|
|
||||||
|
|
||||||
// Detect multiple defaults
|
// Detect multiple defaults
|
||||||
bool hitDefault = false;
|
bool hitDefault = false;
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
@@ -74,7 +73,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for X/Z in non-casex statements
|
// Check for X/Z in non-casex statements
|
||||||
if (!nodep->castCase() || !nodep->castCase()->casex()) {
|
{
|
||||||
m_caseExprp = nodep;
|
m_caseExprp = nodep;
|
||||||
nodep->exprp()->accept(*this);
|
nodep->exprp()->accept(*this);
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
@@ -84,11 +83,18 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
virtual void visit(AstConst* nodep, AstNUser*) {
|
||||||
|
// See also neverItem
|
||||||
if (m_caseExprp && nodep->num().isFourState()) {
|
if (m_caseExprp && nodep->num().isFourState()) {
|
||||||
if (m_caseExprp->castGenCase()) {
|
if (m_caseExprp->castGenCase()) {
|
||||||
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
nodep->v3error("Use of x/? constant in generate case statement, (no such thing as 'generate casez')");
|
||||||
|
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casex()) {
|
||||||
|
// Don't sweat it, we already complained about casex in general
|
||||||
|
} else if (m_caseExprp->castCase() && m_caseExprp->castCase()->casez()) {
|
||||||
|
if (nodep->num().isUnknown()) {
|
||||||
|
nodep->v3warn(CASEWITHX, "Use of x constant in casez statement, (perhaps intended ?/z in constant)");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
nodep->v3error("Use of x/? constant in case statement, (perhaps intended casex/casez)");
|
nodep->v3warn(CASEWITHX, "Use of x/? constant in case statement, (perhaps intended casex/casez)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,22 +132,22 @@ private:
|
|||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
bool checkCaseTree(AstCase* nodep) {
|
bool isCaseTreeFast(AstCase* nodep) {
|
||||||
int width = 0;
|
int width = 0;
|
||||||
m_caseItems = 0;
|
m_caseItems = 0;
|
||||||
m_caseNoOverlapsAllCovered = true;
|
m_caseNoOverlapsAllCovered = true;
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||||
if (icondp->width() > width) width = icondp->width();
|
if (icondp->width() > width) width = icondp->width();
|
||||||
if (!icondp->castConst()) width = 999; // Can't parse; not a constant
|
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
|
||||||
m_caseItems++;
|
m_caseItems++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_caseWidth = width;
|
||||||
if (width==0 || width > CASE_OVERLAP_WIDTH) {
|
if (width==0 || width > CASE_OVERLAP_WIDTH) {
|
||||||
m_caseNoOverlapsAllCovered = false;
|
m_caseNoOverlapsAllCovered = false;
|
||||||
return false; // Too wide for analysis
|
return false; // Too wide for analysis
|
||||||
}
|
}
|
||||||
m_caseWidth = width;
|
|
||||||
UINFO(8,"Simple case statement: "<<nodep<<endl);
|
UINFO(8,"Simple case statement: "<<nodep<<endl);
|
||||||
// Zero list of items for each value
|
// Zero list of items for each value
|
||||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) m_valueItem[i] = NULL;
|
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) m_valueItem[i] = NULL;
|
||||||
@@ -153,26 +159,30 @@ private:
|
|||||||
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
|
//if (debug()>=9) icondp->dumpTree(cout," caseitem: ");
|
||||||
AstConst* iconstp = icondp->castConst();
|
AstConst* iconstp = icondp->castConst();
|
||||||
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
|
if (!iconstp) nodep->v3fatalSrc("above 'can't parse' should have caught this\n");
|
||||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
if (neverItem(nodep, iconstp)) {
|
||||||
nummask.opBitsNonX(iconstp->num());
|
// X in casez can't ever be executed
|
||||||
uint32_t mask = nummask.asInt();
|
} else {
|
||||||
V3Number numval (itemp->fileline(), iconstp->width());
|
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||||
numval.opBitsOne(iconstp->num());
|
nummask.opBitsNonX(iconstp->num());
|
||||||
uint32_t val = numval.asInt();
|
uint32_t mask = nummask.toUInt();
|
||||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
V3Number numval (itemp->fileline(), iconstp->width());
|
||||||
if ((i & mask) == val) {
|
numval.opBitsOne(iconstp->num());
|
||||||
if (!m_valueItem[i]) {
|
uint32_t val = numval.toUInt();
|
||||||
m_valueItem[i] = itemp;
|
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||||
} else if (!itemp->ignoreOverlap() && !bitched) {
|
if ((i & mask) == val) {
|
||||||
itemp->v3warn(CASEOVERLAP,"Case values overlap (example pattern 0x"<<hex<<i<<")");
|
if (!m_valueItem[i]) {
|
||||||
bitched = true;
|
m_valueItem[i] = itemp;
|
||||||
m_caseNoOverlapsAllCovered = false;
|
} else if (!itemp->ignoreOverlap() && !bitched) {
|
||||||
|
itemp->v3warn(CASEOVERLAP,"Case values overlap (example pattern 0x"<<hex<<i<<")");
|
||||||
|
bitched = true;
|
||||||
|
m_caseNoOverlapsAllCovered = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Defaults were moved to last in the caseitem list by V3Link
|
// Defaults were moved to last in the caseitem list by V3Link
|
||||||
if (!itemp->condsp()) { // Case statement's default... Fill the table
|
if (itemp->isDefault()) { // Case statement's default... Fill the table
|
||||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||||
if (!m_valueItem[i]) m_valueItem[i] = itemp;
|
if (!m_valueItem[i]) m_valueItem[i] = itemp;
|
||||||
}
|
}
|
||||||
@@ -207,7 +217,7 @@ private:
|
|||||||
AstNode* tree1p = replaceCaseFastRecurse(cexprp, msb-1, upperValue | (1UL<<msb));
|
AstNode* tree1p = replaceCaseFastRecurse(cexprp, msb-1, upperValue | (1UL<<msb));
|
||||||
|
|
||||||
if (tree0p == tree1p) {
|
if (tree0p == tree1p) {
|
||||||
// Same logic on both sides, so we can just return one of em
|
// Same logic on both sides, so we can just return one of 'em
|
||||||
return tree0p;
|
return tree0p;
|
||||||
}
|
}
|
||||||
// We could have a "checkerboard" with A B A B, we can use the same IF on both edges
|
// We could have a "checkerboard" with A B A B, we can use the same IF on both edges
|
||||||
@@ -218,7 +228,10 @@ private:
|
|||||||
a++, b++) {
|
a++, b++) {
|
||||||
if (m_valueItem[a] != m_valueItem[b]) { same=false; break; }
|
if (m_valueItem[a] != m_valueItem[b]) { same=false; break; }
|
||||||
}
|
}
|
||||||
if (same) return tree0p;
|
if (same) {
|
||||||
|
tree1p->deleteTree(); tree1p=NULL;
|
||||||
|
return tree0p;
|
||||||
|
}
|
||||||
|
|
||||||
// Must have differing logic, so make a selection
|
// Must have differing logic, so make a selection
|
||||||
|
|
||||||
@@ -232,7 +245,7 @@ private:
|
|||||||
// new AstConst(cexprp->fileline(), nummask));
|
// new AstConst(cexprp->fileline(), nummask));
|
||||||
AstNode* and1p = new AstSel(cexprp->fileline(), cexprp->cloneTree(false),
|
AstNode* and1p = new AstSel(cexprp->fileline(), cexprp->cloneTree(false),
|
||||||
msb, 1);
|
msb, 1);
|
||||||
AstNode* eqp = new AstNeq(cexprp->fileline(),
|
AstNode* eqp = new AstNeq(cexprp->fileline(),
|
||||||
new AstConst(cexprp->fileline(), 0),
|
new AstConst(cexprp->fileline(), 0),
|
||||||
and1p);
|
and1p);
|
||||||
AstIf* ifp = new AstIf(cexprp->fileline(), eqp, tree1p, tree0p);
|
AstIf* ifp = new AstIf(cexprp->fileline(), eqp, tree1p, tree0p);
|
||||||
@@ -245,8 +258,7 @@ private:
|
|||||||
// CASEx(cexpr,....
|
// CASEx(cexpr,....
|
||||||
// -> tree of IF(msb, IF(msb-1, 11, 10)
|
// -> tree of IF(msb, IF(msb-1, 11, 10)
|
||||||
// IF(msb-1, 01, 00))
|
// IF(msb-1, 01, 00))
|
||||||
AstNode* cexprp = nodep->exprp();
|
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
|
||||||
cexprp->unlinkFrBack();
|
|
||||||
|
|
||||||
if (debug()>=9) {
|
if (debug()>=9) {
|
||||||
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
for (uint32_t i=0; i<(1UL<<m_caseWidth); i++) {
|
||||||
@@ -264,6 +276,8 @@ private:
|
|||||||
|
|
||||||
if (ifrootp) nodep->replaceWith(ifrootp);
|
if (ifrootp) nodep->replaceWith(ifrootp);
|
||||||
else nodep->unlinkFrBack();
|
else nodep->unlinkFrBack();
|
||||||
|
nodep->deleteTree(); nodep=NULL;
|
||||||
|
cexprp->deleteTree(); cexprp=NULL;
|
||||||
if (debug()>=9) ifrootp->dumpTree(cout," _simp: ");
|
if (debug()>=9) ifrootp->dumpTree(cout," _simp: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,21 +287,15 @@ private:
|
|||||||
// IF((EQ (AND MASK cexpr) (AND MASK icond1)
|
// IF((EQ (AND MASK cexpr) (AND MASK icond1)
|
||||||
// ,istmts2, istmts3
|
// ,istmts2, istmts3
|
||||||
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
|
AstNode* cexprp = nodep->exprp()->unlinkFrBack();
|
||||||
AstNode* ifrootp = NULL;
|
// We'll do this in two stages. First stage, convert the conditions to
|
||||||
AstNode* ifnextp = NULL;
|
// the appropriate IF AND terms.
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout," _comp_IN: ");
|
||||||
|
bool hadDefault = false;
|
||||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
AstNode* istmtsp = itemp->bodysp(); // Maybe null -- no action.
|
|
||||||
if (istmtsp) istmtsp->unlinkFrBackWithNext();
|
|
||||||
if (!itemp->condsp()) {
|
if (!itemp->condsp()) {
|
||||||
// Default clause. We reordered in link, so default is always last
|
// Default clause. Just make true, we'll optimize it away later
|
||||||
if (ifnextp) {
|
itemp->condsp(new AstConst(itemp->fileline(), V3Number(itemp->fileline(), 1,1)));
|
||||||
if (istmtsp) ifnextp->castIf()->addElsesp(istmtsp);
|
hadDefault = true;
|
||||||
} else { // Just a empty case default: endcase
|
|
||||||
ifnextp = istmtsp;
|
|
||||||
}
|
|
||||||
if (!ifrootp) ifrootp = istmtsp;
|
|
||||||
ifnextp = istmtsp;
|
|
||||||
itemp = NULL; break;
|
|
||||||
} else {
|
} else {
|
||||||
// Expressioned clause
|
// Expressioned clause
|
||||||
AstNode* icondNextp = NULL;
|
AstNode* icondNextp = NULL;
|
||||||
@@ -295,21 +303,29 @@ private:
|
|||||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondNextp) {
|
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondNextp) {
|
||||||
icondNextp = icondp->nextp();
|
icondNextp = icondp->nextp();
|
||||||
icondp->unlinkFrBack();
|
icondp->unlinkFrBack();
|
||||||
|
|
||||||
AstNode* and1p;
|
AstNode* and1p;
|
||||||
AstNode* and2p;
|
AstNode* and2p;
|
||||||
AstConst* iconstp = icondp->castConst();
|
AstConst* iconstp = icondp->castConst();
|
||||||
if (iconstp && iconstp->num().isFourState()
|
if (iconstp && neverItem(nodep, iconstp)) {
|
||||||
&& nodep->casex()) {
|
// X in casez can't ever be executed
|
||||||
|
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||||
|
// For simplicity, make expression that is not equal, and let later
|
||||||
|
// optimizations remove it
|
||||||
|
and1p = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,0));
|
||||||
|
and2p = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,1));
|
||||||
|
} else if (iconstp && iconstp->num().isFourState()
|
||||||
|
&& (nodep->casex() || nodep->casez())) {
|
||||||
V3Number nummask (itemp->fileline(), iconstp->width());
|
V3Number nummask (itemp->fileline(), iconstp->width());
|
||||||
nummask.opBitsNonX(iconstp->num());
|
nummask.opBitsNonX(iconstp->num());
|
||||||
V3Number numval (itemp->fileline(), iconstp->width());
|
V3Number numval (itemp->fileline(), iconstp->width());
|
||||||
numval.opBitsOne(iconstp->num());
|
numval.opBitsOne(iconstp->num());
|
||||||
and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
|
and1p = new AstAnd(itemp->fileline(), cexprp->cloneTree(false),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
and2p = new AstAnd(itemp->fileline(),
|
and2p = new AstAnd(itemp->fileline(),
|
||||||
new AstConst(itemp->fileline(), numval),
|
new AstConst(itemp->fileline(), numval),
|
||||||
new AstConst(itemp->fileline(), nummask));
|
new AstConst(itemp->fileline(), nummask));
|
||||||
|
icondp->deleteTree(); icondp=NULL; iconstp=NULL;
|
||||||
} else {
|
} else {
|
||||||
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
|
||||||
and1p = cexprp->cloneTree(false);
|
and1p = cexprp->cloneTree(false);
|
||||||
@@ -322,24 +338,68 @@ private:
|
|||||||
ifexprp = new AstLogOr(itemp->fileline(), ifexprp, condp);
|
ifexprp = new AstLogOr(itemp->fileline(), ifexprp, condp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Replace expression in tree
|
||||||
// Make the new IF and attach in the tree
|
itemp->condsp(ifexprp);
|
||||||
if (ifexprp) {
|
|
||||||
AstIf* newp = new AstIf(itemp->fileline(), ifexprp, istmtsp, NULL);
|
|
||||||
if (ifnextp) {
|
|
||||||
ifnextp->castIf()->addElsesp(newp);
|
|
||||||
}
|
|
||||||
if (!ifrootp) ifrootp = newp;
|
|
||||||
ifnextp = newp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cexprp->deleteTree(); cexprp=NULL;
|
||||||
|
if (!hadDefault) {
|
||||||
|
// If there was no default, add a empty one, this greatly simplifies below code
|
||||||
|
// and constant propagation will just eliminate it for us later.
|
||||||
|
nodep->addItemsp(new AstCaseItem(nodep->fileline(),
|
||||||
|
new AstConst(nodep->fileline(), V3Number(nodep->fileline(),1,1)),
|
||||||
|
NULL));
|
||||||
|
}
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout," _comp_COND: ");
|
||||||
|
// Now build the IF statement tree
|
||||||
|
// The tree can be quite huge. Pull ever group of 8 out, and make a OR tree.
|
||||||
|
// This reduces the depth for the bottom elements, at the cost of some of the top elements.
|
||||||
|
// If we ever have profiling data, we should pull out the most common item from here and
|
||||||
|
// instead make it the first IF branch.
|
||||||
|
int depth = 0;
|
||||||
|
AstNode* grouprootp = NULL;
|
||||||
|
AstIf* groupnextp = NULL;
|
||||||
|
AstIf* itemnextp = NULL;
|
||||||
|
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||||
|
AstNode* istmtsp = itemp->bodysp(); // Maybe null -- no action.
|
||||||
|
if (istmtsp) istmtsp->unlinkFrBackWithNext();
|
||||||
|
// Expressioned clause
|
||||||
|
AstNode* ifexprp = itemp->condsp()->unlinkFrBack();
|
||||||
|
{ // Prepare for next group
|
||||||
|
if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1;
|
||||||
|
if (depth == 1) { // First group or starting new group
|
||||||
|
itemnextp = NULL;
|
||||||
|
AstIf* newp = new AstIf(itemp->fileline(), ifexprp->cloneTree(true), NULL, NULL);
|
||||||
|
if (groupnextp) groupnextp->addElsesp(newp);
|
||||||
|
else grouprootp = newp;
|
||||||
|
groupnextp = newp;
|
||||||
|
} else { // Continue group, modify if condition to OR in this new condition
|
||||||
|
AstNode* condp = groupnextp->condp()->unlinkFrBack();
|
||||||
|
groupnextp->condp(new AstOr(ifexprp->fileline(),
|
||||||
|
condp,
|
||||||
|
ifexprp->cloneTree(true)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // Make the new lower IF and attach in the tree
|
||||||
|
AstNode* itemexprp = ifexprp; ifexprp=NULL;
|
||||||
|
if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition
|
||||||
|
itemexprp->deleteTree(); itemexprp=NULL;
|
||||||
|
itemexprp = new AstConst(itemp->fileline(), V3Number(itemp->fileline(),1,1));
|
||||||
|
}
|
||||||
|
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
|
||||||
|
if (itemnextp) itemnextp->addElsesp(newp);
|
||||||
|
else groupnextp->addIfsp(newp); // First in a new group
|
||||||
|
itemnextp = newp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (debug()>=9) nodep->dumpTree(cout," _comp_TREE: ");
|
||||||
// Handle any assertions
|
// Handle any assertions
|
||||||
replaceCaseParallel(nodep, false);
|
replaceCaseParallel(nodep, false);
|
||||||
// Replace the CASE... with IF...
|
// Replace the CASE... with IF...
|
||||||
if (ifrootp) nodep->replaceWith(ifrootp);
|
if (debug()>=9) grouprootp->dumpTree(cout," _new: ");
|
||||||
|
if (grouprootp) nodep->replaceWith(grouprootp);
|
||||||
else nodep->unlinkFrBack();
|
else nodep->unlinkFrBack();
|
||||||
if (debug()>=9) ifrootp->dumpTree(cout," _new: ");
|
nodep->deleteTree(); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceCaseParallel(AstCase* nodep, bool noOverlapsAllCovered) {
|
void replaceCaseParallel(AstCase* nodep, bool noOverlapsAllCovered) {
|
||||||
@@ -352,12 +412,23 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool neverItem(AstCase* casep, AstConst* itemp) {
|
||||||
|
// Xs in case or casez are impossible due to two state simulations
|
||||||
|
if (casep->casex()) {
|
||||||
|
} else if (casep->casez()) {
|
||||||
|
if (itemp->num().isUnknown()) return true;
|
||||||
|
} else {
|
||||||
|
if (itemp->num().isFourState()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||||
V3Case::caseLint(nodep);
|
V3Case::caseLint(nodep);
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (debug()>=9) nodep->dumpTree(cout," case_old: ");
|
if (debug()>=9) nodep->dumpTree(cout," case_old: ");
|
||||||
if (checkCaseTree(nodep) && v3Global.opt.oCase()) {
|
if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) {
|
||||||
// It's a simple priority encoder or complete statement
|
// It's a simple priority encoder or complete statement
|
||||||
// we can make a tree of statements to avoid extra comparisons
|
// we can make a tree of statements to avoid extra comparisons
|
||||||
m_statCaseFast++;
|
m_statCaseFast++;
|
||||||
@@ -375,13 +446,13 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CaseVisitor(AstNode* nodep) {
|
CaseVisitor(AstNetlist* nodep) {
|
||||||
m_caseNoOverlapsAllCovered = false;
|
m_caseNoOverlapsAllCovered = false;
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~CaseVisitor() {
|
virtual ~CaseVisitor() {
|
||||||
V3Stats::addStat("Optimizations, Cases parallelized", m_statCaseFast);
|
V3Stats::addStat("Optimizations, Cases parallelized", m_statCaseFast);
|
||||||
V3Stats::addStat("Optimizations, Cases priority-encoded", m_statCaseSlow);
|
V3Stats::addStat("Optimizations, Cases complex", m_statCaseSlow);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
// DESCRIPTION: Verilator: Break case statements up and add Unknown assigns
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3CASE_H_
|
#ifndef _V3CASE_H_
|
||||||
#define _V3CASE_H_ 1
|
#define _V3CASE_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+28
-9
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Cast's Transformations:
|
// V3Cast's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// For each math operator, if above operator requires 32 bits,
|
// For each math operator, if above operator requires 32 bits,
|
||||||
// and this isn't, cast to 32 bits.
|
// and this isn't, cast to 32 bits.
|
||||||
@@ -42,9 +41,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -59,6 +59,7 @@ class CastVisitor : public AstNVisitor {
|
|||||||
private:
|
private:
|
||||||
// NODE STATE
|
// NODE STATE
|
||||||
// Entire netlist:
|
// Entire netlist:
|
||||||
|
// AstNode::user() // bool. Indicates node is of known size
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
@@ -75,6 +76,7 @@ private:
|
|||||||
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
||||||
//
|
//
|
||||||
insureLower32Cast(castp);
|
insureLower32Cast(castp);
|
||||||
|
nodep->user(1); // Now must be of known size
|
||||||
}
|
}
|
||||||
int castSize (AstNode* nodep) {
|
int castSize (AstNode* nodep) {
|
||||||
if (nodep->isQuad()) return VL_QUADSIZE;
|
if (nodep->isQuad()) return VL_QUADSIZE;
|
||||||
@@ -83,7 +85,8 @@ private:
|
|||||||
else return VL_WORDSIZE;
|
else return VL_WORDSIZE;
|
||||||
}
|
}
|
||||||
void insureCast(AstNode* nodep) {
|
void insureCast(AstNode* nodep) {
|
||||||
if (castSize(nodep->backp()) != castSize(nodep)) {
|
if (castSize(nodep->backp()) != castSize(nodep)
|
||||||
|
|| !nodep->user()) {
|
||||||
insertCast(nodep, castSize(nodep->backp()));
|
insertCast(nodep, castSize(nodep->backp()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,15 +104,21 @@ private:
|
|||||||
// VISITORS
|
// VISITORS
|
||||||
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
nodep->user(nodep->lhsp()->user());
|
||||||
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
nodep->user(nodep->lhsp()->user()
|
||||||
|
| nodep->rhsp()->user());
|
||||||
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
||||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeTriop* nodep, AstNUser*) {
|
virtual void visit(AstNodeTriop* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
nodep->user(nodep->lhsp()->user()
|
||||||
|
| nodep->rhsp()->user()
|
||||||
|
| nodep->thsp()->user());
|
||||||
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
|
||||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||||
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
||||||
@@ -117,9 +126,11 @@ private:
|
|||||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
virtual void visit(AstCast* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureLower32Cast(nodep);
|
insureLower32Cast(nodep);
|
||||||
|
nodep->user(1);
|
||||||
}
|
}
|
||||||
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
nodep->user(nodep->lhsp()->user());
|
||||||
if (nodep->lhsp()->widthMin()==1) {
|
if (nodep->lhsp()->widthMin()==1) {
|
||||||
// We want to avoid a GCC "converting of negative value" warning
|
// We want to avoid a GCC "converting of negative value" warning
|
||||||
// from our expansion of
|
// from our expansion of
|
||||||
@@ -136,9 +147,16 @@ private:
|
|||||||
&& nodep->backp()->width()
|
&& nodep->backp()->width()
|
||||||
&& castSize(nodep) != castSize(nodep->varp())) {
|
&& castSize(nodep) != castSize(nodep->varp())) {
|
||||||
// Cast vars to IData first, else below has upper bits wrongly set
|
// Cast vars to IData first, else below has upper bits wrongly set
|
||||||
// CData x=3; out = (QData)(x<<30);
|
// CData x=3; out = (QData)(x<<30);
|
||||||
insertCast (nodep, castSize(nodep));
|
insertCast (nodep, castSize(nodep));
|
||||||
}
|
}
|
||||||
|
nodep->user(1);
|
||||||
|
}
|
||||||
|
virtual void visit(AstConst* nodep, AstNUser*) {
|
||||||
|
// Constants are of unknown size if smaller than 33 bits, becase
|
||||||
|
// we're too lazy to wrap every constant in the universe in
|
||||||
|
// ((IData)#).
|
||||||
|
nodep->user(nodep->isQuad() || nodep->isWide());
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOPs
|
// NOPs
|
||||||
@@ -153,6 +171,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
// CONSTUCTORS
|
// CONSTUCTORS
|
||||||
CastVisitor(AstNetlist* nodep) {
|
CastVisitor(AstNetlist* nodep) {
|
||||||
|
AstNode::userClearTree();
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
}
|
}
|
||||||
virtual ~CastVisitor() {}
|
virtual ~CastVisitor() {}
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
// DESCRIPTION: Verilator: Add C++ casts across expression size changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3CAST_H_
|
#ifndef _V3CAST_H_
|
||||||
#define _V3CAST_H_ 1
|
#define _V3CAST_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+8
-7
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for changed nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for changed nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Changed's Transformations:
|
// V3Changed's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// Each combo block
|
// Each combo block
|
||||||
// For each variable that comes from combo block and is generated AFTER a usage
|
// For each variable that comes from combo block and is generated AFTER a usage
|
||||||
@@ -31,9 +30,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -63,6 +63,7 @@ private:
|
|||||||
vscp->v3fatalSrc("Not applicable\n");
|
vscp->v3fatalSrc("Not applicable\n");
|
||||||
#endif
|
#endif
|
||||||
AstVar* varp = vscp->varp();
|
AstVar* varp = vscp->varp();
|
||||||
|
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
||||||
if (varp->arraysp()) {
|
if (varp->arraysp()) {
|
||||||
vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
vscp->v3error("Unsupported: Can't detect changes on arrayed variable (probably with UNOPTFLAT warning suppressed): "<<varp->prettyName());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3CHANGED_H_
|
#ifndef _V3CHANGED_H_
|
||||||
#define _V3CHANGED_H_ 1
|
#define _V3CHANGED_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+16
-12
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for clean nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for clean nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Clean's Transformations:
|
// V3Clean's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// For each math operator, if it requires a clean operand,
|
// For each math operator, if it requires a clean operand,
|
||||||
// and the operand is dirty, insert a CLEAN node.
|
// and the operand is dirty, insert a CLEAN node.
|
||||||
@@ -28,9 +27,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ private:
|
|||||||
|
|
||||||
// ENUMS
|
// ENUMS
|
||||||
enum CleanState { UNKNOWN, CLEAN, DIRTY };
|
enum CleanState { UNKNOWN, CLEAN, DIRTY };
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
// Width resetting
|
// Width resetting
|
||||||
int cppWidth(AstNode* nodep) {
|
int cppWidth(AstNode* nodep) {
|
||||||
@@ -103,11 +103,8 @@ private:
|
|||||||
nodep->unlinkFrBack(&relinkHandle);
|
nodep->unlinkFrBack(&relinkHandle);
|
||||||
//
|
//
|
||||||
computeCppWidth(nodep);
|
computeCppWidth(nodep);
|
||||||
V3Number zero (nodep->fileline(), nodep->widthMin(),0);
|
|
||||||
V3Number masksmall (nodep->fileline(), nodep->widthMin());
|
|
||||||
masksmall.opNot(zero);
|
|
||||||
V3Number mask (nodep->fileline(), cppWidth(nodep));
|
V3Number mask (nodep->fileline(), cppWidth(nodep));
|
||||||
mask.opAssign(masksmall);
|
mask.setMask(nodep->widthMin());
|
||||||
AstNode* cleanp = new AstAnd (nodep->fileline(),
|
AstNode* cleanp = new AstAnd (nodep->fileline(),
|
||||||
new AstConst (nodep->fileline(), mask),
|
new AstConst (nodep->fileline(), mask),
|
||||||
nodep);
|
nodep);
|
||||||
@@ -198,6 +195,9 @@ private:
|
|||||||
virtual void visit(AstText* nodep, AstNUser*) {
|
virtual void visit(AstText* nodep, AstNUser*) {
|
||||||
setClean (nodep, true);
|
setClean (nodep, true);
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||||
|
setClean (nodep, true);
|
||||||
|
}
|
||||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||||
operandTriop(nodep);
|
operandTriop(nodep);
|
||||||
setClean (nodep, nodep->cleanOut());
|
setClean (nodep, nodep->cleanOut());
|
||||||
@@ -239,6 +239,10 @@ private:
|
|||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
insureCleanAndNext (nodep->bodysp());
|
insureCleanAndNext (nodep->bodysp());
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstCCall* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
insureCleanAndNext (nodep->argsp());
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------
|
//--------------------
|
||||||
// Default: Just iterate
|
// Default: Just iterate
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3CLEAN_H_
|
#ifndef _V3CLEAN_H_
|
||||||
#define _V3CLEAN_H_ 1
|
#define _V3CLEAN_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+17
-13
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Clock's Transformations:
|
// V3Clock's Transformations:
|
||||||
//
|
//
|
||||||
// Top Scope:
|
// Top Scope:
|
||||||
// Check created ACTIVEs
|
// Check created ACTIVEs
|
||||||
// Compress adjacent ACTIVEs with same sensitivity list
|
// Compress adjacent ACTIVEs with same sensitivity list
|
||||||
@@ -32,9 +31,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -192,6 +192,7 @@ private:
|
|||||||
funcp->dontCombine(true);
|
funcp->dontCombine(true);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
funcp->isStatic(true);
|
funcp->isStatic(true);
|
||||||
|
funcp->entryPoint(true);
|
||||||
m_scopep->addActivep(funcp);
|
m_scopep->addActivep(funcp);
|
||||||
m_evalFuncp = funcp;
|
m_evalFuncp = funcp;
|
||||||
}
|
}
|
||||||
@@ -202,6 +203,7 @@ private:
|
|||||||
funcp->slow(true);
|
funcp->slow(true);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
funcp->isStatic(true);
|
funcp->isStatic(true);
|
||||||
|
funcp->entryPoint(true);
|
||||||
m_scopep->addActivep(funcp);
|
m_scopep->addActivep(funcp);
|
||||||
m_initFuncp = funcp;
|
m_initFuncp = funcp;
|
||||||
}
|
}
|
||||||
@@ -211,6 +213,7 @@ private:
|
|||||||
funcp->dontCombine(true);
|
funcp->dontCombine(true);
|
||||||
funcp->slow(true);
|
funcp->slow(true);
|
||||||
funcp->isStatic(false);
|
funcp->isStatic(false);
|
||||||
|
funcp->entryPoint(true);
|
||||||
funcp->addInitsp(
|
funcp->addInitsp(
|
||||||
new AstCStmt(nodep->fileline(),
|
new AstCStmt(nodep->fileline(),
|
||||||
" "+EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
|
" "+EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
|
||||||
@@ -225,6 +228,7 @@ private:
|
|||||||
funcp->slow(true);
|
funcp->slow(true);
|
||||||
funcp->isStatic(true);
|
funcp->isStatic(true);
|
||||||
funcp->symProlog(true);
|
funcp->symProlog(true);
|
||||||
|
funcp->entryPoint(true);
|
||||||
m_scopep->addActivep(funcp);
|
m_scopep->addActivep(funcp);
|
||||||
m_settleFuncp = funcp;
|
m_settleFuncp = funcp;
|
||||||
}
|
}
|
||||||
@@ -240,12 +244,12 @@ private:
|
|||||||
//UINFO(4," MOD "<<nodep<<endl);
|
//UINFO(4," MOD "<<nodep<<endl);
|
||||||
m_modp = nodep;
|
m_modp = nodep;
|
||||||
m_stableNum = 0;
|
m_stableNum = 0;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstScope* nodep, AstNUser*) {
|
virtual void visit(AstScope* nodep, AstNUser*) {
|
||||||
//UINFO(4," SCOPE "<<nodep<<endl);
|
//UINFO(4," SCOPE "<<nodep<<endl);
|
||||||
m_scopep = nodep;
|
m_scopep = nodep;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (AstNode* movep = nodep->finalClksp()) {
|
if (AstNode* movep = nodep->finalClksp()) {
|
||||||
if (!m_topScopep) nodep->v3fatalSrc("Final clocks under non-top scope");
|
if (!m_topScopep) nodep->v3fatalSrc("Final clocks under non-top scope");
|
||||||
movep->unlinkFrBackWithNext();
|
movep->unlinkFrBackWithNext();
|
||||||
@@ -360,8 +364,7 @@ private:
|
|||||||
// Move statements to if
|
// Move statements to if
|
||||||
m_lastIfp->addIfsp(stmtsp);
|
m_lastIfp->addIfsp(stmtsp);
|
||||||
} else if (nodep->hasSettle()) {
|
} else if (nodep->hasSettle()) {
|
||||||
// Settlement
|
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
||||||
clearLastSen();
|
|
||||||
// Move statements to function
|
// Move statements to function
|
||||||
addToSettleLoop(stmtsp);
|
addToSettleLoop(stmtsp);
|
||||||
} else {
|
} else {
|
||||||
@@ -412,7 +415,7 @@ private:
|
|||||||
new AstConst(fl, 1)));
|
new AstConst(fl, 1)));
|
||||||
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, countVarp, true),
|
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, countVarp, true),
|
||||||
new AstConst(fl, 0)));
|
new AstConst(fl, 0)));
|
||||||
|
|
||||||
// Add stable variables & preinits
|
// Add stable variables & preinits
|
||||||
AstNode* setChglastp = NULL;
|
AstNode* setChglastp = NULL;
|
||||||
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
|
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
|
||||||
@@ -468,7 +471,8 @@ private:
|
|||||||
ifstmtp->addNext(new AstIf(fl,
|
ifstmtp->addNext(new AstIf(fl,
|
||||||
new AstLt (fl, new AstConst(fl, 100),
|
new AstLt (fl, new AstConst(fl, 100),
|
||||||
new AstVarRef(fl, countVarp, false)),
|
new AstVarRef(fl, countVarp, false)),
|
||||||
(new AstDisplay (fl, '\n', "%%Error: Verilated model didn't converge", NULL, NULL))
|
(new AstDisplay (fl, AstDisplayType::DISPLAY,
|
||||||
|
"%%Error: Verilated model didn't converge", NULL, NULL))
|
||||||
->addNext(new AstStop (fl)),
|
->addNext(new AstStop (fl)),
|
||||||
NULL));
|
NULL));
|
||||||
untilp->addBodysp(new AstIf(fl, new AstNeq(fl, new AstConst(fl, 0),
|
untilp->addBodysp(new AstIf(fl, new AstNeq(fl, new AstConst(fl, 0),
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
// DESCRIPTION: Verilator: Clocking POS/NEGEDGE insertion
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3CLOCK_H_
|
#ifndef _V3CLOCK_H_
|
||||||
#define _V3CLOCK_H_ 1
|
#define _V3CLOCK_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Combine common code into functions
|
// DESCRIPTION: Verilator: Combine common code into functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Combine's Transformations:
|
// V3Combine's Transformations:
|
||||||
//
|
//
|
||||||
// For every function that we spit out
|
// For every function that we spit out
|
||||||
// Examine code to find largest common blocks
|
// Examine code to find largest common blocks
|
||||||
// Hash each node depth first
|
// Hash each node depth first
|
||||||
@@ -32,12 +31,13 @@
|
|||||||
// Make new function
|
// Make new function
|
||||||
// Move common block to function
|
// Move common block to function
|
||||||
// Replace each common block ref with funccall
|
// Replace each common block ref with funccall
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -391,7 +391,7 @@ private:
|
|||||||
m_hashed.clear();
|
m_hashed.clear();
|
||||||
// Compute hash of all statement trees in the function
|
// Compute hash of all statement trees in the function
|
||||||
m_state = STATE_HASH;
|
m_state = STATE_HASH;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_state = STATE_IDLE;
|
m_state = STATE_IDLE;
|
||||||
// Walk the hashes removing empty functions
|
// Walk the hashes removing empty functions
|
||||||
if (emptyFunctionDeletion()) {
|
if (emptyFunctionDeletion()) {
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Combine common code into functions
|
// DESCRIPTION: Verilator: Combine common code into functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3COMBINE_H_
|
#ifndef _V3COMBINE_H_
|
||||||
#define _V3COMBINE_H_ 1
|
#define _V3COMBINE_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+289
-63
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Constant folding
|
// DESCRIPTION: Verilator: Constant folding
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -25,9 +24,10 @@
|
|||||||
// If operands are constant, replace this node with constant.
|
// If operands are constant, replace this node with constant.
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -38,18 +38,70 @@
|
|||||||
#include "V3Width.h"
|
#include "V3Width.h"
|
||||||
#include "V3Signed.h"
|
#include "V3Signed.h"
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// Utilities
|
||||||
|
|
||||||
|
class ConstVarMarkVisitor : public AstNVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// AstVar::userp -> bool, Var marked, 0=not set yet
|
||||||
|
private:
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (nodep->varp()) nodep->varp()->user(1);
|
||||||
|
}
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
ConstVarMarkVisitor(AstNode* nodep) {
|
||||||
|
AstNode::userClearTree();
|
||||||
|
nodep->iterateAndNext(*this, NULL);
|
||||||
|
}
|
||||||
|
virtual ~ConstVarMarkVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ConstVarFindVisitor : public AstNVisitor {
|
||||||
|
// NODE STATE
|
||||||
|
// AstVar::userp -> bool, input from ConstVarMarkVisitor
|
||||||
|
// MEMBERS
|
||||||
|
bool m_found;
|
||||||
|
private:
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
|
if (nodep->varp() && nodep->varp()->user()) m_found = true;
|
||||||
|
}
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
ConstVarFindVisitor(AstNode* nodep) {
|
||||||
|
m_found = false;
|
||||||
|
nodep->iterateAndNext(*this, NULL);
|
||||||
|
}
|
||||||
|
virtual ~ConstVarFindVisitor() {}
|
||||||
|
// METHODS
|
||||||
|
bool found() const { return m_found; }
|
||||||
|
};
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Const state, as a visitor of each AstNode
|
// Const state, as a visitor of each AstNode
|
||||||
|
|
||||||
class ConstVisitor : public AstNVisitor {
|
class ConstVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
|
// NODE STATE
|
||||||
|
// ** only when m_warn is set. If state is needed other times,
|
||||||
|
// ** must track down everywhere V3Const is called and make sure no overlaps.
|
||||||
|
// AstVar::userp -> Used by ConstVarMarkVisitor/ConstVarFindVisitor
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
bool m_params; // If true, propogate parameterized and true numbers only
|
bool m_params; // If true, propogate parameterized and true numbers only
|
||||||
bool m_required; // If true, must become a constant
|
bool m_required; // If true, must become a constant
|
||||||
bool m_wremove; // Inside scope, no assignw removal
|
bool m_wremove; // Inside scope, no assignw removal
|
||||||
bool m_warn; // Output warnings
|
bool m_warn; // Output warnings
|
||||||
bool m_cpp; // C++ conversions only
|
bool m_cpp; // C++ conversions only
|
||||||
AstModule* m_modp; // Current module
|
AstModule* m_modp; // Current module
|
||||||
AstNode* m_scopep; // Current scope
|
AstNode* m_scopep; // Current scope
|
||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
@@ -70,18 +122,28 @@ private:
|
|||||||
if (!rnodep->lhsp()->castConst()) return false;
|
if (!rnodep->lhsp()->castConst()) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool operandAsvSame (AstNode* nodep) {
|
||||||
|
// BIASV(SAMEa, BIASV(SAMEb,...)) -> BIASV( BIASV(SAMEa,SAMEb), ...)
|
||||||
|
AstNodeBiComAsv* bnodep = nodep->castNodeBiComAsv();
|
||||||
|
if (!bnodep) return false;
|
||||||
|
AstNodeBiComAsv* rnodep = bnodep->rhsp()->castNodeBiComAsv();
|
||||||
|
if (!rnodep) return false;
|
||||||
|
if (rnodep->type() != bnodep->type()) return false;
|
||||||
|
if (rnodep->width() != bnodep->width()) return false;
|
||||||
|
return operandsSame(bnodep->lhsp(), rnodep->lhsp());
|
||||||
|
}
|
||||||
bool operandHugeShiftL(AstNodeBiop* nodep) {
|
bool operandHugeShiftL(AstNodeBiop* nodep) {
|
||||||
return (nodep->rhsp()->castConst()
|
return (nodep->rhsp()->castConst()
|
||||||
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->width()));
|
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->width()));
|
||||||
}
|
}
|
||||||
bool operandHugeShiftR(AstNodeBiop* nodep) {
|
bool operandHugeShiftR(AstNodeBiop* nodep) {
|
||||||
return (nodep->rhsp()->castConst()
|
return (nodep->rhsp()->castConst()
|
||||||
&& nodep->rhsp()->castConst()->asInt() >= (uint32_t)(nodep->lhsp()->width()));
|
&& nodep->rhsp()->castConst()->toUInt() >= (uint32_t)(nodep->lhsp()->width()));
|
||||||
}
|
}
|
||||||
bool operandIsTwo(AstNode* nodep) {
|
bool operandIsTwo(AstNode* nodep) {
|
||||||
return (nodep->castConst()
|
return (nodep->castConst()
|
||||||
&& nodep->width() <= VL_QUADSIZE
|
&& nodep->width() <= VL_QUADSIZE
|
||||||
&& nodep->castConst()->asQuad()==2);
|
&& nodep->castConst()->toUQuad()==2);
|
||||||
}
|
}
|
||||||
bool operandIsTwostate(AstNode* nodep) {
|
bool operandIsTwostate(AstNode* nodep) {
|
||||||
return (nodep->castConst()
|
return (nodep->castConst()
|
||||||
@@ -118,7 +180,7 @@ private:
|
|||||||
return (nodep->rhsp()->castConst()
|
return (nodep->rhsp()->castConst()
|
||||||
&& nodep->fromp()->castNodeVarRef()
|
&& nodep->fromp()->castNodeVarRef()
|
||||||
&& !nodep->fromp()->castNodeVarRef()->lvalue()
|
&& !nodep->fromp()->castNodeVarRef()->lvalue()
|
||||||
&& ((int)(nodep->rhsp()->castConst()->asInt())
|
&& ((int)(nodep->rhsp()->castConst()->toUInt())
|
||||||
>= nodep->fromp()->castNodeVarRef()->varp()->widthWords()));
|
>= nodep->fromp()->castNodeVarRef()->varp()->widthWords()));
|
||||||
}
|
}
|
||||||
bool operandSelFull(AstSel* nodep) {
|
bool operandSelFull(AstSel* nodep) {
|
||||||
@@ -153,15 +215,18 @@ private:
|
|||||||
bool warnSelect(AstSel* nodep) {
|
bool warnSelect(AstSel* nodep) {
|
||||||
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
AstNode* basefromp = AstArraySel::baseFromp(nodep->fromp());
|
||||||
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
if (AstNodeVarRef* varrefp = basefromp->castNodeVarRef()) {
|
||||||
|
AstVar* varp = varrefp->varp();
|
||||||
if (m_warn
|
if (m_warn
|
||||||
&& nodep->lsbp()->castConst()
|
&& nodep->lsbp()->castConst()
|
||||||
&& nodep->widthp()->castConst()
|
&& nodep->widthp()->castConst()
|
||||||
&& (!varrefp->varp()->rangep() || varrefp->varp()->msb()) // else it's non-resolvable parameterized
|
&& (!varp->rangep() || varp->msb()) // else it's non-resolvable parameterized
|
||||||
&& ( ( (nodep->msbConst() > varrefp->varp()->msb())
|
&& ( ( (nodep->msbConst() > varp->msbMaxSelect())
|
||||||
|| (nodep->lsbConst() > varrefp->varp()->msb())))) {
|
|| (nodep->lsbConst() > varp->msbMaxSelect())))) {
|
||||||
nodep->v3error("Selection index out of range: "
|
nodep->v3error("Selection index out of range: "
|
||||||
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
<<nodep->msbConst()<<":"<<nodep->lsbConst()
|
||||||
<<" outside "<<varrefp->varp()->msb()<<":0");
|
<<" outside "<<varp->msbMaxSelect()<<":0"
|
||||||
|
<<(varp->lsb()>=0 ? ""
|
||||||
|
:" (adjusted +"+cvtToStr(-varp->lsb())+" to account for negative lsb)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false; // Not a transform, so NOP
|
return false; // Not a transform, so NOP
|
||||||
@@ -170,15 +235,10 @@ private:
|
|||||||
static bool operandsSame(AstNode* node1p, AstNode* node2p) {
|
static bool operandsSame(AstNode* node1p, AstNode* node2p) {
|
||||||
// For now we just detect constants & simple vars, though it could be more generic
|
// For now we just detect constants & simple vars, though it could be more generic
|
||||||
if (node1p->castConst() && node2p->castConst()) {
|
if (node1p->castConst() && node2p->castConst()) {
|
||||||
// Match ignoring any X values
|
return node1p->sameTree(node2p);
|
||||||
V3Number num (node1p->fileline(), 1);
|
|
||||||
num.opCaseEq(node1p->castConst()->num(), node2p->castConst()->num());
|
|
||||||
return num.isNeqZero();
|
|
||||||
}
|
}
|
||||||
else if (node1p->castVarRef() && node2p->castVarRef()
|
else if (node1p->castVarRef() && node2p->castVarRef()) {
|
||||||
&& node1p->sameTree(node2p)) {
|
return node1p->sameTree(node2p);
|
||||||
// Same variable
|
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -239,6 +299,11 @@ private:
|
|||||||
void replaceZero(AstNode* nodep) {
|
void replaceZero(AstNode* nodep) {
|
||||||
replaceNum(nodep, 0); nodep=NULL;
|
replaceNum(nodep, 0); nodep=NULL;
|
||||||
}
|
}
|
||||||
|
void replaceAllOnes (AstNode* nodep) {
|
||||||
|
V3Number ones (nodep->fileline(), nodep->width(), 0);
|
||||||
|
ones.setMask(nodep->width());
|
||||||
|
replaceNum(nodep, ones); nodep=NULL;
|
||||||
|
}
|
||||||
void replaceConst(AstNodeUniop* nodep) {
|
void replaceConst(AstNodeUniop* nodep) {
|
||||||
V3Number num (nodep->fileline(), nodep->width());
|
V3Number num (nodep->fileline(), nodep->width());
|
||||||
nodep->numberOperate(num, nodep->lhsp()->castConst()->num());
|
nodep->numberOperate(num, nodep->lhsp()->castConst()->num());
|
||||||
@@ -283,8 +348,9 @@ private:
|
|||||||
// Keep RHS, remove LHS
|
// Keep RHS, remove LHS
|
||||||
replaceWChild(nodep, nodep->rhsp());
|
replaceWChild(nodep, nodep->rhsp());
|
||||||
}
|
}
|
||||||
void replaceAsvConst (AstNodeBiop* nodep) {
|
void replaceAsv (AstNodeBiop* nodep) {
|
||||||
// BIASV(CONSTa, BIASV(CONSTb, c)) -> BIASV( BIASV_CONSTED(a,b), c)
|
// BIASV(CONSTa, BIASV(CONSTb, c)) -> BIASV( BIASV_CONSTED(a,b), c)
|
||||||
|
// BIASV(SAMEa, BIASV(SAMEb, c)) -> BIASV( BIASV(SAMEa,SAMEb), c)
|
||||||
//nodep->dumpTree(cout, " repAsvConst_old: ");
|
//nodep->dumpTree(cout, " repAsvConst_old: ");
|
||||||
AstNode* ap = nodep->lhsp();
|
AstNode* ap = nodep->lhsp();
|
||||||
AstNodeBiop* rp = nodep->rhsp()->castNodeBiop();
|
AstNodeBiop* rp = nodep->rhsp()->castNodeBiop();
|
||||||
@@ -298,7 +364,7 @@ private:
|
|||||||
nodep->rhsp(cp);
|
nodep->rhsp(cp);
|
||||||
rp->lhsp(ap);
|
rp->lhsp(ap);
|
||||||
rp->rhsp(bp);
|
rp->rhsp(bp);
|
||||||
replaceConst(rp);
|
if (rp->lhsp()->castConst() && rp->rhsp()->castConst()) replaceConst(rp);
|
||||||
//nodep->dumpTree(cout, " repAsvConst_new: ");
|
//nodep->dumpTree(cout, " repAsvConst_new: ");
|
||||||
}
|
}
|
||||||
void replaceExtend (AstNode* nodep, AstNode* arg0p) {
|
void replaceExtend (AstNode* nodep, AstNode* arg0p) {
|
||||||
@@ -369,13 +435,15 @@ private:
|
|||||||
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
nodep->accept(*this); // Further reduce, either node may have more reductions.
|
||||||
} else {
|
} else {
|
||||||
// We know shift amounts are constant, but might be a mixed left/right shift
|
// We know shift amounts are constant, but might be a mixed left/right shift
|
||||||
int shift1 = shift1p->castConst()->asInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
int shift1 = shift1p->castConst()->toUInt(); if (lhsp->castShiftR()) shift1=-shift1;
|
||||||
int shift2 = shift2p->castConst()->asInt(); if (nodep->castShiftR()) shift2=-shift2;
|
int shift2 = shift2p->castConst()->toUInt(); if (nodep->castShiftR()) shift2=-shift2;
|
||||||
int newshift = shift1+shift2;
|
int newshift = shift1+shift2;
|
||||||
|
shift1p->deleteTree(); shift1p=NULL;
|
||||||
|
shift2p->deleteTree(); shift1p=NULL;
|
||||||
AstNode* newp;
|
AstNode* newp;
|
||||||
V3Number mask1 (nodep->fileline(), nodep->width());
|
V3Number mask1 (nodep->fileline(), nodep->width());
|
||||||
V3Number ones (nodep->fileline(), nodep->width());
|
V3Number ones (nodep->fileline(), nodep->width());
|
||||||
ones.opNot(mask1);
|
ones.setMask(nodep->width());
|
||||||
if (shift1<0) {
|
if (shift1<0) {
|
||||||
mask1.opShiftR(ones,V3Number(nodep->fileline(),VL_WORDSIZE,-shift1));
|
mask1.opShiftR(ones,V3Number(nodep->fileline(),VL_WORDSIZE,-shift1));
|
||||||
} else {
|
} else {
|
||||||
@@ -425,11 +493,11 @@ private:
|
|||||||
if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false;
|
if (!varNotReferenced(nodep->rhsp(), varref1p->varp())) return false;
|
||||||
if (!varNotReferenced(nextp->rhsp(), varref2p->varp())) return false;
|
if (!varNotReferenced(nextp->rhsp(), varref2p->varp())) return false;
|
||||||
// Swap?
|
// Swap?
|
||||||
if (( con1p->asInt() != con2p->asInt() + sel2p->width())
|
if (( con1p->toSInt() != con2p->toSInt() + sel2p->width())
|
||||||
&&(con2p->asInt() != con1p->asInt() + sel1p->width())) return false;
|
&&(con2p->toSInt() != con1p->toSInt() + sel1p->width())) return false;
|
||||||
bool lsbFirstAssign = (con1p->asInt() < con2p->asInt());
|
bool lsbFirstAssign = (con1p->toUInt() < con2p->toUInt());
|
||||||
// If the user already has nice 32-bit divisions, keep them to aid later subdivision
|
// If the user already has nice 32-bit divisions, keep them to aid later subdivision
|
||||||
//if (VL_BITBIT_I(con1p->asInt()) == 0) return false;
|
//if (VL_BITBIT_I(con1p->toUInt()) == 0) return false;
|
||||||
UINFO(4,"replaceAssignMultiSel "<<nodep<<endl);
|
UINFO(4,"replaceAssignMultiSel "<<nodep<<endl);
|
||||||
UINFO(4," && "<<nextp<<endl);
|
UINFO(4," && "<<nextp<<endl);
|
||||||
//nodep->dumpTree(cout, "comb1: ");
|
//nodep->dumpTree(cout, "comb1: ");
|
||||||
@@ -452,7 +520,7 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool varNotReferenced(AstNode* nodep, AstVar* varp, bool level=0) {
|
bool varNotReferenced(AstNode* nodep, AstVar* varp, int level=0) {
|
||||||
// Return true if varp never referenced under node.
|
// Return true if varp never referenced under node.
|
||||||
// Return false if referenced, or tree too deep to be worth it
|
// Return false if referenced, or tree too deep to be worth it
|
||||||
if (!nodep) return true;
|
if (!nodep) return true;
|
||||||
@@ -480,10 +548,26 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!m_cpp && nodep->lhsp()->castConcat()) {
|
else if (!m_cpp && nodep->lhsp()->castConcat()) {
|
||||||
UINFO(4," ASSI "<<nodep<<endl);
|
bool need_temp = false;
|
||||||
|
if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS?
|
||||||
|
ConstVarMarkVisitor mark(nodep->lhsp());
|
||||||
|
ConstVarFindVisitor find(nodep->rhsp());
|
||||||
|
if (find.found()) need_temp = true;
|
||||||
|
}
|
||||||
|
if (need_temp) {
|
||||||
|
// The first time we constify, there may be the same variable on the LHS
|
||||||
|
// and RHS. In that case, we must use temporaries, or {a,b}={b,a} will break.
|
||||||
|
UINFO(4," ASSITEMP "<<nodep<<endl);
|
||||||
|
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(temp1,SEL(rhs,{size})),
|
||||||
|
// ASSIGN(temp2,SEL(newrhs,{size}))
|
||||||
|
// ASSIGN(lc1,temp1),
|
||||||
|
// ASSIGN(lc2,temp2)
|
||||||
|
} else {
|
||||||
|
UINFO(4," ASSI "<<nodep<<endl);
|
||||||
|
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(lc1,SEL(rhs,{size})),
|
||||||
|
// ASSIGN(lc2,SEL(newrhs,{size}))
|
||||||
|
}
|
||||||
if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
|
if (debug()>=9) nodep->dumpTree(cout," Ass_old: ");
|
||||||
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(lc1,SEL(rhs,{size})),
|
|
||||||
// ASSIGN(lc2,SEL(newrhs,{size}))
|
|
||||||
// Unlink the stuff
|
// Unlink the stuff
|
||||||
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
|
AstNode* lc1p = nodep->lhsp()->castConcat()->lhsp()->unlinkFrBack();
|
||||||
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
|
AstNode* lc2p = nodep->lhsp()->castConcat()->rhsp()->unlinkFrBack();
|
||||||
@@ -503,16 +587,53 @@ private:
|
|||||||
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
sel2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
// Make new assigns of same flavor as old one
|
// Make new assigns of same flavor as old one
|
||||||
//*** Not cloneTree; just one node.
|
//*** Not cloneTree; just one node.
|
||||||
AstNodeAssign* asn1p=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
|
AstNode* newp = NULL;
|
||||||
AstNodeAssign* asn2p=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
if (!need_temp) {
|
||||||
asn1p->width(msb1-lsb1+1,msb1-lsb1+1);
|
AstNodeAssign* asn1ap=nodep->cloneType(lc1p, sel1p)->castNodeAssign();
|
||||||
asn2p->width(msb2-lsb2+1,msb2-lsb2+1);
|
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
||||||
nodep->addNextHere(asn1p);
|
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
nodep->addNextHere(asn2p);
|
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
if (debug()>=9) asn1p->dumpTree(cout," _new: ");
|
newp = newp->addNext(asn1ap);
|
||||||
if (debug()>=9) asn2p->dumpTree(cout," _new: ");
|
newp = newp->addNext(asn2ap);
|
||||||
|
} else {
|
||||||
|
if (!m_modp) nodep->v3fatalSrc("Not under module");
|
||||||
|
// We could create just one temp variable, but we'll get better optimization
|
||||||
|
// if we make one per term.
|
||||||
|
string name1 = ((string)"__Vconcswap__"+cvtToStr(m_modp->varNumGetInc()));
|
||||||
|
string name2 = ((string)"__Vconcswap__"+cvtToStr(m_modp->varNumGetInc()));
|
||||||
|
AstVar* temp1p = new AstVar(sel1p->fileline(), AstVarType::BLOCKTEMP, name1,
|
||||||
|
new AstRange(sel1p->fileline(), msb1-lsb1, 0));
|
||||||
|
AstVar* temp2p = new AstVar(sel2p->fileline(), AstVarType::BLOCKTEMP, name2,
|
||||||
|
new AstRange(sel2p->fileline(), msb2-lsb2, 0));
|
||||||
|
m_modp->addStmtp(temp1p);
|
||||||
|
m_modp->addStmtp(temp2p);
|
||||||
|
AstNodeAssign* asn1ap=nodep->cloneType
|
||||||
|
(new AstVarRef(sel1p->fileline(), temp1p, true),
|
||||||
|
sel1p)->castNodeAssign();
|
||||||
|
AstNodeAssign* asn2ap=nodep->cloneType
|
||||||
|
(new AstVarRef(sel2p->fileline(), temp2p, true),
|
||||||
|
sel2p)->castNodeAssign();
|
||||||
|
AstNodeAssign* asn1bp=nodep->cloneType
|
||||||
|
(lc1p, new AstVarRef(sel1p->fileline(), temp1p, false))
|
||||||
|
->castNodeAssign();
|
||||||
|
AstNodeAssign* asn2bp=nodep->cloneType
|
||||||
|
(lc2p, new AstVarRef(sel2p->fileline(), temp2p, false))
|
||||||
|
->castNodeAssign();
|
||||||
|
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
|
asn1bp->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||||
|
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
|
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||||
|
// This order matters
|
||||||
|
newp = newp->addNext(asn1ap);
|
||||||
|
newp = newp->addNext(asn2ap);
|
||||||
|
newp = newp->addNext(asn1bp);
|
||||||
|
newp = newp->addNext(asn2bp);
|
||||||
|
}
|
||||||
|
if (debug()>=9) newp->dumpTreeAndNext(cout," _new: ");
|
||||||
|
nodep->addNextHere(newp);
|
||||||
// Cleanup
|
// Cleanup
|
||||||
nodep->unlinkFrBack()->deleteTree();
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
|
conp->deleteTree(); conp=NULL;
|
||||||
// Further reduce, either node may have more reductions.
|
// Further reduce, either node may have more reductions.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -530,7 +651,7 @@ private:
|
|||||||
if (!nodep->castAnd()->rhsp()->castShiftR()) return false;
|
if (!nodep->castAnd()->rhsp()->castShiftR()) return false;
|
||||||
AstShiftR* shiftp = nodep->castAnd()->rhsp()->castShiftR();
|
AstShiftR* shiftp = nodep->castAnd()->rhsp()->castShiftR();
|
||||||
if (!shiftp->rhsp()->castConst()) return false;
|
if (!shiftp->rhsp()->castConst()) return false;
|
||||||
if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->asInt()) return false;
|
if ((uint32_t)(nodep->width()) <= shiftp->rhsp()->castConst()->toUInt()) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void replaceBoolShift(AstNode* nodep) {
|
void replaceBoolShift(AstNode* nodep) {
|
||||||
@@ -625,7 +746,8 @@ private:
|
|||||||
// If bp was a concat, then we have this exact same form again!
|
// If bp was a concat, then we have this exact same form again!
|
||||||
// Recurse rather then calling node->iterate to prevent 2^n recursion!
|
// Recurse rather then calling node->iterate to prevent 2^n recursion!
|
||||||
if (operandConcatMove(abConcp)) moveConcat(abConcp);
|
if (operandConcatMove(abConcp)) moveConcat(abConcp);
|
||||||
} else {
|
bcConcp->deleteTree(); bcConcp=NULL;
|
||||||
|
} else {
|
||||||
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
|
AstConcat* abConcp = nodep->lhsp()->castConcat(); abConcp->unlinkFrBack();
|
||||||
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
|
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
|
||||||
AstNode* bp = abConcp->rhsp()->unlinkFrBack();
|
AstNode* bp = abConcp->rhsp()->unlinkFrBack();
|
||||||
@@ -635,6 +757,7 @@ private:
|
|||||||
nodep->lhsp(ap);
|
nodep->lhsp(ap);
|
||||||
nodep->rhsp(bcConcp);
|
nodep->rhsp(bcConcp);
|
||||||
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
|
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
|
||||||
|
abConcp->deleteTree(); abConcp=NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,7 +787,9 @@ private:
|
|||||||
AstNode* newlsbp;
|
AstNode* newlsbp;
|
||||||
if (lsb1p->castConst() && lsb2p->castConst()) {
|
if (lsb1p->castConst() && lsb2p->castConst()) {
|
||||||
newlsbp = new AstConst(lsb1p->fileline(),
|
newlsbp = new AstConst(lsb1p->fileline(),
|
||||||
lsb1p->castConst()->asInt() + lsb2p->castConst()->asInt());
|
lsb1p->castConst()->toUInt() + lsb2p->castConst()->toUInt());
|
||||||
|
lsb1p->deleteTree(); lsb1p=NULL;
|
||||||
|
lsb2p->deleteTree(); lsb2p=NULL;
|
||||||
} else {
|
} else {
|
||||||
// Width is important, we need the width of the fromp's
|
// Width is important, we need the width of the fromp's
|
||||||
// expression, not the potentially smaller lsb1p's width
|
// expression, not the potentially smaller lsb1p's width
|
||||||
@@ -729,7 +854,7 @@ private:
|
|||||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||||
AstSel* newp = new AstSel(nodep->fileline(),
|
AstSel* newp = new AstSel(nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
new AstConst(lsbp->fileline(), lsbp->asInt() % fromp->width()),
|
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
||||||
widthp);
|
widthp);
|
||||||
newp->widthSignedFrom(nodep);
|
newp->widthSignedFrom(nodep);
|
||||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||||
@@ -744,7 +869,8 @@ private:
|
|||||||
nodep->varp()->initp()->iterateAndNext(*this);
|
nodep->varp()->initp()->iterateAndNext(*this);
|
||||||
if (operandConst(nodep->varp()->initp())
|
if (operandConst(nodep->varp()->initp())
|
||||||
&& !nodep->lvalue()
|
&& !nodep->lvalue()
|
||||||
&& ((v3Global.opt.oConst() && !m_params) // Can reduce constant wires into equations
|
&& ((v3Global.opt.oConst() && !m_params // Can reduce constant wires into equations
|
||||||
|
&& !nodep->varp()->isSigPublic())
|
||||||
|| nodep->varp()->isParam())) {
|
|| nodep->varp()->isParam())) {
|
||||||
AstConst* constp = nodep->varp()->initp()->castConst();
|
AstConst* constp = nodep->varp()->initp()->castConst();
|
||||||
const V3Number& num = constp->num();
|
const V3Number& num = constp->num();
|
||||||
@@ -789,7 +915,12 @@ private:
|
|||||||
if (nodep->sensp()->castConst()
|
if (nodep->sensp()->castConst()
|
||||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
|
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
|
||||||
// Constants in sensitivity lists may be removed (we'll simplify later)
|
// Constants in sensitivity lists may be removed (we'll simplify later)
|
||||||
AstSenItem* newp = new AstSenItem(nodep->fileline(), AstSenItem::Never());
|
AstSenItem* newp;
|
||||||
|
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||||
|
newp = new AstSenItem(nodep->fileline(), AstSenItem::Never());
|
||||||
|
} else { // Otherwise it may compute a result that needs to settle out
|
||||||
|
newp = new AstSenItem(nodep->fileline(), AstSenItem::Combo());
|
||||||
|
}
|
||||||
nodep->replaceWith(newp);
|
nodep->replaceWith(newp);
|
||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); nodep=NULL;
|
||||||
} else if (nodep->sensp()->castNot()) {
|
} else if (nodep->sensp()->castNot()) {
|
||||||
@@ -803,7 +934,7 @@ private:
|
|||||||
}
|
}
|
||||||
UINFO(8,"senItem(NOT...) "<<nodep<<" "<<invert<<endl);
|
UINFO(8,"senItem(NOT...) "<<nodep<<" "<<invert<<endl);
|
||||||
if (invert) nodep->edgeType( nodep->edgeType().invert() );
|
if (invert) nodep->edgeType( nodep->edgeType().invert() );
|
||||||
AstVarRef* senvarp = lastSensp->unlinkFrBack()->castVarRef();
|
AstNodeVarRef* senvarp = lastSensp->unlinkFrBack()->castNodeVarRef();
|
||||||
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
|
if (!senvarp) sensp->v3fatalSrc("Non-varref sensitivity variable");
|
||||||
sensp->replaceWith(senvarp);
|
sensp->replaceWith(senvarp);
|
||||||
sensp->deleteTree(); sensp=NULL;
|
sensp->deleteTree(); sensp=NULL;
|
||||||
@@ -842,7 +973,7 @@ private:
|
|||||||
new AstAssign(nodep->fileline(),
|
new AstAssign(nodep->fileline(),
|
||||||
varrefp, exprp));
|
varrefp, exprp));
|
||||||
m_modp->addStmtp(newinitp);
|
m_modp->addStmtp(newinitp);
|
||||||
nodep->unlinkFrBack(); nodep=NULL;
|
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||||
// Set the initial value right in the variable so we can constant propagate
|
// Set the initial value right in the variable so we can constant propagate
|
||||||
AstNode* initvaluep = exprp->cloneTree(false);
|
AstNode* initvaluep = exprp->cloneTree(false);
|
||||||
varrefp->varp()->initp(initvaluep);
|
varrefp->varp()->initp(initvaluep);
|
||||||
@@ -888,7 +1019,7 @@ private:
|
|||||||
&& nodep->ifsp() && nodep->elsesp()) {
|
&& nodep->ifsp() && nodep->elsesp()) {
|
||||||
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
|
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
|
||||||
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
|
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
|
||||||
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
||||||
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
||||||
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||||
ifp->branchPred(nodep->branchPred().invert());
|
ifp->branchPred(nodep->branchPred().invert());
|
||||||
@@ -909,7 +1040,7 @@ private:
|
|||||||
nodep->deleteTree(); nodep=NULL;
|
nodep->deleteTree(); nodep=NULL;
|
||||||
}
|
}
|
||||||
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
||||||
&& operandIfIf(nodep)) {
|
&& operandIfIf(nodep)) {
|
||||||
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
||||||
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
||||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||||
@@ -925,6 +1056,63 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||||
|
// Substitute constants into displays. The main point of this is to
|
||||||
|
// simplify assertion methodologies which call functions with display's.
|
||||||
|
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
bool anyconst = false;
|
||||||
|
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
|
||||||
|
if (argp->castConst()) { anyconst=true; break; }
|
||||||
|
}
|
||||||
|
if (anyconst) {
|
||||||
|
//UINFO(9," Display in "<<nodep->text()<<endl);
|
||||||
|
string dispout = "";
|
||||||
|
string fmt = "";
|
||||||
|
bool inPct = false;
|
||||||
|
AstNode* argp = nodep->exprsp();
|
||||||
|
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
|
||||||
|
char ch = *inp; // Breaks with iterators...
|
||||||
|
if (!inPct && ch=='%') {
|
||||||
|
inPct = true;
|
||||||
|
fmt = ch;
|
||||||
|
} else if (inPct && isdigit(ch)) {
|
||||||
|
fmt += ch;
|
||||||
|
} else if (inPct) {
|
||||||
|
inPct = false;
|
||||||
|
fmt += ch;
|
||||||
|
switch (tolower(ch)) {
|
||||||
|
case '%': break; // %% - just output a %
|
||||||
|
case 'm': break; // %m - auto insert "name"
|
||||||
|
default: // Most operators, just move to next argument
|
||||||
|
if (argp) {
|
||||||
|
AstNode* nextp=argp->nextp();
|
||||||
|
if (argp && argp->castConst()) { // Convert it
|
||||||
|
string out = argp->castConst()->num().displayed(fmt);
|
||||||
|
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
|
||||||
|
{ // fmt = out w/ replace % with %% as it must be literal.
|
||||||
|
fmt = "";
|
||||||
|
for (string::iterator pos = out.begin(); pos != out.end(); pos++) {
|
||||||
|
if (*pos == '%') fmt += '%';
|
||||||
|
fmt += *pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argp->unlinkFrBack()->deleteTree();
|
||||||
|
}
|
||||||
|
argp=nextp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
dispout += fmt;
|
||||||
|
} else {
|
||||||
|
dispout += ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodep->text(dispout);
|
||||||
|
//UINFO(9," Display out "<<nodep->text()<<endl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
if (nodep->condp()->isZero()) {
|
if (nodep->condp()->isZero()) {
|
||||||
@@ -941,10 +1129,11 @@ private:
|
|||||||
// Below lines are magic expressions processed by astgen
|
// Below lines are magic expressions processed by astgen
|
||||||
// "AstNODETYPE { # bracket not paren
|
// "AstNODETYPE { # bracket not paren
|
||||||
// $accessor_name, ...
|
// $accessor_name, ...
|
||||||
// # ,, gets replaced with a , rather then &&
|
// # ,, gets replaced with a , rather than &&
|
||||||
// }" # bracket not paren
|
// }" # bracket not paren
|
||||||
// ,"function to call"
|
// ,"function to call"
|
||||||
// or ,"AstREPLACEMENT_TYPE{ $accessor }"
|
// or ,"AstREPLACEMENT_TYPE{ $accessor }"
|
||||||
|
// or ,"! # Print line number when matches, so can see operations
|
||||||
|
|
||||||
// Lint Checks
|
// Lint Checks
|
||||||
// v--- *1* These ops are always first, as we warn before replacing
|
// v--- *1* These ops are always first, as we warn before replacing
|
||||||
@@ -969,6 +1158,7 @@ private:
|
|||||||
TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||||
TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||||
TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||||
|
TREEOP("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
|
||||||
TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
|
TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
|
||||||
TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||||
TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||||
@@ -982,6 +1172,7 @@ private:
|
|||||||
TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||||
TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||||
TREEOP("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
TREEOP("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||||
|
TREEOP("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}");
|
||||||
// Non-zero on one side or the other
|
// Non-zero on one side or the other
|
||||||
TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||||
TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
|
TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
|
||||||
@@ -992,6 +1183,7 @@ private:
|
|||||||
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
||||||
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
||||||
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
||||||
|
TREEOP("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||||
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||||
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||||
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||||
@@ -1012,8 +1204,9 @@ private:
|
|||||||
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b
|
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&b
|
||||||
TREEOP("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
|
TREEOP("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
|
||||||
// Prefer constants on left, since that often needs a shift, it lets constant red remove the shift
|
// Prefer constants on left, since that often needs a shift, it lets constant red remove the shift
|
||||||
TREEOP("AstNodeBiCom{$lhsp, $rhsp.castConst}", "swapSides(nodep)");
|
TREEOP("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
||||||
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsvConst(nodep)");
|
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
|
||||||
|
TREEOP("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
||||||
// v--- *1* as These ops are always first, as we warn before replacing
|
// v--- *1* as These ops are always first, as we warn before replacing
|
||||||
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
|
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
|
||||||
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
|
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
|
||||||
@@ -1030,6 +1223,10 @@ private:
|
|||||||
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOP ("AstLogNot{$lhsp.castEqCase}", "AstNeqCase{$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOPV("AstNot {$lhsp.castNeqCase, $lhsp.width1}","AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOP ("AstLogNot{$lhsp.castNeqCase}", "AstEqCase {$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
|
TREEOPV("AstNot {$lhsp.castEqWild, $lhsp.width1}","AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
|
TREEOP ("AstLogNot{$lhsp.castEqWild}", "AstNeqWild{$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
|
TREEOPV("AstNot {$lhsp.castNeqWild, $lhsp.width1}","AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
|
TREEOP ("AstLogNot{$lhsp.castNeqWild}", "AstEqWild {$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOPV("AstNot {$lhsp.castEq, $lhsp.width1}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOP ("AstLogNot{$lhsp.castEq}", "AstNeq {$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}");
|
TREEOPV("AstNot {$lhsp.castNeq, $lhsp.width1}", "AstEq {$lhsp->op1p(),$lhsp->op2p()}");
|
||||||
@@ -1058,6 +1255,33 @@ private:
|
|||||||
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||||
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||||
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
|
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
|
||||||
|
// Identical operands on both sides
|
||||||
|
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
|
||||||
|
// AstAdd->ShiftL(#,1) but uncommon
|
||||||
|
TREEOP("AstAnd {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
|
||||||
|
TREEOP("AstChangeXor{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstDiv {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||||
|
TREEOP("AstDivS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||||
|
TREEOP("AstOr {operandsSame($lhsp,,$rhsp)}", "replaceWLhs(nodep)");
|
||||||
|
TREEOP("AstSub {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
|
||||||
|
TREEOP("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||||
|
TREEOP("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||||
|
TREEOP("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||||
|
TREEOP("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||||
|
TREEOP("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||||
|
TREEOP("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||||
|
TREEOP("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||||
|
TREEOP("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||||
|
TREEOP("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||||
|
TREEOP("AstLogOr {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||||
///=== Verilog operators
|
///=== Verilog operators
|
||||||
// Comparison against 1'b0/1'b1; must be careful about widths.
|
// Comparison against 1'b0/1'b1; must be careful about widths.
|
||||||
// These use Not, so must be Verilog only
|
// These use Not, so must be Verilog only
|
||||||
@@ -1075,7 +1299,6 @@ private:
|
|||||||
TREEOPV("AstLte {$lhsp->width()==$rhsp->width(), $rhsp.isAllOnes}", "replaceNum(nodep,1)");
|
TREEOPV("AstLte {$lhsp->width()==$rhsp->width(), $rhsp.isAllOnes}", "replaceNum(nodep,1)");
|
||||||
// Simplify reduction operators
|
// Simplify reduction operators
|
||||||
// This also gets &{...,0,....} => const 0 (Common for unused_ok signals)
|
// This also gets &{...,0,....} => const 0 (Common for unused_ok signals)
|
||||||
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
|
|
||||||
TREEOPV("AstRedAnd{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
|
TREEOPV("AstRedAnd{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
|
||||||
TREEOPV("AstRedOr {$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
|
TREEOPV("AstRedOr {$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
|
||||||
TREEOPV("AstRedXor{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
|
TREEOPV("AstRedXor{$lhsp, $lhsp.width1}", "replaceWLhs(nodep)");
|
||||||
@@ -1087,7 +1310,7 @@ private:
|
|||||||
TREEOPV("AstRedXor{$lhsp->castExtend()}", "AstRedXor{$lhsp->castExtend()->lhsp()}");
|
TREEOPV("AstRedXor{$lhsp->castExtend()}", "AstRedXor{$lhsp->castExtend()->lhsp()}");
|
||||||
TREEOPV("AstOneHot{$lhsp.width1}", "replaceWLhs(nodep)");
|
TREEOPV("AstOneHot{$lhsp.width1}", "replaceWLhs(nodep)");
|
||||||
TREEOPV("AstOneHot0{$lhsp.width1}", "replaceNum(nodep,1)");
|
TREEOPV("AstOneHot0{$lhsp.width1}", "replaceNum(nodep,1)");
|
||||||
// Binary AND/OR is faster then logical and/or (usually)
|
// Binary AND/OR is faster than logical and/or (usually)
|
||||||
TREEOPV("AstLogAnd{$lhsp.width1, $rhsp.width1}", "AstAnd{$lhsp,$rhsp}");
|
TREEOPV("AstLogAnd{$lhsp.width1, $rhsp.width1}", "AstAnd{$lhsp,$rhsp}");
|
||||||
TREEOPV("AstLogOr {$lhsp.width1, $rhsp.width1}", "AstOr{$lhsp,$rhsp}");
|
TREEOPV("AstLogOr {$lhsp.width1, $rhsp.width1}", "AstOr{$lhsp,$rhsp}");
|
||||||
TREEOPV("AstLogNot{$lhsp.width1}", "AstNot{$lhsp}");
|
TREEOPV("AstLogNot{$lhsp.width1}", "AstNot{$lhsp}");
|
||||||
@@ -1108,6 +1331,7 @@ private:
|
|||||||
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
|
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
|
||||||
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
|
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
|
||||||
// Conversions
|
// Conversions
|
||||||
|
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
|
||||||
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
||||||
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
|
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
|
||||||
|
|
||||||
@@ -1171,12 +1395,14 @@ void V3Const::constifyAll(AstNetlist* nodep) {
|
|||||||
visitor.main(nodep);
|
visitor.main(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Const::constifyAllLint(AstNode* nodep) {
|
void V3Const::constifyAllLint(AstNetlist* nodep) {
|
||||||
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
ConstVisitor visitor (false,false,true,false);
|
ConstVisitor visitor (false,false,true,false);
|
||||||
visitor.main(nodep);
|
visitor.main(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Const::constifyCpp(AstNode* nodep) {
|
void V3Const::constifyCpp(AstNetlist* nodep) {
|
||||||
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
ConstVisitor visitor (false,false,false,true);
|
ConstVisitor visitor (false,false,false,true);
|
||||||
visitor.main(nodep);
|
visitor.main(nodep);
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Propagate constants across AST
|
// DESCRIPTION: Verilator: Propagate constants across AST
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3CONST_H_
|
#ifndef _V3CONST_H_
|
||||||
#define _V3CONST_H_ 1
|
#define _V3CONST_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
@@ -34,9 +35,9 @@ public:
|
|||||||
// Everything that's possible
|
// Everything that's possible
|
||||||
static void constifyAll(AstNetlist* nodep);
|
static void constifyAll(AstNetlist* nodep);
|
||||||
// Also, warn
|
// Also, warn
|
||||||
static void constifyAllLint(AstNode* nodep);
|
static void constifyAllLint(AstNetlist* nodep);
|
||||||
// C++ datatypes
|
// C++ datatypes
|
||||||
static void constifyCpp(AstNode* nodep);
|
static void constifyCpp(AstNetlist* nodep);
|
||||||
// Only the current node and lower
|
// Only the current node and lower
|
||||||
static void constifyTree(AstNode* nodep);
|
static void constifyTree(AstNode* nodep);
|
||||||
};
|
};
|
||||||
|
|||||||
+8
-8
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Netlist (top level) functions
|
// DESCRIPTION: Verilator: Netlist (top level) functions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -29,9 +28,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ private:
|
|||||||
bool m_checkBlock; // Should this block get covered?
|
bool m_checkBlock; // Should this block get covered?
|
||||||
AstModule* m_modp; // Current module to add statement to
|
AstModule* m_modp; // Current module to add statement to
|
||||||
FileMap m_fileps; // Column counts for each fileline
|
FileMap m_fileps; // Column counts for each fileline
|
||||||
|
|
||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -65,7 +65,7 @@ private:
|
|||||||
column = (it->second)++;
|
column = (it->second)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstCoverDecl* declp = new AstCoverDecl(fl, column, type, comment);
|
AstCoverDecl* declp = new AstCoverDecl(fl, column, type, comment);
|
||||||
m_modp->addStmtp(declp);
|
m_modp->addStmtp(declp);
|
||||||
|
|
||||||
return new AstCoverInc(fl, declp);
|
return new AstCoverInc(fl, declp);
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Coverage modules/signals together
|
// DESCRIPTION: Verilator: Coverage modules/signals together
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3COVERAGE_H_
|
#ifndef _V3COVERAGE_H_
|
||||||
#define _V3COVERAGE_H_ 1
|
#define _V3COVERAGE_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+44
-10
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Dead code elimination
|
// DESCRIPTION: Verilator: Dead code elimination
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,14 +20,16 @@
|
|||||||
// DEAD TRANSFORMATIONS:
|
// DEAD TRANSFORMATIONS:
|
||||||
// Remove any unreferenced modules
|
// Remove any unreferenced modules
|
||||||
// Remove any unreferenced variables
|
// Remove any unreferenced variables
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Dead.h"
|
#include "V3Dead.h"
|
||||||
@@ -70,10 +71,15 @@ private:
|
|||||||
// AstVar::user() -> int. Count of number of references
|
// AstVar::user() -> int. Count of number of references
|
||||||
// AstVarScope::user() -> int. Count of number of references
|
// AstVarScope::user() -> int. Count of number of references
|
||||||
|
|
||||||
|
// TYPES
|
||||||
|
typedef multimap<AstVarScope*,AstNodeAssign*> AssignMap;
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
|
vector<AstVar*> m_varsp; // List of all encountered to avoid another loop through tree
|
||||||
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
|
vector<AstVarScope*> m_vscsp; // List of all encountered to avoid another loop through tree
|
||||||
|
AssignMap m_assignMap; // List of all simple assignments for each variable
|
||||||
bool m_elimUserVars; // Allow removal of user's vars
|
bool m_elimUserVars; // Allow removal of user's vars
|
||||||
|
bool m_sideEffect; // Side effects discovered in assign RHS
|
||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
@@ -102,6 +108,25 @@ private:
|
|||||||
m_varsp.push_back(nodep);
|
m_varsp.push_back(nodep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||||
|
// See if simple assignments to variables may be eliminated because that variable is never used.
|
||||||
|
// Similar code in V3Life
|
||||||
|
m_sideEffect = false;
|
||||||
|
nodep->rhsp()->iterateAndNext(*this);
|
||||||
|
// Has to be direct assignment without any EXTRACTing.
|
||||||
|
AstVarRef* varrefp = nodep->lhsp()->castVarRef();
|
||||||
|
if (varrefp && !m_sideEffect
|
||||||
|
&& varrefp->varScopep()) { // For simplicity, we only remove post-scoping
|
||||||
|
m_assignMap.insert(make_pair(varrefp->varScopep(), nodep));
|
||||||
|
} else { // Track like any other statement
|
||||||
|
nodep->lhsp()->iterateAndNext(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void visit(AstUCFunc* nodep, AstNUser*) {
|
||||||
|
m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
|
||||||
//-----
|
//-----
|
||||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
@@ -131,14 +156,22 @@ private:
|
|||||||
}
|
}
|
||||||
bool canElim(AstVar* nodep) {
|
bool canElim(AstVar* nodep) {
|
||||||
return (!nodep->isSigPublic() // Can't elim publics!
|
return (!nodep->isSigPublic() // Can't elim publics!
|
||||||
|
&& !nodep->isIO()
|
||||||
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars));
|
&& (nodep->isTemp() || nodep->isParam() || m_elimUserVars));
|
||||||
}
|
}
|
||||||
void deadCheckVar() {
|
void deadCheckVar() {
|
||||||
// Delete any unused varscopes
|
// Delete any unused varscopes
|
||||||
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
for (vector<AstVarScope*>::iterator it = m_vscsp.begin(); it!=m_vscsp.end(); ++it) {
|
||||||
if ((*it)->user() == 0 && canElim((*it)->varp())) {
|
AstVarScope* vscp = *it;
|
||||||
UINFO(4," Dead "<<(*it)<<endl);
|
if (vscp->user() == 0 && canElim(vscp->varp())) {
|
||||||
(*it)->unlinkFrBack()->deleteTree(); (*it)=NULL;
|
UINFO(4," Dead "<<vscp<<endl);
|
||||||
|
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
||||||
|
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||||
|
AstNodeAssign* assp = it->second;
|
||||||
|
UINFO(4," Dead assign "<<assp<<endl);
|
||||||
|
assp->unlinkFrBack()->deleteTree(); assp=NULL;
|
||||||
|
}
|
||||||
|
vscp->unlinkFrBack()->deleteTree(); vscp=NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) {
|
for (vector<AstVar*>::iterator it = m_varsp.begin(); it!=m_varsp.end(); ++it) {
|
||||||
@@ -153,6 +186,7 @@ public:
|
|||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars) {
|
DeadVisitor(AstNetlist* nodep, bool elimUserVars) {
|
||||||
m_elimUserVars = elimUserVars;
|
m_elimUserVars = elimUserVars;
|
||||||
|
m_sideEffect = false;
|
||||||
// Operate on whole netlist
|
// Operate on whole netlist
|
||||||
AstNode::userClearTree(); // userp() used on entire tree
|
AstNode::userClearTree(); // userp() used on entire tree
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Dead branch elimination
|
// DESCRIPTION: Verilator: Dead branch elimination
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3DEAD_H_
|
#ifndef _V3DEAD_H_
|
||||||
#define _V3DEAD_H_ 1
|
#define _V3DEAD_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+24
-25
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for delayed nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for delayed nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,9 +18,9 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Delayed's Transformations:
|
// V3Delayed's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// Replace ASSIGNDLY var, exp
|
// Replace ASSIGNDLY var, exp
|
||||||
// With ASSIGNDLY newvar, exp
|
// With ASSIGNDLY newvar, exp
|
||||||
// At top of block: VAR newvar
|
// At top of block: VAR newvar
|
||||||
// At bottom of block: ASSIGNW var newvar
|
// At bottom of block: ASSIGNW var newvar
|
||||||
@@ -52,9 +51,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -109,18 +109,6 @@ private:
|
|||||||
}
|
}
|
||||||
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/) {
|
AstVarScope* createVarSc(AstVarScope* oldvarscp, string name, int width/*0==fromoldvar*/) {
|
||||||
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
|
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
|
||||||
AstRange* rangep = NULL;
|
|
||||||
if (width==0) {
|
|
||||||
rangep = new AstRange(oldvarscp->fileline(),
|
|
||||||
oldvarscp->varp()->msb(),
|
|
||||||
oldvarscp->varp()->lsb());
|
|
||||||
} else if (width==1) {
|
|
||||||
rangep = NULL;
|
|
||||||
} else {
|
|
||||||
rangep = new AstRange(oldvarscp->fileline(),
|
|
||||||
width-1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped");
|
if (!oldvarscp->scopep()) oldvarscp->v3fatalSrc("Var unscoped");
|
||||||
AstVar* varp;
|
AstVar* varp;
|
||||||
AstModule* addmodp = oldvarscp->scopep()->modp();
|
AstModule* addmodp = oldvarscp->scopep()->modp();
|
||||||
@@ -130,6 +118,17 @@ private:
|
|||||||
// Created module's AstVar earlier under some other scope
|
// Created module's AstVar earlier under some other scope
|
||||||
varp = iter->second;
|
varp = iter->second;
|
||||||
} else {
|
} else {
|
||||||
|
AstRange* rangep = NULL;
|
||||||
|
if (width==0) {
|
||||||
|
rangep = new AstRange(oldvarscp->fileline(),
|
||||||
|
oldvarscp->varp()->msb(),
|
||||||
|
oldvarscp->varp()->lsb());
|
||||||
|
} else if (width==1) {
|
||||||
|
rangep = NULL;
|
||||||
|
} else {
|
||||||
|
rangep = new AstRange(oldvarscp->fileline(),
|
||||||
|
width-1, 0);
|
||||||
|
}
|
||||||
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, rangep);
|
varp = new AstVar (oldvarscp->fileline(), AstVarType::BLOCKTEMP, name, rangep);
|
||||||
if (width==0) varp->widthSignedFrom(oldvarscp);
|
if (width==0) varp->widthSignedFrom(oldvarscp);
|
||||||
addmodp->addStmtp(varp);
|
addmodp->addStmtp(varp);
|
||||||
@@ -225,7 +224,7 @@ private:
|
|||||||
|
|
||||||
if (nodep->user5p()) {
|
if (nodep->user5p()) {
|
||||||
// Simplistic optimization. If the previous statement in same scope was also a =>,
|
// Simplistic optimization. If the previous statement in same scope was also a =>,
|
||||||
// then we told this nodep->user5 we can use its Vdlyvset rather then making a new one.
|
// then we told this nodep->user5 we can use its Vdlyvset rather than making a new one.
|
||||||
// This is good for code like:
|
// This is good for code like:
|
||||||
// for (i=0; i<5; i++) vector[i] <= something;
|
// for (i=0; i<5; i++) vector[i] <= something;
|
||||||
sharedVset = true;
|
sharedVset = true;
|
||||||
@@ -269,7 +268,7 @@ private:
|
|||||||
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
|
AstAlwaysPost* finalp = varrefp->varScopep()->user4p()->castNode()->castAlwaysPost();
|
||||||
if (!finalp) {
|
if (!finalp) {
|
||||||
finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/);
|
finalp = new AstAlwaysPost(nodep->fileline(), NULL/*sens*/, NULL/*body*/);
|
||||||
UINFO(9," Created "<<finalp<<endl);
|
UINFO(9," Created "<<finalp<<endl);
|
||||||
m_activep->addStmtsp(finalp);
|
m_activep->addStmtsp(finalp);
|
||||||
varrefp->varScopep()->user4p(finalp);
|
varrefp->varScopep()->user4p(finalp);
|
||||||
}
|
}
|
||||||
@@ -284,7 +283,7 @@ private:
|
|||||||
new AstVarRef(nodep->fileline(), setvscp, false),
|
new AstVarRef(nodep->fileline(), setvscp, false),
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
UINFO(9," Created "<<postLogicp<<endl);
|
UINFO(9," Created "<<postLogicp<<endl);
|
||||||
finalp->addBodysp(postLogicp);
|
finalp->addBodysp(postLogicp);
|
||||||
finalp->user5p(setvscp); // Remember IF's vset variable
|
finalp->user5p(setvscp); // Remember IF's vset variable
|
||||||
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
|
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
|
||||||
@@ -347,7 +346,7 @@ private:
|
|||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
if (!nodep->user2()) { // Not done yet
|
if (!nodep->user2()) { // Not done yet
|
||||||
nodep->user2(true);
|
nodep->user2(true);
|
||||||
|
|
||||||
if (m_inDly && nodep->lvalue()) {
|
if (m_inDly && nodep->lvalue()) {
|
||||||
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
||||||
markVarUsage(nodep->varp(), VU_DLY);
|
markVarUsage(nodep->varp(), VU_DLY);
|
||||||
@@ -401,7 +400,7 @@ private:
|
|||||||
m_activep->sensesp());
|
m_activep->sensesp());
|
||||||
newactp->addStmtsp(prep); // Add to FRONT of statements
|
newactp->addStmtsp(prep); // Add to FRONT of statements
|
||||||
newactp->addStmtsp(postp);
|
newactp->addStmtsp(postp);
|
||||||
m_activep->addNext(newactp);
|
m_activep->addNext(newactp);
|
||||||
dlyvscp->user2p(newactp);
|
dlyvscp->user2p(newactp);
|
||||||
}
|
}
|
||||||
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
// DESCRIPTION: Verilator: Pre C-Emit stage changes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3DELAYED_H_
|
#ifndef _V3DELAYED_H_
|
||||||
#define _V3DELAYED_H_ 1
|
#define _V3DELAYED_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+14
-22
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Depth's Transformations:
|
// V3Depth's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// For each wide OP, assign a temporary variable.
|
// For each wide OP, assign a temporary variable.
|
||||||
// For each deep expression, assign expression to temporary.
|
// For each deep expression, assign expression to temporary.
|
||||||
@@ -28,9 +27,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -39,7 +39,6 @@
|
|||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Depth state, as a visitor of each AstNode
|
|
||||||
|
|
||||||
class DepthVisitor : public AstNVisitor {
|
class DepthVisitor : public AstNVisitor {
|
||||||
private:
|
private:
|
||||||
@@ -54,11 +53,6 @@ private:
|
|||||||
|
|
||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
// MSVC++ has a limit of 100 parenthesis. We have some operator
|
|
||||||
// defines that use 2 parens. Thus we can't have a expression deeper
|
|
||||||
// then 50 operators. We'll add some margin though.
|
|
||||||
enum en { MAX_EXPR_DEPTH = 40 }; // Expressions deeper then this need temp
|
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void createDeepTemp(AstNode* nodep) {
|
void createDeepTemp(AstNode* nodep) {
|
||||||
UINFO(6," Deep "<<nodep<<endl);
|
UINFO(6," Deep "<<nodep<<endl);
|
||||||
@@ -113,13 +107,15 @@ private:
|
|||||||
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
|
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
virtual void visit(AstNodeMath* nodep, AstNUser*) {
|
||||||
m_depth++;
|
// We have some operator defines that use 2 parens, so += 2.
|
||||||
|
m_depth += 2;
|
||||||
if (m_depth>m_maxdepth) m_maxdepth=m_depth;
|
if (m_depth>m_maxdepth) m_maxdepth=m_depth;
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
m_depth--;
|
m_depth -= 2;
|
||||||
|
|
||||||
if ((m_maxdepth-m_depth) > MAX_EXPR_DEPTH
|
if (m_stmtp
|
||||||
&& m_stmtp
|
&& (v3Global.opt.compLimitParens() >= 1) // Else compiler doesn't need it
|
||||||
|
&& (m_maxdepth-m_depth) > v3Global.opt.compLimitParens()
|
||||||
&& !nodep->backp()->castNodeStmt() // Not much point if we're about to use it
|
&& !nodep->backp()->castNodeStmt() // Not much point if we're about to use it
|
||||||
) {
|
) {
|
||||||
m_maxdepth = m_depth;
|
m_maxdepth = m_depth;
|
||||||
@@ -172,14 +168,10 @@ public:
|
|||||||
virtual ~DepthVisitor() {}
|
virtual ~DepthVisitor() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
// Top loop
|
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// Depth class functions
|
// Depth class functions
|
||||||
|
|
||||||
void V3Depth::depthAll(AstNetlist* nodep) {
|
void V3Depth::depthAll(AstNetlist* nodep) {
|
||||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
// We must do it in bottom-up module
|
|
||||||
DepthVisitor visitor (nodep);
|
DepthVisitor visitor (nodep);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Prevent very deep expressions
|
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3DEPTH_H_
|
#ifndef _V3DEPTH_H_
|
||||||
#define _V3DEPTH_H_ 1
|
#define _V3DEPTH_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// General Public License or the Perl Artistic License.
|
||||||
|
//
|
||||||
|
// Verilator 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.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
// V3DepthBlock's Transformations:
|
||||||
|
//
|
||||||
|
// Each module:
|
||||||
|
// For each deep block, create cfunc including that block.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "V3Global.h"
|
||||||
|
#include "V3DepthBlock.h"
|
||||||
|
#include "V3Ast.h"
|
||||||
|
#include "V3EmitCBase.h"
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
class DepthBlockVisitor : public AstNVisitor {
|
||||||
|
private:
|
||||||
|
// NODE STATE
|
||||||
|
|
||||||
|
// STATE
|
||||||
|
AstModule* m_modp; // Current module
|
||||||
|
AstCFunc* m_funcp; // Current function
|
||||||
|
int m_depth; // How deep in an expression
|
||||||
|
int m_deepNum; // How many functions made
|
||||||
|
|
||||||
|
//int debug() { return 9; }
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
AstCFunc* createDeepFunc(AstNode* nodep) {
|
||||||
|
AstNRelinker relinkHandle;
|
||||||
|
nodep->unlinkFrBack(&relinkHandle);
|
||||||
|
// Create function
|
||||||
|
string name = m_funcp->name()+"__deep"+cvtToStr(++m_deepNum);
|
||||||
|
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, NULL);
|
||||||
|
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||||
|
funcp->symProlog(true);
|
||||||
|
funcp->slow(m_funcp->slow());
|
||||||
|
funcp->addStmtsp(nodep);
|
||||||
|
m_modp->addStmtp(funcp);
|
||||||
|
// Call it at the point where the body was removed from
|
||||||
|
AstCCall* callp = new AstCCall(nodep->fileline(), funcp);
|
||||||
|
callp->argTypes("vlSymsp");
|
||||||
|
UINFO(6," New "<<callp<<endl);
|
||||||
|
//
|
||||||
|
relinkHandle.relink(callp);
|
||||||
|
return funcp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||||
|
UINFO(4," MOD "<<nodep<<endl);
|
||||||
|
m_modp = nodep;
|
||||||
|
m_deepNum = 0;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||||
|
// We recurse into this.
|
||||||
|
int lastDepth = m_depth;
|
||||||
|
AstCFunc* lastFuncp = m_funcp;
|
||||||
|
{
|
||||||
|
m_depth = 0;
|
||||||
|
m_funcp = nodep;
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
m_depth = lastDepth;
|
||||||
|
m_funcp = lastFuncp;
|
||||||
|
}
|
||||||
|
void visitStmt(AstNodeStmt* nodep) {
|
||||||
|
m_depth++;
|
||||||
|
if (m_depth > v3Global.opt.compLimitBlocks()
|
||||||
|
&& !nodep->castCCall()) { // Already done
|
||||||
|
UINFO(4, "DeepBlocks "<<m_depth<<" "<<nodep<<endl);
|
||||||
|
AstNode* backp = nodep->backp(); // Only for debug
|
||||||
|
if (debug()>=9) backp->dumpTree(cout,"- pre : ");
|
||||||
|
AstCFunc* funcp = createDeepFunc(nodep);
|
||||||
|
funcp->accept(*this);
|
||||||
|
if (debug()>=9) backp->dumpTree(cout,"- post: ");
|
||||||
|
if (debug()>=9) funcp->dumpTree(cout,"- func: ");
|
||||||
|
} else {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
m_depth--;
|
||||||
|
}
|
||||||
|
virtual void visit(AstNodeStmt* nodep, AstNUser*) {
|
||||||
|
visitStmt(nodep);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void visit(AstNodeMath* nodep, AstNUser*) {} // Accelerate
|
||||||
|
//--------------------
|
||||||
|
// Default: Just iterate
|
||||||
|
virtual void visit(AstVar* nodep, AstNUser*) {} // Don't hit varrefs under vars
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// CONSTUCTORS
|
||||||
|
DepthBlockVisitor(AstNode* nodep) {
|
||||||
|
m_modp=NULL;
|
||||||
|
m_depth=0;
|
||||||
|
//
|
||||||
|
nodep->accept(*this);
|
||||||
|
}
|
||||||
|
virtual ~DepthBlockVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// DepthBlock class functions
|
||||||
|
|
||||||
|
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
|
||||||
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
|
DepthBlockVisitor visitor (nodep);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Prevent very deep expressions
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// General Public License or the Perl Artistic License.
|
||||||
|
//
|
||||||
|
// Verilator 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.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#ifndef _V3DEPTHBLOCK_H_
|
||||||
|
#define _V3DEPTHBLOCK_H_ 1
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include "V3Error.h"
|
||||||
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
class V3DepthBlock {
|
||||||
|
public:
|
||||||
|
static void depthBlockAll(AstNetlist* nodep);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // Guard
|
||||||
+16
-15
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Rename scope references to module-local references
|
// DESCRIPTION: Verilator: Rename scope references to module-local references
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -24,12 +23,13 @@
|
|||||||
// Change varref name() to be relative to current module
|
// Change varref name() to be relative to current module
|
||||||
// Remove varScopep()
|
// Remove varScopep()
|
||||||
// This allows for better V3Combine'ing.
|
// This allows for better V3Combine'ing.
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -159,8 +159,8 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Not really any way the user could do this, and we'd need to come up with some return value
|
// Not really any way the user could do this, and we'd need to come up with some return value
|
||||||
//newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(),
|
//newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), AstDisplayType::DISPLAY,
|
||||||
// '\n', string("%%Error: ")+name+"() called with bad scope", NULL));
|
// string("%%Error: ")+name+"() called with bad scope", NULL));
|
||||||
//newfuncp->addStmtsp(new AstStop (newfuncp->fileline()));
|
//newfuncp->addStmtsp(new AstStop (newfuncp->fileline()));
|
||||||
if (debug()>=9) newfuncp->dumpTree(cout," newfunc: ");
|
if (debug()>=9) newfuncp->dumpTree(cout," newfunc: ");
|
||||||
} else {
|
} else {
|
||||||
@@ -224,12 +224,13 @@ private:
|
|||||||
if (m_scopep) {
|
if (m_scopep) {
|
||||||
nodep->unlinkFrBack();
|
nodep->unlinkFrBack();
|
||||||
m_modp->addStmtp(nodep);
|
m_modp->addStmtp(nodep);
|
||||||
}
|
|
||||||
if (nodep->funcPublic()) {
|
if (nodep->funcPublic()) {
|
||||||
// There may be multiple public functions by the same name;
|
// There may be multiple public functions by the same name;
|
||||||
// record for later correction or making of shells
|
// record for later correction or making of shells
|
||||||
m_modFuncs.insert(make_pair(nodep->name(), nodep));
|
m_modFuncs.insert(make_pair(nodep->name(), nodep));
|
||||||
nodep->name(m_scopep->nameDotless() +"__" + nodep->name());
|
nodep->name(m_scopep->nameDotless() +"__" + nodep->name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Rename scope references to module-local references
|
// DESCRIPTION: Verilator: Rename scope references to module-local references
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3DESCOPE_H_
|
#ifndef _V3DESCOPE_H_
|
||||||
#define _V3DESCOPE_H_ 1
|
#define _V3DESCOPE_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+363
-235
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit C++ for tree
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,11 +18,12 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -78,10 +78,10 @@ public:
|
|||||||
//int debug() { return 9; }
|
//int debug() { return 9; }
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void displayEmit(AstDisplay* nodep);
|
void displayNode(AstNode* nodep, const string& vformat, AstNode* exprsp, bool isScan);
|
||||||
string displayFormat(AstNode* widthNode, string in,
|
void displayEmit(AstNode* nodep, bool isScan);
|
||||||
char fmtLetter, bool padZero, bool reallyString);
|
void displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
|
||||||
void displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, char fmtLetter);
|
string vfmt, char fmtLetter);
|
||||||
|
|
||||||
void emitVarDecl(AstVar* nodep, const string& prefixIfImp);
|
void emitVarDecl(AstVar* nodep, const string& prefixIfImp);
|
||||||
typedef enum {EVL_IO, EVL_SIG, EVL_TEMP, EVL_STATIC, EVL_ALL} EisWhich;
|
typedef enum {EVL_IO, EVL_SIG, EVL_TEMP, EVL_STATIC, EVL_ALL} EisWhich;
|
||||||
@@ -91,17 +91,23 @@ public:
|
|||||||
void emitIQW(AstNode* nodep) {
|
void emitIQW(AstNode* nodep) {
|
||||||
puts (nodep->isWide()?"W":(nodep->isQuad()?"Q":"I"));
|
puts (nodep->isWide()?"W":(nodep->isQuad()?"Q":"I"));
|
||||||
}
|
}
|
||||||
void emitOpName(AstNode* nodep, const string& name);
|
void emitOpName(AstNode* nodep, const string& format,
|
||||||
|
AstNode* lhsp, AstNode* rhsp, AstNode* thsp);
|
||||||
|
|
||||||
string cFuncArgs(AstCFunc* nodep) {
|
string cFuncArgs(AstCFunc* nodep) {
|
||||||
// Return argument list for given C function
|
// Return argument list for given C function
|
||||||
string args = nodep->argTypes();
|
string args = nodep->argTypes();
|
||||||
if (args=="") {
|
// Might be a user function with argument list.
|
||||||
// Might be a user function with argument list.
|
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||||
for (AstNode* stmtp = nodep->argsp(); stmtp; stmtp=stmtp->nextp()) {
|
if (AstVar* portp = stmtp->castVar()) {
|
||||||
if (AstVar* portp = stmtp->castVar()) {
|
if (portp->isIO() && !portp->isFuncReturn()) {
|
||||||
if (portp->isIO() && !portp->isFuncReturn()) {
|
if (args != "") args+= ", ";
|
||||||
if (args != "") args+= ", ";
|
if (portp->isWide()) {
|
||||||
|
if (portp->isInOnly()) args += "const ";
|
||||||
|
args += portp->cType();
|
||||||
|
args += " (& "+portp->name();
|
||||||
|
args += ")["+cvtToStr(portp->widthWords())+"]";
|
||||||
|
} else {
|
||||||
args += portp->cType();
|
args += portp->cType();
|
||||||
if (portp->isOutput()) args += "&";
|
if (portp->isOutput()) args += "&";
|
||||||
args += " "+portp->name();
|
args += " "+portp->name();
|
||||||
@@ -206,7 +212,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
|
virtual void visit(AstCoverDecl* nodep, AstNUser*) {
|
||||||
puts("__vlCoverInsert("); // As Declared in emitCoverageDecl
|
puts("__vlCoverInsert("); // As Declared in emitCoverageDecl
|
||||||
puts("&__Vcoverage[");
|
puts("&__Vcoverage[");
|
||||||
puts(cvtToStr(m_coverIds.remap(nodep))); puts("]");
|
puts(cvtToStr(m_coverIds.remap(nodep))); puts("]");
|
||||||
puts(", \""); puts(nodep->fileline()->filebasename()); puts("\"");
|
puts(", \""); puts(nodep->fileline()->filebasename()); puts("\"");
|
||||||
puts(", "); puts(cvtToStr(nodep->fileline()->lineno()));
|
puts(", "); puts(cvtToStr(nodep->fileline()->lineno()));
|
||||||
@@ -217,8 +223,7 @@ public:
|
|||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstCoverInc* nodep, AstNUser*) {
|
virtual void visit(AstCoverInc* nodep, AstNUser*) {
|
||||||
puts("if (VL_LIKELY(vlSymsp->__Vm_coverageRequest))");
|
puts("++this->__Vcoverage[");
|
||||||
puts(" ++this->__Vcoverage[");
|
|
||||||
puts(cvtToStr(m_coverIds.remap(nodep->declp()))); puts("];\n");
|
puts(cvtToStr(m_coverIds.remap(nodep->declp()))); puts("];\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstCReturn* nodep, AstNUser*) {
|
virtual void visit(AstCReturn* nodep, AstNUser*) {
|
||||||
@@ -226,7 +231,23 @@ public:
|
|||||||
nodep->lhsp()->iterateAndNext(*this);
|
nodep->lhsp()->iterateAndNext(*this);
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
virtual void visit(AstDisplay* nodep, AstNUser*); // BELOW
|
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||||
|
string text = nodep->text();
|
||||||
|
if (nodep->addNewline()) text += "\\n";
|
||||||
|
displayNode(nodep, text, nodep->exprsp(), false);
|
||||||
|
}
|
||||||
|
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||||
|
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
|
||||||
|
}
|
||||||
|
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||||
|
displayNode(nodep, nodep->text(), nodep->exprsp(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkMaxWords(AstNode* nodep) {
|
||||||
|
if (nodep->widthWords() > VL_TO_STRING_MAX_WORDS) {
|
||||||
|
nodep->v3error("String of "<<nodep->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
||||||
nodep->filep()->iterateAndNext(*this);
|
nodep->filep()->iterateAndNext(*this);
|
||||||
puts(" = VL_FOPEN_");
|
puts(" = VL_FOPEN_");
|
||||||
@@ -234,16 +255,47 @@ public:
|
|||||||
emitIQW(nodep->modep());
|
emitIQW(nodep->modep());
|
||||||
if (nodep->modep()->width()>4*8) nodep->modep()->v3error("$fopen mode should be <= 4 characters");
|
if (nodep->modep()->width()>4*8) nodep->modep()->v3error("$fopen mode should be <= 4 characters");
|
||||||
puts("(");
|
puts("(");
|
||||||
if (nodep->filenamep()->isWide()) puts(cvtToStr(nodep->filenamep()->widthWords()));
|
if (nodep->filenamep()->isWide()) {
|
||||||
if (nodep->filenamep()->widthWords() > VL_TO_STRING_MAX_WORDS) {
|
puts(cvtToStr(nodep->filenamep()->widthWords()));
|
||||||
nodep->v3error("String of "<<nodep->filenamep()->width()<<" bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h\n");
|
putbs(", ");
|
||||||
}
|
}
|
||||||
putbs(", ");
|
checkMaxWords(nodep->filenamep());
|
||||||
nodep->filenamep()->iterateAndNext(*this);
|
nodep->filenamep()->iterateAndNext(*this);
|
||||||
putbs(", ");
|
putbs(", ");
|
||||||
nodep->modep()->iterateAndNext(*this);
|
nodep->modep()->iterateAndNext(*this);
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
||||||
|
puts("VL_READMEM_");
|
||||||
|
emitIQW(nodep->filenamep());
|
||||||
|
puts(" ("); // We take a void* rather than emitIQW(nodep->memp());
|
||||||
|
puts(nodep->isHex()?"true":"false");
|
||||||
|
putbs(",");
|
||||||
|
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width
|
||||||
|
putbs(",");
|
||||||
|
uint32_t array_lsb = 0;
|
||||||
|
{
|
||||||
|
AstVarRef* varrefp = nodep->memp()->castVarRef();
|
||||||
|
if (!varrefp || !varrefp->varp()->arrayp(0)) { nodep->v3error("Readmem loading non-arrayed variable"); }
|
||||||
|
else {
|
||||||
|
puts(cvtToStr(varrefp->varp()->arrayElements()));
|
||||||
|
array_lsb = varrefp->varp()->arrayp(0)->lsbConst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putbs(", ");
|
||||||
|
puts(cvtToStr(array_lsb));
|
||||||
|
putbs(",");
|
||||||
|
puts(cvtToStr(nodep->filenamep()->widthWords()));
|
||||||
|
checkMaxWords(nodep->filenamep());
|
||||||
|
putbs(", ");
|
||||||
|
nodep->filenamep()->iterateAndNext(*this);
|
||||||
|
putbs(", ");
|
||||||
|
nodep->memp()->iterateAndNext(*this);
|
||||||
|
putbs(","); if (nodep->lsbp()) { nodep->lsbp()->iterateAndNext(*this); }
|
||||||
|
else puts(cvtToStr(array_lsb));
|
||||||
|
putbs(","); if (nodep->msbp()) { nodep->msbp()->iterateAndNext(*this); } else puts("~0");
|
||||||
|
puts(");\n");
|
||||||
|
}
|
||||||
virtual void visit(AstFClose* nodep, AstNUser*) {
|
virtual void visit(AstFClose* nodep, AstNUser*) {
|
||||||
puts("if (");
|
puts("if (");
|
||||||
nodep->filep()->iterateAndNext(*this);
|
nodep->filep()->iterateAndNext(*this);
|
||||||
@@ -253,6 +305,17 @@ public:
|
|||||||
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
|
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
|
||||||
puts("=0; }\n");
|
puts("=0; }\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||||
|
if (!nodep->filep()) {
|
||||||
|
puts("fflush (stdout);\n");
|
||||||
|
} else {
|
||||||
|
puts("if (");
|
||||||
|
nodep->filep()->iterateAndNext(*this);
|
||||||
|
puts(") { fflush (VL_CVT_Q_FP(");
|
||||||
|
nodep->filep()->iterateAndNext(*this);
|
||||||
|
puts(")); }\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||||
nodep->precondsp()->iterateAndNext(*this);
|
nodep->precondsp()->iterateAndNext(*this);
|
||||||
puts("while (");
|
puts("while (");
|
||||||
@@ -314,26 +377,24 @@ public:
|
|||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
|
virtual void visit(AstNodeTermop* nodep, AstNUser*) {
|
||||||
emitOpName(nodep,nodep->emitOperator());
|
emitOpName(nodep, nodep->emitC(), NULL, NULL, NULL);
|
||||||
puts(")");
|
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
virtual void visit(AstNodeUniop* nodep, AstNUser*) {
|
||||||
if (emitSimpleOk(nodep)) {
|
if (emitSimpleOk(nodep)) {
|
||||||
putbs("("); puts(nodep->emitSimpleOperator()); puts(" ");
|
putbs("("); puts(nodep->emitSimpleOperator()); puts(" ");
|
||||||
|
nodep->lhsp()->iterateAndNext(*this); puts(")");
|
||||||
} else {
|
} else {
|
||||||
emitOpName(nodep,nodep->emitOperator());
|
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), NULL, NULL);
|
||||||
}
|
}
|
||||||
nodep->lhsp()->iterateAndNext(*this); puts(")");
|
|
||||||
}
|
}
|
||||||
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
virtual void visit(AstNodeBiop* nodep, AstNUser*) {
|
||||||
if (emitSimpleOk(nodep)) {
|
if (emitSimpleOk(nodep)) {
|
||||||
putbs("("); nodep->lhsp()->iterateAndNext(*this);
|
putbs("("); nodep->lhsp()->iterateAndNext(*this);
|
||||||
puts(" "); putbs(nodep->emitSimpleOperator()); puts(" ");
|
puts(" "); putbs(nodep->emitSimpleOperator()); puts(" ");
|
||||||
|
nodep->rhsp()->iterateAndNext(*this); puts(")");
|
||||||
} else {
|
} else {
|
||||||
emitOpName(nodep,nodep->emitOperator());
|
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
|
||||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
|
||||||
}
|
}
|
||||||
nodep->rhsp()->iterateAndNext(*this); puts(")");
|
|
||||||
}
|
}
|
||||||
virtual void visit(AstRedXor* nodep, AstNUser* vup) {
|
virtual void visit(AstRedXor* nodep, AstNUser* vup) {
|
||||||
if (nodep->lhsp()->isWide()) {
|
if (nodep->lhsp()->isWide()) {
|
||||||
@@ -348,7 +409,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstMulS* nodep, AstNUser* vup) {
|
virtual void visit(AstMulS* nodep, AstNUser* vup) {
|
||||||
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
|
if (nodep->widthWords() > VL_MULS_MAX_WORDS) {
|
||||||
nodep->v3error("Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h\n");
|
nodep->v3error("Unsupported: Signed multiply of "<<nodep->width()<<" bits exceeds hardcoded limit VL_MULS_MAX_WORDS in verilatedos.h\n");
|
||||||
}
|
}
|
||||||
visit(nodep->castNodeBiop(), vup);
|
visit(nodep->castNodeBiop(), vup);
|
||||||
}
|
}
|
||||||
@@ -365,10 +426,7 @@ public:
|
|||||||
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
virtual void visit(AstNodeCond* nodep, AstNUser*) {
|
||||||
// Widths match up already, so we'll just use C++'s operator w/o any temps.
|
// Widths match up already, so we'll just use C++'s operator w/o any temps.
|
||||||
if (nodep->expr1p()->isWide()) {
|
if (nodep->expr1p()->isWide()) {
|
||||||
emitOpName(nodep,nodep->emitOperator());
|
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p());
|
||||||
nodep->condp()->iterateAndNext(*this); puts(", ");
|
|
||||||
nodep->expr1p()->iterateAndNext(*this); puts(", ");
|
|
||||||
nodep->expr2p()->iterateAndNext(*this); puts(")");
|
|
||||||
} else {
|
} else {
|
||||||
putbs("(");
|
putbs("(");
|
||||||
nodep->condp()->iterateAndNext(*this); putbs(" ? ");
|
nodep->condp()->iterateAndNext(*this); putbs(" ? ");
|
||||||
@@ -378,20 +436,11 @@ public:
|
|||||||
}
|
}
|
||||||
virtual void visit(AstSel* nodep, AstNUser*) {
|
virtual void visit(AstSel* nodep, AstNUser*) {
|
||||||
// Note ASSIGN checks for this on a LHS
|
// Note ASSIGN checks for this on a LHS
|
||||||
if (nodep->widthp()->isOne()) {
|
emitOpName(nodep, nodep->emitC(), nodep->fromp(), nodep->lsbp(), nodep->thsp());
|
||||||
emitOpName(nodep,"VL_BITSEL");
|
|
||||||
nodep->fromp()->iterateAndNext(*this); puts(", ");
|
|
||||||
nodep->lsbp()->iterateAndNext(*this); puts(")");
|
|
||||||
} else {
|
|
||||||
emitOpName(nodep,"VL_SEL");
|
|
||||||
nodep->fromp()->iterateAndNext(*this); puts(", ");
|
|
||||||
nodep->lsbp()->iterateAndNext(*this); puts(", ");
|
|
||||||
nodep->widthp()->iterateAndNext(*this); puts(")");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
||||||
if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) {
|
if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) {
|
||||||
if (((int)nodep->rhsp()->castConst()->asInt()
|
if (((int)nodep->rhsp()->castConst()->toUInt()
|
||||||
* nodep->lhsp()->widthMin()) != nodep->widthMin())
|
* nodep->lhsp()->widthMin()) != nodep->widthMin())
|
||||||
nodep->v3fatalSrc("Replicate non-constant or width miscomputed");
|
nodep->v3fatalSrc("Replicate non-constant or width miscomputed");
|
||||||
puts("VL_REPLICATE_");
|
puts("VL_REPLICATE_");
|
||||||
@@ -401,24 +450,16 @@ public:
|
|||||||
if (nodep->lhsp()) { puts(","+cvtToStr(nodep->lhsp()->widthMin())); }
|
if (nodep->lhsp()) { puts(","+cvtToStr(nodep->lhsp()->widthMin())); }
|
||||||
if (nodep->rhsp()) { puts(","+cvtToStr(nodep->rhsp()->widthMin())); }
|
if (nodep->rhsp()) { puts(","+cvtToStr(nodep->rhsp()->widthMin())); }
|
||||||
puts(",");
|
puts(",");
|
||||||
|
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||||
|
nodep->rhsp()->iterateAndNext(*this); puts(")");
|
||||||
} else {
|
} else {
|
||||||
emitOpName(nodep,nodep->emitOperator());
|
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL);
|
||||||
}
|
}
|
||||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
|
||||||
nodep->rhsp()->iterateAndNext(*this); puts(")");
|
|
||||||
}
|
|
||||||
virtual void visit(AstArraySel* nodep, AstNUser*) {
|
|
||||||
nodep->fromp()->iterateAndNext(*this); putbs("[");
|
|
||||||
nodep->bitp()->iterateAndNext(*this); puts("]");
|
|
||||||
}
|
|
||||||
virtual void visit(AstWordSel* nodep, AstNUser*) {
|
|
||||||
nodep->fromp()->iterateAndNext(*this); puts("["); // Not putbs, as usually it's a small constant next
|
|
||||||
nodep->bitp()->iterateAndNext(*this); puts("]");
|
|
||||||
}
|
}
|
||||||
// Terminals
|
// Terminals
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
puts(nodep->hiername());
|
puts(nodep->hiername());
|
||||||
puts(nodep->varp()->name());
|
puts(nodep->varp()->name());
|
||||||
}
|
}
|
||||||
void emitConstant(AstConst* nodep, AstVarRef* assigntop, const string& assignString) {
|
void emitConstant(AstConst* nodep, AstVarRef* assigntop, const string& assignString) {
|
||||||
// Put out constant set to the specified variable, or given variable in a string
|
// Put out constant set to the specified variable, or given variable in a string
|
||||||
@@ -443,11 +484,11 @@ public:
|
|||||||
}
|
}
|
||||||
ofp()->printf(",0x%08x)", nodep->num().dataWord(0));
|
ofp()->printf(",0x%08x)", nodep->num().dataWord(0));
|
||||||
} else if (nodep->isQuad()) {
|
} else if (nodep->isQuad()) {
|
||||||
vluint64_t num = nodep->asQuad();
|
vluint64_t num = nodep->toUQuad();
|
||||||
if (num<10) ofp()->printf("VL_ULL(%lld)", (long long)num);
|
if (num<10) ofp()->printf("VL_ULL(%lld)", (long long)num);
|
||||||
else ofp()->printf("VL_ULL(0x%llx)", (long long)num);
|
else ofp()->printf("VL_ULL(0x%llx)", (long long)num);
|
||||||
} else {
|
} else {
|
||||||
uint32_t num = nodep->asInt();
|
uint32_t num = nodep->toUInt();
|
||||||
if (num<10) puts(cvtToStr(num));
|
if (num<10) puts(cvtToStr(num));
|
||||||
else ofp()->printf("0x%x", num);
|
else ofp()->printf("0x%x", num);
|
||||||
//Unneeded-Causes %lx format warnings:
|
//Unneeded-Causes %lx format warnings:
|
||||||
@@ -554,7 +595,14 @@ class EmitCImp : EmitCStmts {
|
|||||||
if (filenum) filenameNoExt += "__"+cvtToStr(filenum);
|
if (filenum) filenameNoExt += "__"+cvtToStr(filenum);
|
||||||
filenameNoExt += (slow ? "__Slow":"");
|
filenameNoExt += (slow ? "__Slow":"");
|
||||||
V3OutCFile* ofp = NULL;
|
V3OutCFile* ofp = NULL;
|
||||||
if (optSystemPerl()) {
|
if (v3Global.opt.lintOnly()) {
|
||||||
|
// Unfortunately we have some lint checks here, so we can't just skip processing.
|
||||||
|
// We should move them to a different stage.
|
||||||
|
string filename = "/dev/null";
|
||||||
|
newCFile(filename, slow, source);
|
||||||
|
ofp = new V3OutSpFile (filename);
|
||||||
|
}
|
||||||
|
else if (optSystemPerl()) {
|
||||||
string filename = filenameNoExt+".sp";
|
string filename = filenameNoExt+".sp";
|
||||||
newCFile(filename, slow, source);
|
newCFile(filename, slow, source);
|
||||||
ofp = new V3OutSpFile (filename);
|
ofp = new V3OutSpFile (filename);
|
||||||
@@ -592,7 +640,7 @@ class EmitCImp : EmitCStmts {
|
|||||||
puts(modClassName(m_modp)+"::"+nodep->name()
|
puts(modClassName(m_modp)+"::"+nodep->name()
|
||||||
+"("+cFuncArgs(nodep)+") {\n");
|
+"("+cFuncArgs(nodep)+") {\n");
|
||||||
|
|
||||||
puts("VL_DEBUG_IF(cout<<\" ");
|
puts("VL_DEBUG_IF(cout<<\" ");
|
||||||
for (int i=0;i<m_modp->level();i++) { puts(" "); }
|
for (int i=0;i<m_modp->level();i++) { puts(" "); }
|
||||||
puts(modClassName(m_modp)+"::"+nodep->name()
|
puts(modClassName(m_modp)+"::"+nodep->name()
|
||||||
+"\"<<endl; );\n");
|
+"\"<<endl; );\n");
|
||||||
@@ -647,6 +695,21 @@ class EmitCImp : EmitCStmts {
|
|||||||
if (gotOne) {
|
if (gotOne) {
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
//puts("VL_DEBUG_IF( if (__req) cout<<\"\tCLOCKREQ );");
|
//puts("VL_DEBUG_IF( if (__req) cout<<\"\tCLOCKREQ );");
|
||||||
|
for (vector<AstChangeDet*>::iterator it = m_blkChangeDetVec.begin();
|
||||||
|
it != m_blkChangeDetVec.end(); ++it) {
|
||||||
|
AstChangeDet* nodep = *it;
|
||||||
|
if (nodep->lhsp()) {
|
||||||
|
puts("VL_DEBUG_IF( if(__req && (");
|
||||||
|
bool gotOneIgnore = false;
|
||||||
|
doubleOrDetect(nodep, gotOneIgnore);
|
||||||
|
string varname;
|
||||||
|
if (nodep->lhsp()->castVarRef()) {
|
||||||
|
varname = ": "+nodep->lhsp()->castVarRef()->varp()->prettyName();
|
||||||
|
}
|
||||||
|
puts(")) cout<<\"\tCHANGE: "+nodep->fileline()->ascii()
|
||||||
|
+varname+"\"<<endl; );");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,19 +766,19 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
|
|||||||
if (nodep->attrScClocked() && nodep->isInput()) {
|
if (nodep->attrScClocked() && nodep->isInput()) {
|
||||||
puts("sc_in_clk\t");
|
puts("sc_in_clk\t");
|
||||||
} else {
|
} else {
|
||||||
if (nodep->isTristate()) puts("sc_inout<");
|
if (nodep->isInout()) puts("sc_inout<");
|
||||||
else if (nodep->isInput()) puts("sc_in<");
|
else if (nodep->isInput()) puts("sc_in<");
|
||||||
else if (nodep->isOutput()) puts("sc_out<");
|
else if (nodep->isOutput()) puts("sc_out<");
|
||||||
else nodep->v3fatalSrc("Unknown type");
|
else nodep->v3fatalSrc("Unknown type");
|
||||||
|
|
||||||
puts(nodep->cType());
|
puts(nodep->scType());
|
||||||
puts(">\t");
|
puts(">\t");
|
||||||
}
|
}
|
||||||
puts(nodep->name());
|
puts(nodep->name());
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
} else { // C++ signals
|
} else { // C++ signals
|
||||||
ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes());
|
ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes());
|
||||||
if (nodep->isTristate()) puts("VL_INOUT");
|
if (nodep->isInout()) puts("VL_INOUT");
|
||||||
else if (nodep->isInput()) puts("VL_IN");
|
else if (nodep->isInput()) puts("VL_IN");
|
||||||
else if (nodep->isOutput()) puts("VL_OUT");
|
else if (nodep->isOutput()) puts("VL_OUT");
|
||||||
else nodep->v3fatalSrc("Unknown type");
|
else nodep->v3fatalSrc("Unknown type");
|
||||||
@@ -791,33 +854,95 @@ bool EmitCStmts::emitSimpleOk(AstNodeMath* nodep) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCStmts::emitOpName(AstNode* nodep, const string& opname) {
|
void EmitCStmts::emitOpName(AstNode* nodep, const string& format,
|
||||||
putbs(opname+"_");
|
AstNode* lhsp, AstNode* rhsp, AstNode* thsp) {
|
||||||
if (nodep->emitWordForm()) {
|
// Look at emitOperator() format for term/uni/dual/triops,
|
||||||
emitIQW(nodep->op1p());
|
// and write out appropriate text.
|
||||||
puts("(");
|
// %n* node
|
||||||
if (nodep->op1p()->isWide()) {
|
// %nq emitIQW on the [node]
|
||||||
puts(cvtToStr(nodep->op1p()->widthWords()));
|
// %nw width in bits
|
||||||
puts(", ");
|
// %nW width in words
|
||||||
|
// %ni iterate
|
||||||
|
// %l* lhsp - if appropriate, then second char as above
|
||||||
|
// %r* rhsp - if appropriate, then second char as above
|
||||||
|
// %t* thsp - if appropriate, then second char as above
|
||||||
|
// %k Potential line break
|
||||||
|
// %P Wide temporary name
|
||||||
|
// , Commas suppressed if the previous field is suppressed
|
||||||
|
string nextComma;
|
||||||
|
bool needComma = false;
|
||||||
|
#define COMMA { if (nextComma!="") { puts(nextComma); nextComma=""; } }
|
||||||
|
|
||||||
|
putbs("");
|
||||||
|
for (string::const_iterator pos = format.begin(); pos != format.end(); ++pos) {
|
||||||
|
if (pos[0]==',') {
|
||||||
|
// Remember we need to add one, but don't do yet to avoid ",)"
|
||||||
|
if (needComma) {
|
||||||
|
if (pos[1]==' ') { nextComma=", "; }
|
||||||
|
else nextComma = ",";
|
||||||
|
needComma = false;
|
||||||
|
}
|
||||||
|
if (pos[1]==' ') { ++pos; } // Must do even if no nextComma
|
||||||
|
}
|
||||||
|
else if (pos[0]=='%') {
|
||||||
|
++pos;
|
||||||
|
bool detail = false;
|
||||||
|
AstNode* detailp = NULL;
|
||||||
|
switch (pos[0]) {
|
||||||
|
case '%': puts("%"); break;
|
||||||
|
case 'k': putbs(""); break;
|
||||||
|
case 'n': detail = true; detailp = nodep; break;
|
||||||
|
case 'l': detail = true; detailp = lhsp; break;
|
||||||
|
case 'r': detail = true; detailp = rhsp; break;
|
||||||
|
case 't': detail = true; detailp = thsp; break;
|
||||||
|
case 'P':
|
||||||
|
if (nodep->isWide()) {
|
||||||
|
if (!m_wideTempRefp) nodep->v3fatalSrc("Wide Op w/ no temp, perhaps missing op in V3EmitC?");
|
||||||
|
COMMA;
|
||||||
|
puts(m_wideTempRefp->hiername());
|
||||||
|
puts(m_wideTempRefp->varp()->name());
|
||||||
|
m_wideTempRefp = NULL;
|
||||||
|
needComma = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nodep->v3fatalSrc("Unknown emitOperator format code: %"<<pos[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (detail) {
|
||||||
|
// Get next letter of %[nlrt]
|
||||||
|
++pos;
|
||||||
|
switch (pos[0]) {
|
||||||
|
case 'q': emitIQW(detailp); break;
|
||||||
|
case 'w':
|
||||||
|
COMMA;
|
||||||
|
puts(cvtToStr(detailp->widthMin()));
|
||||||
|
needComma = true;
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
if (lhsp->isWide()) {
|
||||||
|
COMMA;
|
||||||
|
puts(cvtToStr(lhsp->widthWords()));
|
||||||
|
needComma = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
COMMA;
|
||||||
|
if (!detailp) { nodep->v3fatalSrc("emitOperator() references undef node"); }
|
||||||
|
else detailp->iterateAndNext(*this);
|
||||||
|
needComma = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nodep->v3fatalSrc("Unknown emitOperator format code: %[nlrt]"<<pos[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal text
|
||||||
|
if (pos[0] == ')') nextComma="";
|
||||||
|
COMMA;
|
||||||
|
string s; s+=pos[0]; puts(s);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
emitIQW(nodep);
|
|
||||||
if (nodep->op1p()) { emitIQW(nodep->op1p()); }
|
|
||||||
if (nodep->op2p()) { emitIQW(nodep->op2p()); }
|
|
||||||
if (nodep->op3p()) { emitIQW(nodep->op3p()); }
|
|
||||||
puts("(");
|
|
||||||
puts(cvtToStr(nodep->widthMin()));
|
|
||||||
if (nodep->op1p()) { puts(","+cvtToStr(nodep->op1p()->widthMin())); }
|
|
||||||
if (nodep->op2p()) { puts(","+cvtToStr(nodep->op2p()->widthMin())); }
|
|
||||||
if (nodep->op3p()) { puts(","+cvtToStr(nodep->op3p()->widthMin())); }
|
|
||||||
if (nodep->op1p() || nodep->isWide()) puts(", ");
|
|
||||||
}
|
|
||||||
if (nodep->isWide()) {
|
|
||||||
if (!m_wideTempRefp) nodep->v3fatalSrc("Wide Op w/ no temp, perhaps missing op in V3EmitC?");
|
|
||||||
puts(m_wideTempRefp->hiername());
|
|
||||||
puts(m_wideTempRefp->varp()->name());
|
|
||||||
m_wideTempRefp = NULL;
|
|
||||||
if (nodep->op1p()) puts(", ");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -827,13 +952,11 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& opname) {
|
|||||||
// We only do one display at once, so can just use static state
|
// We only do one display at once, so can just use static state
|
||||||
|
|
||||||
struct EmitDispState {
|
struct EmitDispState {
|
||||||
bool m_wide; // Put out a wide func that needs string buffer
|
|
||||||
string m_format; // "%s" and text from user
|
string m_format; // "%s" and text from user
|
||||||
vector<AstNode*> m_argsp; // Each argument to be printed
|
vector<AstNode*> m_argsp; // Each argument to be printed
|
||||||
vector<string> m_argsFunc; // Function before each argument to be printed
|
vector<string> m_argsFunc; // Function before each argument to be printed
|
||||||
EmitDispState() { clear(); }
|
EmitDispState() { clear(); }
|
||||||
void clear() {
|
void clear() {
|
||||||
m_wide = false;
|
|
||||||
m_format = "";
|
m_format = "";
|
||||||
m_argsp.clear();
|
m_argsp.clear();
|
||||||
m_argsFunc.clear();
|
m_argsFunc.clear();
|
||||||
@@ -845,18 +968,40 @@ struct EmitDispState {
|
|||||||
}
|
}
|
||||||
} emitDispState;
|
} emitDispState;
|
||||||
|
|
||||||
void EmitCStmts::displayEmit(AstDisplay* nodep) {
|
void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) {
|
||||||
if (emitDispState.m_format != "") {
|
if (emitDispState.m_format == ""
|
||||||
|
&& nodep->castDisplay()) { // not fscanf etc, as they need to return value
|
||||||
|
// NOP
|
||||||
|
} else {
|
||||||
// Format
|
// Format
|
||||||
if (nodep->filep()) {
|
bool isStmt;
|
||||||
puts("if (");
|
if (AstFScanF* dispp = nodep->castFScanF()) {
|
||||||
nodep->filep()->iterate(*this); // Check if closed, to avoid core dump
|
isStmt = false;
|
||||||
puts(") fprintf(VL_CVT_Q_FP(");
|
puts("VL_FSCANF_IX(");
|
||||||
nodep->filep()->iterate(*this);
|
dispp->filep()->iterate(*this);
|
||||||
puts("),\"");
|
puts(",");
|
||||||
|
} else if (AstSScanF* dispp = nodep->castSScanF()) {
|
||||||
|
isStmt = false;
|
||||||
|
checkMaxWords(dispp->fromp());
|
||||||
|
puts("VL_SSCANF_I"); emitIQW(dispp->fromp()); puts("X(");
|
||||||
|
puts(cvtToStr(dispp->fromp()->widthMin()));
|
||||||
|
puts(",");
|
||||||
|
dispp->fromp()->iterate(*this);
|
||||||
|
puts(",");
|
||||||
|
} else if (AstDisplay* dispp = nodep->castDisplay()) {
|
||||||
|
isStmt = true;
|
||||||
|
if (dispp->filep()) {
|
||||||
|
puts("VL_FWRITEF(");
|
||||||
|
dispp->filep()->iterate(*this);
|
||||||
|
puts(",");
|
||||||
|
} else {
|
||||||
|
puts("VL_WRITEF(");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
puts("VL_PRINTF(\"");
|
isStmt = true;
|
||||||
|
nodep->v3fatalSrc("Unknown displayEmit node type");
|
||||||
}
|
}
|
||||||
|
puts("\"");
|
||||||
ofp()->putsNoTracking(emitDispState.m_format);
|
ofp()->putsNoTracking(emitDispState.m_format);
|
||||||
puts("\"");
|
puts("\"");
|
||||||
// Arguments
|
// Arguments
|
||||||
@@ -867,156 +1012,133 @@ void EmitCStmts::displayEmit(AstDisplay* nodep) {
|
|||||||
ofp()->indentInc();
|
ofp()->indentInc();
|
||||||
ofp()->putbs("");
|
ofp()->putbs("");
|
||||||
if (func!="") puts(func);
|
if (func!="") puts(func);
|
||||||
if (argp) argp->iterate(*this);
|
if (argp) {
|
||||||
if (func!="") puts(")");
|
if (isScan) puts("&(");
|
||||||
|
argp->iterate(*this);
|
||||||
|
if (isScan) puts(")");
|
||||||
|
}
|
||||||
ofp()->indentDec();
|
ofp()->indentDec();
|
||||||
}
|
}
|
||||||
// End
|
// End
|
||||||
puts(");\n");
|
puts(")");
|
||||||
|
if (isStmt) puts(";\n");
|
||||||
|
else puts(" ");
|
||||||
// Prep for next
|
// Prep for next
|
||||||
emitDispState.clear();
|
emitDispState.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string EmitCStmts::displayFormat(AstNode* widthNodep, string in,
|
void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
|
||||||
char fmtLetter, bool padZero, bool reallyString) {
|
string vfmt, char fmtLetter) {
|
||||||
if (fmtLetter=='s') padZero = false;
|
|
||||||
if (widthNodep && widthNodep->isWide()
|
|
||||||
&& (fmtLetter=='d'||fmtLetter=='u')) {
|
|
||||||
widthNodep->v3error("Unsupported: $display of dec format of > 64 bit results (use hex format instead)");
|
|
||||||
}
|
|
||||||
if (widthNodep && widthNodep->widthMin()>8 && fmtLetter=='c') {
|
|
||||||
widthNodep->v3error("$display of char format of > 8 bit result");
|
|
||||||
}
|
|
||||||
string fmt;
|
|
||||||
if (in == "") {
|
|
||||||
// Size naturally
|
|
||||||
if (widthNodep == NULL) fmt=""; // Out of args, will get error
|
|
||||||
if (fmtLetter=='u' || fmtLetter=='d') { // Decimal. Spec says leading spaces, not zeros
|
|
||||||
double mantissabits = widthNodep->widthMin() - ((fmtLetter=='d')?1:0);
|
|
||||||
double maxval = pow(2.0, mantissabits);
|
|
||||||
double dchars = log10(maxval)+1.0;
|
|
||||||
if (fmtLetter=='d') dchars++; // space for sign
|
|
||||||
int nchars = int(dchars);
|
|
||||||
fmt=cvtToStr(nchars);
|
|
||||||
} else if (fmtLetter!='s' && fmtLetter!='c') { // Strings/chars don't get padding
|
|
||||||
int bitsPerChar = (fmtLetter=='b'?1 : fmtLetter=='o'?3 : 4);
|
|
||||||
int nchars = (widthNodep->widthMin() + bitsPerChar-1)/bitsPerChar;
|
|
||||||
if (padZero) fmt=(string)("0")+cvtToStr(nchars);
|
|
||||||
else fmt=cvtToStr(nchars);
|
|
||||||
}
|
|
||||||
} else if (in == "0") {
|
|
||||||
fmt=""; // No width
|
|
||||||
} else {
|
|
||||||
fmt=in;
|
|
||||||
}
|
|
||||||
if (widthNodep->isQuad() && fmtLetter!='c' && fmtLetter!='s' && !reallyString) fmt+="ll";
|
|
||||||
return fmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitCStmts::displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, char fmtLetter) {
|
|
||||||
// Print display argument, edits elistp
|
// Print display argument, edits elistp
|
||||||
if (!*elistp) {
|
AstNode* argp = *elistp;
|
||||||
dispp->v3error("Missing arguments for $display format");
|
if (!argp) {
|
||||||
|
// expectDisplay() checks this first, so internal error if found here
|
||||||
|
dispp->v3error("Internal: Missing arguments for $display format");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((*elistp)->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
|
if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
|
||||||
dispp->v3error("Exceeded limit of 1024 bits for any display arguments");
|
dispp->v3error("Exceeded limit of 1024 bits for any display arguments");
|
||||||
}
|
}
|
||||||
|
if (argp && argp->isWide()
|
||||||
if ((*elistp)->isWide() // Have to use our own function for wide,
|
&& (fmtLetter=='d'||fmtLetter=='u')) {
|
||||||
|| fmtLetter=='s' // ... Verilog strings
|
argp->v3error("Unsupported: "<<dispp->verilogKwd()<<" of dec format of > 64 bit results (use hex format instead)");
|
||||||
|| fmtLetter=='b' // ... binary, no printf %b in C
|
|
||||||
|| fmtLetter=='d') { // ... Signed decimal
|
|
||||||
// We use a single static string, so must only have one call per VL_PRINT
|
|
||||||
if (emitDispState.m_wide) { displayEmit(dispp); }
|
|
||||||
emitDispState.m_wide = true;
|
|
||||||
string nfmt = displayFormat(*elistp, fmt, fmtLetter, false, true);
|
|
||||||
string pfmt = "%"+nfmt+"s";
|
|
||||||
string func = "VL_VALUE_FORMATTED_";
|
|
||||||
func += ((*elistp)->isWide()) ? "W(" : ((*elistp)->isQuad()) ? "Q(" : "I(";
|
|
||||||
func += (cvtToStr((*elistp)->widthMin())
|
|
||||||
+",'"+fmtLetter+"'"
|
|
||||||
+","+(fmt=="0"?"true":"false")+",");
|
|
||||||
emitDispState.pushFormat(pfmt);
|
|
||||||
emitDispState.pushArg(*elistp,func);
|
|
||||||
} else {
|
|
||||||
string nfmt = displayFormat(*elistp, fmt, fmtLetter, true, false);
|
|
||||||
string pfmt = "%"+nfmt+fmtLetter;
|
|
||||||
emitDispState.pushFormat(pfmt);
|
|
||||||
emitDispState.pushArg(*elistp,"");
|
|
||||||
}
|
}
|
||||||
|
if (argp && argp->widthMin()>8 && fmtLetter=='c') {
|
||||||
|
// Technically legal, but surely not what the user intended.
|
||||||
|
argp->v3error(dispp->verilogKwd()<<" of char format of > 8 bit result");
|
||||||
|
}
|
||||||
|
|
||||||
|
//string pfmt = "%"+displayFormat(argp, vfmt, fmtLetter)+fmtLetter;
|
||||||
|
string pfmt;
|
||||||
|
if ((fmtLetter=='u' || fmtLetter=='d' || fmtLetter=='t')
|
||||||
|
&& !isScan
|
||||||
|
&& vfmt == "") { // Size decimal output. Spec says leading spaces, not zeros
|
||||||
|
double mantissabits = argp->widthMin() - ((fmtLetter=='d')?1:0);
|
||||||
|
double maxval = pow(2.0, mantissabits);
|
||||||
|
double dchars = log10(maxval)+1.0;
|
||||||
|
if (fmtLetter=='d') dchars++; // space for sign
|
||||||
|
int nchars = int(dchars);
|
||||||
|
pfmt = string("%") + cvtToStr(nchars) + fmtLetter;
|
||||||
|
} else {
|
||||||
|
pfmt = string("%") + vfmt + fmtLetter;
|
||||||
|
}
|
||||||
|
emitDispState.pushFormat(pfmt);
|
||||||
|
emitDispState.pushArg(NULL,cvtToStr(argp->widthMin()));
|
||||||
|
emitDispState.pushArg(argp,"");
|
||||||
|
|
||||||
// Next parameter
|
// Next parameter
|
||||||
*elistp = (*elistp)->nextp();
|
*elistp = (*elistp)->nextp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCStmts::visit(AstDisplay* nodep, AstNUser*) {
|
void EmitCStmts::displayNode(AstNode* nodep, const string& vformat, AstNode* exprsp,
|
||||||
string vformat = nodep->text();
|
bool isScan) {
|
||||||
bool addNewline = (nodep->newline() == '\n');
|
AstNode* elistp = exprsp;
|
||||||
AstNode* elistp = nodep->exprsp();
|
|
||||||
|
|
||||||
// Convert Verilog display to C printf formats
|
// Convert Verilog display to C printf formats
|
||||||
// "%0t" becomes "%d"
|
// "%0t" becomes "%d"
|
||||||
emitDispState.clear();
|
emitDispState.clear();
|
||||||
string fmt = "";
|
string vfmt = "";
|
||||||
string::iterator pos = vformat.begin();
|
string::const_iterator pos = vformat.begin();
|
||||||
if (*pos == '"') pos++;
|
|
||||||
bool inPct = false;
|
bool inPct = false;
|
||||||
for (; pos != vformat.end(); ++pos) {
|
for (; pos != vformat.end(); ++pos) {
|
||||||
if (pos[0]=='"' && (pos+1)==vformat.end()) break;
|
//UINFO(1,"Parse '"<<*pos<<"' IP"<<inPct<<" List "<<(void*)(elistp)<<endl);
|
||||||
if (inPct && pos[0]=='%') {
|
if (!inPct && pos[0]=='%') {
|
||||||
emitDispState.pushFormat("%%"); // We're printf'ing it, so need to quote the %
|
|
||||||
inPct = false;
|
|
||||||
} else if (pos[0]=='%') {
|
|
||||||
inPct = true;
|
inPct = true;
|
||||||
fmt = "";
|
vfmt = "";
|
||||||
} else if (!inPct) { // Normal text
|
} else if (!inPct) { // Normal text
|
||||||
//char text[2]; text[0]=*pos; text[1]='\0';
|
|
||||||
emitDispState.pushFormat(*pos);
|
emitDispState.pushFormat(*pos);
|
||||||
} else { // Format character
|
} else { // Format character
|
||||||
if (isdigit(pos[0])) {
|
inPct = false;
|
||||||
|
switch (tolower(pos[0])) {
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
// Digits, like %5d, etc.
|
// Digits, like %5d, etc.
|
||||||
fmt += pos[0];
|
vfmt += pos[0];
|
||||||
} else {
|
inPct = true; // Get more digits
|
||||||
inPct = false;
|
break;
|
||||||
switch (tolower(pos[0])) {
|
case '%':
|
||||||
// Special codes
|
emitDispState.pushFormat("%%"); // We're printf'ing it, so need to quote the %
|
||||||
case '~': displayArg(nodep,&elistp,fmt,'d'); break; // Signed decimal
|
break;
|
||||||
// Spec: h d o b c l
|
// Special codes
|
||||||
case 'b': displayArg(nodep,&elistp,fmt,'b'); break;
|
case '~': displayArg(nodep,&elistp,isScan, vfmt,'d'); break; // Signed decimal
|
||||||
case 'c': displayArg(nodep,&elistp,fmt,'c'); break;
|
// Spec: h d o b c l
|
||||||
case 'd': displayArg(nodep,&elistp,fmt,'u'); break; // Unsigned decimal
|
case 'b': displayArg(nodep,&elistp,isScan, vfmt,'b'); break;
|
||||||
case 'o': displayArg(nodep,&elistp,fmt,'o'); break;
|
case 'c': displayArg(nodep,&elistp,isScan, vfmt,'c'); break;
|
||||||
case 'h':
|
case 't': displayArg(nodep,&elistp,isScan, vfmt,'t'); break;
|
||||||
case 'x': displayArg(nodep,&elistp,fmt,'x'); break;
|
case 'd': displayArg(nodep,&elistp,isScan, vfmt,'u'); break; // Unsigned decimal
|
||||||
case 's': displayArg(nodep,&elistp,fmt,'s'); break;
|
case 'o': displayArg(nodep,&elistp,isScan, vfmt,'o'); break;
|
||||||
case 't': displayArg(nodep,&elistp,fmt,'u'); break;
|
case 'h':
|
||||||
case 'm': {
|
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
|
||||||
emitDispState.pushFormat("%s");
|
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
|
||||||
emitDispState.pushArg(NULL, "vlSymsp->name(");
|
case 'm': {
|
||||||
for (AstText* textp=nodep->scopeTextp(); textp; textp=textp->nextp()->castText()) {
|
emitDispState.pushFormat("%S");
|
||||||
emitDispState.pushFormat(textp->text());
|
emitDispState.pushArg(NULL, "vlSymsp->name()");
|
||||||
}
|
if (!nodep->castDisplay()) nodep->v3fatalSrc("Non-Display with %m");
|
||||||
break;
|
AstScopeName* scopenamep = nodep->castDisplay()->scopeNamep();
|
||||||
}
|
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||||
case 'u':
|
for (AstText* textp=scopenamep->scopeAttrp(); textp; textp=textp->nextp()->castText()) {
|
||||||
case 'z':
|
emitDispState.pushFormat(textp->text());
|
||||||
case 'l':
|
|
||||||
case 'v':
|
|
||||||
nodep->v3error("Unsupported: $display format code: %"<<pos[0]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
nodep->v3error("Unknown $display format code: %"<<pos[0]);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u':
|
||||||
|
case 'z':
|
||||||
|
case 'l':
|
||||||
|
case 'v':
|
||||||
|
nodep->v3error("Unsupported: $display format code: %"<<pos[0]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nodep->v3error("Unknown $display format code: %"<<pos[0]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (elistp != NULL) {
|
if (elistp != NULL) {
|
||||||
nodep->v3error("Extra arguments for $display format\n");
|
// expectFormat also checks this, and should have found it first, so internal
|
||||||
|
elistp->v3error("Internal: Extra arguments for $display format\n");
|
||||||
}
|
}
|
||||||
if (addNewline) emitDispState.pushFormat("\\n");
|
displayEmit(nodep, isScan);
|
||||||
displayEmit(nodep);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
@@ -1146,7 +1268,7 @@ void EmitCImp::emitConfigureImp(AstModule* modp) {
|
|||||||
void EmitCImp::emitCoverageImp(AstModule* modp) {
|
void EmitCImp::emitCoverageImp(AstModule* modp) {
|
||||||
if (m_coverIds.size()) {
|
if (m_coverIds.size()) {
|
||||||
puts("\n// Coverage\n");
|
puts("\n// Coverage\n");
|
||||||
// Rather then putting out SP_COVER_INSERT calls directly, we do it via this function
|
// Rather than putting out SP_COVER_INSERT calls directly, we do it via this function
|
||||||
// This gets around gcc slowness constructing all of the template arguments
|
// This gets around gcc slowness constructing all of the template arguments
|
||||||
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(SpZeroed<uint32_t>* countp, const char* filename, int lineno, int column,\n");
|
puts("void "+modClassName(m_modp)+"::__vlCoverInsert(SpZeroed<uint32_t>* countp, const char* filename, int lineno, int column,\n");
|
||||||
puts( "const char* hier, const char* type, const char* comment) {\n");
|
puts( "const char* hier, const char* type, const char* comment) {\n");
|
||||||
@@ -1246,12 +1368,8 @@ void EmitCImp::emitWrapEval(AstModule* modp) {
|
|||||||
puts("while (VL_LIKELY(__Vchange)) {\n");
|
puts("while (VL_LIKELY(__Vchange)) {\n");
|
||||||
puts( "VL_DEBUG_IF(cout<<\" Clock loop\"<<endl;);\n");
|
puts( "VL_DEBUG_IF(cout<<\" Clock loop\"<<endl;);\n");
|
||||||
#endif
|
#endif
|
||||||
// Not exactly correct for coverage. w/combo logic interspersed, this is complicated. Punt.
|
|
||||||
// Perhaps have temp & each _combo_ turn it on or off
|
|
||||||
if (v3Global.opt.coverage()) puts( "vlSymsp->__Vm_coverageRequest = true;\n");
|
|
||||||
puts( "vlSymsp->__Vm_activity = true;\n");
|
puts( "vlSymsp->__Vm_activity = true;\n");
|
||||||
puts( "_eval(vlSymsp);\n");
|
puts( "_eval(vlSymsp);\n");
|
||||||
if (v3Global.opt.coverage()) puts( "vlSymsp->__Vm_coverageRequest = false;\n");
|
|
||||||
#ifndef NEW_ORDERING
|
#ifndef NEW_ORDERING
|
||||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||||
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
|
puts( "if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
|
||||||
@@ -1284,7 +1402,7 @@ void EmitCImp::emitWrapEval(AstModule* modp) {
|
|||||||
|
|
||||||
void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& prefixIfImp) {
|
void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& prefixIfImp) {
|
||||||
// Put out a list of signal declarations
|
// Put out a list of signal declarations
|
||||||
// in order of 0:clocks, 1:uint8, 2:uint16, 4:uint32, 5:uint64, 6:wide, 7:arrays
|
// in order of 0:clocks, 1:vluint8, 2:vluint16, 4:vluint32, 5:vluint64, 6:wide, 7:arrays
|
||||||
// This aids cache packing and locality
|
// This aids cache packing and locality
|
||||||
// Largest->smallest reduces the number of pad variables.
|
// Largest->smallest reduces the number of pad variables.
|
||||||
// But for now, Smallest->largest makes it more likely a small offset will allow access to the signal.
|
// But for now, Smallest->largest makes it more likely a small offset will allow access to the signal.
|
||||||
@@ -1364,6 +1482,9 @@ void EmitCImp::emitInt(AstModule* modp) {
|
|||||||
if (v3Global.opt.coverage()) {
|
if (v3Global.opt.coverage()) {
|
||||||
puts("#include \"SpCoverage.h\"\n");
|
puts("#include \"SpCoverage.h\"\n");
|
||||||
}
|
}
|
||||||
|
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
|
||||||
|
puts("#include \""+topClassName()+"__Inlines.h\"\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Declare foreign instances up front to make C++ happy
|
// Declare foreign instances up front to make C++ happy
|
||||||
puts("class "+symClassName()+";\n");
|
puts("class "+symClassName()+";\n");
|
||||||
@@ -1372,6 +1493,13 @@ void EmitCImp::emitInt(AstModule* modp) {
|
|||||||
puts("class "+modClassName(cellp->modp())+";\n");
|
puts("class "+modClassName(cellp->modp())+";\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (v3Global.opt.trace()) {
|
||||||
|
if (optSystemPerl()) {
|
||||||
|
puts("class SpTraceVcd;\n");
|
||||||
|
} else {
|
||||||
|
puts("class SpTraceVcdCFile;\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
puts("\n//----------\n\n");
|
puts("\n//----------\n\n");
|
||||||
emitTextSection(AstType::SCHDR);
|
emitTextSection(AstType::SCHDR);
|
||||||
@@ -1462,9 +1590,9 @@ void EmitCImp::emitInt(AstModule* modp) {
|
|||||||
} else {
|
} else {
|
||||||
puts(modClassName(modp)+"(const char* name=\"TOP\");\n");
|
puts(modClassName(modp)+"(const char* name=\"TOP\");\n");
|
||||||
puts("~"+modClassName(modp)+"();\n");
|
puts("~"+modClassName(modp)+"();\n");
|
||||||
if (v3Global.opt.trace()) {
|
}
|
||||||
puts("void\ttrace (SpTraceVcdCFile* tfp, int levels, int options=0);\n");
|
if (v3Global.opt.trace() && !optSystemPerl()) {
|
||||||
}
|
puts("void\ttrace (SpTraceVcdCFile* tfp, int levels, int options=0);\n");
|
||||||
}
|
}
|
||||||
puts("void\t__Vconfigure("+symClassName()+"* symsp);\n");
|
puts("void\t__Vconfigure("+symClassName()+"* symsp);\n");
|
||||||
if (optSystemPerl()) puts("/*AUTOMETHODS*/\n");
|
if (optSystemPerl()) puts("/*AUTOMETHODS*/\n");
|
||||||
@@ -1550,7 +1678,7 @@ void EmitCImp::emitImp(AstModule* modp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_fast && m_splitFilenum==0) {
|
if (m_fast && m_splitFilenum==0) {
|
||||||
if (v3Global.opt.trace() && optSystemC() && m_modp->isTop()) {
|
if (v3Global.opt.trace() && optSystemPerl() && m_modp->isTop()) {
|
||||||
puts("\n");
|
puts("\n");
|
||||||
puts("\n/*AUTOTRACE(__MODULE__,recurse,activity,exists)*/\n\n");
|
puts("\n/*AUTOTRACE(__MODULE__,recurse,activity,exists)*/\n\n");
|
||||||
}
|
}
|
||||||
@@ -1606,7 +1734,7 @@ void EmitCImp::main(AstModule* modp, bool slow, bool fast) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
emitImp (modp);
|
emitImp (modp);
|
||||||
|
|
||||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||||
if (AstCFunc* funcp = nodep->castCFunc()) {
|
if (AstCFunc* funcp = nodep->castCFunc()) {
|
||||||
if (v3Global.opt.outputSplit() > 1 && splitSize()
|
if (v3Global.opt.outputSplit() > 1 && splitSize()
|
||||||
@@ -1637,7 +1765,7 @@ class EmitCTrace : EmitCStmts {
|
|||||||
// METHODS
|
// METHODS
|
||||||
void emitTraceHeader() {
|
void emitTraceHeader() {
|
||||||
// Includes
|
// Includes
|
||||||
if (optSystemC()) {
|
if (optSystemPerl()) {
|
||||||
puts("#include \"SpTraceVcd.h\"\n");
|
puts("#include \"SpTraceVcd.h\"\n");
|
||||||
}
|
}
|
||||||
puts("#include \"SpTraceVcdC.h\"\n");
|
puts("#include \"SpTraceVcdC.h\"\n");
|
||||||
@@ -1649,7 +1777,7 @@ class EmitCTrace : EmitCStmts {
|
|||||||
puts("\n//======================\n\n");
|
puts("\n//======================\n\n");
|
||||||
|
|
||||||
puts("void "+topClassName()+"::trace (");
|
puts("void "+topClassName()+"::trace (");
|
||||||
if (optSystemC()) {
|
if (optSystemPerl()) {
|
||||||
puts("SpTraceFile* tfp, int, int) {\n");
|
puts("SpTraceFile* tfp, int, int) {\n");
|
||||||
} else {
|
} else {
|
||||||
puts("SpTraceVcdCFile* tfp, int, int) {\n");
|
puts("SpTraceVcdCFile* tfp, int, int) {\n");
|
||||||
@@ -1667,7 +1795,7 @@ class EmitCTrace : EmitCStmts {
|
|||||||
puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
||||||
puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
|
puts("t->traceInitThis (vlSymsp, vcdp, code);\n");
|
||||||
puts("}\n");
|
puts("}\n");
|
||||||
|
|
||||||
puts("void "+topClassName()+"::traceFull(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
|
puts("void "+topClassName()+"::traceFull(SpTraceVcd* vcdp, void* userthis, uint32_t code) {\n");
|
||||||
puts("// Callback from vcd->dump()\n");
|
puts("// Callback from vcd->dump()\n");
|
||||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||||
@@ -1837,7 +1965,7 @@ class EmitCTrace : EmitCStmts {
|
|||||||
}
|
}
|
||||||
virtual void visit(AstCoverInc* nodep, AstNUser*) {
|
virtual void visit(AstCoverInc* nodep, AstNUser*) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EmitCTrace(bool slow) {
|
EmitCTrace(bool slow) {
|
||||||
m_funcp = NULL;
|
m_funcp = NULL;
|
||||||
|
|||||||
+6
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit C++ code for module tree
|
// DESCRIPTION: Verilator: Emit C++ code for module tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3EMITC_H_
|
#ifndef _V3EMITC_H_
|
||||||
#define _V3EMITC_H_ 1
|
#define _V3EMITC_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
class V3EmitC {
|
class V3EmitC {
|
||||||
public:
|
public:
|
||||||
static void emitc();
|
static void emitc();
|
||||||
|
static void emitcInlines();
|
||||||
static void emitcSyms();
|
static void emitcSyms();
|
||||||
static void emitcTrace();
|
static void emitcTrace();
|
||||||
};
|
};
|
||||||
|
|||||||
+9
-8
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit C++ for tree
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -22,11 +22,12 @@
|
|||||||
#ifndef _V3EMITCBASE_H_
|
#ifndef _V3EMITCBASE_H_
|
||||||
#define _V3EMITCBASE_H_ 1
|
#define _V3EMITCBASE_H_ 1
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3File.h"
|
#include "V3File.h"
|
||||||
@@ -109,7 +110,7 @@ public:
|
|||||||
bool optSystemPerl() { return v3Global.opt.systemPerl(); }
|
bool optSystemPerl() { return v3Global.opt.systemPerl(); }
|
||||||
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }
|
static string symClassName() { return v3Global.opt.prefix()+"__Syms"; }
|
||||||
static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; }
|
static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; }
|
||||||
static string symTopAssign() { return v3Global.opt.prefix()+"* __restrict vlTOPp = vlSymsp->TOPp;"; }
|
static string symTopAssign() { return v3Global.opt.prefix()+"* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; }
|
||||||
static string modClassName(AstModule* modp) { // Return name of current module being processed
|
static string modClassName(AstModule* modp) { // Return name of current module being processed
|
||||||
if (modp->isTop()) {
|
if (modp->isTop()) {
|
||||||
return v3Global.opt.prefix();
|
return v3Global.opt.prefix();
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
//*************************************************************************
|
||||||
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
||||||
|
//
|
||||||
|
// Code available from: http://www.veripool.org/verilator
|
||||||
|
//
|
||||||
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
//
|
||||||
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
// General Public License or the Perl Artistic License.
|
||||||
|
//
|
||||||
|
// Verilator 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.
|
||||||
|
//
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "V3Global.h"
|
||||||
|
#include "V3EmitC.h"
|
||||||
|
#include "V3EmitCBase.h"
|
||||||
|
#include "V3Stats.h"
|
||||||
|
|
||||||
|
#define EMITCINLINES_NUM_CONSTW 10 // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_9X is last)
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
class EmitCInlines : EmitCBaseVisitor {
|
||||||
|
// STATE
|
||||||
|
vector<V3Double0> m_wordWidths; // What sizes are used?
|
||||||
|
|
||||||
|
// METHODS
|
||||||
|
void emitInt();
|
||||||
|
|
||||||
|
// VISITORS
|
||||||
|
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||||
|
// All wide constants load into variables, so we can just hunt for them
|
||||||
|
if (nodep->widthWords() >= EMITCINLINES_NUM_CONSTW ) {
|
||||||
|
if (int(m_wordWidths.size()) <= nodep->widthWords()) {
|
||||||
|
m_wordWidths.resize(nodep->widthWords()+5);
|
||||||
|
}
|
||||||
|
++ m_wordWidths.at(nodep->widthWords());
|
||||||
|
v3Global.needHInlines(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOPs
|
||||||
|
virtual void visit(AstNodeStmt*, AstNUser*) {}
|
||||||
|
// Default
|
||||||
|
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
//---------------------------------------
|
||||||
|
// ACCESSORS
|
||||||
|
public:
|
||||||
|
EmitCInlines(AstNetlist* nodep) {
|
||||||
|
nodep->accept(*this);
|
||||||
|
if (v3Global.needHInlines()) {
|
||||||
|
emitInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void EmitCInlines::emitInt() {
|
||||||
|
string filename = v3Global.opt.makeDir()+"/"+topClassName()+"__Inlines.h";
|
||||||
|
newCFile(filename, false/*slow*/, false/*source*/);
|
||||||
|
V3OutCFile hf (filename);
|
||||||
|
m_ofp = &hf;
|
||||||
|
|
||||||
|
ofp()->putsHeader();
|
||||||
|
puts("#ifndef _"+topClassName()+"__Inlines_H_\n");
|
||||||
|
puts("#define _"+topClassName()+"__Inlines_H_\n");
|
||||||
|
puts("\n");
|
||||||
|
|
||||||
|
puts("#include \"verilated.h\"\n");
|
||||||
|
|
||||||
|
puts("\n//======================\n\n");
|
||||||
|
|
||||||
|
for (unsigned words=0; words<m_wordWidths.size(); words++) {
|
||||||
|
if (m_wordWidths.at(words)) {
|
||||||
|
puts("#ifndef VL_HAVE_CONST_W_"+cvtToStr(words)+"X\n");
|
||||||
|
puts("# define VL_HAVE_CONST_W_"+cvtToStr(words)+"X\n");
|
||||||
|
puts("static inline WDataOutP VL_CONST_W_"+cvtToStr(words)+"X(int obits, WDataOutP o\n");
|
||||||
|
puts("\t");
|
||||||
|
for (int i=words-1; i>=0; --i) {
|
||||||
|
puts(",IData d"+cvtToStr(i));
|
||||||
|
if (i && (i % 8 == 0)) puts("\n\t");
|
||||||
|
}
|
||||||
|
puts(") {\n");
|
||||||
|
puts(" ");
|
||||||
|
for (int i=words-1; i>=0; --i) {
|
||||||
|
puts(" o["+cvtToStr(i)+"]=d"+cvtToStr(i)+";");
|
||||||
|
if (i && (i % 8 == 0)) puts("\n ");
|
||||||
|
}
|
||||||
|
puts("\n");
|
||||||
|
puts(" for(int i="+cvtToStr(words)+";i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0;\n");
|
||||||
|
puts(" return o;\n");
|
||||||
|
puts("}\n");
|
||||||
|
puts("#endif\n");
|
||||||
|
puts("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("//======================\n\n");
|
||||||
|
puts("#endif /*guard*/\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
// EmitC class functions
|
||||||
|
|
||||||
|
void V3EmitC::emitcInlines() {
|
||||||
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||||
|
EmitCInlines syms (v3Global.rootp());
|
||||||
|
}
|
||||||
+10
-15
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit C++ for tree
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,11 +18,12 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -67,7 +67,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||||||
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
virtual void visit(AstNetlist* nodep, AstNUser*) {
|
||||||
// Collect list of scopes
|
// Collect list of scopes
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
|
||||||
// Sort m_scopes by scope name
|
// Sort m_scopes by scope name
|
||||||
sort(m_scopes.begin(), m_scopes.end(), CmpName());
|
sort(m_scopes.begin(), m_scopes.end(), CmpName());
|
||||||
// Output
|
// Output
|
||||||
@@ -124,18 +124,14 @@ void EmitCSyms::emitInt() {
|
|||||||
//puts("\n// STATIC STATE\n");
|
//puts("\n// STATIC STATE\n");
|
||||||
|
|
||||||
puts("\n// LOCAL STATE\n");
|
puts("\n// LOCAL STATE\n");
|
||||||
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint64_t));
|
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(vluint64_t));
|
||||||
puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert.
|
puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert.
|
||||||
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
|
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
|
||||||
puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n");
|
puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n");
|
||||||
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
|
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
|
||||||
puts("bool\t__Vm_didInit;\n");
|
puts("bool\t__Vm_didInit;\n");
|
||||||
if (v3Global.opt.coverage()) {
|
|
||||||
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
|
|
||||||
puts("bool __Vm_coverageRequest;\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint64_t));
|
ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(vluint64_t));
|
||||||
puts("\n// SUBCELL STATE\n");
|
puts("\n// SUBCELL STATE\n");
|
||||||
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||||
AstScope* scopep = it->first; AstModule* modp = it->second;
|
AstScope* scopep = it->first; AstModule* modp = it->second;
|
||||||
@@ -184,7 +180,6 @@ void EmitCSyms::emitImp() {
|
|||||||
puts("\t: __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed
|
puts("\t: __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed
|
||||||
puts("\t, __Vm_activity(false)\n");
|
puts("\t, __Vm_activity(false)\n");
|
||||||
puts("\t, __Vm_didInit(false)\n");
|
puts("\t, __Vm_didInit(false)\n");
|
||||||
if (v3Global.opt.coverage()) puts("\t, __Vm_coverageRequest(false)\n");
|
|
||||||
puts("\t// Setup submodule names\n");
|
puts("\t// Setup submodule names\n");
|
||||||
char comma=',';
|
char comma=',';
|
||||||
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||||
|
|||||||
+16
-12
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit Makefile
|
// DESCRIPTION: Verilator: Emit Makefile
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,11 +18,12 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -46,6 +46,7 @@ public:
|
|||||||
of.putsHeader();
|
of.putsHeader();
|
||||||
of.puts("\n");
|
of.puts("\n");
|
||||||
|
|
||||||
|
of.puts("VM_COVERAGE = "); of.puts(v3Global.opt.coverage()?"1":"0"); of.puts("\n");
|
||||||
of.puts("VM_TRACE = "); of.puts(v3Global.opt.trace()?"1":"0"); of.puts("\n");
|
of.puts("VM_TRACE = "); of.puts(v3Global.opt.trace()?"1":"0"); of.puts("\n");
|
||||||
of.puts("\n");
|
of.puts("\n");
|
||||||
|
|
||||||
@@ -78,16 +79,16 @@ public:
|
|||||||
of.puts("default: "+v3Global.opt.prefix()+"__ALL.a\n");
|
of.puts("default: "+v3Global.opt.prefix()+"__ALL.a\n");
|
||||||
}
|
}
|
||||||
of.puts("\n# Constants...\n");
|
of.puts("\n# Constants...\n");
|
||||||
of.puts("PERL = "+V3Options::getenvStr("PERL","perl")+"\n");
|
of.puts("PERL = "+V3Options::getenvPERL()+"\n");
|
||||||
of.puts("VERILATOR_ROOT = "+V3Options::getenvStr("VERILATOR_ROOT","")+"\n");
|
of.puts("VERILATOR_ROOT = "+V3Options::getenvVERILATOR_ROOT()+"\n");
|
||||||
of.puts("SYSTEMPERL = "+V3Options::getenvStr("SYSTEMPERL","")+"\n");
|
of.puts("SYSTEMPERL = "+V3Options::getenvSYSTEMPERL()+"\n");
|
||||||
|
|
||||||
of.puts("\n# Switches...\n");
|
of.puts("\n# Switches...\n");
|
||||||
of.puts(string("VM_SP = ")+(v3Global.opt.systemPerl()?"1":"0")+"\n");
|
of.puts(string("VM_SP = ")+(v3Global.opt.systemPerl()?"1":"0")+"\n");
|
||||||
of.puts(string("VM_SC = ")+((v3Global.opt.systemC()&&!v3Global.opt.systemPerl())?"1":"0")+"\n");
|
of.puts(string("VM_SC = ")+((v3Global.opt.systemC()&&!v3Global.opt.systemPerl())?"1":"0")+"\n");
|
||||||
of.puts(string("VM_SP_OR_SC = ")+(v3Global.opt.systemC()?"1":"0")+"\n");
|
of.puts(string("VM_SP_OR_SC = ")+(v3Global.opt.systemC()?"1":"0")+"\n");
|
||||||
of.puts(string("VM_PCLI = ")+(v3Global.opt.systemC()?"0":"1")+"\n");
|
of.puts(string("VM_PCLI = ")+(v3Global.opt.systemC()?"0":"1")+"\n");
|
||||||
of.puts(string("VM_SC_TARGET_ARCH = ")+V3Options::getenvStr("SYSTEMC_ARCH","")+"\n");
|
of.puts(string("VM_SC_TARGET_ARCH = ")+V3Options::getenvSYSTEMC_ARCH()+"\n");
|
||||||
|
|
||||||
of.puts("\n# Vars...\n");
|
of.puts("\n# Vars...\n");
|
||||||
of.puts(string("VM_PREFIX = ")+v3Global.opt.prefix()+"\n");
|
of.puts(string("VM_PREFIX = ")+v3Global.opt.prefix()+"\n");
|
||||||
@@ -96,6 +97,9 @@ public:
|
|||||||
// Imply generating verilated.o
|
// Imply generating verilated.o
|
||||||
if (v3Global.opt.exe()) {
|
if (v3Global.opt.exe()) {
|
||||||
v3Global.opt.addCppFile("verilated.cpp");
|
v3Global.opt.addCppFile("verilated.cpp");
|
||||||
|
if (v3Global.opt.trace()) {
|
||||||
|
v3Global.opt.addCppFile("SpTraceVcdC.cpp");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
V3StringSet dirs;
|
V3StringSet dirs;
|
||||||
@@ -134,7 +138,7 @@ public:
|
|||||||
|
|
||||||
of.puts("\n# Link rules...\n");
|
of.puts("\n# Link rules...\n");
|
||||||
of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(SP_SRCS) $(VM_PREFIX)__ALL.a\n");
|
of.puts(v3Global.opt.prefix()+": $(VK_USER_OBJS) $(SP_SRCS) $(VM_PREFIX)__ALL.a\n");
|
||||||
of.puts("\t$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) 2>&1 | c++filt\n");
|
of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LIBS) $(SC_LIBS) 2>&1 | c++filt\n");
|
||||||
of.puts("\n");
|
of.puts("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit Makefile
|
// DESCRIPTION: Verilator: Emit Makefile
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3EMITMK_H_
|
#ifndef _V3EMITMK_H_
|
||||||
#define _V3EMITMK_H_ 1
|
#define _V3EMITMK_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+45
-16
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit Verilog from tree
|
// DESCRIPTION: Verilator: Emit Verilog from tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,11 +18,12 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <cmath>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -163,19 +163,30 @@ public:
|
|||||||
virtual void visit(AstCoverInc*, AstNUser*) {
|
virtual void visit(AstCoverInc*, AstNUser*) {
|
||||||
// N/A
|
// N/A
|
||||||
}
|
}
|
||||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
|
||||||
|
void visitNodeDisplay(AstNode* nodep, AstNode* filep, const string& text, AstNode* exprsp) {
|
||||||
putbs(nodep->verilogKwd());
|
putbs(nodep->verilogKwd());
|
||||||
putbs(" (");
|
putbs(" (");
|
||||||
if (nodep->filep()) { nodep->filep()->iterateAndNext(*this); putbs(","); }
|
if (filep) { filep->iterateAndNext(*this); putbs(","); }
|
||||||
puts("\"");
|
puts("\"");
|
||||||
ofp()->putsNoTracking(nodep->text());
|
ofp()->putsNoTracking(text);
|
||||||
puts("\"");
|
puts("\"");
|
||||||
for (AstNode* expp=nodep->exprsp(); expp; expp = expp->nextp()) {
|
for (AstNode* expp=exprsp; expp; expp = expp->nextp()) {
|
||||||
puts(",");
|
puts(",");
|
||||||
expp->iterateAndNext(*this);
|
expp->iterateAndNext(*this);
|
||||||
}
|
}
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||||
|
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
||||||
|
}
|
||||||
|
virtual void visit(AstFScanF* nodep, AstNUser*) {
|
||||||
|
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
||||||
|
}
|
||||||
|
virtual void visit(AstSScanF* nodep, AstNUser*) {
|
||||||
|
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
|
||||||
|
}
|
||||||
|
|
||||||
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
virtual void visit(AstFOpen* nodep, AstNUser*) {
|
||||||
putbs(nodep->verilogKwd());
|
putbs(nodep->verilogKwd());
|
||||||
putbs(" (");
|
putbs(" (");
|
||||||
@@ -192,6 +203,22 @@ public:
|
|||||||
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
|
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
|
||||||
puts(");\n");
|
puts(");\n");
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||||
|
putbs(nodep->verilogKwd());
|
||||||
|
putbs(" (");
|
||||||
|
if (nodep->filep()) nodep->filep()->iterateChildren(*this);
|
||||||
|
puts(");\n");
|
||||||
|
}
|
||||||
|
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
||||||
|
putbs(nodep->verilogKwd());
|
||||||
|
putbs(" (");
|
||||||
|
if (nodep->filenamep()) nodep->filenamep()->iterateChildren(*this);
|
||||||
|
putbs(",");
|
||||||
|
if (nodep->memp()) nodep->memp()->iterateChildren(*this);
|
||||||
|
if (nodep->lsbp()) { putbs(","); nodep->lsbp()->iterateChildren(*this); }
|
||||||
|
if (nodep->msbp()) { putbs(","); nodep->msbp()->iterateChildren(*this); }
|
||||||
|
puts(");\n");
|
||||||
|
}
|
||||||
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
virtual void visit(AstNodeFor* nodep, AstNUser*) {
|
||||||
puts("for (");
|
puts("for (");
|
||||||
m_suppressSemi = true;
|
m_suppressSemi = true;
|
||||||
@@ -235,6 +262,8 @@ public:
|
|||||||
virtual void visit(AstText* nodep, AstNUser*) {
|
virtual void visit(AstText* nodep, AstNUser*) {
|
||||||
ofp()->putsNoTracking(nodep->text());
|
ofp()->putsNoTracking(nodep->text());
|
||||||
}
|
}
|
||||||
|
virtual void visit(AstScopeName* nodep, AstNUser*) {
|
||||||
|
}
|
||||||
virtual void visit(AstCStmt* nodep, AstNUser*) {
|
virtual void visit(AstCStmt* nodep, AstNUser*) {
|
||||||
putbs("$_CSTMT(");
|
putbs("$_CSTMT(");
|
||||||
nodep->bodysp()->iterateAndNext(*this);
|
nodep->bodysp()->iterateAndNext(*this);
|
||||||
@@ -333,11 +362,11 @@ public:
|
|||||||
if (nodep->widthp()->isOne()) {
|
if (nodep->widthp()->isOne()) {
|
||||||
nodep->lsbp()->iterateAndNext(*this);
|
nodep->lsbp()->iterateAndNext(*this);
|
||||||
} else {
|
} else {
|
||||||
puts(cvtToStr(nodep->lsbp()->castConst()->asInt()
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()
|
||||||
+nodep->widthp()->castConst()->asInt()
|
+nodep->widthp()->castConst()->toSInt()
|
||||||
-1));
|
-1));
|
||||||
puts(":");
|
puts(":");
|
||||||
nodep->lsbp()->iterateAndNext(*this);
|
puts(cvtToStr(nodep->lsbp()->castConst()->toSInt()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nodep->lsbp()->iterateAndNext(*this); puts("+:");
|
nodep->lsbp()->iterateAndNext(*this); puts("+:");
|
||||||
@@ -355,12 +384,12 @@ public:
|
|||||||
// Terminals
|
// Terminals
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
puts(nodep->hiername());
|
puts(nodep->hiername());
|
||||||
puts(nodep->varp()->name());
|
puts(nodep->varp()->name());
|
||||||
}
|
}
|
||||||
virtual void visit(AstVarXRef* nodep, AstNUser*) {
|
virtual void visit(AstVarXRef* nodep, AstNUser*) {
|
||||||
puts(nodep->dotted());
|
puts(nodep->dotted());
|
||||||
puts(".");
|
puts(".");
|
||||||
puts(nodep->varp()->name());
|
puts(nodep->varp()->name());
|
||||||
}
|
}
|
||||||
virtual void visit(AstConst* nodep, AstNUser*) {
|
virtual void visit(AstConst* nodep, AstNUser*) {
|
||||||
puts(nodep->num().ascii(true,true));
|
puts(nodep->num().ascii(true,true));
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
//-*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Emit Verilog code for module tree
|
// DESCRIPTION: Verilator: Emit Verilog code for module tree
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3EMITV_H_
|
#ifndef _V3EMITV_H_
|
||||||
#define _V3EMITV_H_ 1
|
#define _V3EMITV_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+126
-24
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Error handling
|
// DESCRIPTION: Verilator: Error handling
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,9 +18,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stdarg.h>
|
#include <cstdarg>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
|
#include <set>
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#ifndef _V3ERROR_NO_GLOBAL_
|
#ifndef _V3ERROR_NO_GLOBAL_
|
||||||
# include "V3Ast.h"
|
# include "V3Ast.h"
|
||||||
@@ -34,7 +34,8 @@
|
|||||||
|
|
||||||
FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret());
|
FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret());
|
||||||
|
|
||||||
int V3Error::s_errcnt = 0;
|
int V3Error::s_errCount = 0;
|
||||||
|
int V3Error::s_warnCount = 0;
|
||||||
int V3Error::s_debugDefault = 0;
|
int V3Error::s_debugDefault = 0;
|
||||||
ostringstream V3Error::s_errorStr; // Error string being formed
|
ostringstream V3Error::s_errorStr; // Error string being formed
|
||||||
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL;
|
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::FATAL;
|
||||||
@@ -45,7 +46,7 @@ bool V3Error::s_pretendError[V3ErrorCode::MAX];
|
|||||||
struct v3errorIniter {
|
struct v3errorIniter {
|
||||||
v3errorIniter() { V3Error::init(); };
|
v3errorIniter() { V3Error::init(); };
|
||||||
};
|
};
|
||||||
v3errorIniter v3errorInit;
|
v3errorIniter v3errorInit;
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// ErrorCode class functions
|
// ErrorCode class functions
|
||||||
@@ -64,6 +65,17 @@ V3ErrorCode::V3ErrorCode(const char* msgp) {
|
|||||||
//######################################################################
|
//######################################################################
|
||||||
// FileLine class functions
|
// FileLine class functions
|
||||||
|
|
||||||
|
FileLine::FileLine(FileLine::EmptySecret) {
|
||||||
|
m_lineno=0;
|
||||||
|
m_filename="COMMAND_LINE";
|
||||||
|
|
||||||
|
m_warnOff=0;
|
||||||
|
for (int codei=V3ErrorCode::FIRST_WARN; codei<V3ErrorCode::MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
if (code.defaultsOff()) warnOff(code, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FileLine::lineDirective(const char* textp) {
|
void FileLine::lineDirective(const char* textp) {
|
||||||
// Handle `line directive
|
// Handle `line directive
|
||||||
// Skip `line
|
// Skip `line
|
||||||
@@ -92,7 +104,7 @@ void FileLine::lineDirective(const char* textp) {
|
|||||||
|
|
||||||
bool FileLine::warnOff(const string& msg, bool flag) {
|
bool FileLine::warnOff(const string& msg, bool flag) {
|
||||||
V3ErrorCode code (msg.c_str());
|
V3ErrorCode code (msg.c_str());
|
||||||
if (code == V3ErrorCode::ERROR) {
|
if (code < V3ErrorCode::FIRST_WARN) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
warnOff(code, flag);
|
warnOff(code, flag);
|
||||||
@@ -100,9 +112,16 @@ bool FileLine::warnOff(const string& msg, bool flag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileLine::warnLintOff(bool flag) {
|
||||||
|
for (int codei=V3ErrorCode::FIRST_WARN; codei<V3ErrorCode::MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
if (code.lintError()) warnOff(code, flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FileLine* FileLine::copyOrSameFileLine() {
|
FileLine* FileLine::copyOrSameFileLine() {
|
||||||
// Return this, or a copy of this
|
// Return this, or a copy of this
|
||||||
// There are often more then one token per line, thus we use the
|
// There are often more than one token per line, thus we use the
|
||||||
// same pointer as long as we're on the same line.
|
// same pointer as long as we're on the same line.
|
||||||
static FileLine* lastNewp = NULL;
|
static FileLine* lastNewp = NULL;
|
||||||
if (lastNewp && *lastNewp == *this) {
|
if (lastNewp && *lastNewp == *this) {
|
||||||
@@ -145,13 +164,23 @@ ostream& operator<<(ostream& os, FileLine* fileline) {
|
|||||||
return(os);
|
return(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLine::warnIsOff(V3ErrorCode code) {
|
bool FileLine::warnIsOff(V3ErrorCode code) const {
|
||||||
if (m_warnOff.test(code)) return true;
|
if (m_warnOff.test(code)) return true;
|
||||||
// UNOPTFLAT implies UNOPT
|
// UNOPTFLAT implies UNOPT
|
||||||
if (code==V3ErrorCode::UNOPT && m_warnOff.test(V3ErrorCode::UNOPTFLAT)) return true;
|
if (code==V3ErrorCode::UNOPT && m_warnOff.test(V3ErrorCode::UNOPTFLAT)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileLine::warnStateInherit(const FileLine& from) {
|
||||||
|
// Any warnings that are off in "from", become off in "this".
|
||||||
|
for (int codei=V3ErrorCode::FIRST_WARN; codei<V3ErrorCode::MAX; codei++) {
|
||||||
|
V3ErrorCode code = (V3ErrorCode)codei;
|
||||||
|
if (from.warnIsOff(code)) {
|
||||||
|
this->warnOff(code, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FileLine::v3errorEnd(ostringstream& str) {
|
void FileLine::v3errorEnd(ostringstream& str) {
|
||||||
if (this && m_lineno) {
|
if (this && m_lineno) {
|
||||||
ostringstream nsstr;
|
ostringstream nsstr;
|
||||||
@@ -162,15 +191,54 @@ void FileLine::v3errorEnd(ostringstream& str) {
|
|||||||
V3Error::v3errorEnd(str);
|
V3Error::v3errorEnd(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
typedef set<FileLine*> FileLineCheckSet;
|
||||||
|
FileLineCheckSet fileLineLeakChecks;
|
||||||
|
|
||||||
|
void* FileLine::operator new(size_t size) {
|
||||||
|
FileLine* objp = static_cast<FileLine*>(::operator new(size));
|
||||||
|
fileLineLeakChecks.insert(objp);
|
||||||
|
return objp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLine::operator delete(void* objp, size_t size) {
|
||||||
|
if (!objp) return;
|
||||||
|
FileLine* flp = static_cast<FileLine*>(objp);
|
||||||
|
FileLineCheckSet::iterator it = fileLineLeakChecks.find(flp);
|
||||||
|
if (it != fileLineLeakChecks.end()) {
|
||||||
|
fileLineLeakChecks.erase(it);
|
||||||
|
} else {
|
||||||
|
flp->v3fatalSrc("Deleting FileLine object that was never tracked\n");
|
||||||
|
}
|
||||||
|
::operator delete(objp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void FileLine::deleteAllRemaining() {
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
// FileLines are allocated, but never nicely freed, as it's much faster
|
||||||
|
// that way. Unfortunately this makes our leak checking a big mess, so
|
||||||
|
// only when leak checking we'll track them all and cleanup.
|
||||||
|
while (1) {
|
||||||
|
FileLineCheckSet::iterator it=fileLineLeakChecks.begin();
|
||||||
|
if (it==fileLineLeakChecks.end()) break;
|
||||||
|
delete *it;
|
||||||
|
// Operator delete will remove the iterated object from the list.
|
||||||
|
// Eventually the list will be empty and terminate the loop.
|
||||||
|
}
|
||||||
|
fileLineLeakChecks.clear();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3Error class functions
|
// V3Error class functions
|
||||||
|
|
||||||
void V3Error::init() {
|
void V3Error::init() {
|
||||||
for (int i=0; i<V3ErrorCode::MAX; i++) {
|
for (int i=0; i<V3ErrorCode::MAX; i++) {
|
||||||
s_describedEachWarn[i] = false;
|
s_describedEachWarn[i] = false;
|
||||||
s_pretendError[i] = false;
|
s_pretendError[i] = V3ErrorCode(i).pretendError();
|
||||||
}
|
}
|
||||||
pretendError(V3ErrorCode::BLKANDNBLK, true);
|
|
||||||
|
|
||||||
if (string(V3ErrorCode(V3ErrorCode::MAX).ascii()) != " MAX") {
|
if (string(V3ErrorCode(V3ErrorCode::MAX).ascii()) != " MAX") {
|
||||||
v3fatalSrc("Enum table in V3ErrorCode::ascii() is munged");
|
v3fatalSrc("Enum table in V3ErrorCode::ascii() is munged");
|
||||||
@@ -188,24 +256,46 @@ string V3Error::lineStr (const char* filename, int lineno) {
|
|||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Error::incWarnings() {
|
||||||
|
s_warnCount++;
|
||||||
|
// We don't exit on a lot of warnings.
|
||||||
|
}
|
||||||
|
|
||||||
void V3Error::incErrors() {
|
void V3Error::incErrors() {
|
||||||
s_errcnt++;
|
s_errCount++;
|
||||||
if (errorCount() == MAX_ERRORS) { // Not >= as would otherwise recurse
|
if (errorCount() == v3Global.opt.errorLimit()) { // Not >= as would otherwise recurse
|
||||||
v3fatal ("Exiting due to too many errors encountered\n");
|
v3fatal ("Exiting due to too many errors encountered; --error-limit="<<errorCount()<<endl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void V3Error::abortIfErrors() {
|
void V3Error::abortIfErrors() {
|
||||||
if (errorCount()) {
|
if (errorCount()) {
|
||||||
v3fatal ("Exiting due to "<<dec<<errorCount()<<" warning(s)\n");
|
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3Error::abortIfWarnings() {
|
||||||
|
if (errorOrWarnCount()) {
|
||||||
|
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool V3Error::isError(V3ErrorCode code) {
|
||||||
|
if (code==V3ErrorCode::SUPPRESS) return false;
|
||||||
|
else if (code==V3ErrorCode::INFO) return false;
|
||||||
|
else if (code==V3ErrorCode::FATAL) return true;
|
||||||
|
else if (code==V3ErrorCode::ERROR) return true;
|
||||||
|
else if (code<V3ErrorCode::FIRST_WARN
|
||||||
|
|| s_pretendError[code]) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
string V3Error::msgPrefix(V3ErrorCode code) {
|
string V3Error::msgPrefix(V3ErrorCode code) {
|
||||||
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
|
if (code==V3ErrorCode::SUPPRESS) return "-arning-suppressed: ";
|
||||||
|
else if (code==V3ErrorCode::INFO) return "-Info: ";
|
||||||
else if (code==V3ErrorCode::FATAL) return "%Error: ";
|
else if (code==V3ErrorCode::FATAL) return "%Error: ";
|
||||||
else if (code==V3ErrorCode::ERROR
|
else if (code==V3ErrorCode::ERROR) return "%Error: ";
|
||||||
|| s_pretendError[code]) return "%Error: ";
|
else if (isError(code)) return "%Error-"+(string)code.ascii()+": ";
|
||||||
else return "%Warning-"+(string)code.ascii()+": ";
|
else return "%Warning-"+(string)code.ascii()+": ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,12 +326,18 @@ void V3Error::v3abort () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void V3Error::v3errorEnd (ostringstream& sstr) {
|
void V3Error::v3errorEnd (ostringstream& sstr) {
|
||||||
if (s_errorCode!=V3ErrorCode::SUPPRESS || debug()) {
|
#ifdef __COVERITY__
|
||||||
|
if (s_errorCode==V3ErrorCode::FATAL) __coverity_panic__(x);
|
||||||
|
#endif
|
||||||
|
if (s_errorCode!=V3ErrorCode::SUPPRESS
|
||||||
|
// On debug, show only non default-off warning to prevent pages of warnings
|
||||||
|
|| (debug() && !s_errorCode.defaultsOff())) {
|
||||||
cerr<<msgPrefix()<<sstr.str();
|
cerr<<msgPrefix()<<sstr.str();
|
||||||
if (sstr.str()[sstr.str().length()-1] != '\n') {
|
if (sstr.str()[sstr.str().length()-1] != '\n') {
|
||||||
cerr<<endl;
|
cerr<<endl;
|
||||||
}
|
}
|
||||||
if (s_errorCode!=V3ErrorCode::SUPPRESS) {
|
if (s_errorCode!=V3ErrorCode::SUPPRESS
|
||||||
|
&& s_errorCode!=V3ErrorCode::INFO) {
|
||||||
if (!s_describedEachWarn[s_errorCode]
|
if (!s_describedEachWarn[s_errorCode]
|
||||||
&& !s_pretendError[s_errorCode]) {
|
&& !s_pretendError[s_errorCode]) {
|
||||||
s_describedEachWarn[s_errorCode] = true;
|
s_describedEachWarn[s_errorCode] = true;
|
||||||
@@ -255,7 +351,8 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
|
|||||||
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
|
cerr<<msgPrefix()<<"else you may end up with different sim results."<<endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
incErrors();
|
if (isError(s_errorCode)) incErrors();
|
||||||
|
else incWarnings();
|
||||||
if (s_errorCode==V3ErrorCode::FATAL) {
|
if (s_errorCode==V3ErrorCode::FATAL) {
|
||||||
static bool inFatal = false;
|
static bool inFatal = false;
|
||||||
if (!inFatal) {
|
if (!inFatal) {
|
||||||
@@ -268,8 +365,13 @@ void V3Error::v3errorEnd (ostringstream& sstr) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
abort();
|
|
||||||
// exit(10);
|
if (V3Error::debugDefault()) {
|
||||||
|
cerr<<msgPrefix()<<"Aborting since under --debug"<<endl;
|
||||||
|
abort();
|
||||||
|
} else {
|
||||||
|
exit(10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+61
-18
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Error handling
|
// DESCRIPTION: Verilator: Error handling
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3ERROR_H_
|
#ifndef _V3ERROR_H_
|
||||||
#define _V3ERROR_H_ 1
|
#define _V3ERROR_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -33,19 +34,29 @@ class V3ErrorCode {
|
|||||||
public:
|
public:
|
||||||
enum en {
|
enum en {
|
||||||
SUPPRESS, // Warning suppressed by user
|
SUPPRESS, // Warning suppressed by user
|
||||||
|
INFO, // General information out
|
||||||
FATAL, // Kill the program
|
FATAL, // Kill the program
|
||||||
ERROR, // Error out, can't suppress
|
ERROR, // General error out, can't suppress
|
||||||
|
// Error codes:
|
||||||
|
MULTITOP, // Error: Multiple top level modules
|
||||||
|
TASKNSVAR, // Error: Task I/O not simple
|
||||||
// Warning codes:
|
// Warning codes:
|
||||||
FIRST_WARN, // Just a code so the program knows where to start warnings
|
FIRST_WARN, // Just a code so the program knows where to start warnings
|
||||||
|
//
|
||||||
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
|
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
|
||||||
CASEINCOMPLETE, // Case statement has missing values
|
CASEINCOMPLETE, // Case statement has missing values
|
||||||
CASEOVERLAP, // Case statements overlap
|
CASEOVERLAP, // Case statements overlap
|
||||||
|
CASEWITHX, // Case with X values
|
||||||
CASEX, // Casex
|
CASEX, // Casex
|
||||||
CMPCONST, // Comparison is constant due to limited range
|
CMPCONST, // Comparison is constant due to limited range
|
||||||
COMBDLY, // Combinatorial delayed assignment
|
COMBDLY, // Combinatorial delayed assignment
|
||||||
|
STMTDLY, // Delayed statement
|
||||||
GENCLK, // Generated Clock
|
GENCLK, // Generated Clock
|
||||||
|
IMPERFECTSCH, // Imperfect schedule (disabled by default)
|
||||||
IMPLICIT, // Implicit wire
|
IMPLICIT, // Implicit wire
|
||||||
|
IMPURE, // Impure function not being inlined
|
||||||
MULTIDRIVEN, // Driven from multiple blocks
|
MULTIDRIVEN, // Driven from multiple blocks
|
||||||
|
REDEFMACRO, // Redefining existing define macro
|
||||||
UNDRIVEN, // No drivers
|
UNDRIVEN, // No drivers
|
||||||
UNOPT, // Unoptimizable block
|
UNOPT, // Unoptimizable block
|
||||||
UNOPTFLAT, // Unoptimizable block after flattening
|
UNOPTFLAT, // Unoptimizable block after flattening
|
||||||
@@ -53,6 +64,7 @@ public:
|
|||||||
UNUSED, // No receivers
|
UNUSED, // No receivers
|
||||||
VARHIDDEN, // Hiding variable
|
VARHIDDEN, // Hiding variable
|
||||||
WIDTH, // Width mismatch
|
WIDTH, // Width mismatch
|
||||||
|
WIDTHCONCAT, // Unsized numbers/parameters in concatenations
|
||||||
MAX
|
MAX
|
||||||
// ***Add new elements below also***
|
// ***Add new elements below also***
|
||||||
};
|
};
|
||||||
@@ -65,20 +77,34 @@ public:
|
|||||||
const char* ascii() const {
|
const char* ascii() const {
|
||||||
const char* names[] = {
|
const char* names[] = {
|
||||||
// Leading spaces indicate it can't be disabled.
|
// Leading spaces indicate it can't be disabled.
|
||||||
" SUPPRESS", " FATAL", " ERROR",
|
" SUPPRESS", " INFO", " FATAL", " ERROR",
|
||||||
|
"MULTITOP", "TASKNSVAR",
|
||||||
" FIRST_WARN",
|
" FIRST_WARN",
|
||||||
"BLKANDNBLK",
|
"BLKANDNBLK",
|
||||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEX", "CMPCONST",
|
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CMPCONST",
|
||||||
"COMBDLY", "GENCLK", "IMPLICIT",
|
"COMBDLY", "STMTDLY", "GENCLK", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
|
||||||
"MULTIDRIVEN",
|
"MULTIDRIVEN", "REDEFMACRO",
|
||||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
||||||
"VARHIDDEN", "WIDTH",
|
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
|
||||||
" MAX"
|
" MAX"
|
||||||
};
|
};
|
||||||
return names[m_e];
|
return names[m_e];
|
||||||
};
|
};
|
||||||
|
// Warnings that default to off
|
||||||
|
bool defaultsOff() const { return ( m_e==IMPERFECTSCH );};
|
||||||
// Warnings that warn about nasty side effects
|
// Warnings that warn about nasty side effects
|
||||||
bool dangerous() const { return ( m_e==COMBDLY );};
|
bool dangerous() const { return ( m_e==COMBDLY );};
|
||||||
|
// Warnings we'll present to the user as errors
|
||||||
|
// Later -Werror- options may make more of these.
|
||||||
|
bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE); };
|
||||||
|
// Warnings that are lint only
|
||||||
|
bool lintError() const { return ( m_e==CASEINCOMPLETE || m_e==CASEOVERLAP
|
||||||
|
|| m_e==CASEWITHX || m_e==CASEX
|
||||||
|
|| m_e==CMPCONST
|
||||||
|
|| m_e==IMPLICIT
|
||||||
|
|| m_e==UNDRIVEN || m_e==UNSIGNED
|
||||||
|
|| m_e==UNUSED || m_e==VARHIDDEN
|
||||||
|
|| m_e==WIDTH); };
|
||||||
};
|
};
|
||||||
inline bool operator== (V3ErrorCode lhs, V3ErrorCode rhs) { return (lhs.m_e == rhs.m_e); }
|
inline bool operator== (V3ErrorCode lhs, V3ErrorCode rhs) { return (lhs.m_e == rhs.m_e); }
|
||||||
inline bool operator== (V3ErrorCode lhs, V3ErrorCode::en rhs) { return (lhs.m_e == rhs); }
|
inline bool operator== (V3ErrorCode lhs, V3ErrorCode::en rhs) { return (lhs.m_e == rhs); }
|
||||||
@@ -94,11 +120,11 @@ class V3Error {
|
|||||||
static bool s_describedEachWarn[V3ErrorCode::MAX]; // Told user specifics about this warning
|
static bool s_describedEachWarn[V3ErrorCode::MAX]; // Told user specifics about this warning
|
||||||
static bool s_pretendError[V3ErrorCode::MAX]; // Pretend this warning is an error
|
static bool s_pretendError[V3ErrorCode::MAX]; // Pretend this warning is an error
|
||||||
static int s_debugDefault; // Default debugging level
|
static int s_debugDefault; // Default debugging level
|
||||||
static int s_errcnt; // Error count
|
static int s_errCount; // Error count
|
||||||
|
static int s_warnCount; // Error count
|
||||||
static ostringstream s_errorStr; // Error string being formed
|
static ostringstream s_errorStr; // Error string being formed
|
||||||
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
||||||
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
|
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
|
||||||
static void incErrors();
|
|
||||||
|
|
||||||
V3Error() { cerr<<("Static class"); abort(); }
|
V3Error() { cerr<<("Static class"); abort(); }
|
||||||
|
|
||||||
@@ -108,12 +134,18 @@ class V3Error {
|
|||||||
static void debugDefault(int level) { s_debugDefault = level; }
|
static void debugDefault(int level) { s_debugDefault = level; }
|
||||||
static int debugDefault() { return s_debugDefault; }
|
static int debugDefault() { return s_debugDefault; }
|
||||||
static string msgPrefix(V3ErrorCode code=s_errorCode); // returns %Error/%Warn
|
static string msgPrefix(V3ErrorCode code=s_errorCode); // returns %Error/%Warn
|
||||||
static int errorCount() { return s_errcnt; }
|
static int errorCount() { return s_errCount; }
|
||||||
|
static int warnCount() { return s_warnCount; }
|
||||||
|
static int errorOrWarnCount() { return errorCount()+warnCount(); }
|
||||||
// METHODS
|
// METHODS
|
||||||
|
static void incErrors();
|
||||||
|
static void incWarnings();
|
||||||
static void init();
|
static void init();
|
||||||
static void abortIfErrors();
|
static void abortIfErrors();
|
||||||
|
static void abortIfWarnings();
|
||||||
static void suppressThisWarning(); // Suppress next %Warn if user has it off
|
static void suppressThisWarning(); // Suppress next %Warn if user has it off
|
||||||
static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; }
|
static void pretendError(V3ErrorCode code, bool flag) { s_pretendError[code]=flag; }
|
||||||
|
static bool isError(V3ErrorCode code);
|
||||||
static string v3sform (const char* format, ...);
|
static string v3sform (const char* format, ...);
|
||||||
static string lineStr (const char* filename, int lineno);
|
static string lineStr (const char* filename, int lineno);
|
||||||
static V3ErrorCode errorCode() { return s_errorCode; }
|
static V3ErrorCode errorCode() { return s_errorCode; }
|
||||||
@@ -133,6 +165,7 @@ inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
|||||||
|
|
||||||
// These allow errors using << operators: v3error("foo"<<"bar");
|
// These allow errors using << operators: v3error("foo"<<"bar");
|
||||||
// Careful, you can't put () around msg, as you would in most macro definitions
|
// Careful, you can't put () around msg, as you would in most macro definitions
|
||||||
|
#define v3info(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::INFO)<<msg),V3Error::v3errorStr()));
|
||||||
#define v3fatal(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::FATAL)<<msg),V3Error::v3errorStr()));
|
#define v3fatal(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::FATAL)<<msg),V3Error::v3errorStr()));
|
||||||
#define v3error(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::ERROR)<<msg),V3Error::v3errorStr()));
|
#define v3error(msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::ERROR)<<msg),V3Error::v3errorStr()));
|
||||||
#define v3warn(code,msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::code)<<msg),V3Error::v3errorStr()));
|
#define v3warn(code,msg) v3errorEnd(((V3Error::v3errorPrep(V3ErrorCode::code)<<msg),V3Error::v3errorStr()));
|
||||||
@@ -175,9 +208,14 @@ protected:
|
|||||||
void incLineno() { m_lineno++; }
|
void incLineno() { m_lineno++; }
|
||||||
FileLine* copyOrSameFileLine();
|
FileLine* copyOrSameFileLine();
|
||||||
public:
|
public:
|
||||||
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOff=s_defaultFileLine.m_warnOff;}
|
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOff=s_defaultFileLine.m_warnOff; }
|
||||||
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOff=fromp->m_warnOff;};
|
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOff=fromp->m_warnOff; }
|
||||||
FileLine (EmptySecret) { m_lineno=0; m_filename="COMMAND_LINE"; m_warnOff=0; } // Only for static constructor
|
FileLine (EmptySecret);
|
||||||
|
~FileLine() { }
|
||||||
|
#ifdef VL_LEAK_CHECKS
|
||||||
|
static void* operator new(size_t size);
|
||||||
|
static void operator delete(void* obj, size_t size);
|
||||||
|
#endif
|
||||||
static FileLine& defaultFileLine() { return s_defaultFileLine; }
|
static FileLine& defaultFileLine() { return s_defaultFileLine; }
|
||||||
int lineno () const { return m_lineno; }
|
int lineno () const { return m_lineno; }
|
||||||
string ascii() const;
|
string ascii() const;
|
||||||
@@ -187,11 +225,16 @@ public:
|
|||||||
const string profileFuncname() const;
|
const string profileFuncname() const;
|
||||||
void warnOff(V3ErrorCode code, bool flag) { m_warnOff.set(code,flag); } // Turn on/off warning messages on this line.
|
void warnOff(V3ErrorCode code, bool flag) { m_warnOff.set(code,flag); } // Turn on/off warning messages on this line.
|
||||||
bool warnOff(const string& code, bool flag); // Returns 1 if ok
|
bool warnOff(const string& code, bool flag); // Returns 1 if ok
|
||||||
bool warnIsOff(V3ErrorCode code);
|
bool warnIsOff(V3ErrorCode code) const;
|
||||||
void warnResetDefault() { m_warnOff=s_defaultFileLine.m_warnOff; }
|
void warnLintOff(bool flag);
|
||||||
|
void warnStateFrom(const FileLine& from) { m_warnOff=from.m_warnOff; }
|
||||||
|
void warnStateInherit(const FileLine& from);
|
||||||
|
void warnResetDefault() { warnStateFrom(s_defaultFileLine); }
|
||||||
|
|
||||||
void v3errorEnd(ostringstream& str);
|
void v3errorEnd(ostringstream& str);
|
||||||
inline bool operator==(FileLine rhs) { return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename); }
|
inline bool operator==(FileLine rhs) { return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename); }
|
||||||
|
|
||||||
|
static void deleteAllRemaining();
|
||||||
};
|
};
|
||||||
ostream& operator<<(ostream& os, FileLine* fileline);
|
ostream& operator<<(ostream& os, FileLine* fileline);
|
||||||
|
|
||||||
|
|||||||
+33
-31
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Add temporaries, such as for expand nodes
|
// DESCRIPTION: Verilator: Add temporaries, such as for expand nodes
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2004-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2004-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Expand's Transformations:
|
// V3Expand's Transformations:
|
||||||
//
|
//
|
||||||
// Each module:
|
// Each module:
|
||||||
// Expand verilated.h macros into internal micro optimizations (RTL)
|
// Expand verilated.h macros into internal micro optimizations (RTL)
|
||||||
// this will enable later optimizations.
|
// this will enable later optimizations.
|
||||||
@@ -30,9 +29,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -64,11 +64,8 @@ private:
|
|||||||
if (nodep->isWide()) {
|
if (nodep->isWide()) {
|
||||||
return V3Number (nodep->fileline(), VL_WORDSIZE, VL_MASK_I(nodep->widthMin()));
|
return V3Number (nodep->fileline(), VL_WORDSIZE, VL_MASK_I(nodep->widthMin()));
|
||||||
} else {
|
} else {
|
||||||
V3Number zero (nodep->fileline(), nodep->widthMin(),0);
|
|
||||||
V3Number masksmall (nodep->fileline(), nodep->widthMin());
|
|
||||||
masksmall.opNot(zero);
|
|
||||||
V3Number mask (nodep->fileline(), longOrQuadWidth(nodep));
|
V3Number mask (nodep->fileline(), longOrQuadWidth(nodep));
|
||||||
mask.opAssign(masksmall);
|
mask.setMask(nodep->widthMin());
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,12 +167,12 @@ private:
|
|||||||
}
|
}
|
||||||
return newp;
|
return newp;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode* newSelBitWord(AstNode* lsbp, int wordAdder) {
|
AstNode* newSelBitWord(AstNode* lsbp, int wordAdder) {
|
||||||
// Return equation to get the VL_BITWORD of a constant or non-constant
|
// Return equation to get the VL_BITWORD of a constant or non-constant
|
||||||
if (lsbp->castConst()) {
|
if (lsbp->castConst()) {
|
||||||
return new AstConst (lsbp->fileline(),
|
return new AstConst (lsbp->fileline(),
|
||||||
wordAdder + VL_BITWORD_I(lsbp->castConst()->asInt()));
|
wordAdder + VL_BITWORD_I(lsbp->castConst()->toUInt()));
|
||||||
} else {
|
} else {
|
||||||
AstNode* shiftp = new AstShiftR (lsbp->fileline(),
|
AstNode* shiftp = new AstShiftR (lsbp->fileline(),
|
||||||
lsbp->cloneTree(true),
|
lsbp->cloneTree(true),
|
||||||
@@ -206,7 +203,7 @@ private:
|
|||||||
// Return equation to get the VL_BITBIT of a constant or non-constant
|
// Return equation to get the VL_BITBIT of a constant or non-constant
|
||||||
if (lsbp->castConst()) {
|
if (lsbp->castConst()) {
|
||||||
return new AstConst (lsbp->fileline(),
|
return new AstConst (lsbp->fileline(),
|
||||||
VL_BITBIT_I(lsbp->castConst()->asInt()));
|
VL_BITBIT_I(lsbp->castConst()->toUInt()));
|
||||||
} else {
|
} else {
|
||||||
return new AstAnd (lsbp->fileline(),
|
return new AstAnd (lsbp->fileline(),
|
||||||
new AstConst(lsbp->fileline(), VL_WORDSIZE-1),
|
new AstConst(lsbp->fileline(), VL_WORDSIZE-1),
|
||||||
@@ -357,7 +354,7 @@ private:
|
|||||||
AstNode* lowwordp = new AstWordSel (nodep->fromp()->fileline(),
|
AstNode* lowwordp = new AstWordSel (nodep->fromp()->fileline(),
|
||||||
nodep->fromp()->cloneTree(true),
|
nodep->fromp()->cloneTree(true),
|
||||||
newSelBitWord(nodep->lsbp(), 0));
|
newSelBitWord(nodep->lsbp(), 0));
|
||||||
if (nodep->isQuad() && !lowwordp->isQuad()) lowwordp = new AstCast(nodep->fileline(), lowwordp, nodep);
|
if (nodep->isQuad() && !lowwordp->isQuad()) lowwordp = new AstCast(nodep->fileline(), lowwordp, nodep);
|
||||||
AstNode* lowp = new AstShiftR (nodep->fileline(),
|
AstNode* lowp = new AstShiftR (nodep->fileline(),
|
||||||
lowwordp,
|
lowwordp,
|
||||||
newSelBitBit(nodep->lsbp()),
|
newSelBitBit(nodep->lsbp()),
|
||||||
@@ -370,7 +367,7 @@ private:
|
|||||||
new AstWordSel (nodep->fromp()->fileline(),
|
new AstWordSel (nodep->fromp()->fileline(),
|
||||||
nodep->fromp()->cloneTree(true),
|
nodep->fromp()->cloneTree(true),
|
||||||
newSelBitWord(nodep->lsbp(), 1));
|
newSelBitWord(nodep->lsbp(), 1));
|
||||||
if (nodep->isQuad() && !midwordp->isQuad()) midwordp = new AstCast(nodep->fileline(), midwordp, nodep);
|
if (nodep->isQuad() && !midwordp->isQuad()) midwordp = new AstCast(nodep->fileline(), midwordp, nodep);
|
||||||
// If we're selecting bit zero, then all 32 bits in word 1 get shifted << by 32 bits
|
// If we're selecting bit zero, then all 32 bits in word 1 get shifted << by 32 bits
|
||||||
// else we need to form the lower word, so we << by 31 or less
|
// else we need to form the lower word, so we << by 31 or less
|
||||||
// nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb)
|
// nbitsfromlow <= (lsb==0) ? 64-bitbit(lsb) : 32-bitbit(lsb)
|
||||||
@@ -408,7 +405,7 @@ private:
|
|||||||
new AstWordSel (nodep->fromp()->fileline(),
|
new AstWordSel (nodep->fromp()->fileline(),
|
||||||
nodep->fromp()->cloneTree(true),
|
nodep->fromp()->cloneTree(true),
|
||||||
newSelBitWord(nodep->lsbp(), 2));
|
newSelBitWord(nodep->lsbp(), 2));
|
||||||
if (nodep->isQuad() && !hiwordp->isQuad()) hiwordp = new AstCast(nodep->fileline(), hiwordp, nodep);
|
if (nodep->isQuad() && !hiwordp->isQuad()) hiwordp = new AstCast(nodep->fileline(), hiwordp, nodep);
|
||||||
AstNode* himayp =
|
AstNode* himayp =
|
||||||
new AstShiftL (nodep->fileline(),
|
new AstShiftL (nodep->fileline(),
|
||||||
hiwordp,
|
hiwordp,
|
||||||
@@ -436,7 +433,7 @@ private:
|
|||||||
UINFO(8," SEL->SHIFT "<<nodep<<endl);
|
UINFO(8," SEL->SHIFT "<<nodep<<endl);
|
||||||
AstNode* fromp = nodep->fromp()->unlinkFrBack();
|
AstNode* fromp = nodep->fromp()->unlinkFrBack();
|
||||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||||
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCast(nodep->fileline(), fromp, nodep);
|
if (nodep->isQuad() && !fromp->isQuad()) fromp = new AstCast(nodep->fileline(), fromp, nodep);
|
||||||
AstNode* newp = new AstShiftR (nodep->fileline(),
|
AstNode* newp = new AstShiftR (nodep->fileline(),
|
||||||
fromp,
|
fromp,
|
||||||
dropCondBound(lsbp),
|
dropCondBound(lsbp),
|
||||||
@@ -506,7 +503,7 @@ private:
|
|||||||
bool destwide = lhsp->fromp()->isWide();
|
bool destwide = lhsp->fromp()->isWide();
|
||||||
bool ones = nodep->rhsp()->isAllOnesV();
|
bool ones = nodep->rhsp()->isAllOnesV();
|
||||||
if (lhsp->lsbp()->castConst()) {
|
if (lhsp->lsbp()->castConst()) {
|
||||||
// The code should work without this constant test, but it won't
|
// The code should work without this constant test, but it won't
|
||||||
// constify as nicely as we'd like.
|
// constify as nicely as we'd like.
|
||||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||||
AstNode* destp = lhsp->fromp()->unlinkFrBack();
|
AstNode* destp = lhsp->fromp()->unlinkFrBack();
|
||||||
@@ -533,6 +530,8 @@ private:
|
|||||||
rhsp, lsb)));
|
rhsp, lsb)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rhsp->deleteTree(); rhsp=NULL;
|
||||||
|
destp->deleteTree(); destp=NULL;
|
||||||
} else {
|
} else {
|
||||||
UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl);
|
UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl);
|
||||||
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
|
if (destp->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
|
||||||
@@ -592,7 +591,7 @@ private:
|
|||||||
// For wide destp, we can either form a equation for every destination word,
|
// For wide destp, we can either form a equation for every destination word,
|
||||||
// with the appropriate long equation of if it's being written or not.
|
// with the appropriate long equation of if it's being written or not.
|
||||||
// Or, we can use a LHS variable arraysel with non-constant index to set the vector.
|
// Or, we can use a LHS variable arraysel with non-constant index to set the vector.
|
||||||
// Doing the variable arraysel is better for globals and large arrays,
|
// Doing the variable arraysel is better for globals and large arrays,
|
||||||
// doing every word is better for temporaries and if we're setting most words
|
// doing every word is better for temporaries and if we're setting most words
|
||||||
// since it may result in better substitution optimizations later.
|
// since it may result in better substitution optimizations later.
|
||||||
// This results in so much code, we're better off leaving a function call.
|
// This results in so much code, we're better off leaving a function call.
|
||||||
@@ -630,7 +629,7 @@ private:
|
|||||||
//newp->dumpTree(cout,"- new: ");
|
//newp->dumpTree(cout,"- new: ");
|
||||||
insertBefore(nodep,newp);
|
insertBefore(nodep,newp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -641,10 +640,10 @@ private:
|
|||||||
} else {
|
} else {
|
||||||
UINFO(8," CONCAT "<<nodep<<endl);
|
UINFO(8," CONCAT "<<nodep<<endl);
|
||||||
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||||
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
|
||||||
int rhsshift = rhsp->widthMin();
|
int rhsshift = rhsp->widthMin();
|
||||||
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
||||||
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
|
if (nodep->isQuad() && !rhsp->isQuad()) rhsp = new AstCast(nodep->fileline(), rhsp, nodep);
|
||||||
AstNode* newp = new AstOr (nodep->fileline(),
|
AstNode* newp = new AstOr (nodep->fileline(),
|
||||||
new AstShiftL (nodep->fileline(),
|
new AstShiftL (nodep->fileline(),
|
||||||
lhsp,
|
lhsp,
|
||||||
@@ -657,9 +656,12 @@ private:
|
|||||||
}
|
}
|
||||||
bool expandWide (AstNodeAssign* nodep, AstConcat* rhsp) {
|
bool expandWide (AstNodeAssign* nodep, AstConcat* rhsp) {
|
||||||
UINFO(8," Wordize ASSIGN(CONCAT) "<<nodep<<endl);
|
UINFO(8," Wordize ASSIGN(CONCAT) "<<nodep<<endl);
|
||||||
// Lhs or Rhs may be word, long, or quad.
|
// Lhs or Rhs may be word, long, or quad.
|
||||||
// newAstWordSelClone nicely abstracts the difference.
|
// newAstWordSelClone nicely abstracts the difference.
|
||||||
int rhsshift = rhsp->rhsp()->widthMin();
|
int rhsshift = rhsp->rhsp()->widthMin();
|
||||||
|
// Sometimes doing the words backwards is preferrable.
|
||||||
|
// When we have x={x,foo} backwards is better, when x={foo,x} forward is better
|
||||||
|
// However V3Subst tends to rip this up, so not worth optimizing now.
|
||||||
for (int w=0; w<rhsp->widthWords(); w++) {
|
for (int w=0; w<rhsp->widthWords(); w++) {
|
||||||
addWordAssign(nodep, w,
|
addWordAssign(nodep, w,
|
||||||
new AstOr (rhsp->fileline(),
|
new AstOr (rhsp->fileline(),
|
||||||
@@ -667,7 +669,7 @@ private:
|
|||||||
rhsp->lhsp(), rhsshift),
|
rhsp->lhsp(), rhsshift),
|
||||||
newAstWordSelClone (rhsp->rhsp(), w)));
|
newAstWordSelClone (rhsp->rhsp(), w)));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
virtual void visit(AstReplicate* nodep, AstNUser*) {
|
||||||
@@ -686,8 +688,8 @@ private:
|
|||||||
UINFO(8," REPLICATE "<<nodep<<endl);
|
UINFO(8," REPLICATE "<<nodep<<endl);
|
||||||
AstConst* constp = nodep->rhsp()->castConst();
|
AstConst* constp = nodep->rhsp()->castConst();
|
||||||
if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
if (!constp) nodep->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
||||||
uint32_t times = constp->asInt();
|
uint32_t times = constp->toUInt();
|
||||||
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
if (nodep->isQuad() && !lhsp->isQuad()) lhsp = new AstCast(nodep->fileline(), lhsp, nodep);
|
||||||
newp = lhsp->cloneTree(true);
|
newp = lhsp->cloneTree(true);
|
||||||
for (unsigned repnum=1; repnum<times; repnum++) {
|
for (unsigned repnum=1; repnum<times; repnum++) {
|
||||||
int rhsshift = repnum*lhswidth;
|
int rhsshift = repnum*lhswidth;
|
||||||
@@ -711,7 +713,7 @@ private:
|
|||||||
int lhswidth = lhsp->widthMin();
|
int lhswidth = lhsp->widthMin();
|
||||||
AstConst* constp = rhsp->rhsp()->castConst();
|
AstConst* constp = rhsp->rhsp()->castConst();
|
||||||
if (!constp) rhsp->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
if (!constp) rhsp->v3fatalSrc("Replication value isn't a constant. Checked earlier!");
|
||||||
uint32_t times = constp->asInt();
|
uint32_t times = constp->toUInt();
|
||||||
for (int w=0; w<rhsp->widthWords(); w++) {
|
for (int w=0; w<rhsp->widthWords(); w++) {
|
||||||
AstNode* newp;
|
AstNode* newp;
|
||||||
if (lhswidth==1) {
|
if (lhswidth==1) {
|
||||||
@@ -728,7 +730,7 @@ private:
|
|||||||
}
|
}
|
||||||
addWordAssign(nodep, w, newp);
|
addWordAssign(nodep, w, newp);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void visit(AstChangeXor* nodep, AstNUser*) {
|
virtual void visit(AstChangeXor* nodep, AstNUser*) {
|
||||||
@@ -802,7 +804,7 @@ private:
|
|||||||
for (int w=0; w<nodep->lhsp()->widthWords(); w++) {
|
for (int w=0; w<nodep->lhsp()->widthWords(); w++) {
|
||||||
AstNode* eqp = newAstWordSelClone (nodep->lhsp(), w);
|
AstNode* eqp = newAstWordSelClone (nodep->lhsp(), w);
|
||||||
if (w==nodep->lhsp()->widthWords()-1) {
|
if (w==nodep->lhsp()->widthWords()-1) {
|
||||||
// Rather then doing a (slowish) ==##, we OR in the bits that aren't part of the mask
|
// Rather than doing a (slowish) ==##, we OR in the bits that aren't part of the mask
|
||||||
eqp = new AstOr (nodep->fileline(),
|
eqp = new AstOr (nodep->fileline(),
|
||||||
new AstConst (nodep->fileline(), notWideMask(nodep->lhsp())),
|
new AstConst (nodep->fileline(), notWideMask(nodep->lhsp())),
|
||||||
eqp);
|
eqp);
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Expansion of wide operator macros to C operators
|
// DESCRIPTION: Verilator: Expansion of wide operator macros to C operators
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3EXPAND_H_
|
#ifndef _V3EXPAND_H_
|
||||||
#define _V3EXPAND_H_ 1
|
#define _V3EXPAND_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+17
-7
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,9 +18,11 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdarg.h>
|
#include "verilatedos.h"
|
||||||
|
#include <cstdarg>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -231,12 +232,21 @@ bool V3File::checkTimes(const string& filename, const string& cmdline) {
|
|||||||
return dependImp.checkTimes(filename, cmdline);
|
return dependImp.checkTimes(filename, cmdline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V3File::createMakeDir() {
|
||||||
|
static bool created = false;
|
||||||
|
if (!created) {
|
||||||
|
created = true;
|
||||||
|
mkdir(v3Global.opt.makeDir().c_str(), 0777);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//######################################################################
|
//######################################################################
|
||||||
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
|
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
|
||||||
|
|
||||||
V3OutFile::V3OutFile(const string& filename)
|
V3OutFile::V3OutFile(const string& filename)
|
||||||
: m_lineno(1), m_column(0), m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
: m_filename(filename), m_lineno(1), m_column(0)
|
||||||
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
, m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
|
||||||
|
, m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
|
||||||
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
|
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
|
||||||
v3fatal("Cannot write "<<filename);
|
v3fatal("Cannot write "<<filename);
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-7
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
// DESCRIPTION: Verilator: File stream wrapper that understands indentation
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,9 +21,10 @@
|
|||||||
|
|
||||||
#ifndef _V3FILE_H_
|
#ifndef _V3FILE_H_
|
||||||
#define _V3FILE_H_ 1
|
#define _V3FILE_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@@ -42,6 +43,10 @@ public:
|
|||||||
}
|
}
|
||||||
static ofstream* new_ofstream(const string& filename, bool append=false) {
|
static ofstream* new_ofstream(const string& filename, bool append=false) {
|
||||||
addTgtDepend(filename);
|
addTgtDepend(filename);
|
||||||
|
return new_ofstream_nodepend (filename, append);
|
||||||
|
}
|
||||||
|
static ofstream* new_ofstream_nodepend(const string& filename, bool append=false) {
|
||||||
|
if (filename != "/dev/null") createMakeDir();
|
||||||
if (append) {
|
if (append) {
|
||||||
return new ofstream(filename.c_str(), ios::app);
|
return new ofstream(filename.c_str(), ios::app);
|
||||||
} else {
|
} else {
|
||||||
@@ -49,15 +54,20 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static FILE* new_fopen_w(const string& filename) {
|
static FILE* new_fopen_w(const string& filename) {
|
||||||
|
if (filename != "/dev/null") createMakeDir();
|
||||||
addTgtDepend(filename);
|
addTgtDepend(filename);
|
||||||
return fopen(filename.c_str(),"w");
|
return fopen(filename.c_str(),"w");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
static void addSrcDepend(const string& filename);
|
static void addSrcDepend(const string& filename);
|
||||||
static void addTgtDepend(const string& filename);
|
static void addTgtDepend(const string& filename);
|
||||||
static void writeDepend(const string& filename);
|
static void writeDepend(const string& filename);
|
||||||
static void writeTimes(const string& filename, const string& cmdline);
|
static void writeTimes(const string& filename, const string& cmdline);
|
||||||
static bool checkTimes(const string& filename, const string& cmdline);
|
static bool checkTimes(const string& filename, const string& cmdline);
|
||||||
|
|
||||||
|
// Directory utilities
|
||||||
|
static void createMakeDir();
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
@@ -77,6 +87,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
FILE* m_fp;
|
FILE* m_fp;
|
||||||
|
string m_filename;
|
||||||
int m_lineno;
|
int m_lineno;
|
||||||
int m_column;
|
int m_column;
|
||||||
int m_nobreak; // Basic operator or begin paren, don't break next
|
int m_nobreak; // Basic operator or begin paren, don't break next
|
||||||
@@ -110,8 +121,9 @@ public:
|
|||||||
bool tokenStart(const char* cp, const char* cmp);
|
bool tokenStart(const char* cp, const char* cmp);
|
||||||
bool tokenEnd(const char* cp);
|
bool tokenEnd(const char* cp);
|
||||||
void indentInc() { m_indentLevel += INDBLK; };
|
void indentInc() { m_indentLevel += INDBLK; };
|
||||||
void indentDec() { m_indentLevel -= INDBLK;
|
void indentDec() {
|
||||||
UASSERT(m_indentLevel>=0,"Underflow of indentation\n");
|
m_indentLevel -= INDBLK;
|
||||||
|
UASSERT(m_indentLevel>=0, ": "<<m_filename<<": Underflow of indentation\n");
|
||||||
}
|
}
|
||||||
void blockInc() { m_parenVec.push(m_indentLevel + INDBLK); }
|
void blockInc() { m_parenVec.push(m_indentLevel + INDBLK); }
|
||||||
void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); }
|
void blockDec() { if (!m_parenVec.empty()) m_parenVec.pop(); }
|
||||||
|
|||||||
+22
-12
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Gate optimizations, such as wire elimination
|
// DESCRIPTION: Verilator: Gate optimizations, such as wire elimination
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,16 +18,17 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// V3Gate's Transformations:
|
// V3Gate's Transformations:
|
||||||
//
|
//
|
||||||
// Extract a graph of the *entire* netlist with cells expanded
|
// Extract a graph of the *entire* netlist with cells expanded
|
||||||
// Perform constant optimization across the graph
|
// Perform constant optimization across the graph
|
||||||
// Create VARSCOPEs for any variables we can rip out
|
// Create VARSCOPEs for any variables we can rip out
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@@ -169,7 +169,7 @@ private:
|
|||||||
// V3Const cleans up any NOTs by flipping the edges for us
|
// V3Const cleans up any NOTs by flipping the edges for us
|
||||||
if (m_buffersOnly
|
if (m_buffersOnly
|
||||||
&& !(nodep->rhsp()->castVarRef()
|
&& !(nodep->rhsp()->castVarRef()
|
||||||
// Until NEW_ORDERING, avoid making non-clocked logic into clocked,
|
// Until NEW_ORDERING, avoid making non-clocked logic into clocked,
|
||||||
// as it slows down the verilator_sim_benchmark
|
// as it slows down the verilator_sim_benchmark
|
||||||
|| (nodep->rhsp()->castNot()
|
|| (nodep->rhsp()->castNot()
|
||||||
&& nodep->rhsp()->castNot()->lhsp()->castVarRef()
|
&& nodep->rhsp()->castNot()->lhsp()->castVarRef()
|
||||||
@@ -197,10 +197,18 @@ public:
|
|||||||
m_substTreep = NULL;
|
m_substTreep = NULL;
|
||||||
m_buffersOnly = buffersOnly;
|
m_buffersOnly = buffersOnly;
|
||||||
m_lhsVarRef = NULL;
|
m_lhsVarRef = NULL;
|
||||||
|
// Iterate
|
||||||
nodep->accept(*this);
|
nodep->accept(*this);
|
||||||
|
// Check results
|
||||||
if (!m_substTreep) {
|
if (!m_substTreep) {
|
||||||
clearSimple("No assignment found\n");
|
clearSimple("No assignment found\n");
|
||||||
}
|
}
|
||||||
|
for (GateVarRefList::const_iterator it = rhsVarRefs().begin();
|
||||||
|
it != rhsVarRefs().end(); ++it) {
|
||||||
|
if (m_lhsVarRef && m_lhsVarRef->varScopep() == (*it)->varScopep()) {
|
||||||
|
clearSimple("Circular logic\n"); // Oh my, we'll get a UNOPTFLAT much later.
|
||||||
|
}
|
||||||
|
}
|
||||||
if (debug()>=9 && !m_isSimple) {
|
if (debug()>=9 && !m_isSimple) {
|
||||||
nodep->dumpTree(cout,"\tgate!Ok: ");
|
nodep->dumpTree(cout,"\tgate!Ok: ");
|
||||||
}
|
}
|
||||||
@@ -223,6 +231,7 @@ private:
|
|||||||
//Entire netlist:
|
//Entire netlist:
|
||||||
// AstVarScope::userp -> GateVarVertex* for usage var, 0=not set yet
|
// AstVarScope::userp -> GateVarVertex* for usage var, 0=not set yet
|
||||||
// {statement}Node::userp -> GateLogicVertex* for this statement
|
// {statement}Node::userp -> GateLogicVertex* for this statement
|
||||||
|
|
||||||
// STATE
|
// STATE
|
||||||
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
||||||
GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored
|
GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored
|
||||||
@@ -331,9 +340,9 @@ private:
|
|||||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
||||||
GateVarVertex* varvertexp = makeVarVertex(varscp);
|
GateVarVertex* varvertexp = makeVarVertex(varscp);
|
||||||
UINFO(5," VARREF to "<<varscp<<endl);
|
UINFO(5," VARREF to "<<varscp<<endl);
|
||||||
// We use weight of one; if we ref the var more then once, when we simplify,
|
// We use weight of one; if we ref the var more than once, when we simplify,
|
||||||
// the weight will increase
|
// the weight will increase
|
||||||
if (nodep->lvalue()) {
|
if (nodep->lvalue()) {
|
||||||
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
||||||
} else {
|
} else {
|
||||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||||
@@ -423,7 +432,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!vvertexp->inSize1()) {
|
else if (!vvertexp->inSize1()) {
|
||||||
vvertexp->clearReducible("size!1"); // Can't deal with more then one src
|
vvertexp->clearReducible("size!1"); // Can't deal with more than one src
|
||||||
}
|
}
|
||||||
// Reduce it?
|
// Reduce it?
|
||||||
if (!vvertexp->reducible()) {
|
if (!vvertexp->reducible()) {
|
||||||
@@ -457,6 +466,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Process it
|
||||||
if (!doit) {
|
if (!doit) {
|
||||||
if (allowMultiIn && (debug()>=9)) {
|
if (allowMultiIn && (debug()>=9)) {
|
||||||
UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs
|
UINFO(9, "Not ok simp"<<okVisitor.isSimple()<<" mi"<<multiInputs
|
||||||
@@ -479,7 +489,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
|||||||
if (debug()>=5) substp->dumpTree(cout,"\t subst: ");
|
if (debug()>=5) substp->dumpTree(cout,"\t subst: ");
|
||||||
m_statSigs++;
|
m_statSigs++;
|
||||||
while (V3GraphEdge* edgep = vvertexp->outBeginp()) {
|
while (V3GraphEdge* edgep = vvertexp->outBeginp()) {
|
||||||
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
|
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
|
||||||
AstNode* consumerp = consumeVertexp->nodep();
|
AstNode* consumerp = consumeVertexp->nodep();
|
||||||
optimizeElimVar(vvertexp->varScp(), substp, consumerp);
|
optimizeElimVar(vvertexp->varScp(), substp, consumerp);
|
||||||
// If the new replacement referred to a signal,
|
// If the new replacement referred to a signal,
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
// DESCRIPTION: Verilator: Break always into sensitivity block domains
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3GATE_H_
|
#ifndef _V3GATE_H_
|
||||||
#define _V3GATE_H_ 1
|
#define _V3GATE_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Generated Clock repairs
|
// DESCRIPTION: Verilator: Generated Clock repairs
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,12 +20,13 @@
|
|||||||
// GENCLK TRANSFORMATIONS:
|
// GENCLK TRANSFORMATIONS:
|
||||||
// Follow control-flow graph with assignments and var usages
|
// Follow control-flow graph with assignments and var usages
|
||||||
// ASSIGNDLY to variable later used as clock requires change detect
|
// ASSIGNDLY to variable later used as clock requires change detect
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
@@ -92,7 +92,7 @@ private:
|
|||||||
}
|
}
|
||||||
//----
|
//----
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
// Consumption/generation of a variable,
|
// Consumption/generation of a variable,
|
||||||
AstVarScope* vscp = nodep->varScopep();
|
AstVarScope* vscp = nodep->varScopep();
|
||||||
if (!vscp) nodep->v3fatalSrc("Scope not assigned");
|
if (!vscp) nodep->v3fatalSrc("Scope not assigned");
|
||||||
if (m_activep && !nodep->user3()) {
|
if (m_activep && !nodep->user3()) {
|
||||||
@@ -171,7 +171,7 @@ private:
|
|||||||
//----
|
//----
|
||||||
|
|
||||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||||
// Consumption/generation of a variable,
|
// Consumption/generation of a variable,
|
||||||
AstVarScope* vscp = nodep->varScopep();
|
AstVarScope* vscp = nodep->varScopep();
|
||||||
if (!vscp) nodep->v3fatalSrc("Scope not assigned");
|
if (!vscp) nodep->v3fatalSrc("Scope not assigned");
|
||||||
if (m_activep) {
|
if (m_activep) {
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
//-*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Generated Clock Repairs
|
// DESCRIPTION: Verilator: Generated Clock Repairs
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3GENCLK_H_
|
#ifndef _V3GENCLK_H_
|
||||||
#define _V3GENCLK_H_ 1
|
#define _V3GENCLK_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3Ast.h"
|
#include "V3Ast.h"
|
||||||
|
|
||||||
|
|||||||
+11
-5
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Common headers
|
// DESCRIPTION: Verilator: Common headers
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -22,7 +22,8 @@
|
|||||||
#ifndef _V3GLOBAL_H_
|
#ifndef _V3GLOBAL_H_
|
||||||
#define _V3GLOBAL_H_ 1
|
#define _V3GLOBAL_H_ 1
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
@@ -41,8 +42,10 @@ class V3Global {
|
|||||||
AstNetlist* m_rootp; // Root of entire netlist
|
AstNetlist* m_rootp; // Root of entire netlist
|
||||||
int m_debugFileNumber; // Number to append to debug files created
|
int m_debugFileNumber; // Number to append to debug files created
|
||||||
bool m_assertWidthsSame; // Tree should have width()==widthMin()
|
bool m_assertWidthsSame; // Tree should have width()==widthMin()
|
||||||
// Options
|
bool m_needHInlines; // Need a __Inlines file
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Options
|
||||||
V3Options opt; // All options; let user see them directly
|
V3Options opt; // All options; let user see them directly
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -51,6 +54,7 @@ public:
|
|||||||
m_rootp = new AstNetlist;
|
m_rootp = new AstNetlist;
|
||||||
m_debugFileNumber = 0;
|
m_debugFileNumber = 0;
|
||||||
m_assertWidthsSame = false;
|
m_assertWidthsSame = false;
|
||||||
|
m_needHInlines = false;
|
||||||
}
|
}
|
||||||
void clear() {
|
void clear() {
|
||||||
if (m_rootp) m_rootp->deleteTree(); m_rootp=NULL;
|
if (m_rootp) m_rootp->deleteTree(); m_rootp=NULL;
|
||||||
@@ -69,6 +73,8 @@ public:
|
|||||||
char digits[100]; sprintf(digits, "%02d", m_debugFileNumber);
|
char digits[100]; sprintf(digits, "%02d", m_debugFileNumber);
|
||||||
return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment;
|
return opt.makeDir()+"/"+opt.prefix()+"_"+digits+"_"+nameComment;
|
||||||
}
|
}
|
||||||
|
bool needHInlines() const { return m_needHInlines; }
|
||||||
|
void needHInlines(bool flag) { m_needHInlines=flag; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern V3Global v3Global;
|
extern V3Global v3Global;
|
||||||
|
|||||||
+14
-9
@@ -1,14 +1,14 @@
|
|||||||
// $Id$
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Graph optimizations
|
// DESCRIPTION: Verilator: Graph optimizations
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,9 +19,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -105,7 +106,7 @@ ostream& operator<<(ostream& os, V3GraphVertex* vertexp) {
|
|||||||
//######################################################################
|
//######################################################################
|
||||||
// Edges
|
// Edges
|
||||||
|
|
||||||
V3GraphEdge::V3GraphEdge(V3Graph* graphp,
|
V3GraphEdge::V3GraphEdge(V3Graph* graphp,
|
||||||
V3GraphVertex* fromp, V3GraphVertex* top, int weight,
|
V3GraphVertex* fromp, V3GraphVertex* top, int weight,
|
||||||
bool cutable) {
|
bool cutable) {
|
||||||
UASSERT(fromp, "Null from pointer\n");
|
UASSERT(fromp, "Null from pointer\n");
|
||||||
@@ -176,9 +177,10 @@ void V3Graph::clear() {
|
|||||||
void V3Graph::userClearVertices() {
|
void V3Graph::userClearVertices() {
|
||||||
// Clear user() in all of tree
|
// Clear user() in all of tree
|
||||||
// We may use the userCnt trick in V3Ast later... For now we don't call this often, and
|
// We may use the userCnt trick in V3Ast later... For now we don't call this often, and
|
||||||
// the extra code on each read of user() would probably slow things down more then help.
|
// the extra code on each read of user() would probably slow things down more than help.
|
||||||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
vertexp->user(0);
|
vertexp->user(0);
|
||||||
|
vertexp->userp(NULL); // Its a union, but might be different size than user()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +188,8 @@ void V3Graph::userClearEdges() {
|
|||||||
// Clear user() in all of tree
|
// Clear user() in all of tree
|
||||||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
edgep->userp(NULL);
|
edgep->user(0);
|
||||||
|
edgep->userp(NULL); // Its a union, but might be different size than user()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -252,6 +255,8 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
|
|||||||
*logp<<"digraph v3graph {\n";
|
*logp<<"digraph v3graph {\n";
|
||||||
*logp<<"\trankdir="<<dotRankDir()<<"\n";
|
*logp<<"\trankdir="<<dotRankDir()<<"\n";
|
||||||
*logp<<"\tsize="<<"\"7.5,10\""<<"\n";
|
*logp<<"\tsize="<<"\"7.5,10\""<<"\n";
|
||||||
|
*logp<<"\tnTITLE\t[fontsize=20 label=\""<<filename<<"\", shape=box, style=bold, color=black];\n";
|
||||||
|
*logp<<"\n";
|
||||||
|
|
||||||
// List of all possible subgraphs
|
// List of all possible subgraphs
|
||||||
typedef multimap<string,V3GraphVertex*> SubgraphMmap;
|
typedef multimap<string,V3GraphVertex*> SubgraphMmap;
|
||||||
|
|||||||
+6
-5
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
//-*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Graph optimizations
|
// DESCRIPTION: Verilator: Graph optimizations
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3GRAPH_H_
|
#ifndef _V3GRAPH_H_
|
||||||
#define _V3GRAPH_H_ 1
|
#define _V3GRAPH_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
#include "V3Error.h"
|
#include "V3Error.h"
|
||||||
#include "V3List.h"
|
#include "V3List.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -66,7 +67,7 @@ public:
|
|||||||
virtual ~V3Graph();
|
virtual ~V3Graph();
|
||||||
static void debug(int level) { s_debug = level; }
|
static void debug(int level) { s_debug = level; }
|
||||||
virtual string dotRankDir() { return "TB"; } // rankdir for dot plotting
|
virtual string dotRankDir() { return "TB"; } // rankdir for dot plotting
|
||||||
|
|
||||||
// METHODS
|
// METHODS
|
||||||
void clear(); // Empty it of all vertices/edges, as if making a new object
|
void clear(); // Empty it of all vertices/edges, as if making a new object
|
||||||
|
|
||||||
|
|||||||
+15
-11
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Graph acyclic algorithm
|
// DESCRIPTION: Verilator: Graph acyclic algorithm
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,9 +18,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
// Break the minimal number of backward edges to make the graph acyclic
|
// Break the minimal number of backward edges to make the graph acyclic
|
||||||
|
|
||||||
class GraphAcycVertex : public V3GraphVertex {
|
class GraphAcycVertex : public V3GraphVertex {
|
||||||
|
// user() is used for various sub-algorithm pieces
|
||||||
V3GraphVertex* m_origVertexp; // Pointer to first vertex this represents
|
V3GraphVertex* m_origVertexp; // Pointer to first vertex this represents
|
||||||
protected:
|
protected:
|
||||||
friend class GraphAcyc;
|
friend class GraphAcyc;
|
||||||
@@ -307,6 +308,9 @@ void GraphAcyc::simplifyOne (GraphAcycVertex* avertexp) {
|
|||||||
avertexp->setDelete(); // Mark so we won't delete it twice
|
avertexp->setDelete(); // Mark so we won't delete it twice
|
||||||
// Make a new edge connecting the two vertices directly
|
// Make a new edge connecting the two vertices directly
|
||||||
// If both are breakable, we pick the one with less weight, else it's arbitrary
|
// If both are breakable, we pick the one with less weight, else it's arbitrary
|
||||||
|
// We can forget about the origEdge list for the "non-selected" set of edges,
|
||||||
|
// as we need to break only one set or the other set of edges, not both.
|
||||||
|
// (This is why we must give preference to the cutable set.)
|
||||||
V3GraphEdge* templateEdgep = ( (inEdgep->cutable()
|
V3GraphEdge* templateEdgep = ( (inEdgep->cutable()
|
||||||
&& (!outEdgep->cutable()
|
&& (!outEdgep->cutable()
|
||||||
|| inEdgep->weight()<outEdgep->weight() ))
|
|| inEdgep->weight()<outEdgep->weight() ))
|
||||||
@@ -352,7 +356,7 @@ void GraphAcyc::simplifyDup (GraphAcycVertex* avertexp) {
|
|||||||
if (avertexp->isDelete()) return;
|
if (avertexp->isDelete()) return;
|
||||||
// Clear marks
|
// Clear marks
|
||||||
for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
edgep->top()->user(false);
|
edgep->top()->userp(NULL);
|
||||||
}
|
}
|
||||||
// Mark edges and detect duplications
|
// Mark edges and detect duplications
|
||||||
for (V3GraphEdge* nextp, *edgep = avertexp->outBeginp(); edgep; edgep=nextp) {
|
for (V3GraphEdge* nextp, *edgep = avertexp->outBeginp(); edgep; edgep=nextp) {
|
||||||
@@ -363,16 +367,16 @@ void GraphAcyc::simplifyDup (GraphAcycVertex* avertexp) {
|
|||||||
if (!prevEdgep->cutable()) {
|
if (!prevEdgep->cutable()) {
|
||||||
// !cutable duplicates prev !cutable: we can ignore it, redundant
|
// !cutable duplicates prev !cutable: we can ignore it, redundant
|
||||||
// cutable duplicates prev !cutable: know it's not a relevant loop, ignore it
|
// cutable duplicates prev !cutable: know it's not a relevant loop, ignore it
|
||||||
UINFO(8," DelDupEdge "<<avertexp<<endl);
|
UINFO(8," DelDupEdge "<<avertexp<<" -> "<<edgep->top()<<endl);
|
||||||
edgep->unlinkDelete(); edgep = NULL;
|
edgep->unlinkDelete(); edgep = NULL;
|
||||||
} else if (!edgep->cutable()) {
|
} else if (!edgep->cutable()) {
|
||||||
// !cutable duplicates prev cutable: delete the earlier cutable
|
// !cutable duplicates prev cutable: delete the earlier cutable
|
||||||
UINFO(8," DelDupPrev "<<avertexp<<endl);
|
UINFO(8," DelDupPrev "<<avertexp<<" -> "<<prevEdgep->top()<<endl);
|
||||||
prevEdgep->unlinkDelete(); prevEdgep = NULL;
|
prevEdgep->unlinkDelete(); prevEdgep = NULL;
|
||||||
outVertexp->userp(edgep);
|
outVertexp->userp(edgep);
|
||||||
} else {
|
} else {
|
||||||
// cutable duplicates prev cutable: combine weights
|
// cutable duplicates prev cutable: combine weights
|
||||||
UINFO(8," DelDupComb "<<avertexp<<endl);
|
UINFO(8," DelDupComb "<<avertexp<<" -> "<<edgep->top()<<endl);
|
||||||
prevEdgep->weight (prevEdgep->weight() + edgep->weight());
|
prevEdgep->weight (prevEdgep->weight() + edgep->weight());
|
||||||
addOrigEdgep (prevEdgep, edgep);
|
addOrigEdgep (prevEdgep, edgep);
|
||||||
edgep->unlinkDelete(); edgep = NULL;
|
edgep->unlinkDelete(); edgep = NULL;
|
||||||
@@ -435,7 +439,7 @@ void GraphAcyc::place() {
|
|||||||
UINFO(4, " Cutable edges = "<<numEdges<<endl);
|
UINFO(4, " Cutable edges = "<<numEdges<<endl);
|
||||||
|
|
||||||
vector<V3GraphEdge*> edges; // List of all edges to be processed
|
vector<V3GraphEdge*> edges; // List of all edges to be processed
|
||||||
edges.reserve(numEdges+1); // Make the vector properly sized right off the bat -- faster then reallocating
|
edges.reserve(numEdges+1); // Make the vector properly sized right off the bat -- faster than reallocating
|
||||||
for (V3GraphVertex* vertexp = m_breakGraph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
for (V3GraphVertex* vertexp = m_breakGraph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
vertexp->user(0); // Clear in prep of next step
|
vertexp->user(0); // Clear in prep of next step
|
||||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
|
|||||||
+11
-11
@@ -1,14 +1,13 @@
|
|||||||
// $Id$
|
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Graph optimizations
|
// DESCRIPTION: Verilator: Graph optimizations
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -19,9 +18,10 @@
|
|||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
#include <stdio.h>
|
#include "verilatedos.h"
|
||||||
#include <stdarg.h>
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -57,7 +57,7 @@ void V3Graph::deleteCutableOnlyEdges() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pass 2, delete those marked
|
// Pass 2, delete those marked
|
||||||
// Rather then doing a delete() we set the weight to 0 which disconnects the edge.
|
// Rather than doing a delete() we set the weight to 0 which disconnects the edge.
|
||||||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||||
if (vertexp->user()) {
|
if (vertexp->user()) {
|
||||||
//UINFO(7,"Disconnect "<<vertexp->name()<<endl);
|
//UINFO(7,"Disconnect "<<vertexp->name()<<endl);
|
||||||
@@ -85,7 +85,7 @@ private:
|
|||||||
void vertexIterate(V3GraphVertex* vertexp) {
|
void vertexIterate(V3GraphVertex* vertexp) {
|
||||||
// Clear marks
|
// Clear marks
|
||||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||||
edgep->top()->user(false);
|
edgep->top()->userp(NULL);
|
||||||
}
|
}
|
||||||
// Mark edges and detect duplications
|
// Mark edges and detect duplications
|
||||||
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
for (V3GraphEdge* nextp, *edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
|
||||||
@@ -98,9 +98,9 @@ private:
|
|||||||
} else { // Duplicate
|
} else { // Duplicate
|
||||||
bool saveOld = true;
|
bool saveOld = true;
|
||||||
if (prevEdgep->cutable() && !edgep->cutable()) {
|
if (prevEdgep->cutable() && !edgep->cutable()) {
|
||||||
saveOld = false; // new !cutable more important then old
|
saveOld = false; // new !cutable more important than old
|
||||||
} else if (!prevEdgep->cutable() && edgep->cutable()) {
|
} else if (!prevEdgep->cutable() && edgep->cutable()) {
|
||||||
saveOld = true; // old !cutable more important then new
|
saveOld = true; // old !cutable more important than new
|
||||||
} else {
|
} else {
|
||||||
saveOld = true;
|
saveOld = true;
|
||||||
if (!m_sumWeights && (prevEdgep->weight() < edgep->weight())) { // Keep max weight
|
if (!m_sumWeights && (prevEdgep->weight() < edgep->weight())) { // Keep max weight
|
||||||
@@ -344,7 +344,7 @@ private:
|
|||||||
if (m_done) return;
|
if (m_done) return;
|
||||||
|
|
||||||
m_callTrace.reserve(currentRank+10); // Leave slop for speed
|
m_callTrace.reserve(currentRank+10); // Leave slop for speed
|
||||||
m_callTrace[currentRank++] = vertexp;
|
m_callTrace[currentRank++] = vertexp;
|
||||||
|
|
||||||
if (vertexp->user() == 1) {
|
if (vertexp->user() == 1) {
|
||||||
for (unsigned i=0; i<currentRank; i++) {
|
for (unsigned i=0; i<currentRank; i++) {
|
||||||
|
|||||||
+5
-4
@@ -1,14 +1,14 @@
|
|||||||
// $Id$ //-*- C++ -*-
|
// -*- C++ -*-
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
// DESCRIPTION: Verilator: Graph algorithm base class
|
// DESCRIPTION: Verilator: Graph algorithm base class
|
||||||
//
|
//
|
||||||
// Code available from: http://www.veripool.com/verilator
|
// Code available from: http://www.veripool.org/verilator
|
||||||
//
|
//
|
||||||
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
||||||
//
|
//
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
//
|
//
|
||||||
// Copyright 2003-2006 by Wilson Snyder. This program is free software; you can
|
// Copyright 2003-2008 by Wilson Snyder. This program is free software; you can
|
||||||
// redistribute it and/or modify it under the terms of either the GNU
|
// redistribute it and/or modify it under the terms of either the GNU
|
||||||
// General Public License or the Perl Artistic License.
|
// General Public License or the Perl Artistic License.
|
||||||
//
|
//
|
||||||
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
#ifndef _V3GRAPHALG_H_
|
#ifndef _V3GRAPHALG_H_
|
||||||
#define _V3GRAPHALG_H_ 1
|
#define _V3GRAPHALG_H_ 1
|
||||||
#include "config.h"
|
#include "config_build.h"
|
||||||
|
#include "verilatedos.h"
|
||||||
|
|
||||||
#include "V3Global.h"
|
#include "V3Global.h"
|
||||||
#include "V3Graph.h"
|
#include "V3Graph.h"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user