mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4100f20a69 | ||
|
|
bedf946fb2 | ||
|
|
b9e67157c6 | ||
|
|
b30b2a183b | ||
|
|
9ab3bcdde3 | ||
|
|
5df3bbe188 | ||
|
|
8cf12416c0 | ||
|
|
b7c2c83c88 | ||
|
|
3b6da93331 | ||
|
|
b4642d3fd4 | ||
|
|
88a2b0b911 | ||
|
|
954e127f1d | ||
|
|
7654add5e5 | ||
|
|
85a37ea53f | ||
|
|
b337acebcc | ||
|
|
fb9ca54c95 | ||
|
|
1a15d41523 | ||
|
|
e378cc5791 | ||
|
|
748c189c79 | ||
|
|
b89be6c4b9 | ||
|
|
df207807b6 | ||
|
|
1f2b40cff1 | ||
|
|
734400fd37 | ||
|
|
f19979d928 | ||
|
|
19be7a53da | ||
|
|
e56af34fb0 | ||
|
|
7737aa20e8 | ||
|
|
ead046201c | ||
|
|
0aa7c3f659 | ||
|
|
4aa7222022 | ||
|
|
86e3c78776 | ||
|
|
40076287ea | ||
|
|
ca81db8edf | ||
|
|
ae68a80e98 | ||
|
|
beb7c58375 | ||
|
|
e080b9d565 | ||
|
|
ca2db37039 | ||
|
|
194825f78e | ||
|
|
55bd765ea0 | ||
|
|
b03d61e2cf | ||
|
|
6fc0e5167b | ||
|
|
0065be011f | ||
|
|
3f7cbce58c | ||
|
|
246b62e322 | ||
|
|
7c2fdd1ee9 | ||
|
|
f77aa2623c | ||
|
|
20847a3ff5 | ||
|
|
eb6d42acf9 | ||
|
|
094d676a8b | ||
|
|
71306ceb1d | ||
|
|
8bbfc7fc22 | ||
|
|
19baba12b1 | ||
|
|
15b8819136 | ||
|
|
3fae8ade05 | ||
|
|
f9bbf31d65 | ||
|
|
df1da3dda9 | ||
|
|
c83f2a4abd | ||
|
|
ad53833040 | ||
|
|
bc8c85668a | ||
|
|
d12a3dde45 | ||
|
|
301c878c0f | ||
|
|
bd55bfa071 | ||
|
|
6d2f09b579 | ||
|
|
4bfea7f54d | ||
|
|
55906486d8 | ||
|
|
d5478e6e08 | ||
|
|
d88d85c172 | ||
|
|
59c3c536c7 | ||
|
|
a007458cb8 | ||
|
|
d051912f21 | ||
|
|
a547158a50 | ||
|
|
95f2351aa0 | ||
|
|
698aaffb0b | ||
|
|
73eccecbf8 | ||
|
|
ae4a261463 | ||
|
|
c9f0d0cec2 | ||
|
|
4fa1e45d45 | ||
|
|
1b3d252bfe | ||
|
|
a9ba4a9fcd | ||
|
|
7f49619875 | ||
|
|
696660639a | ||
|
|
da4323062d | ||
|
|
a901e171b2 | ||
|
|
6e41d532fe | ||
|
|
4fc78ffb58 | ||
|
|
8137f41fc3 | ||
|
|
2e9471797d | ||
|
|
344248cea0 | ||
|
|
2789e3dba5 | ||
|
|
cca759a41e | ||
|
|
4f7b3d8882 | ||
|
|
2b330b78b7 | ||
|
|
d47ca1912b | ||
|
|
3fd2108b10 | ||
|
|
96e2a407f4 | ||
|
|
cdf18c96f4 | ||
|
|
53acaa05b8 | ||
|
|
fb85679068 | ||
|
|
9558e14479 | ||
|
|
4af0af93bf | ||
|
|
df4bc950fe | ||
|
|
250394f72b | ||
|
|
ca83fd6dc1 | ||
|
|
d5e9e7cd2b | ||
|
|
9a96f621ef | ||
|
|
5d7ce096c6 | ||
|
|
c9f8109c06 | ||
|
|
a20b4f2864 | ||
|
|
44a19d2a0a | ||
|
|
02f3beb8db | ||
|
|
3269cc3d90 | ||
|
|
fb70a1f4ab | ||
|
|
df0aa483ce | ||
|
|
c83f12a55c | ||
|
|
9704f59566 | ||
|
|
2923893d34 | ||
|
|
890dab0742 | ||
|
|
607e26b041 | ||
|
|
ea75290f65 | ||
|
|
a176054118 | ||
|
|
9a697dc5f5 | ||
|
|
cfdb852843 | ||
|
|
2e67a91982 | ||
|
|
074ca9330d | ||
|
|
f0d7cdcb20 | ||
|
|
40d961e059 | ||
|
|
e5de759236 | ||
|
|
e26a75c59d | ||
|
|
8701145b40 | ||
|
|
a2558886c8 | ||
|
|
f818ee86ae | ||
|
|
ad0dbdaa9c | ||
|
|
a9f14b294f | ||
|
|
a435ae98f9 | ||
|
|
481b261458 | ||
|
|
48df52d743 | ||
|
|
0af0d3b171 | ||
|
|
8287cf35e7 | ||
|
|
fab7924cc2 | ||
|
|
0ab739e8b1 | ||
|
|
2dcd4d171b | ||
|
|
e7f4d18c3d | ||
|
|
1611362c22 | ||
|
|
2327698160 | ||
|
|
71c1f00ec2 | ||
|
|
6574a126ef | ||
|
|
1e68086355 | ||
|
|
326cc8fd67 | ||
|
|
4afcb421bd | ||
|
|
8d21917035 | ||
|
|
4ca7f8834c | ||
|
|
b43299c8da | ||
|
|
b763809f5e | ||
|
|
2cb97f7475 | ||
|
|
6283df7491 | ||
|
|
acc4490370 | ||
|
|
f85c1a995a | ||
|
|
809e5fda8a | ||
|
|
dce245da5a | ||
|
|
d261c4cd27 | ||
|
|
c33299d542 | ||
|
|
ebdf8a5f3c | ||
|
|
c8852d183f | ||
|
|
9f161b20ef | ||
|
|
40f9d64973 | ||
|
|
4a2e68a0fd | ||
|
|
bcd90d3401 | ||
|
|
114af7d33f | ||
|
|
7b83d2de49 | ||
|
|
850de5913d | ||
|
|
bb9ee46f40 | ||
|
|
e94fc1305b | ||
|
|
3e4e8feb29 | ||
|
|
fedf347b1a | ||
|
|
285277a50b | ||
|
|
323c96f42f | ||
|
|
7dee344ea9 | ||
|
|
65bce588e4 | ||
|
|
233ff1b744 | ||
|
|
0837e39787 | ||
|
|
86db565a21 | ||
|
|
d6ac5e5001 | ||
|
|
e6443f1981 | ||
|
|
d13e6c73db | ||
|
|
79ca7f3cb5 | ||
|
|
cfd07ccd34 | ||
|
|
48047d523a | ||
|
|
eeb8fc2626 | ||
|
|
3d1baf3f2f | ||
|
|
4e382d6765 | ||
|
|
582963375d | ||
|
|
56c7c1bcc8 | ||
|
|
f88e57ddb8 | ||
|
|
9d98e012e4 | ||
|
|
d305a774f0 | ||
|
|
16b0c8d353 | ||
|
|
55da4fdbf6 | ||
|
|
ed2fbd8f25 | ||
|
|
42199bc8e5 | ||
|
|
7c5318768c | ||
|
|
aba25aab19 | ||
|
|
f99bd33f91 | ||
|
|
a6a6ce83f0 | ||
|
|
f4908a9758 | ||
|
|
5e4ca4b76a | ||
|
|
1e938d0e90 | ||
|
|
f3704f4c05 | ||
|
|
8800efe953 | ||
|
|
a320c4584e | ||
|
|
3841850168 | ||
|
|
beb3885840 | ||
|
|
06967c0c46 | ||
|
|
9a382c572c | ||
|
|
44b6c371db | ||
|
|
00970be996 | ||
|
|
aca4ab015f | ||
|
|
68b63d5783 | ||
|
|
4b499f2bb1 | ||
|
|
ed17581f92 | ||
|
|
a46c4ec912 | ||
|
|
930cbeec17 | ||
|
|
10689ffaba | ||
|
|
29b0ea0af9 | ||
|
|
57d00946be | ||
|
|
ef51de72c9 | ||
|
|
c807bf1e0e | ||
|
|
2525b3fb05 | ||
|
|
9163ce0f6e | ||
|
|
d776638f53 | ||
|
|
83fff41312 | ||
|
|
dd7d9bc95b | ||
|
|
f8eabbc100 | ||
|
|
7ed18ac62d | ||
|
|
3ac707c645 | ||
|
|
8e9a1e0bf3 | ||
|
|
bc31b5d27a | ||
|
|
936738b750 | ||
|
|
7c3048ab9c | ||
|
|
64719f3ace | ||
|
|
a11a5f04d5 | ||
|
|
eb5c035dde | ||
|
|
c3887efbf3 | ||
|
|
495585830d | ||
|
|
6715cb9880 | ||
|
|
41b167d23c | ||
|
|
7ea8b54210 | ||
|
|
bcea39a858 | ||
|
|
fb560abac4 | ||
|
|
ba93a08b40 | ||
|
|
2be6b3481c |
@@ -24,6 +24,8 @@ src/Makefile_obj$
|
||||
include/verilated.mk$
|
||||
config.cache$
|
||||
config.status$
|
||||
verilator.log
|
||||
verilator.tex
|
||||
verilator_bin.*
|
||||
.vcsmx_rebuild$
|
||||
autom4te\.cache/
|
||||
|
||||
+92
-39
@@ -9,7 +9,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -88,7 +88,10 @@ pkgdatadir = @pkgdatadir@
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
# Compile options
|
||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
######################################################################
|
||||
@@ -101,8 +104,6 @@ INFOS = README internals.txt verilator.txt verilator.html verilator.1 verilator.
|
||||
|
||||
# Files that can be generated, but should be up to date for a distribution.
|
||||
DISTDEP = info Makefile
|
||||
# Files to distribute.
|
||||
DISTBIN = $(wildcard bin/verilator-*)
|
||||
|
||||
DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
*.in *.ac \
|
||||
@@ -118,8 +119,9 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
src/.*ignore src/*.in src/*.cpp src/*.[chly] src/astgen src/bisonpre src/*fix \
|
||||
src/*.pl src/*.pod \
|
||||
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/vlint \
|
||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
|
||||
test_verilated/vgen*.pl \
|
||||
test_regress/t/tsub/*.v* \
|
||||
test_regress/t/*.cpp \
|
||||
test_regress/t/*.h \
|
||||
test_regress/t/*.dat \
|
||||
@@ -128,16 +130,14 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
test_regress/t/*.pl \
|
||||
test_regress/t/*.pf \
|
||||
test_regress/t/*.v* \
|
||||
verilator.* \
|
||||
|
||||
INST_PROJ_FILES = \
|
||||
bin/verilator \
|
||||
bin/verilator_includer \
|
||||
bin/verilator_profcfunc \
|
||||
include/verilated.[chv]* \
|
||||
include/verilated.mk \
|
||||
include/verilatedos.[chv]* \
|
||||
include/verilated_*.[chv]* \
|
||||
include/*.[chv]* \
|
||||
include/vltstd/*.[chv]* \
|
||||
|
||||
INST_PROJ_BIN_FILES = \
|
||||
verilator_bin \
|
||||
@@ -171,7 +171,7 @@ msg_test:
|
||||
@echo
|
||||
|
||||
.PHONY:test
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
ifeq ($(CFG_WITH_LONGTESTS),yes) # Local... Else don't burden users
|
||||
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
||||
else
|
||||
test: test_c test_sc test_sp
|
||||
@@ -203,17 +203,18 @@ test_regress: all_nomsg
|
||||
info: $(INFOS)
|
||||
|
||||
# Use --no-split to avoid creating filenames > 14 chars.
|
||||
verilator.1: bin/verilator
|
||||
verilator.1: ${srcdir}/bin/verilator
|
||||
pod2man $< $@
|
||||
|
||||
verilator.txt: bin/verilator
|
||||
verilator.txt: ${srcdir}/bin/verilator
|
||||
$(POD2TEXT) $< $@
|
||||
|
||||
verilator.html: bin/verilator
|
||||
verilator.html: ${srcdir}/bin/verilator
|
||||
pod2html $< >$@
|
||||
|
||||
verilator.pdf: bin/verilator $(DISTCONFIG)
|
||||
pod2latex --full --out verilator.tex bin/verilator
|
||||
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
|
||||
verilator.pdf: ${srcdir}/bin/verilator Makefile
|
||||
pod2latex --full --out verilator.tex ${srcdir}/bin/verilator
|
||||
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}/' \
|
||||
@@ -245,15 +246,19 @@ VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg \
|
||||
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
||||
VL_INST_MAN_FILES = verilator.1
|
||||
|
||||
VL_INST_INC_FILES = \
|
||||
include/*.[chv]* include/verilated.mk \
|
||||
VL_INST_INC_BLDDIR_FILES = \
|
||||
include/verilated.mk \
|
||||
|
||||
# Files under srcdir, instead of build time
|
||||
VL_INST_INC_SRCDIR_FILES = \
|
||||
include/*.[chv]* \
|
||||
include/vltstd/*.[chv]* \
|
||||
|
||||
VL_INST_DATA_FILES = \
|
||||
VL_INST_DATA_SRCDIR_FILES = \
|
||||
test_v/*.[chv]* \
|
||||
test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \
|
||||
test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \
|
||||
test_sp/*.[chv]* test_sp/Makefile test_sp/Makefile_obj \
|
||||
test_sp/Makefile test_sp/Makefile_obj \
|
||||
|
||||
installbin:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
|
||||
@@ -264,23 +269,30 @@ installbin:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
||||
|
||||
# Man files can either be part of the original kit, or built in current directory
|
||||
# So important we use $< so VPATH is searched
|
||||
installman: $(VL_INST_MAN_FILES)
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||
for p in $(VL_INST_MAN_FILES) ; do \
|
||||
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||
for p in $< ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||
done
|
||||
|
||||
installdata:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/include/vltstd
|
||||
for p in $(VL_INST_INC_FILES) ; do \
|
||||
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
||||
for p in $(VL_INST_INC_BLDDIR_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
||||
done
|
||||
cd $(srcdir) \
|
||||
; for p in $(VL_INST_INC_SRCDIR_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
||||
done
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_c
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sc
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_sp
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/test_v
|
||||
for p in $(VL_INST_DATA_FILES) ; do \
|
||||
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
|
||||
cd $(srcdir) \
|
||||
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
|
||||
done
|
||||
|
||||
# We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
|
||||
@@ -288,8 +300,9 @@ uninstall:
|
||||
-cd $(DESTDIR)$(bindir) && rm -f $(VL_INST_BIN_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir)/bin && rm -f $(VL_INST_BIN_FILES)
|
||||
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_SRCDIR_FILES)
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/bin
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/include
|
||||
@@ -305,15 +318,18 @@ install: all_nomsg installbin installman installdata install-msg
|
||||
install-here: installman ftp
|
||||
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
DISTNAMEREV = $(shell sed -e '/DTVERSION/!d' -e 's/.*verilator_\([^"]*\).*/\1/' -e q ${srcdir}/src/config_rev.h)
|
||||
|
||||
DIRPROJECT := $(shell project_dir --project)
|
||||
VERILATOR_CAD_DIR = $(CAD_DIR)/verilator/$(DISTNAMEREV)/$(DIRPROJECT_ARCH)
|
||||
INST_PROJ_CVS = cp_if_cvs_diff
|
||||
|
||||
install-project: dist
|
||||
@echo "Install-project to $(DIRPROJECT)"
|
||||
strip verilator_bin*
|
||||
$(MAKE) install-project-quick
|
||||
for p in verilator.1 ; do \
|
||||
$(INSTALL_PROGRAM) -m 0666 $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
||||
for p in $(VL_INST_MAN_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
||||
done
|
||||
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
|
||||
rm $(DISTNAME).tgz
|
||||
@@ -330,18 +346,52 @@ endif
|
||||
for p in $(INST_PROJ_BIN_FILES) ; do \
|
||||
$(INST_PROJ_CVS) $$p $(DIRPROJECT)/hw/utils/verilator/$$p-$(DIRPROJECT_ARCH); \
|
||||
done
|
||||
|
||||
install-cadtools: dist
|
||||
@echo "Install-project to $(CAD_DIR)"
|
||||
strip verilator_bin*
|
||||
$(MAKE) install-cadtools-quick
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1
|
||||
for p in $(VL_INST_MAN_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(VERILATOR_CAD_DIR)/man/man1/$$p; \
|
||||
done
|
||||
$(INST_PROJ_CVS) $(DISTNAME).tgz $(VERILATOR_CAD_DIR)/verilator.tgz
|
||||
rm $(DISTNAME).tgz
|
||||
|
||||
install-cadtools-quick:
|
||||
ifeq ($(CFG_WITH_DEFENV),yes)
|
||||
@echo "%Error: Reconfigure with './configure --disable-defenv' to avoid hardcoded paths."
|
||||
false
|
||||
endif
|
||||
@echo "Install-cadtools-quick (no strip) to $(VERILATOR_CAD_DIR)"
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/include/vltstd
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/bin
|
||||
for p in $(INST_PROJ_FILES) ; do \
|
||||
$(INST_PROJ_CVS) $$p $(VERILATOR_CAD_DIR)/$$p; \
|
||||
done
|
||||
for p in $(INST_PROJ_BIN_FILES) ; do \
|
||||
$(INST_PROJ_CVS) $$p $(VERILATOR_CAD_DIR)/$$p; \
|
||||
done
|
||||
|
||||
# VERILATOR_AUTHOR_SITE
|
||||
endif
|
||||
|
||||
CPPCHECK = cppcheck
|
||||
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject
|
||||
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
|
||||
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
|
||||
|
||||
cppcheck: $(CPPCHECK_DEP)
|
||||
%.cppcheck: %.cpp
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -I$(srcdir)/include -I$(srcdir)/src $<
|
||||
|
||||
ftp: info
|
||||
|
||||
install-msg:
|
||||
@echo "Installed!"
|
||||
@echo
|
||||
@echo "Add to your startup file (for bash or csh, as appropriate):"
|
||||
@echo " export VERILATOR_ROOT="`pwd`
|
||||
@echo " setenv VERILATOR_ROOT "`pwd` " ; export VERILATOR_ROOT "
|
||||
@echo
|
||||
@echo "See 'verilator.txt' for documentation."
|
||||
@echo "Fod documentation see 'man verilator' or 'verilator --help'"
|
||||
@echo "For forums and to report bugs see http://www.veripool.org/verilator"
|
||||
@echo
|
||||
|
||||
IN_WILD := ${srcdir}/*.in ${srcdir}/*/*.in
|
||||
@@ -355,8 +405,13 @@ Makefile: Makefile.in config.status $(IN_WILD)
|
||||
src/Makefile: src/Makefile.in Makefile
|
||||
config.status: configure
|
||||
./config.status --recheck
|
||||
|
||||
configure: configure.ac
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
autoconf --warnings=all
|
||||
else
|
||||
autoconf
|
||||
endif
|
||||
|
||||
maintainer-clean::
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@@ -397,14 +452,12 @@ dist-file-list:
|
||||
######################################################################
|
||||
# Distributions
|
||||
|
||||
DISTCONFIG = ${srcdir}/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))
|
||||
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/.*\([1-2][0-9][0-9][0-9].[0-9]*[0-9].[0-9]*[0-9]\).*/\1/' -e q $(DISTCONFIG))
|
||||
DISTTITLE := Verilator $(word 1,$(PACKAGE_VERSION))
|
||||
DISTNAME := verilator-$(word 1,$(PACKAGE_VERSION))
|
||||
DISTDATEPRE := $(word 2,$(PACKAGE_VERSION))
|
||||
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
||||
|
||||
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
||||
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
||||
|
||||
tag:
|
||||
svnorcvs tag $(DISTTAGNAME)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// DESCRIPTION: Verilator: List of To Do issues.
|
||||
//
|
||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -62,11 +62,15 @@ Usability:
|
||||
* Print version/etc message at runtime. (4.000?)
|
||||
Include number of lines of code, percent comments, code complexity measurement
|
||||
<-80chars------------------------------------------------------------------->
|
||||
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2010.
|
||||
Verilator 3.600 - fast, free, open-sourced. Copyright 2001-2011.
|
||||
Verilated #### modules, #### instances, ##### sigs,
|
||||
#### non-comment lines, ##### ops, ### KB model size
|
||||
* Default the --l2name to remove extra "v" level of hierarchy (flag to make "top")
|
||||
|
||||
Lint:
|
||||
* CDCRSTLOGIC should allow filtering with paths
|
||||
"waive CDCRSTLOGIC --from a.b.sig --to a.c.sig --via OR"
|
||||
|
||||
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.
|
||||
|
||||
+551
-134
File diff suppressed because it is too large
Load Diff
@@ -99,7 +99,7 @@ sub filter {
|
||||
next if $line =~ / This=/;
|
||||
$line =~ s/0x[a-f0-9]+/0x/g;
|
||||
$line =~ s/<e[0-9]+\#?>/<e>/g;
|
||||
$line =~ s/{\d+}/{}/g if !$Opt_Lineno;
|
||||
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
|
||||
print $f2 $line;
|
||||
}
|
||||
$f1->close;
|
||||
@@ -109,7 +109,7 @@ sub filter {
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ Do not show differences in line numbering.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/verilator>.
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you can
|
||||
Copyright 2005-2011 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 Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ eval 'exec perl -wS $0 ${1+"$@"}'
|
||||
if 0;
|
||||
# DESCRIPTION: Print include statements for each ARGV
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This package is free software; you can
|
||||
# Copyright 2003-2011 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 Version 3 or the Perl Artistic License Version 2.0.
|
||||
######################################################################
|
||||
|
||||
@@ -39,7 +39,7 @@ profcfunc($Opt_File);
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ Displays this message and program version and exits.
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2007-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2007-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
|
||||
+100
-31
@@ -1,35 +1,83 @@
|
||||
dnl DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
dnl Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
dnl redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
dnl General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
# Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
AC_INIT(src/Verilator.cpp)
|
||||
AC_INIT([Verilator],[3.830])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||
|
||||
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_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||
|
||||
# Special Substitutions - CFG_WITH_DEFENV
|
||||
AC_MSG_CHECKING(whether to disable hardcoded paths)
|
||||
AC_ARG_ENABLE([defenv],
|
||||
[AS_HELP_STRING([--disable-defenv],
|
||||
[disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])],
|
||||
[case "${enableval}" in
|
||||
yes) CFG_WITH_DEFENV=yes ;;
|
||||
no) CFG_WITH_DEFENV=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --disable-defenv]) ;;
|
||||
esac],
|
||||
CFG_WITH_DEFENV=yes)
|
||||
AC_SUBST(CFG_WITH_DEFENV)
|
||||
AC_MSG_RESULT($CFG_WITH_DEFENV)
|
||||
|
||||
dnl Compiler flags
|
||||
# Special Substitutions - CFG_WITH_CCWARN
|
||||
AC_MSG_CHECKING(whether to show and stop on compilation warnings)
|
||||
AC_ARG_ENABLE([ccwarn],
|
||||
[AS_HELP_STRING([--enable-ccwarn],
|
||||
[enable showing and stopping on compilation warnings])],
|
||||
[case "${enableval}" in
|
||||
yes) CFG_WITH_CCWARN=yes ;;
|
||||
no) CFG_WITH_CCWARN=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ccwarn]) ;;
|
||||
esac],
|
||||
[case "x${VERILATOR_AUTHOR_SITE}" in
|
||||
x) CFG_WITH_CCWARN=no ;;
|
||||
*) CFG_WITH_CCWARN=yes ;;
|
||||
esac]
|
||||
)
|
||||
AC_SUBST(CFG_WITH_CCWARN)
|
||||
AC_MSG_RESULT($CFG_WITH_CCWARN)
|
||||
|
||||
# Special Substitutions - CFG_WITH_LONGTESTS
|
||||
AC_MSG_CHECKING(whether to run long tests)
|
||||
AC_ARG_ENABLE([longtests],
|
||||
[AS_HELP_STRING([--enable-longtests],
|
||||
[enable running long developer tests])],
|
||||
[case "${enableval}" in
|
||||
yes) CFG_WITH_LONGTESTS=yes ;;
|
||||
no) CFG_WITH_LONGTESTS=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-longtests]) ;;
|
||||
esac],
|
||||
[case "x${VERILATOR_AUTHOR_SITE}" in
|
||||
x) CFG_WITH_LONGTESTS=no ;;
|
||||
*) CFG_WITH_LONGTESTS=yes ;;
|
||||
esac]
|
||||
)
|
||||
AC_SUBST(CFG_WITH_LONGTESTS)
|
||||
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
||||
|
||||
# Compiler flags
|
||||
CFLAGS=-I${includedir}
|
||||
CPPFLAGS=-I${includedir}
|
||||
CXXFLAGS=-I${includedir}
|
||||
LDFLAGS=-L${libdir}
|
||||
|
||||
dnl Checks for programs.
|
||||
# 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_RUN_IFELSE(
|
||||
[AC_LANG_SOURCE([int main() { return 0; }])],
|
||||
AC_MSG_RESULT(yes),
|
||||
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]))
|
||||
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]),
|
||||
AC_MSG_RESULT(yes))
|
||||
|
||||
AC_PATH_PROG(PERL,perl)
|
||||
if test "x$PERL" = "x" ; then
|
||||
@@ -44,33 +92,54 @@ if test "x$YACC" = "x" ; then
|
||||
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
|
||||
fi
|
||||
|
||||
dnl Checks for libraries.
|
||||
# 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
|
||||
# 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.
|
||||
# Checks for compiler characteristics.
|
||||
AC_C_INLINE
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_DEFUN([_MY_CXX_CHECK_OPT],
|
||||
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
|
||||
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
|
||||
# -Werror needed otherwise unknown -Wno-div-by-zero won't report problems
|
||||
CXXFLAGS="$CXXFLAGS $1 -Werror"
|
||||
AC_MSG_CHECKING([whether $CXX accepts $1])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([],[])],
|
||||
[_my_result=yes],
|
||||
[_my_result=no])
|
||||
AC_MSG_RESULT($_my_result)
|
||||
if test "$_my_result" = "yes" ; then
|
||||
CFG_CXXFLAGS_NO_UNUSED="$CFG_CXXFLAGS_NO_UNUSED $1"
|
||||
fi
|
||||
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
|
||||
])# _MY_CXX_CHECK_OPT
|
||||
|
||||
dnl Checks for system services
|
||||
# For example, -Wno-div-by-zero isn't in 4.1.2
|
||||
_MY_CXX_CHECK_OPT(-Wno-char-subscripts)
|
||||
# Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn
|
||||
# without this flag, even though there's a conditional to prevent the divide.
|
||||
# We still don't add no-div-by-zero as it throws message to stdout, though doesn't die.
|
||||
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
|
||||
_MY_CXX_CHECK_OPT(-Wno-sign-compare)
|
||||
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
|
||||
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
|
||||
dnl Other install directories
|
||||
# Checks for library functions.
|
||||
|
||||
# Checks for system services
|
||||
|
||||
# Other install directories
|
||||
pkgdatadir=${datadir}/verilator
|
||||
AC_SUBST(pkgdatadir)
|
||||
|
||||
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([Now type 'gmake'])
|
||||
AC_MSG_RESULT([Now type 'make' (or sometimes 'gmake') to build Verilator.])
|
||||
AC_MSG_RESULT([])
|
||||
|
||||
+155
-19
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -26,7 +26,6 @@
|
||||
#define _VERILATED_CPP_
|
||||
#include "verilated_imp.h"
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
||||
|
||||
@@ -38,7 +37,7 @@ int Verilated::s_randReset = 0;
|
||||
VerilatedVoidCb Verilated::s_flushCb = NULL;
|
||||
|
||||
// Keep below together in one cache line
|
||||
int Verilated::s_debug = 1;
|
||||
int Verilated::s_debug = 0;
|
||||
bool Verilated::s_calcUnusedSigs = false;
|
||||
bool Verilated::s_gotFinish = false;
|
||||
bool Verilated::s_assertOn = true;
|
||||
@@ -285,12 +284,15 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Note also assumes variables < 64 are not wide, this assumption is
|
||||
// sometimes not true in low-level routines written here in verilated.cpp
|
||||
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const char* pctp = NULL; // Most recent %##.##g format
|
||||
bool inPct = false;
|
||||
bool widthSet = false;
|
||||
int width = 0;
|
||||
const char* pos = formatp;
|
||||
for (; *pos; ++pos) {
|
||||
if (!inPct && pos[0]=='%') {
|
||||
pctp = pos;
|
||||
inPct = true;
|
||||
widthSet = false;
|
||||
width = 0;
|
||||
@@ -312,6 +314,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
widthSet = true;
|
||||
width = width*10 + (fmt - '0');
|
||||
break;
|
||||
case '.':
|
||||
inPct = true; // Get more digits
|
||||
break;
|
||||
case '%':
|
||||
output += '%';
|
||||
break;
|
||||
@@ -325,6 +330,18 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
output += cstrp;
|
||||
break;
|
||||
}
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g': {
|
||||
const int lbits = va_arg(ap, int);
|
||||
double d = va_arg(ap, double);
|
||||
if (lbits) {} // UNUSED - always 64
|
||||
strncpy(tmpf, pctp, pos-pctp+1);
|
||||
tmpf[pos-pctp+1] = '\0';
|
||||
sprintf(tmp, tmpf, d);
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
@@ -358,14 +375,26 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
case 'd': { // Signed decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
output.append(needmore,'0'); // Pre-pad zero
|
||||
} else {
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
case 'u': { // Unsigned decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
output.append(needmore,'0'); // Pre-pad zero
|
||||
} else {
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
@@ -569,6 +598,17 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
VL_SET_WQ(owp,ld);
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'g': { // Real number
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "+-.0123456789eE");
|
||||
if (!tmp[0]) goto done;
|
||||
union { double r; vlsint64_t ld; } u;
|
||||
u.r = strtod(tmp, NULL);
|
||||
VL_SET_WQ(owp,u.ld);
|
||||
break;
|
||||
}
|
||||
case 't': // FALLTHRU // Time
|
||||
case 'u': { // Unsigned decimal
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
@@ -628,6 +668,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
//===========================================================================
|
||||
// File I/O
|
||||
|
||||
FILE* VL_CVT_I_FP(IData lhs) {
|
||||
return VerilatedImp::fdToFp(lhs);
|
||||
}
|
||||
|
||||
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||
// See also VL_DATA_TO_STRING_NW
|
||||
int lsb=obits-1;
|
||||
@@ -655,8 +699,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||
for (; i<bytes; i++) { *op++ = 0; }
|
||||
}
|
||||
|
||||
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
// The string needs to be padded with 0's in unused spaces in front of
|
||||
@@ -683,16 +727,26 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
return got;
|
||||
}
|
||||
|
||||
QData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||
return VL_FOPEN_WI(2, fnw, mode);
|
||||
}
|
||||
QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
|
||||
char modez[5];
|
||||
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
|
||||
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
||||
return VL_FOPEN_S(filenamez,modez);
|
||||
}
|
||||
IData VL_FOPEN_S(const char* filenamep, const char* modep) {
|
||||
return VerilatedImp::fdNew(fopen(filenamep,modep));
|
||||
}
|
||||
|
||||
void VL_FCLOSE_I(IData fdi) {
|
||||
FILE* fp = VL_CVT_I_FP(fdi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
fclose(fp);
|
||||
VerilatedImp::fdDelete(fdi);
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
@@ -726,8 +780,8 @@ void VL_WRITEF(const char* formatp, ...) {
|
||||
VL_PRINTF("%s", output.c_str());
|
||||
}
|
||||
|
||||
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
|
||||
va_list ap;
|
||||
@@ -739,8 +793,8 @@ void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
fputs(output.c_str(), fp);
|
||||
}
|
||||
|
||||
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
va_list ap;
|
||||
@@ -833,7 +887,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
} else {
|
||||
needinc = true;
|
||||
//printf(" Value width=%d @%x = %c\n", width, addr, c);
|
||||
if (addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb)) {
|
||||
if (VL_UNLIKELY(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;
|
||||
@@ -861,7 +915,7 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
|
||||
datap[0] |= value;
|
||||
}
|
||||
if (value>=(1<<shift)) {
|
||||
if (VL_UNLIKELY(value>=(1<<shift))) {
|
||||
vl_fatal (ofilenamez, linenum, "", "$readmemb (binary) file contains hex characters");
|
||||
}
|
||||
}
|
||||
@@ -878,11 +932,22 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
|
||||
// Final checks
|
||||
fclose(fp);
|
||||
if (end != VL_UL(0xffffffff) && addr != (end+1)) {
|
||||
if (VL_UNLIKELY(end != VL_UL(0xffffffff) && addr != (end+1))) {
|
||||
vl_fatal (ofilenamez, linenum, "", "$readmem file ended before specified ending-address");
|
||||
}
|
||||
}
|
||||
|
||||
IData VL_SYSTEM_IQ(QData lhs) {
|
||||
IData lhsw[2]; VL_SET_WQ(lhsw, lhs);
|
||||
return VL_SYSTEM_IW(2, lhsw);
|
||||
}
|
||||
IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
|
||||
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(lhswords*VL_WORDSIZE, filenamez, filenamep);
|
||||
int code = system(filenamez);
|
||||
return code >> 8; // Want exit status
|
||||
}
|
||||
|
||||
IData VL_TESTPLUSARGS_I(const char* formatp) {
|
||||
string match = VerilatedImp::argPlusMatch(formatp);
|
||||
if (match == "") return 0;
|
||||
@@ -995,6 +1060,10 @@ void Verilated::scopesDump() {
|
||||
VerilatedImp::scopesDump();
|
||||
}
|
||||
|
||||
const VerilatedScope* Verilated::scopeFind(const char* namep) {
|
||||
return VerilatedImp::scopeFind(namep);
|
||||
}
|
||||
|
||||
int Verilated::exportFuncNum(const char* namep) {
|
||||
return VerilatedImp::exportFind(namep);
|
||||
}
|
||||
@@ -1010,6 +1079,23 @@ VerilatedModule::~VerilatedModule() {
|
||||
if (m_namep) free((void*)m_namep); m_namep=NULL;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// VerilatedVar:: Methods
|
||||
|
||||
vluint32_t VerilatedVar::entSize() const {
|
||||
vluint32_t size = 1;
|
||||
switch (vltype()) {
|
||||
case VLVT_PTR: size=sizeof(void*); break;
|
||||
case VLVT_UINT8: size=sizeof(CData); break;
|
||||
case VLVT_UINT16: size=sizeof(SData); break;
|
||||
case VLVT_UINT32: size=sizeof(IData); break;
|
||||
case VLVT_UINT64: size=sizeof(QData); break;
|
||||
case VLVT_WDATA: size=VL_WORDS_I(range().bits())*sizeof(IData); break;
|
||||
default: size=0; break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// VerilatedScope:: Methods
|
||||
|
||||
@@ -1017,12 +1103,15 @@ VerilatedScope::VerilatedScope() {
|
||||
m_callbacksp = NULL;
|
||||
m_namep = NULL;
|
||||
m_funcnumMax = 0;
|
||||
m_symsp = NULL;
|
||||
m_varsp = NULL;
|
||||
}
|
||||
|
||||
VerilatedScope::~VerilatedScope() {
|
||||
VerilatedImp::scopeErase(this);
|
||||
if (m_namep) { delete [] m_namep; m_namep = NULL; }
|
||||
if (m_callbacksp) { delete [] m_callbacksp; m_callbacksp = NULL; }
|
||||
if (m_varsp) { delete m_varsp; m_varsp = NULL; }
|
||||
m_funcnumMax = 0; // Force callback table to empty
|
||||
}
|
||||
|
||||
@@ -1047,10 +1136,10 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) {
|
||||
// Alternative is to dynamically stretch the array, which is more code, and slower.
|
||||
if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; }
|
||||
} else {
|
||||
if (funcnum >= m_funcnumMax) {
|
||||
if (VL_UNLIKELY(funcnum >= m_funcnumMax)) {
|
||||
vl_fatal(__FILE__,__LINE__,"","Internal: Bad funcnum vs. pre-finalize maximum");
|
||||
}
|
||||
if (!m_callbacksp) { // First allocation
|
||||
if (VL_UNLIKELY(!m_callbacksp)) { // First allocation
|
||||
m_callbacksp = new void* [m_funcnumMax];
|
||||
memset(m_callbacksp, 0, m_funcnumMax*sizeof(void*));
|
||||
}
|
||||
@@ -1058,6 +1147,47 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) {
|
||||
}
|
||||
}
|
||||
|
||||
void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
|
||||
VerilatedVarType vltype, int vlflags, int dims, ...) {
|
||||
// Grab dimensions
|
||||
// In the future we may just create a large table at emit time and statically construct from that.
|
||||
if (!finalize) return;
|
||||
|
||||
if (!m_varsp) m_varsp = new VerilatedVarNameMap();
|
||||
VerilatedVar var (namep, datap, vltype, (VerilatedVarFlags)vlflags, dims);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,dims);
|
||||
for (int i=0; i<dims; ++i) {
|
||||
int msb = va_arg(ap,int);
|
||||
int lsb = va_arg(ap,int);
|
||||
if (i==0) {
|
||||
var.m_range.m_lhs = msb;
|
||||
var.m_range.m_rhs = lsb;
|
||||
} else if (i==1) {
|
||||
var.m_array.m_lhs = msb;
|
||||
var.m_array.m_rhs = lsb;
|
||||
} else {
|
||||
// We could have a linked list of ranges, but really this whole thing needs
|
||||
// to be generalized to support structs and unions, etc.
|
||||
vl_fatal(__FILE__,__LINE__,"",(string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
m_varsp->insert(make_pair(namep,var));
|
||||
}
|
||||
|
||||
VerilatedVar* VerilatedScope::varFind(const char* namep) const {
|
||||
if (VL_LIKELY(m_varsp)) {
|
||||
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
|
||||
if (VL_LIKELY(it != m_varsp->end())) {
|
||||
return &(it->second);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* VerilatedScope::exportFindNullError(int funcnum) const {
|
||||
// Slowpath - Called only when find has failed
|
||||
string msg = (string("Testbench C called '")
|
||||
@@ -1085,6 +1215,12 @@ void VerilatedScope::scopeDump() const {
|
||||
m_callbacksp[i], VerilatedImp::exportName(i));
|
||||
}
|
||||
}
|
||||
if (varsp()) {
|
||||
for (VerilatedVarNameMap::const_iterator it = varsp()->begin();
|
||||
it != varsp()->end(); ++it) {
|
||||
VL_PRINTF(" VAR %p: %s\n", &(it->second), it->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
+83
-30
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
// <iostream> avoided to reduce compile time
|
||||
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
||||
using namespace std;
|
||||
@@ -66,9 +67,33 @@ typedef void (*VerilatedVoidCb)(void);
|
||||
|
||||
class SpTraceVcd;
|
||||
class SpTraceVcdCFile;
|
||||
class VerilatedVar;
|
||||
class VerilatedVarNameMap;
|
||||
class VerilatedVcd;
|
||||
class VerilatedVcdC;
|
||||
|
||||
enum VerilatedVarType {
|
||||
VLVT_UNKNOWN=0,
|
||||
VLVT_PTR, // Pointer to something
|
||||
VLVT_UINT8, // AKA CData
|
||||
VLVT_UINT16, // AKA SData
|
||||
VLVT_UINT32, // AKA IData
|
||||
VLVT_UINT64, // AKA QData
|
||||
VLVT_WDATA, // AKA WData
|
||||
VLVT_STRING // C++ string
|
||||
};
|
||||
|
||||
enum VerilatedVarFlags {
|
||||
VLVD_IN=1, // == vpiInput
|
||||
VLVD_OUT=2, // == vpiOutput
|
||||
VLVD_INOUT=3, // == vpiInOut
|
||||
VLVD_NODIR=5, // == vpiNoDirection
|
||||
VLVF_MASK_DIR=7, // Bit mask for above directions
|
||||
// Flags
|
||||
VLVF_PUB_RD=(1<<8), // Public readable
|
||||
VLVF_PUB_RW=(1<<9) // Public writable
|
||||
};
|
||||
|
||||
//=========================================================================
|
||||
/// Base class for all Verilated module classes
|
||||
|
||||
@@ -138,6 +163,9 @@ public:
|
||||
#ifndef VL_PRINTF
|
||||
# define VL_PRINTF printf ///< Print ala printf; may redefine if desired
|
||||
#endif
|
||||
#ifndef VL_VPRINTF
|
||||
# define VL_VPRINTF vprintf ///< Print ala vprintf; may redefine if desired
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator symbol table base class
|
||||
@@ -155,6 +183,7 @@ class VerilatedScope {
|
||||
void** m_callbacksp; ///< Callback table pointer (Fastpath)
|
||||
int m_funcnumMax; ///< Maxium function number stored (Fastpath)
|
||||
// 4 bytes padding (on -m64), for rent.
|
||||
VerilatedVarNameMap* m_varsp; ///< Variable map
|
||||
const char* m_namep; ///< Scope name (Slowpath)
|
||||
|
||||
public: // But internals only - called from VerilatedModule's
|
||||
@@ -162,9 +191,13 @@ public: // But internals only - called from VerilatedModule's
|
||||
~VerilatedScope();
|
||||
void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp);
|
||||
void exportInsert(int finalize, const char* namep, void* cb);
|
||||
void varInsert(int finalize, const char* namep, void* datap,
|
||||
VerilatedVarType vltype, int vlflags, int dims, ...);
|
||||
// ACCESSORS
|
||||
const char* name() const { return m_namep; }
|
||||
inline VerilatedSyms* symsp() const { return m_symsp; }
|
||||
VerilatedVar* varFind(const char* namep) const;
|
||||
VerilatedVarNameMap* varsp() const { return m_varsp; }
|
||||
void* exportFindError(int funcnum) const;
|
||||
void* exportFindNullError(int funcnum) const;
|
||||
void scopeDump() const;
|
||||
@@ -247,6 +280,8 @@ public:
|
||||
// METHODS - INTERNAL USE ONLY
|
||||
// Internal: Create a new module name by concatenating two strings
|
||||
static const char* catName(const char* n1, const char* n2); // Returns new'ed data
|
||||
// Internal: Find scope
|
||||
static const VerilatedScope* scopeFind(const char* namep);
|
||||
// Internal: Get and set DPI context
|
||||
static const VerilatedScope* dpiScope() { return t_dpiScopep; }
|
||||
static void dpiScope(const VerilatedScope* scopep) { t_dpiScopep=scopep; }
|
||||
@@ -287,11 +322,14 @@ extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a
|
||||
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
|
||||
|
||||
/// File I/O
|
||||
extern IData VL_FGETS_IXQ(int obits, void* destp, QData fpq);
|
||||
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
|
||||
|
||||
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 IData VL_FOPEN_S(const char* filenamep, const char* mode);
|
||||
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||
|
||||
extern void VL_FCLOSE_I(IData fdi);
|
||||
|
||||
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilename, void* memp, IData start, IData end);
|
||||
@@ -302,15 +340,19 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
||||
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 void VL_FWRITEF(IData fpi, const char* formatp, ...);
|
||||
|
||||
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
|
||||
extern IData VL_FSCANF_IX(IData fpi, 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, ...);
|
||||
|
||||
extern void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...);
|
||||
|
||||
extern IData VL_SYSTEM_IW(int lhsnwords, WDataInP lhs);
|
||||
extern IData VL_SYSTEM_IQ(QData lhs);
|
||||
inline IData VL_SYSTEM_II(IData lhs) { return VL_SYSTEM_IQ(lhs); }
|
||||
|
||||
extern IData VL_TESTPLUSARGS_I(const char* formatp);
|
||||
extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp);
|
||||
extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
@@ -330,15 +372,24 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) ))
|
||||
#define _VL_SET_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
|
||||
|
||||
/// Return FILE* from IData
|
||||
extern FILE* VL_CVT_I_FP(IData lhs);
|
||||
|
||||
// Use a union to avoid cast-to-different-size warnings
|
||||
/// Return FILE* from QData
|
||||
static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return void* from QData
|
||||
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return QData from FILE*
|
||||
static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return QData from void*
|
||||
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return double from QData (bits, not numerically)
|
||||
static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||
/// Return QData from double (bits, not numerically)
|
||||
static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||
/// Return double from QData (numeric)
|
||||
static inline double VL_ITOR_D_I(IData lhs) { return ((double)((vlsint32_t)(lhs))); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(VL_TRUNC(lhs))); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(VL_ROUND(lhs))); }
|
||||
|
||||
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
||||
// (Requires clean input)
|
||||
@@ -357,6 +408,9 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
//=========================================================================
|
||||
// Pli macros
|
||||
|
||||
#ifndef VL_TIME_PRECISION
|
||||
# define VL_TIME_PRECISION -12 ///< Timescale units only for for VPI return - picoseconds
|
||||
#endif
|
||||
#ifndef VL_TIME_MULTIPLIER
|
||||
# define VL_TIME_MULTIPLIER 1
|
||||
#endif
|
||||
@@ -365,9 +419,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
||||
# define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() ((double)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
#else
|
||||
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
extern double sc_time_stamp();
|
||||
#endif
|
||||
|
||||
@@ -908,16 +964,13 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
|
||||
return(owp);
|
||||
}
|
||||
|
||||
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround
|
||||
#if 1 //defined(__GNUC__) && __GNUC__ < 3
|
||||
static inline IData VL_UNARYMIN_I(IData data) { return -data; }
|
||||
static inline QData VL_UNARYMIN_Q(QData data) { return -data; }
|
||||
#else
|
||||
# define VL_UNARYMIN_I(IData data) (-(data))
|
||||
# define VL_UNARYMIN_Q(QData data) (-(data))
|
||||
#endif
|
||||
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
|
||||
// we can't just
|
||||
//# define VL_NEGATE_I(data) (-(data))
|
||||
static inline IData VL_NEGATE_I(IData data) { return -data; }
|
||||
static inline QData VL_NEGATE_Q(QData data) { return -data; }
|
||||
|
||||
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){
|
||||
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; i++) {
|
||||
carry = carry + (QData)(IData)(~lwp[i]);
|
||||
@@ -964,18 +1017,18 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
|
||||
IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
|
||||
if (lneg) { // Negate lhs
|
||||
lwusp = lwstore;
|
||||
VL_UNARYMIN_W(words, lwstore, lwp);
|
||||
VL_NEGATE_W(words, lwstore, lwp);
|
||||
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||
}
|
||||
IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
|
||||
if (rneg) { // Negate rhs
|
||||
rwusp = rwstore;
|
||||
VL_UNARYMIN_W(words, rwstore, rwp);
|
||||
VL_NEGATE_W(words, rwstore, rwp);
|
||||
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||
}
|
||||
VL_MUL_W(words,owp,lwusp,rwusp);
|
||||
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
|
||||
if ((lneg ^ rneg) & 1) { // Negate output (not using UNARYMIN, as owp==lwp)
|
||||
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; i++) {
|
||||
carry = carry + (QData)(IData)(~owp[i]);
|
||||
@@ -1022,12 +1075,12 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
|
||||
IData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP ltup = lwp;
|
||||
WDataInP rtup = rwp;
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if ((lsign && !rsign) || (!lsign && rsign)) {
|
||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||
VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
return owp;
|
||||
} else {
|
||||
return VL_DIV_WWW(lbits,owp,ltup,rtup);
|
||||
@@ -1041,12 +1094,12 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
|
||||
IData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP ltup = lwp;
|
||||
WDataInP rtup = rwp;
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { // Only dividend sign matters for modulus
|
||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
return owp;
|
||||
} else {
|
||||
return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
|
||||
@@ -1599,6 +1652,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
||||
|
||||
#undef _END
|
||||
|
||||
// Debugging
|
||||
//======================================================================
|
||||
|
||||
#endif /*_VERILATED_H_*/
|
||||
|
||||
+20
-7
@@ -2,7 +2,7 @@
|
||||
######################################################################
|
||||
# DESCRIPTION: Makefile commands for all verilated target files
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
######################################################################
|
||||
@@ -13,12 +13,25 @@ LINK = @CXX@
|
||||
AR = ar
|
||||
RANLIB = ranlib
|
||||
|
||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||
|
||||
# Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero
|
||||
CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
|
||||
|
||||
######################################################################
|
||||
# Programs
|
||||
|
||||
SP_PREPROC = sp_preproc
|
||||
SP_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
|
||||
|
||||
######################################################################
|
||||
# Make checks
|
||||
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# C Preprocessor flags
|
||||
|
||||
@@ -31,13 +44,9 @@ VK_CPPFLAGS_ALWAYS += \
|
||||
-DVM_TRACE=$(VM_TRACE) \
|
||||
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
VK_CPPFLAGS_WALL += -Wall \
|
||||
-Wno-char-subscripts \
|
||||
-Wno-sign-compare \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-unused-variable \
|
||||
-Wno-uninitialized \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
-Werror
|
||||
endif
|
||||
|
||||
@@ -109,6 +118,10 @@ ifeq ($(VM_SP),1)
|
||||
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
|
||||
--preproc $(VK_CLASSES_SP)
|
||||
else
|
||||
ifeq ($(VM_COVERAGE),1)
|
||||
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
|
||||
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||
endif
|
||||
preproc:
|
||||
endif
|
||||
|
||||
|
||||
+3
-7
@@ -5,7 +5,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -27,11 +27,7 @@
|
||||
`define coverage_block_off
|
||||
`endif
|
||||
|
||||
// Hide file descriptor difference
|
||||
`ifdef verilator
|
||||
`define verilator_file_descriptor reg [63:0]
|
||||
`else
|
||||
`define verilator_file_descriptor integer
|
||||
`endif
|
||||
// Hide file descriptor difference - deprecated - for older versions
|
||||
`define verilator_file_descriptor integer
|
||||
|
||||
`endif // guard
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define _VERILATED_DPI_CPP_
|
||||
#include "verilatedos.h"
|
||||
#include "verilated_dpi.h"
|
||||
#include "verilated_imp.h"
|
||||
|
||||
// On MSVC++ we need svdpi.h to declare exports, not imports
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: Common include for all Verilated C files that use DPI
|
||||
///
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all C++ files it generates where DPI is used. It contains
|
||||
/// DPI interface functions required by the Verilated code.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#ifndef _VERILATED_DPI_H_
|
||||
#define _VERILATED_DPI_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated.h" // Presumed done by caller
|
||||
#include "svdpi.h"
|
||||
|
||||
//===================================================================
|
||||
// SETTING OPERATORS
|
||||
|
||||
/// Return svBitVecVal from WData
|
||||
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
|
||||
// Note we ignore X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
|
||||
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
|
||||
// Note we don't create X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words; i++) owp[i].bval=0;
|
||||
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
|
||||
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif // _VERILATED_DPI_H_
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
+42
-10
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -31,9 +31,11 @@
|
||||
#include "verilatedos.h"
|
||||
#include "verilated.h"
|
||||
#include "verilated_heavy.h"
|
||||
#include "verilated_syms.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
class VerilatedScope;
|
||||
@@ -41,13 +43,6 @@ class VerilatedScope;
|
||||
//======================================================================
|
||||
// Types
|
||||
|
||||
struct VerilatedCStrCmp {
|
||||
// For ordering maps keyed by const char*'s
|
||||
bool operator() (const char *a, const char *b) const {
|
||||
return std::strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedImp {
|
||||
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||
|
||||
@@ -55,7 +50,7 @@ class VerilatedImp {
|
||||
typedef vector<string> ArgVec;
|
||||
typedef map<pair<const void*,void*>,void*> UserMap;
|
||||
typedef map<const char*, const VerilatedScope*, VerilatedCStrCmp> ScopeNameMap;
|
||||
typedef map<const char*, int> ExportNameMap;
|
||||
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||
|
||||
// MEMBERS
|
||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
||||
@@ -68,9 +63,18 @@ class VerilatedImp {
|
||||
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
||||
int m_exportNext; ///< Next export funcnum
|
||||
|
||||
// File I/O
|
||||
vector<FILE*> m_fdps; ///< File descriptors
|
||||
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {}
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
|
||||
m_fdps.resize(3);
|
||||
m_fdps[0] = stdin;
|
||||
m_fdps[1] = stdout;
|
||||
m_fdps[2] = stderr;
|
||||
}
|
||||
~VerilatedImp() {}
|
||||
|
||||
// METHODS - arguments
|
||||
@@ -190,6 +194,34 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
// We don't free up m_exportMap until the end, because we can't be sure
|
||||
// what other models are using the assigned funcnum's.
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - file IO
|
||||
static IData fdNew(FILE* fp) {
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
// Bit 31 indicates it's a descriptor not a MCD
|
||||
if (s_s.m_fdFree.empty()) {
|
||||
// Need to create more space in m_fdps and m_fdFree
|
||||
size_t start = s_s.m_fdps.size();
|
||||
s_s.m_fdps.resize(start*2);
|
||||
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
|
||||
}
|
||||
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
|
||||
s_s.m_fdps[idx] = fp;
|
||||
return (idx | (1UL<<31)); // bit 31 indicates not MCD
|
||||
}
|
||||
static void fdDelete(IData fdi) {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
|
||||
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
|
||||
s_s.m_fdps[idx] = NULL;
|
||||
s_s.m_fdFree.push_back(idx);
|
||||
}
|
||||
static inline FILE* fdToFp(IData fdi) {
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
|
||||
return s_s.m_fdps[idx];
|
||||
}
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: Include to allow symbol inspection
|
||||
///
|
||||
/// This file is for inclusion by files that need to inspect
|
||||
/// the symbol table. It is not included in verilated.h
|
||||
/// as it requires some heavyweight C++ classes.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#ifndef _VERILATED_SYMS_H_
|
||||
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated_heavy.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
//======================================================================
|
||||
// Types
|
||||
|
||||
struct VerilatedCStrCmp {
|
||||
/// Ordering maps keyed by const char*'s
|
||||
bool operator() (const char *a, const char *b) const {
|
||||
return std::strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator range
|
||||
|
||||
class VerilatedRange {
|
||||
int m_lhs;
|
||||
int m_rhs;
|
||||
protected:
|
||||
friend class VerilatedVar;
|
||||
friend class VerilatedScope;
|
||||
VerilatedRange() : m_lhs(0), m_rhs(0) {}
|
||||
void sets(int lhs, int rhs) { m_lhs=lhs; m_rhs=rhs; }
|
||||
public:
|
||||
~VerilatedRange() {}
|
||||
int lhs() const { return m_lhs; }
|
||||
int rhs() const { return m_rhs; }
|
||||
int bits() const { return (VL_LIKELY(m_lhs>=m_rhs)?(m_lhs-m_rhs+1):(m_rhs-m_lhs+1)); }
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
/// Verilator variable
|
||||
|
||||
class VerilatedVar {
|
||||
void* m_datap; // Location of data
|
||||
VerilatedVarType m_vltype; // Data type
|
||||
VerilatedVarFlags m_vlflags; // Direction
|
||||
VerilatedRange m_range; // First range
|
||||
VerilatedRange m_array; // Array
|
||||
int m_dims; // Dimensions
|
||||
const char* m_namep; // Name - slowpath
|
||||
protected:
|
||||
friend class VerilatedScope;
|
||||
VerilatedVar(const char* namep, void* datap,
|
||||
VerilatedVarType vltype, VerilatedVarFlags vlflags, int dims)
|
||||
: m_datap(datap), m_vltype(vltype), m_vlflags(vlflags), m_dims(dims), m_namep(namep) {}
|
||||
public:
|
||||
~VerilatedVar() {}
|
||||
void* datap() const { return m_datap; }
|
||||
VerilatedVarType vltype() const { return m_vltype; }
|
||||
VerilatedVarFlags vldir() const { return (VerilatedVarFlags)((int)m_vlflags & VLVF_MASK_DIR); }
|
||||
vluint32_t entSize() const;
|
||||
bool isPublicRW() const { return ((m_vlflags & VLVF_PUB_RW) != 0); }
|
||||
const VerilatedRange& range() const { return m_range; }
|
||||
const VerilatedRange& array() const { return m_array; }
|
||||
const char* name() const { return m_namep; }
|
||||
int dims() const { return m_dims; }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
/// Types
|
||||
|
||||
struct VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||
VerilatedVarNameMap() {}
|
||||
~VerilatedVarNameMap() {}
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
+40
-13
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
@@ -154,6 +154,39 @@ void VerilatedVcd::openNext (bool incFilename) {
|
||||
m_wroteBytes = 0;
|
||||
}
|
||||
|
||||
void VerilatedVcd::makeNameMap() {
|
||||
// Take signal information from each module and build m_namemapp
|
||||
m_namemapp = new NameMap;
|
||||
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||
cip->m_code = nextCode();
|
||||
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
|
||||
}
|
||||
|
||||
// Though not speced, it's illegal to generate a vcd with signals
|
||||
// not under any module - it crashes at least two viewers.
|
||||
// If no scope was specified, prefix everything with a "top"
|
||||
// This comes from user instantiations with no name - IE Vtop("").
|
||||
bool nullScope = false;
|
||||
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||
const char* hiername = (*it).first.c_str();
|
||||
if (hiername[0] == '\t') nullScope=true;
|
||||
}
|
||||
if (nullScope) {
|
||||
NameMap* newmapp = new NameMap;
|
||||
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||
const string& hiername = it->first;
|
||||
const string& decl = it->second;
|
||||
string newname = string("top");
|
||||
if (hiername[0] != '\t') newname += ' ';
|
||||
newname += hiername;
|
||||
newmapp->insert(make_pair(newname,decl));
|
||||
}
|
||||
delete m_namemapp; m_namemapp=NULL;
|
||||
m_namemapp = newmapp;
|
||||
}
|
||||
}
|
||||
|
||||
VerilatedVcd::~VerilatedVcd() {
|
||||
close();
|
||||
if (m_wrBufp) { delete[] m_wrBufp; m_wrBufp=NULL; }
|
||||
@@ -201,7 +234,7 @@ void VerilatedVcd::printStr (const char* str) {
|
||||
|
||||
void VerilatedVcd::printQuad (vluint64_t n) {
|
||||
char buf [100];
|
||||
sprintf(buf,"%" VL_PRI64 "u",(long long unsigned)n);
|
||||
sprintf(buf,"%" VL_PRI64 "u", n);
|
||||
printStr(buf);
|
||||
}
|
||||
|
||||
@@ -227,10 +260,10 @@ void VerilatedVcd::bufferFlush () {
|
||||
if (VL_UNLIKELY(!isOpen())) return;
|
||||
char* wp = m_wrBufp;
|
||||
while (1) {
|
||||
size_t remaining = (m_writep - wp);
|
||||
ssize_t remaining = (m_writep - wp);
|
||||
if (remaining==0) break;
|
||||
errno = 0;
|
||||
int got = write (m_fd, wp, remaining);
|
||||
ssize_t got = write (m_fd, wp, remaining);
|
||||
if (got>0) {
|
||||
wp += got;
|
||||
m_wroteBytes += got;
|
||||
@@ -314,13 +347,7 @@ void VerilatedVcd::dumpHeader () {
|
||||
printStr(doubleToTimescale(m_timeRes).c_str());
|
||||
printStr(" $end\n");
|
||||
|
||||
// Take signal information from each module and build m_namemapp
|
||||
m_namemapp = new NameMap;
|
||||
for (vluint32_t ent = 0; ent< m_callbacks.size(); ent++) {
|
||||
VerilatedVcdCallInfo *cip = m_callbacks[ent];
|
||||
cip->m_code = nextCode();
|
||||
(cip->m_initcb) (this, cip->m_userthis, cip->m_code);
|
||||
}
|
||||
makeNameMap();
|
||||
|
||||
// Signal header
|
||||
assert (m_modDepth==0);
|
||||
@@ -346,7 +373,7 @@ void VerilatedVcd::dumpHeader () {
|
||||
// Skip common prefix, it must break at a space or tab
|
||||
for (; *np && (*np == *lp); np++, lp++) {}
|
||||
while (np!=hiername && *np && *np!=' ' && *np!='\t') { np--; lp--; }
|
||||
//cout <<"hier "<<hiername<<endl<<" lp "<<lp<<endl<<" np "<<np<<endl;
|
||||
//printf("hier %s\n lp=%s\n np=%s\n",hiername,lp,np);
|
||||
|
||||
// Any extra spaces in last name are scope ups we need to do
|
||||
bool first = true;
|
||||
@@ -394,7 +421,7 @@ void VerilatedVcd::module (string name) {
|
||||
}
|
||||
|
||||
void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep,
|
||||
int arraynum, bool tri, bool bussed, int msb, int lsb) {
|
||||
int arraynum, bool tri, bool bussed, int msb, int lsb) {
|
||||
if (!code) { vl_fatal(__FILE__,__LINE__,"","Internal: internal trace problem, code 0 is illegal"); }
|
||||
|
||||
int bits = ((msb>lsb)?(msb-lsb):(lsb-msb))+1;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
@@ -86,8 +86,8 @@ private:
|
||||
NameMap* m_namemapp; ///< List of names for the header
|
||||
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
|
||||
|
||||
inline size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline size_t bufferInsertSize() { return 16*1024; }
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
void bufferFlush();
|
||||
void bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
@@ -99,6 +99,7 @@ private:
|
||||
void closePrev();
|
||||
void closeErr();
|
||||
void openNext();
|
||||
void makeNameMap();
|
||||
void printIndent (int levelchange);
|
||||
void printStr (const char* str);
|
||||
void printQuad (vluint64_t n);
|
||||
@@ -109,6 +110,7 @@ private:
|
||||
void dumpHeader();
|
||||
void dumpPrep (vluint64_t timeui);
|
||||
void dumpFull (vluint64_t timeui);
|
||||
// cppcheck-suppress functionConst
|
||||
void dumpDone ();
|
||||
inline void printCode (vluint32_t code) {
|
||||
if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33));
|
||||
@@ -116,7 +118,7 @@ private:
|
||||
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
|
||||
*m_writep++ = ((char)((code)%94+33));
|
||||
}
|
||||
string stringCode (vluint32_t code) {
|
||||
static string stringCode (vluint32_t code) {
|
||||
string out;
|
||||
if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33));
|
||||
if (code>=(94*94)) out += ((char)((code/94/94)%94+33));
|
||||
@@ -140,6 +142,8 @@ public:
|
||||
m_evcd = false;
|
||||
m_scopeEscape = '.'; // Backward compatibility
|
||||
m_wroteBytes = 0;
|
||||
m_fd = 0;
|
||||
m_fullDump = true;
|
||||
}
|
||||
~VerilatedVcd();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// THIS MODULE IS PUBLICLY LICENSED
|
||||
//
|
||||
// Copyright 2001-2010 by Wilson Snyder. This program is free software;
|
||||
// Copyright 2001-2011 by Wilson Snyder. This program is free software;
|
||||
// you can redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
//
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//=========================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: VPI implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all objects
|
||||
/// created from Verilator or called by Verilator that use the VPI.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//=========================================================================
|
||||
|
||||
#include "verilated_vpi.h"
|
||||
|
||||
//======================================================================
|
||||
|
||||
VerilatedVpi VerilatedVpi::s_s; // Singleton
|
||||
vluint8_t* VerilatedVpio::s_freeHead = NULL;
|
||||
|
||||
//======================================================================
|
||||
@@ -0,0 +1,857 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2009-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//=========================================================================
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: VPI implementation code
|
||||
///
|
||||
/// This file must be compiled and linked against all objects
|
||||
/// created from Verilator or called by Verilator that use the VPI.
|
||||
///
|
||||
/// "//-" indicates features that are as yet unimplemented.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//=========================================================================
|
||||
|
||||
#ifndef CHPI_VERILATED_VPI_H
|
||||
#define CHPI_VERILATED_VPI_H 1
|
||||
|
||||
#include "verilated.h"
|
||||
#include "verilated_syms.h"
|
||||
|
||||
//======================================================================
|
||||
// From IEEE 1800-2009 annex K
|
||||
|
||||
#include "vltstd/vpi_user.h"
|
||||
|
||||
//======================================================================
|
||||
// Internal macros
|
||||
|
||||
// Not supported yet
|
||||
#define _VL_VPI_UNIMP() \
|
||||
vl_fatal(__FILE__,__LINE__,"",Verilated::catName("Unsupported VPI function: ",VL_FUNC))
|
||||
|
||||
//======================================================================
|
||||
// Implementation
|
||||
|
||||
#include <set>
|
||||
|
||||
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
|
||||
|
||||
// Base VPI handled object
|
||||
class VerilatedVpio {
|
||||
// MEM MANGLEMENT
|
||||
static vluint8_t* s_freeHead;
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedVpio() {}
|
||||
virtual ~VerilatedVpio() {}
|
||||
inline static void* operator new(size_t size) {
|
||||
// We new and delete tons of vpi structures, so keep them around
|
||||
// To simplify our free list, we use a size large enough for all derived types
|
||||
// We reserve word zero for the next pointer, as that's safer in case a
|
||||
// dangling reference to the original remains around.
|
||||
static size_t chunk = 96;
|
||||
if (VL_UNLIKELY(size>chunk)) vl_fatal(__FILE__,__LINE__,"", "increase chunk");
|
||||
if (VL_LIKELY(s_freeHead)) {
|
||||
vluint8_t* newp = s_freeHead;
|
||||
s_freeHead = *((vluint8_t**)newp);
|
||||
return newp+8;
|
||||
} else {
|
||||
// +8: 8 bytes for next
|
||||
vluint8_t* newp = (vluint8_t*)(::operator new(chunk+8));
|
||||
return newp+8;
|
||||
}
|
||||
}
|
||||
inline static void operator delete(void* obj, size_t size) {
|
||||
vluint8_t* oldp = ((vluint8_t*)obj)-8;
|
||||
*((void**)oldp) = s_freeHead;
|
||||
s_freeHead = oldp;
|
||||
}
|
||||
// MEMBERS
|
||||
static inline VerilatedVpio* castp(vpiHandle h) { return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
|
||||
inline vpiHandle castVpiHandle() { return (vpiHandle)(this); }
|
||||
// ACCESSORS
|
||||
virtual const char* name() { return "<null>"; }
|
||||
virtual const char* fullname() { return "<null>"; }
|
||||
virtual const char* defname() { return "<null>"; }
|
||||
virtual vpiHandle dovpi_scan() { return 0; }
|
||||
};
|
||||
|
||||
typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
|
||||
|
||||
class VerilatedVpioCb : public VerilatedVpio {
|
||||
t_cb_data m_cbData;
|
||||
s_vpi_value m_value;
|
||||
QData m_time;
|
||||
public:
|
||||
// cppcheck-suppress uninitVar // m_value
|
||||
VerilatedVpioCb(const t_cb_data* cbDatap, QData time)
|
||||
: m_cbData(*cbDatap), m_time(time) {
|
||||
m_cbData.value = &m_value;
|
||||
}
|
||||
virtual ~VerilatedVpioCb() {}
|
||||
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
|
||||
vluint32_t reason() const { return m_cbData.reason; }
|
||||
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
|
||||
t_cb_data* cb_datap() { return &(m_cbData); }
|
||||
QData time() const { return m_time; }
|
||||
};
|
||||
|
||||
class VerilatedVpioConst : public VerilatedVpio {
|
||||
vlsint32_t m_num;
|
||||
public:
|
||||
VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
|
||||
virtual ~VerilatedVpioConst() {}
|
||||
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
|
||||
vlsint32_t num() const { return m_num; }
|
||||
};
|
||||
|
||||
class VerilatedVpioRange : public VerilatedVpio {
|
||||
vlsint32_t m_lhs; // Ranges can be signed
|
||||
vlsint32_t m_rhs;
|
||||
bool m_iteration;
|
||||
public:
|
||||
VerilatedVpioRange(vlsint32_t lhs, vlsint32_t rhs) : m_lhs(lhs), m_rhs(rhs), m_iteration(0) {}
|
||||
virtual ~VerilatedVpioRange() {}
|
||||
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
|
||||
vlsint32_t lhs() const { return m_lhs; }
|
||||
vlsint32_t rhs() const { return m_rhs; }
|
||||
int iteration() const { return m_iteration; }
|
||||
void iterationInc() { ++m_iteration; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (!iteration()) {
|
||||
VerilatedVpioRange* nextp = new VerilatedVpioRange(*this);
|
||||
nextp->iterationInc();
|
||||
return ((nextp)->castVpiHandle());
|
||||
} else {
|
||||
return 0; // End of list - only one deep
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioScope : public VerilatedVpio {
|
||||
const VerilatedScope* m_scopep;
|
||||
public:
|
||||
VerilatedVpioScope(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep) {}
|
||||
virtual ~VerilatedVpioScope() {}
|
||||
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
virtual const char* name() { return m_scopep->name(); }
|
||||
virtual const char* fullname() { return m_scopep->name(); }
|
||||
};
|
||||
|
||||
class VerilatedVpioVar : public VerilatedVpio {
|
||||
const VerilatedVar* m_varp;
|
||||
const VerilatedScope* m_scopep;
|
||||
vluint8_t* m_prevDatap; // Previous value of data, for cbValueChange
|
||||
vluint32_t m_mask; // memoized variable mask
|
||||
vluint32_t m_entSize; // memoized variable size
|
||||
protected:
|
||||
void* m_varDatap; // varp()->datap() adjusted for array entries
|
||||
vlsint32_t m_index;
|
||||
public:
|
||||
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
|
||||
: m_varp(varp), m_scopep(scopep), m_index(0) {
|
||||
m_prevDatap = NULL;
|
||||
m_mask = VL_MASK_I(varp->range().bits());
|
||||
m_entSize = varp->entSize();
|
||||
m_varDatap = varp->datap();
|
||||
}
|
||||
virtual ~VerilatedVpioVar() {
|
||||
if (m_prevDatap) { delete [] m_prevDatap; m_prevDatap = NULL; }
|
||||
}
|
||||
static inline VerilatedVpioVar* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVar*>((VerilatedVpio*)h); }
|
||||
const VerilatedVar* varp() const { return m_varp; }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
vluint32_t mask() const { return m_mask; }
|
||||
vluint32_t entSize() const { return m_entSize; }
|
||||
virtual const char* name() { return m_varp->name(); }
|
||||
virtual const char* fullname() {
|
||||
static VL_THREAD string out;
|
||||
out = string(m_scopep->name())+"."+name();
|
||||
return out.c_str();
|
||||
}
|
||||
void* prevDatap() const { return m_prevDatap; }
|
||||
void* varDatap() const { return m_varDatap; }
|
||||
void createPrevDatap() {
|
||||
if (VL_UNLIKELY(!m_prevDatap)) {
|
||||
m_prevDatap = new vluint8_t [entSize()];
|
||||
memcpy(prevDatap(), varp()->datap(), entSize());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioVarIndex : public VerilatedVpioVar {
|
||||
public:
|
||||
VerilatedVpioVarIndex(const VerilatedVar* varp, const VerilatedScope* scopep,
|
||||
vlsint32_t index, int offset)
|
||||
: VerilatedVpioVar(varp, scopep) {
|
||||
m_index = index;
|
||||
m_varDatap = ((vluint8_t*)varp->datap()) + entSize()*offset;
|
||||
}
|
||||
virtual ~VerilatedVpioVarIndex() {}
|
||||
static inline VerilatedVpioVarIndex* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIndex*>((VerilatedVpio*)h); }
|
||||
virtual const char* fullname() {
|
||||
static VL_THREAD string out;
|
||||
char num[20]; sprintf(num,"%d",m_index);
|
||||
out = string(scopep()->name())+"."+name()+"["+num+"]";
|
||||
return out.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioVarIter : public VerilatedVpio {
|
||||
const VerilatedScope* m_scopep;
|
||||
VerilatedVarNameMap::iterator m_it;
|
||||
bool m_started;
|
||||
public:
|
||||
VerilatedVpioVarIter(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep), m_started(false) { }
|
||||
virtual ~VerilatedVpioVarIter() {}
|
||||
static inline VerilatedVpioVarIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioVarIter*>((VerilatedVpio*)h); }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (VL_LIKELY(m_scopep->varsp())) {
|
||||
if (VL_UNLIKELY(!m_started)) { m_it = m_scopep->varsp()->begin(); m_started=true; }
|
||||
else if (VL_UNLIKELY(m_it == m_scopep->varsp()->end())) return 0;
|
||||
else ++m_it;
|
||||
if (m_it == m_scopep->varsp()->end()) return 0;
|
||||
return ((new VerilatedVpioVar(&(m_it->second), m_scopep))
|
||||
->castVpiHandle());
|
||||
} else {
|
||||
return 0; // End of list - only one deep
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
||||
struct VerilatedVpiTimedCbsCmp {
|
||||
/// Ordering sets keyed by time, then callback descriptor
|
||||
bool operator() (const pair<QData,VerilatedVpioCb*>& a,
|
||||
const pair<QData,VerilatedVpioCb*>& b) const {
|
||||
if (a.first < b.first) return 1;
|
||||
if (a.first > b.first) return 0;
|
||||
return a.second < b.second;
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpi {
|
||||
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
|
||||
typedef set<VerilatedVpioCb*> VpioCbSet;
|
||||
typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
|
||||
|
||||
VpioCbSet m_cbObjSets[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
|
||||
VpioTimedCbs m_timedCbs; // Time based callbacks
|
||||
|
||||
static VerilatedVpi s_s; // Singleton
|
||||
|
||||
public:
|
||||
VerilatedVpi() {}
|
||||
~VerilatedVpi() {}
|
||||
static void cbReasonAdd(VerilatedVpioCb* vop) {
|
||||
if (vop->reason() == cbValueChange) {
|
||||
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
|
||||
varop->createPrevDatap();
|
||||
}
|
||||
}
|
||||
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) vl_fatal(__FILE__,__LINE__,"", "vpi bb reason too large");
|
||||
s_s.m_cbObjSets[vop->reason()].insert(vop);
|
||||
}
|
||||
static void cbTimedAdd(VerilatedVpioCb* vop) {
|
||||
s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
|
||||
}
|
||||
static void cbReasonRemove(VerilatedVpioCb* cbp) {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbp->reason()];
|
||||
VpioCbSet::iterator it=cbObjSet.find(cbp);
|
||||
if (VL_LIKELY(it != cbObjSet.end())) {
|
||||
cbObjSet.erase(it);
|
||||
}
|
||||
}
|
||||
static void cbTimedRemove(VerilatedVpioCb* cbp) {
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(make_pair(cbp->time(),cbp));
|
||||
if (VL_LIKELY(it != s_s.m_timedCbs.end())) {
|
||||
s_s.m_timedCbs.erase(it);
|
||||
}
|
||||
}
|
||||
static void callTimedCbs() {
|
||||
QData time = VL_TIME_Q();
|
||||
for (VpioTimedCbs::iterator it=s_s.m_timedCbs.begin(); it!=s_s.m_timedCbs.end(); ) {
|
||||
if (VL_UNLIKELY(it->first <= time)) {
|
||||
VerilatedVpioCb* vop = it->second;
|
||||
++it; // iterator may be deleted by callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: timed_callback %p\n",vop););
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
else { ++it; }
|
||||
}
|
||||
}
|
||||
static QData cbNextDeadline() {
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.begin();
|
||||
if (VL_LIKELY(it!=s_s.m_timedCbs.end())) {
|
||||
return it->first;
|
||||
} else {
|
||||
return ~VL_ULL(0); // maxquad
|
||||
}
|
||||
}
|
||||
static void callCbs(vluint32_t reason) {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[reason];
|
||||
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
|
||||
VerilatedVpioCb* vop = *it;
|
||||
++it; // iterator may be deleted by callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: reason_callback %d %p\n",reason,vop););
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
static void callValueCbs() {
|
||||
VpioCbSet& cbObjSet = s_s.m_cbObjSets[cbValueChange];
|
||||
for (VpioCbSet::iterator it=cbObjSet.begin(); it!=cbObjSet.end();) {
|
||||
VerilatedVpioCb* vop = *it;
|
||||
++it; // iterator may be deleted by callback
|
||||
if (VerilatedVpioVar* varop = VerilatedVpioVar::castp(vop->cb_datap()->obj)) {
|
||||
void* newDatap = varop->varDatap();
|
||||
void* prevDatap = varop->prevDatap(); // Was malloced when we added the callback
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_test %s v[0]=%d/%d %p %p\n",
|
||||
varop->fullname(), *((CData*)newDatap), *((CData*)prevDatap),
|
||||
newDatap, prevDatap););
|
||||
if (memcmp(prevDatap, newDatap, varop->entSize())) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
|
||||
vop,varop->fullname(), *((CData*)newDatap)););
|
||||
memcpy(prevDatap, newDatap, varop->entSize());
|
||||
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// callback related
|
||||
|
||||
vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
|
||||
if (VL_UNLIKELY(!cb_data_p)) return NULL;
|
||||
switch (cb_data_p->reason) {
|
||||
case cbAfterDelay: {
|
||||
QData time = 0;
|
||||
if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
|
||||
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time);
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p delay=%" VL_PRI64 "d\n",cb_data_p->reason,vop,time););
|
||||
VerilatedVpi::cbTimedAdd(vop);
|
||||
return vop->castVpiHandle();
|
||||
}
|
||||
case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbReadOnlySynch: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbNextSimTime: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbStartOfSimulation: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbEndOfSimulation: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbValueChange: // FALLTHRU // Supported via vlt_main.cpp
|
||||
case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object
|
||||
case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object
|
||||
case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object
|
||||
VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0);
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p\n",cb_data_p->reason,vop););
|
||||
VerilatedVpi::cbReasonAdd(vop);
|
||||
return vop->castVpiHandle();
|
||||
}
|
||||
default:
|
||||
_VL_VPI_UNIMP(); return NULL;
|
||||
};
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_remove_cb(vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_remove_cb %p\n",object););
|
||||
VerilatedVpioCb* vop = VerilatedVpioCb::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
if (vop->cb_datap()->reason == cbAfterDelay) {
|
||||
VerilatedVpi::cbTimedRemove(vop);
|
||||
} else {
|
||||
VerilatedVpi::cbReasonRemove(vop);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-void vpi_get_cb_info(vpiHandle object, p_cb_data cb_data_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-vpiHandle vpi_register_systf(p_vpi_systf_data systf_data_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-void vpi_get_systf_info(vpiHandle object, p_vpi_systf_data systf_data_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
// for obtaining handles
|
||||
|
||||
vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
|
||||
if (VL_UNLIKELY(!namep)) return NULL;
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_name %s %p\n",namep,scope););
|
||||
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope);
|
||||
const VerilatedVar* varp;
|
||||
const VerilatedScope* scopep;
|
||||
string scopeAndName = namep;
|
||||
if (voScopep) {
|
||||
scopeAndName = string(voScopep->fullname()) + "." + namep;
|
||||
namep = (PLI_BYTE8*)scopeAndName.c_str();
|
||||
}
|
||||
{
|
||||
// This doesn't yet follow the hierarchy in the proper way
|
||||
scopep = Verilated::scopeFind(namep);
|
||||
if (scopep) { // Whole thing found as a scope
|
||||
return (new VerilatedVpioScope(scopep))->castVpiHandle();
|
||||
}
|
||||
const char* baseNamep = scopeAndName.c_str();
|
||||
string scopename;
|
||||
const char* dotp = strrchr(namep, '.');
|
||||
if (VL_LIKELY(dotp)) {
|
||||
baseNamep = dotp+1;
|
||||
scopename = string(namep,dotp-namep);
|
||||
}
|
||||
scopep = Verilated::scopeFind(scopename.c_str());
|
||||
if (!scopep) return NULL;
|
||||
varp = scopep->varFind(baseNamep);
|
||||
}
|
||||
if (!varp) return NULL;
|
||||
return (new VerilatedVpioVar(varp, scopep))->castVpiHandle();
|
||||
}
|
||||
|
||||
vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
|
||||
// Used to get array entries
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_index %p %d\n",object, indx););
|
||||
VerilatedVpioVar* varop = VerilatedVpioVar::castp(object);
|
||||
if (VL_LIKELY(varop)) {
|
||||
if (varop->varp()->dims()<2) return 0;
|
||||
if (VL_LIKELY(varop->varp()->array().lhs() >= varop->varp()->array().rhs())) {
|
||||
if (VL_UNLIKELY(indx > varop->varp()->array().lhs() || indx < varop->varp()->array().rhs())) return 0;
|
||||
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
|
||||
indx - varop->varp()->array().rhs()))
|
||||
->castVpiHandle();
|
||||
} else {
|
||||
if (VL_UNLIKELY(indx < varop->varp()->array().lhs() || indx > varop->varp()->array().rhs())) return 0;
|
||||
return (new VerilatedVpioVarIndex(varop->varp(), varop->scopep(), indx,
|
||||
indx - varop->varp()->array().lhs()))
|
||||
->castVpiHandle();
|
||||
}
|
||||
} else {
|
||||
_VL_VPI_UNIMP(); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// for traversing relationships
|
||||
|
||||
vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle %d %p\n",type,object););
|
||||
switch (type) {
|
||||
case vpiLeftRange: // FALLTHRU
|
||||
case vpiRightRange: {
|
||||
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
|
||||
vluint32_t num = ((type==vpiLeftRange)
|
||||
? vop->varp()->range().lhs()
|
||||
: vop->varp()->range().rhs());
|
||||
return (new VerilatedVpioConst(num))->castVpiHandle();
|
||||
} else if (VerilatedVpioRange* vop = VerilatedVpioRange::castp(object)) {
|
||||
vluint32_t num = ((type==vpiLeftRange)
|
||||
? vop->lhs()
|
||||
: vop->rhs());
|
||||
return (new VerilatedVpioConst(num))->castVpiHandle();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1, vpiHandle refHandle2, ... ) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_iterate %d %p\n",type,object););
|
||||
switch (type) {
|
||||
case vpiMemoryWord: {
|
||||
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
if (vop->varp()->dims() < 2) return 0;
|
||||
// Unsupported is multidim list
|
||||
return ((new VerilatedVpioRange(vop->varp()->array().lhs(),
|
||||
vop->varp()->array().rhs()))
|
||||
->castVpiHandle());
|
||||
}
|
||||
case vpiReg: {
|
||||
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
return ((new VerilatedVpioVarIter(vop->scopep()))
|
||||
->castVpiHandle());
|
||||
}
|
||||
case vpiIODecl: // Skipping - we'll put under reg
|
||||
case vpiNet: // Skipping - we'll put under reg
|
||||
return 0;
|
||||
default:
|
||||
_VL_VPI_UNIMP(); return 0;
|
||||
}
|
||||
}
|
||||
vpiHandle vpi_scan(vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_scan %p\n",object););
|
||||
VerilatedVpio* vop = VerilatedVpio::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return NULL;
|
||||
return vop->dovpi_scan();
|
||||
}
|
||||
|
||||
// for processing properties
|
||||
|
||||
PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
|
||||
// Leave this in the header file - in many cases the compiler can constant propagate "object"
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get %d %p\n",property,object););
|
||||
switch (property) {
|
||||
case vpiTimePrecision: {
|
||||
return VL_TIME_PRECISION;
|
||||
}
|
||||
case vpiType: {
|
||||
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
return ((vop->varp()->dims()>1) ? vpiMemory : vpiReg);
|
||||
}
|
||||
case vpiDirection: {
|
||||
// By forthought, the directions already are vpi enumerated
|
||||
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
return vop->varp()->vldir();
|
||||
}
|
||||
case vpiVector: {
|
||||
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
if (vop->varp()->dims()==0) return 0;
|
||||
else return 1;
|
||||
}
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-PLI_INT64 vpi_get64(PLI_INT32 property, vpiHandle object) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_BYTE8 *vpi_get_str(PLI_INT32 property, vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_str %d %p\n",property,object););
|
||||
VerilatedVpio* vop = VerilatedVpio::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return NULL;
|
||||
switch (property) {
|
||||
case vpiName: {
|
||||
return (PLI_BYTE8*)vop->name();
|
||||
}
|
||||
case vpiFullName: {
|
||||
return (PLI_BYTE8*)vop->fullname();
|
||||
}
|
||||
case vpiDefName: {
|
||||
return (PLI_BYTE8*)vop->defname();
|
||||
}
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// delay processing
|
||||
|
||||
//-void vpi_get_delays(vpiHandle object, p_vpi_delay delay_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
// value processing
|
||||
|
||||
void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object););
|
||||
if (VL_UNLIKELY(!value_p)) return;
|
||||
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
|
||||
// We presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
|
||||
if (value_p->format == vpiVectorVal) {
|
||||
// Vector pointer must come from our memory pool
|
||||
// It only needs to persist until the next vpi_get_value
|
||||
static VL_THREAD t_vpi_vecval out[VL_MULS_MAX_WORDS*2];
|
||||
value_p->value.vector = out;
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
out[0].aval = *((CData*)(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT16:
|
||||
out[0].aval = *((SData*)(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT32:
|
||||
out[0].aval = *((IData*)(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_WDATA: {
|
||||
int words = VL_WORDS_I(vop->varp()->range().bits());
|
||||
if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) {
|
||||
vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
|
||||
}
|
||||
WDataInP datap = ((IData*)(vop->varDatap()));
|
||||
for (int i=0; i<words; i++) {
|
||||
out[i].aval = datap[i];
|
||||
out[i].bval = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case VLVT_UINT64: {
|
||||
QData data = *((QData*)(vop->varDatap()));
|
||||
out[1].aval = (IData)(data>>VL_ULL(32));
|
||||
out[1].bval = 0;
|
||||
out[0].aval = (IData)(data);
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
_VL_VPI_UNIMP();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
value_p->value.integer = *((CData*)(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_UINT16:
|
||||
value_p->value.integer = *((SData*)(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_UINT32:
|
||||
value_p->value.integer = *((IData*)(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_WDATA:
|
||||
case VLVT_UINT64:
|
||||
// Not legal
|
||||
value_p->value.integer = 0;
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) {
|
||||
value_p->value.integer = vop->num();
|
||||
return;
|
||||
}
|
||||
_VL_VPI_UNIMP();
|
||||
}
|
||||
|
||||
vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
p_vpi_time time_p, PLI_INT32 flags) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value %p %p\n",object, value_p););
|
||||
if (VL_UNLIKELY(!value_p)) return 0;
|
||||
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
|
||||
// We presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value name=%s fmt=%d vali=%d\n",
|
||||
vop->fullname(), value_p->format, value_p->value.integer);
|
||||
VL_PRINTF("-vltVpi: varp=%p putatp=%p\n",
|
||||
vop->varp()->datap(), vop->varDatap()););
|
||||
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
|
||||
VL_PRINTF("%%Warning: Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: %s\n",
|
||||
vop->fullname());
|
||||
return 0;
|
||||
}
|
||||
if (value_p->format == vpiVectorVal) {
|
||||
if (VL_UNLIKELY(!value_p->value.vector)) return NULL;
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
*((CData*)(vop->varDatap())) = value_p->value.vector[0].aval;
|
||||
return object;
|
||||
case VLVT_UINT16:
|
||||
*((SData*)(vop->varDatap())) = value_p->value.vector[0].aval;
|
||||
return object;
|
||||
case VLVT_UINT32:
|
||||
*((IData*)(vop->varDatap())) = value_p->value.vector[0].aval;
|
||||
return object;
|
||||
case VLVT_WDATA: {
|
||||
int words = VL_WORDS_I(vop->varp()->range().bits());
|
||||
WDataOutP datap = ((IData*)(vop->varDatap()));
|
||||
for (int i=0; i<words; i++) {
|
||||
datap[i] = value_p->value.vector[i].aval;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
case VLVT_UINT64: {
|
||||
*((QData*)(vop->varDatap())) = _VL_SET_QII(
|
||||
value_p->value.vector[1].aval,
|
||||
value_p->value.vector[0].aval);
|
||||
return object;
|
||||
}
|
||||
default: {
|
||||
_VL_VPI_UNIMP();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
*((CData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_UINT16:
|
||||
*((SData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_UINT32:
|
||||
*((IData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_WDATA: // FALLTHRU
|
||||
case VLVT_UINT64: // FALLTHRU
|
||||
default:
|
||||
_VL_VPI_UNIMP();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
_VL_VPI_UNIMP(); return NULL;
|
||||
}
|
||||
|
||||
//-void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
//- PLI_INT32 *index_p, PLI_UINT32 num) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p,
|
||||
//- PLI_INT32 *index_p, PLI_UINT32 num) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
|
||||
// time processing
|
||||
|
||||
//-void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
|
||||
//- _VL_VPI_UNIMP();
|
||||
//-}
|
||||
|
||||
// I/O routines
|
||||
|
||||
PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
|
||||
return VL_FOPEN_S(filenamep,"wb");
|
||||
}
|
||||
|
||||
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
|
||||
VL_FCLOSE_I(mcd); return 0;
|
||||
}
|
||||
|
||||
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
|
||||
va_end(ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
int chars = vpi_vprintf(formatp, ap);
|
||||
va_end(ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
|
||||
return VL_VPRINTF(formatp, ap);
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
|
||||
FILE* fp = VL_CVT_I_FP(mcd);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
int chars = vfprintf(fp, format, ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_flush(void) {
|
||||
Verilated::flushCall();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
|
||||
FILE* fp = VL_CVT_I_FP(mcd);
|
||||
if (VL_UNLIKELY(!fp)) return 1;
|
||||
fflush(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// utility routines
|
||||
|
||||
//-PLI_INT32 vpi_compare_objects(vpiHandle object1, vpiHandle object2) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_INT32 vpi_free_object(vpiHandle object) {
|
||||
return vpi_release_handle(object); // Deprecated
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_release_handle (vpiHandle object) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_release_handle %p\n",object););
|
||||
VerilatedVpio* vop = VerilatedVpio::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return 0;
|
||||
vpi_remove_cb(object); // May not be a callback, but that's ok
|
||||
delete vop;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
// routines added with 1364-2001
|
||||
|
||||
//-PLI_INT32 vpi_get_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_put_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-void *vpi_get_userdata(vpiHandle obj) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_put_userdata(vpiHandle obj, void *userdata) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_control %d\n",operation););
|
||||
switch (operation) {
|
||||
case vpiFinish: {
|
||||
vl_finish(__FILE__,__LINE__,"*VPI*");
|
||||
return 1;
|
||||
}
|
||||
case vpiStop: {
|
||||
vl_stop(__FILE__,__LINE__,"*VPI*");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
_VL_VPI_UNIMP(); return 0;
|
||||
}
|
||||
|
||||
//-vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index, PLI_INT32 *index_array) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif // Guard
|
||||
+37
-3
@@ -1,7 +1,7 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
@@ -126,8 +126,13 @@ typedef unsigned long uint32_t; ///< 32-bit unsigned type (backward compatibili
|
||||
typedef long vlsint32_t; ///< 32-bit signed type
|
||||
typedef unsigned long vluint32_t; ///< 32-bit unsigned type
|
||||
# endif
|
||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
# else
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# endif
|
||||
|
||||
#elif defined(_WIN32) && defined(_MSC_VER)
|
||||
|
||||
@@ -141,6 +146,14 @@ typedef unsigned __int32 vluint32_t; ///< 32-bit unsigned type
|
||||
typedef signed __int64 vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned __int64 vluint64_t; ///< 64-bit unsigned type
|
||||
|
||||
# ifndef _SSIZE_T_DEFINED
|
||||
# ifdef _WIN64
|
||||
typedef signed __int64 ssize_t; ///< signed size_t; returned from read()
|
||||
# else
|
||||
typedef signed __int32 ssize_t; ///< signed size_t; returned from read()
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#else // Linux or compliant Unix flavors, -m64
|
||||
|
||||
# include <stdint.h> // Linux and most flavors
|
||||
@@ -149,8 +162,13 @@ 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
|
||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||
typedef long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long vluint64_t; ///< 64-bit unsigned type
|
||||
# else
|
||||
typedef long long vlsint64_t; ///< 64-bit signed type
|
||||
typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
@@ -160,7 +178,11 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
#ifdef _WIN32
|
||||
# define VL_PRI64 "I64"
|
||||
#else // Linux or compliant Unix flavors
|
||||
# define VL_PRI64 "ll"
|
||||
# if defined(__WORDSIZE) && (__WORDSIZE == 64)
|
||||
# define VL_PRI64 "l"
|
||||
# else
|
||||
# define VL_PRI64 "ll"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
@@ -199,6 +221,18 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long
|
||||
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad
|
||||
|
||||
//=========================================================================
|
||||
// Floating point
|
||||
// #defines, to avoid requiring math.h on all compile runs
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define VL_TRUNC(n) (((n)<0) ? ceil((n)) : floor((n)))
|
||||
# define VL_ROUND(n) (((n)<0) ? ceil((n)-0.5) : floor((n)+0.5))
|
||||
#else
|
||||
# define VL_TRUNC(n) trunc(n)
|
||||
# define VL_ROUND(n) round(n)
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
|
||||
#endif /*guard*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+7
-6
@@ -207,10 +207,10 @@ viewers let us know; ZGRViewer isn't great for large graphs.
|
||||
Tree files are dumps of the AST Tree and are produced between every major
|
||||
algorithmic stage. An example:
|
||||
|
||||
NETLIST 0x90fb00 <e1> {0} w0
|
||||
1: MODULE 0x912b20 <e8822> {8} w0 top L2 [P]
|
||||
*1:2: VAR 0x91a780 <e74#> {22} w70 out_wide [O] WIRE
|
||||
1:2:1: BASICDTYPE 0x91a3c0 <e73> {22} w70 [logic]
|
||||
NETLIST 0x90fb00 <e1> {a0} w0
|
||||
1: MODULE 0x912b20 <e8822> {a8} w0 top L2 [P]
|
||||
*1:2: VAR 0x91a780 <e74#> {a22} w70 out_wide [O] WIRE
|
||||
1:2:1: BASICDTYPE 0x91a3c0 <e73> {a22} w70 [logic]
|
||||
|
||||
=over 4
|
||||
|
||||
@@ -224,7 +224,8 @@ algorithmic stage. An example:
|
||||
this node. A trailing # indicates this node changed since the last tree
|
||||
dump was made. You can gdb break on this edit; see below.
|
||||
|
||||
"{22}" indicates this node is related to line 22 in the source.
|
||||
"{a22}" indicates this node is related to line 22 in the source filename
|
||||
"a", where "a" is the first file read, "z" the 36th, and "aa" the 37th.
|
||||
|
||||
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits.
|
||||
|
||||
@@ -250,7 +251,7 @@ what made a <e####> line in the tree dumps):
|
||||
|
||||
The latest version is available from L<http://www.veripool.org/>.
|
||||
|
||||
Copyright 2008-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2008-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2011 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 Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2011 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 Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ cwrite ("graph_export.cpp");
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ dotwrite();
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2007-2011 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 Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
+56
-12
@@ -12,12 +12,15 @@ use vars qw ($Debug);
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
our $Opt_Stage = 0;
|
||||
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config ("no_auto_abbrev");
|
||||
if (! GetOptions (
|
||||
"debug" => sub { $Debug = 1; },
|
||||
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
||||
"stage=i" => \$Opt_Stage,
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'install_test --help'\n";
|
||||
}
|
||||
@@ -37,8 +40,10 @@ sub test {
|
||||
my $srcdir = getcwd();
|
||||
my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld";
|
||||
my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix";
|
||||
my $testdir = $srcdir."/test_regress/obj_dir/install_test_test";
|
||||
if (1) {
|
||||
my $testdirp= $srcdir."/test_regress/obj_dir/install_test_testp";
|
||||
my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn";
|
||||
|
||||
if ($Opt_Stage <= 0) {
|
||||
run("/bin/rm -rf $blddir");
|
||||
run("/bin/mkdir -p $blddir");
|
||||
run("cd $blddir && $srcdir/configure --prefix $prefix");
|
||||
@@ -46,24 +51,63 @@ sub test {
|
||||
}
|
||||
|
||||
# Install it under the prefix
|
||||
if (1) {
|
||||
if ($Opt_Stage <= 1) {
|
||||
run("/bin/rm -rf $prefix");
|
||||
run("/bin/mkdir -p $prefix");
|
||||
run("cd $blddir && make install");
|
||||
run("test -e $prefix/share/man/man1/verilator.1");
|
||||
run("test -e $prefix/share/verilator/examples/test_c/Makefile");
|
||||
run("test -e $prefix/share/verilator/include/verilated.h");
|
||||
run("test -e $prefix/bin/verilator");
|
||||
run("test -e $prefix/bin/verilator_bin");
|
||||
run("test -e $prefix/bin/verilator_bin_dbg");
|
||||
run("test -e $prefix/bin/verilator_profcfunc");
|
||||
}
|
||||
|
||||
# Run a test using just the path
|
||||
if (1) {
|
||||
run("/bin/rm -rf $testdir");
|
||||
run("/bin/mkdir -p $testdir");
|
||||
if ($Opt_Stage <= 2) {
|
||||
my $dir = $testdirp;
|
||||
run("/bin/rm -rf $dir");
|
||||
run("/bin/mkdir -p $dir");
|
||||
my $bin1 = $prefix."/bin";
|
||||
my $bin2 = $prefix."/share/bin";
|
||||
IO::File->new(">$testdir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); end endmodule'."\n");
|
||||
run("cd $testdir && PATH=$bin1:$bin2:\$PATH verilator --cc --exe foo.v");
|
||||
run("cd $testdir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
|
||||
#Need .c file for this to work
|
||||
#run("cd $testdir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
|
||||
write_verilog($dir);
|
||||
run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp");
|
||||
run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
|
||||
run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
|
||||
}
|
||||
|
||||
# Run a test using exact path to binary
|
||||
if ($Opt_Stage <= 3) {
|
||||
my $dir = $testdirn;
|
||||
run("/bin/rm -rf $dir");
|
||||
run("/bin/mkdir -p $dir");
|
||||
write_verilog($dir);
|
||||
my $bin1 = $prefix."/bin";
|
||||
my $bin2 = $prefix."/share/bin";
|
||||
run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp");
|
||||
run("cd $dir/obj_dir && make -f Vfoo.mk");
|
||||
run("cd $dir/obj_dir && ./Vfoo");
|
||||
}
|
||||
}
|
||||
|
||||
sub write_verilog {
|
||||
my $dir = shift;
|
||||
IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n");
|
||||
my $fh = IO::File->new(">$dir/foo.cpp");
|
||||
$fh->print('#include "Vfoo.h"' ,"\n");
|
||||
$fh->print('unsigned int main_time = 0;' ,"\n");
|
||||
$fh->print('double sc_time_stamp () {' ,"\n");
|
||||
$fh->print(' return main_time;' ,"\n");
|
||||
$fh->print('}' ,"\n");
|
||||
$fh->print('int main() {' ,"\n");
|
||||
$fh->print(' Vfoo *top = new Vfoo;' ,"\n");
|
||||
$fh->print(' while (!Verilated::gotFinish()) {',"\n");
|
||||
$fh->print(' top->eval();' ,"\n");
|
||||
$fh->print(' main_time++;' ,"\n");
|
||||
$fh->print(' }' ,"\n");
|
||||
$fh->print(' top->final();' ,"\n");
|
||||
$fh->print('}' ,"\n");
|
||||
}
|
||||
|
||||
sub cleanenv {
|
||||
@@ -117,7 +161,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2009-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2009-2011 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 Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/perl -w
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
require 5.006_001;
|
||||
use strict;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
eval `modulecmd perl add axiom-athdl`;
|
||||
exec('atsim',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
invoke_atsim - Invoke tool under "modules" command
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
invoke_atsim {ncv arguments}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2011 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 Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <[email protected]>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./invoke_atsim -help"
|
||||
### End:
|
||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence-ius');
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('iccr',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
@@ -40,7 +28,7 @@ invoke_iccr - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2007-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2007-2011 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 Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence-ius');
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('ncverilog',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
@@ -40,7 +28,7 @@ invoke_ncverilog - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2011 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 Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+2
-14
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','synopsys-vcs');
|
||||
eval `modulecmd perl add synopsys-vcs`;
|
||||
exec('vcs',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
@@ -40,7 +28,7 @@ invoke_vcs - Invoke tool under "modules" command
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. This package is free software; you
|
||||
Copyright 2005-2011 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 Version 3 or the Perl Artistic License
|
||||
Version 2.0.
|
||||
|
||||
+3
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/perl -w
|
||||
######################################################################
|
||||
#
|
||||
# Copyright 2010-2010 by Wilson Snyder. This package is free software; you
|
||||
# Copyright 2010-2011 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 Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -81,6 +81,7 @@ sub prep {
|
||||
$line =~ s/SP_NOTICE.*// if $sp;
|
||||
$line =~ s/vl_fatal.*// if !$sp;
|
||||
$line =~ s/VL_PRINT.*// if !$sp;
|
||||
$line =~ s/Copyright \d+-\d+/Copyright #-#/g;
|
||||
|
||||
push @wf, $line;
|
||||
|
||||
@@ -126,6 +127,7 @@ sub prep {
|
||||
#
|
||||
$wholefile =~ s/\b(uint[0-9]+_t)/vl$1/g;
|
||||
$wholefile =~ s/%ll/%" VL_PRI64 "/g;
|
||||
$wholefile =~ s/\(long long unsigned\)n/ n/g; # printQuad
|
||||
#
|
||||
$wholefile =~ s/\bSP_SC_BV/VL_SC_BV/g;
|
||||
$wholefile =~ s/\bSP_UNLIKELY/VL_UNLIKELY/g;
|
||||
|
||||
@@ -40,7 +40,7 @@ print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ sub gentree {
|
||||
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
|
||||
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
|
||||
'UNARYMIN' => sub { p " -";p1; },
|
||||
'NEGATE' => sub { p " -";p1; },
|
||||
'VAR' => sub { p_var(); },
|
||||
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'VARREF' => sub { a1; },
|
||||
@@ -331,7 +331,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2005-2010 by Wilson Snyder. Verilator is free software; you can
|
||||
Copyright 2005-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
|
||||
+51
-21
@@ -9,7 +9,7 @@ This is the Verilator Package README file.
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
This package is Copyright 2003-2010 by Wilson Snyder. (Report bugs to
|
||||
This package is Copyright 2003-2011 by Wilson Snyder. (Report bugs to
|
||||
L<http://www.veripool.org/>.)
|
||||
|
||||
Verilator is free software; you can redistribute it and/or modify it under
|
||||
@@ -72,15 +72,14 @@ Download the latest package from that site, and decompress.
|
||||
|
||||
If you will be using SystemC (vs straight C++ output), download SystemC
|
||||
2.0.1 from L<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'.
|
||||
instructions. You will need to set the SYSTEMC environment variable to
|
||||
point to this download. Also, setenv SYSTEMC_ARCH to the architecture name
|
||||
you used with SystemC, generally 'linux' or 'cygwin'.
|
||||
|
||||
=item
|
||||
|
||||
If you will be using SystemPerl or coverage, download and install
|
||||
Verilog-Perl, L<http://www.veripool.org/verilog-perl>.
|
||||
Verilator assumes you did a make in the SystemC kit directory and SYSTEMC
|
||||
points to that directory. There must be appropriate files in
|
||||
C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux> for SystemC compilation to
|
||||
work.
|
||||
|
||||
=item
|
||||
|
||||
@@ -92,26 +91,59 @@ headers.
|
||||
|
||||
=item
|
||||
|
||||
You will need the C<flex> and C<bison> packages installed.
|
||||
|
||||
=item
|
||||
|
||||
C<cd> to the Verilator directory containing this README.
|
||||
|
||||
=item
|
||||
|
||||
You now have to decide how you're going to eventually install the kit.
|
||||
|
||||
Note Verilator builds the current value of VERILATOR_ROOT, SYSTEMC,
|
||||
SYSTEMC_ARCH, SYSTEMPERL, and SYSTEMPERL_INCLUDE as defaults into the
|
||||
executable, so try to have them correct before configuring.
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
Our personal favorite is to always run Verilator from the kit directory.
|
||||
This allows the easiest experimentation and upgrading. It's also how most
|
||||
EDA tools operate; you just point to the tarball.
|
||||
EDA tools operate; to run any of them you point to the tarball.
|
||||
|
||||
export VERILATOR_ROOT=`pwd` # if your shell is bash
|
||||
setenv VERILATOR_ROOT `pwd` # if your shell is csh
|
||||
./configure
|
||||
|
||||
=item 2.
|
||||
|
||||
To install globally onto a "cad" disk with multiple versions of every tool,
|
||||
and add it to path using Modules/modulecmd:
|
||||
|
||||
unset VERILATOR_ROOT # if your shell is bash
|
||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||
# For the tarball, use the version number instead of git describe
|
||||
./configure --prefix /CAD_DISK/verilator/`git describe | sed "s/verilator_//"`
|
||||
|
||||
After installing you'll want a module file like the following:
|
||||
|
||||
set install_root /CAD_DISK/verilator/{version-number-used-above}
|
||||
setenv VERILATOR_ROOT $install_root
|
||||
prepend-path PATH $install_root/bin
|
||||
prepend-path MANPATH $install_root/man
|
||||
|
||||
=item 3.
|
||||
|
||||
The next option is to install it globally, using the normal system paths:
|
||||
|
||||
unset VERILATOR_ROOT # if your shell is bash
|
||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||
./configure
|
||||
|
||||
=item 4.
|
||||
|
||||
Alternatively you can configure a prefix that install will populate, as
|
||||
most GNU tools support:
|
||||
|
||||
@@ -119,11 +151,10 @@ most GNU tools support:
|
||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||
./configure --prefix /opt/verilator-VERSION
|
||||
|
||||
Finally, if you are configuring Verilator to be part of a RPM or other
|
||||
distribution package system, you may want to tune the various install
|
||||
directories and use the --enable-defenv configure flag. This will take the
|
||||
current value of VERILATOR_ROOT, SYSTEMC, SYSTEMC_ARCH, SYSTEMPERL, and
|
||||
SYSTEMPERL_INCLUDE and build them as defaults into the executable.
|
||||
Then after installing you will need to add /opt/verilator-VERSION/bin to
|
||||
PATH.
|
||||
|
||||
=back
|
||||
|
||||
=item
|
||||
|
||||
@@ -141,16 +172,15 @@ unsigned long uint32_t;}.
|
||||
|
||||
=item
|
||||
|
||||
If you used the VERILATOR_ROOT sheme you're done. Programs should set the
|
||||
If you used the VERILATOR_ROOT scheme you're done. 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.
|
||||
|
||||
If you used the prefix scheme, now do a C<make install>.
|
||||
|
||||
Verilator assumes you did a make in the SystemC kit directory. If not, you
|
||||
will need to populate C<$SYSTEMC/include> and C<$SYSTEMC/lib-linux>
|
||||
appropriately.
|
||||
If you used the prefix scheme, now do a C<make install>. To run verilator,
|
||||
have the verilator binary directory in your PATH (this should already be
|
||||
true if using the default configure), and make sure VERILATOR_ROOT is not
|
||||
set.
|
||||
|
||||
=back
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ This is the Verilator Package.
|
||||
@node Copyright, Description, Top, Top
|
||||
@section Copyright
|
||||
|
||||
This package is Copyright 2003-2010 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
||||
This package is Copyright 2003-2011 by Wilson Snyder @email{wsnyder@@wsnyder.org}.
|
||||
|
||||
Verilator is free software; you can redistribute it and/or modify it
|
||||
under the terms of either the GNU Lesser General Public License
|
||||
|
||||
+16
-23
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -24,6 +24,7 @@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
PERL = @PERL@
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
@@ -32,21 +33,11 @@ default: dbg opt
|
||||
debug: dbg
|
||||
optimize: opt
|
||||
|
||||
ifeq ($(OBJCACHE_HOSTS),)
|
||||
ifneq ($(SLCHOOSED_HOST),)
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1)
|
||||
export OBJCACHE_HOSTS := $(shell rschedule --no-allow-reserved --similar hostnames)
|
||||
endif
|
||||
endif
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
endif
|
||||
|
||||
ifeq ($(OBJCACHE_JOBS),)
|
||||
ifneq ($(OBJCACHE_HOSTS),)
|
||||
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
||||
endif
|
||||
endif
|
||||
|
||||
UNDER_GIT = $(wildcard ../.git/logs/HEAD)
|
||||
UNDER_GIT = $(wildcard ${srcdir}/../.git/logs/HEAD)
|
||||
|
||||
#*********************************************************************
|
||||
|
||||
@@ -61,26 +52,25 @@ opt: ../verilator_bin
|
||||
ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build
|
||||
../verilator_bin: ../verilator_bin_dbg
|
||||
-rm -rf $@ $@.exe
|
||||
-cp -p $< $@
|
||||
-cp -p $<.exe $@.exe
|
||||
-cp -p $<$(EXEEXT) $@$(EXEEXT)
|
||||
else
|
||||
../verilator_bin: obj_opt prefiles
|
||||
cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial
|
||||
cd obj_opt && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ -f ../Makefile_obj
|
||||
cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial
|
||||
cd obj_opt && $(MAKE) TGT=../$@ -f ../Makefile_obj
|
||||
endif
|
||||
|
||||
dbg: ../verilator_bin_dbg
|
||||
../verilator_bin_dbg: obj_dbg prefiles
|
||||
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial
|
||||
cd obj_dbg && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
|
||||
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial
|
||||
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
|
||||
|
||||
prefiles::
|
||||
|
||||
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||
prefiles:: config_rev.h
|
||||
# This output goes into srcdir, as we need to distribute it as part of the kit.
|
||||
config_rev.h: config_rev.pl ../.git/logs/HEAD
|
||||
$(PERL) config_rev.pl . >$@
|
||||
# This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
|
||||
config_rev.h: ${srcdir}/config_rev.pl ${srcdir}/../.git/logs/HEAD
|
||||
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
|
||||
endif
|
||||
|
||||
maintainer-copy::
|
||||
@@ -92,3 +82,6 @@ clean mostlyclean distclean maintainer-clean::
|
||||
|
||||
distclean maintainer-clean::
|
||||
-rm -f Makefile Makefile_obj config_build.h
|
||||
|
||||
maintainer-clean::
|
||||
-rm -f config_rev.h
|
||||
|
||||
+16
-15
@@ -7,7 +7,7 @@
|
||||
#
|
||||
#*****************************************************************************
|
||||
#
|
||||
# Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
# Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
@@ -57,9 +57,11 @@ datarootdir = @datarootdir@
|
||||
pkgdatadir = @pkgdatadir@
|
||||
|
||||
# Compile options
|
||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||
CPPFLAGSNOWALL += @CPPFLAGS@
|
||||
CPPFLAGS += @CPPFLAGS@
|
||||
LDFLAGS += @LDFLAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
@@ -85,17 +87,18 @@ endif
|
||||
# -lfl not needed as Flex invoked with %nowrap option
|
||||
LIBS = -lm
|
||||
|
||||
CPPFLAGSNOWALL += -MMD
|
||||
CPPFLAGSNOWALL += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
|
||||
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages
|
||||
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
||||
CPPFLAGSNOWALL += $(COPT)
|
||||
CPPFLAGS = $(CPPFLAGSNOWALL)
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
CPPFLAGSNOWALL += -MP # Only works on recent GCC versions
|
||||
CPPFLAGS += -MMD
|
||||
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
|
||||
CPPFLAGS += -DYYDEBUG # Required to get nice error messages
|
||||
#CPPFLAGS += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
||||
CPPFLAGS += $(COPT)
|
||||
CPPFLAGS += -MP # Only works on recent GCC versions
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
|
||||
#CPPFLAGS += -pedantic-errors
|
||||
endif
|
||||
CPPFLAGSWALL = $(CPPFLAGS)
|
||||
CPPFLAGSNOWALL = $(CPPFLAGS) -Wno-unused
|
||||
|
||||
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
|
||||
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
|
||||
@@ -209,7 +212,6 @@ RAW_OBJS = \
|
||||
V3PreShell.o \
|
||||
V3Premit.o \
|
||||
V3Scope.o \
|
||||
V3Signed.o \
|
||||
V3Slice.o \
|
||||
V3Split.o \
|
||||
V3SplitAs.o \
|
||||
@@ -221,6 +223,7 @@ RAW_OBJS = \
|
||||
V3Trace.o \
|
||||
V3TraceDecl.o \
|
||||
V3Tristate.o \
|
||||
V3Undriven.o \
|
||||
V3Unknown.o \
|
||||
V3Unroll.o \
|
||||
V3Width.o \
|
||||
@@ -250,8 +253,6 @@ $(TGT): V3Ast__gen_classes.h $(OBJS)
|
||||
@echo " Linking $@..."
|
||||
-rm -rf $@ [email protected]
|
||||
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
|
||||
@-(cp [email protected] $@ || true)
|
||||
# ok if cp failes on linux, it's there to insure executable works on NT
|
||||
|
||||
V3Number_test: V3Number_test.o
|
||||
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
|
||||
@@ -262,9 +263,9 @@ V3Number_test: V3Number_test.o
|
||||
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
|
||||
|
||||
%.o: %.cpp
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGS} -c $<
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGSWALL} -c $<
|
||||
%.o: %.c
|
||||
$(OBJCACHE) ${CC} ${CPPFLAGS} -c $<
|
||||
$(OBJCACHE) ${CC} ${CPPFLAGSWALL} -c $<
|
||||
|
||||
V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
||||
|
||||
+82
-37
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -148,7 +148,11 @@ public:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ActiveNamer() {}
|
||||
ActiveNamer() {
|
||||
m_scopep = NULL;
|
||||
m_iActivep = NULL;
|
||||
m_cActivep = NULL;
|
||||
}
|
||||
virtual ~ActiveNamer() {}
|
||||
void main(AstScope* nodep) {
|
||||
nodep->accept(*this);
|
||||
@@ -160,26 +164,58 @@ public:
|
||||
|
||||
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
||||
private:
|
||||
bool m_combo; // Combo logic
|
||||
AstNode* m_alwaysp; // Always we're under
|
||||
AstNode* m_assignp; // In assign
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignDly* nodep, AstNUser*) {
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) blocks should be non-delayed assignments (=).");
|
||||
AstNode* newp = new AstAssign (nodep->fileline(),
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
if (m_combo) {
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5," ASSIGNDLY "<<nodep<<endl);
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||
AstNode* newp = new AstAssign (nodep->fileline(),
|
||||
nodep->lhsp()->unlinkFrBack(),
|
||||
nodep->rhsp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep = NULL;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssign* nodep, AstNUser*) {
|
||||
if (!m_combo) {
|
||||
AstNode* las = m_assignp;
|
||||
m_assignp = nodep;
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
m_assignp = las;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
AstVar* varp=nodep->varp();
|
||||
if (!m_combo
|
||||
&& m_assignp
|
||||
&& !varp->isUsedLoopIdx() // Ignore loop indicies
|
||||
&& !varp->isTemp()
|
||||
) {
|
||||
// Allow turning off warnings on the always, or the variable also
|
||||
if (!m_alwaysp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||
&& !m_assignp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||
&& !varp->fileline()->warnIsOff(V3ErrorCode::BLKSEQ)
|
||||
) {
|
||||
m_alwaysp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Complain just once for the entire always
|
||||
varp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
|
||||
nodep->v3warn(BLKSEQ,"Blocking assignments (=) in sequential (flop or latch) block; suggest delayed assignments (<=).");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Empty visitors, speed things up
|
||||
virtual void visit(AstNodeMath* nodep, AstNUser*) {}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ActiveDlyVisitor(AstNode* nodep) {
|
||||
ActiveDlyVisitor(AstNode* nodep, bool combo) {
|
||||
m_alwaysp = nodep;
|
||||
m_combo = combo;
|
||||
m_assignp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~ActiveDlyVisitor() {}
|
||||
@@ -197,7 +233,6 @@ private:
|
||||
// STATE
|
||||
ActiveNamer m_namer; // Tracking of active names
|
||||
AstCFunc* m_scopeFinalp; // Final function for this scope
|
||||
AstAlways* m_alwaysp; // Under always
|
||||
bool m_itemCombo; // Found a SenItem combo
|
||||
bool m_itemSequent; // Found a SenItem sequential
|
||||
|
||||
@@ -264,32 +299,22 @@ private:
|
||||
}
|
||||
|
||||
// METHODS
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
void visitAlways(AstNode* nodep, AstSenTree* oldsensesp) {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4," ALW "<<nodep<<endl);
|
||||
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
||||
|
||||
if (!nodep->bodysp()) {
|
||||
// Empty always. Kill it.
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
return;
|
||||
}
|
||||
if (nodep->sensesp()
|
||||
&& nodep->sensesp()->sensesp()
|
||||
&& nodep->sensesp()->sensesp()->castSenItem()
|
||||
&& nodep->sensesp()->sensesp()->castSenItem()->isNever()) {
|
||||
if (oldsensesp
|
||||
&& oldsensesp->sensesp()
|
||||
&& oldsensesp->sensesp()->castSenItem()
|
||||
&& oldsensesp->sensesp()->castSenItem()->isNever()) {
|
||||
// Never executing. Kill it.
|
||||
if (nodep->sensesp()->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
||||
if (oldsensesp->sensesp()->nextp()) nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Read sensitivitues
|
||||
m_alwaysp = nodep;
|
||||
m_itemCombo = false;
|
||||
m_itemSequent = false;
|
||||
nodep->sensesp()->iterateAndNext(*this);
|
||||
m_alwaysp = NULL;
|
||||
oldsensesp->iterateAndNext(*this);
|
||||
bool combo = m_itemCombo;
|
||||
bool sequent = m_itemSequent;
|
||||
|
||||
@@ -311,15 +336,15 @@ private:
|
||||
// always (posedge RESET) { if (RESET).... } we know RESET is true.
|
||||
// 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) oldsensesp->addSensesp
|
||||
(new AstSenItem(nodep->fileline(),AstSenItem::Combo()));
|
||||
#endif
|
||||
wantactivep = m_namer.getActive(nodep->fileline(), nodep->sensesp());
|
||||
wantactivep = m_namer.getActive(nodep->fileline(), oldsensesp);
|
||||
}
|
||||
|
||||
// Delete sensitivity list
|
||||
if (AstNode* oldsense = nodep->sensesp()) {
|
||||
oldsense->unlinkFrBackWithNext()->deleteTree(); oldsense=NULL;
|
||||
if (oldsensesp) {
|
||||
oldsensesp->unlinkFrBackWithNext()->deleteTree(); oldsensesp=NULL;
|
||||
}
|
||||
|
||||
// Move node to new active
|
||||
@@ -328,8 +353,29 @@ private:
|
||||
|
||||
// Warn and/or convert any delayed assignments
|
||||
if (combo && !sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep);
|
||||
ActiveDlyVisitor dlyvisitor (nodep, true);
|
||||
}
|
||||
else if (!combo && sequent) {
|
||||
ActiveDlyVisitor dlyvisitor (nodep, false);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4," ALW "<<nodep<<endl);
|
||||
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
||||
|
||||
if (!nodep->bodysp()) {
|
||||
// Empty always. Kill it.
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
return;
|
||||
}
|
||||
visitAlways(nodep, nodep->sensesp());
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4," ALWPub "<<nodep<<endl);
|
||||
//if (debug()>=9) nodep->dumpTree(cout," Alw: ");
|
||||
visitAlways(nodep, nodep->sensesp());
|
||||
}
|
||||
virtual void visit(AstSenGate* nodep, AstNUser*) {
|
||||
AstSenItem* subitemp = nodep->sensesp();
|
||||
@@ -366,7 +412,6 @@ public:
|
||||
// CONSTUCTORS
|
||||
ActiveVisitor(AstNetlist* nodep) {
|
||||
m_scopeFinalp = NULL;
|
||||
m_alwaysp = NULL;
|
||||
m_itemCombo = false;
|
||||
m_itemSequent = false;
|
||||
nodep->accept(*this);
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+4
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -133,6 +133,9 @@ private:
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstFinal* nodep, AstNUser*) {
|
||||
nodep->v3fatalSrc("Node should have been deleted");
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+11
-11
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -177,24 +177,23 @@ private:
|
||||
// VISITORS //========== Case assertions
|
||||
virtual void visit(AstCase* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->user1()) {
|
||||
nodep->user1(true);
|
||||
if (!nodep->user1Inc()) {
|
||||
bool has_default=false;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
if (itemp->isDefault()) has_default=true;
|
||||
}
|
||||
if (nodep->fullPragma()) {
|
||||
if (nodep->fullPragma() || nodep->priorityPragma()) {
|
||||
// Simply need to add a default if there isn't one already
|
||||
m_statAsFull++;
|
||||
++m_statAsFull;
|
||||
if (!has_default) {
|
||||
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/,
|
||||
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
||||
}
|
||||
}
|
||||
if (nodep->parallelPragma()) {
|
||||
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||
// Need to check that one, and only one of the case items match at any moment
|
||||
// If there's a default, we allow none to match, else exactly one must match
|
||||
m_statAsFull++;
|
||||
++m_statAsFull;
|
||||
if (!has_default && !nodep->itemsp()) {
|
||||
// Not parallel, but harmlessly so.
|
||||
} else {
|
||||
@@ -208,7 +207,8 @@ private:
|
||||
else propp = onep;
|
||||
}
|
||||
}
|
||||
AstNode* ohot = (has_default
|
||||
bool allow_none = has_default || nodep->unique0Pragma();
|
||||
AstNode* ohot = (allow_none
|
||||
? (new AstOneHot0(nodep->fileline(), propp))->castNode()
|
||||
: (new AstOneHot (nodep->fileline(), propp))->castNode());
|
||||
AstIf* ifp = new AstIf (nodep->fileline(),
|
||||
@@ -241,18 +241,18 @@ private:
|
||||
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*) {
|
||||
nodep->iterateChildren(*this);
|
||||
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++;
|
||||
++m_statAsSV;
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2005-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+9
-6
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -74,7 +74,9 @@ void AstNode::init() {
|
||||
m_clonep = NULL;
|
||||
m_cloneCnt = 0;
|
||||
// Attributes
|
||||
m_signed = false;
|
||||
m_numeric = (int)AstNumeric::UNSIGNED;
|
||||
m_didWidth = false;
|
||||
m_doingWidth = false;
|
||||
m_width = 0;
|
||||
m_widthMin = 0;
|
||||
m_user1p = NULL;
|
||||
@@ -192,6 +194,7 @@ string AstNode::prettyName(const string& namein) {
|
||||
}
|
||||
}
|
||||
if (pretty.substr(0,4) == "TOP.") pretty.replace(0,4,"");
|
||||
if (pretty.substr(0,5) == "TOP->") pretty.replace(0,5,"");
|
||||
return pretty;
|
||||
}
|
||||
|
||||
@@ -427,7 +430,7 @@ void AstNode::replaceWith(AstNode* newp) {
|
||||
repHandle.relink(newp);
|
||||
}
|
||||
|
||||
void AstNRelinker::dump(ostream& str) {
|
||||
void AstNRelinker::dump(ostream& str) const {
|
||||
str<<" BK="<<(uint32_t*)m_backp;
|
||||
str<<" ITER="<<(uint32_t*)m_iterpp;
|
||||
str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":"");
|
||||
@@ -813,7 +816,7 @@ void AstNode::iterateAndNextIgnoreEdit(AstNVisitor& v, AstNUser* vup) {
|
||||
AstNode* AstNode::acceptSubtreeReturnEdits(AstNVisitor& v, AstNUser* vup) {
|
||||
// Some visitors perform tree edits (such as V3Const), and may even
|
||||
// replace/delete the exact nodep that the visitor is called with. If
|
||||
// this happens, the parent will loose the handle to the node that was
|
||||
// this happens, the parent will lose the handle to the node that was
|
||||
// processed.
|
||||
// To solve this, this function returns the pointer to the replacement node,
|
||||
// which in many cases is just the same node that was passed in.
|
||||
@@ -872,7 +875,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
|
||||
if (this==NULL || node2p==NULL) return false;
|
||||
if (this->type() != node2p->type()
|
||||
|| this->width() != node2p->width()
|
||||
|| this->isSigned() != node2p->isSigned()
|
||||
|| this->numeric() != node2p->numeric()
|
||||
|| !this->same(node2p)) {
|
||||
return false;
|
||||
}
|
||||
@@ -944,7 +947,7 @@ void AstNode::checkTree() {
|
||||
}
|
||||
}
|
||||
|
||||
void AstNode::dumpPtrs(ostream& os) {
|
||||
void AstNode::dumpPtrs(ostream& os) const {
|
||||
os<<"This="<<typeName()<<" "<<(void*)this;
|
||||
os<<" back="<<(void*)backp();
|
||||
if (nextp()) os<<" next="<<(void*)nextp();
|
||||
|
||||
+96
-29
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "V3Error.h"
|
||||
#include "V3Number.h"
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "V3Ast__gen_classes.h" // From ./astgen
|
||||
// Things like:
|
||||
@@ -56,9 +57,40 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstNumeric {
|
||||
public:
|
||||
enum en {
|
||||
UNSIGNED,
|
||||
SIGNED,
|
||||
DOUBLE
|
||||
// Limited to 2 bits, unless change V3Ast's packing function
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"UNSIGNED","SIGNED","DOUBLE"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstNumeric () : m_e(UNSIGNED) {}
|
||||
inline AstNumeric (en _e) : m_e(_e) {}
|
||||
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
inline bool isDouble() const { return m_e==DOUBLE; }
|
||||
inline bool isSigned() const { return m_e==SIGNED; }
|
||||
inline bool isUnsigned() const { return m_e==UNSIGNED; }
|
||||
};
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
|
||||
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstPragmaType {
|
||||
public:
|
||||
enum en {
|
||||
ILLEGAL,
|
||||
COVERAGE_BLOCK_OFF,
|
||||
INLINE_MODULE,
|
||||
NO_INLINE_MODULE,
|
||||
@@ -67,7 +99,7 @@ public:
|
||||
PUBLIC_TASK
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstPragmaType () {}
|
||||
inline AstPragmaType () : m_e(ILLEGAL) {}
|
||||
inline AstPragmaType (en _e) : m_e(_e) {}
|
||||
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -90,7 +122,7 @@ public:
|
||||
TRACE_CHANGE_SUB
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstCFuncType () {}
|
||||
inline AstCFuncType () : m_e(FT_NORMAL) {}
|
||||
inline AstCFuncType (en _e) : m_e(_e) {}
|
||||
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -158,7 +190,7 @@ public:
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstEdgeType () {}
|
||||
inline AstEdgeType () : m_e(ET_ILLEGAL) {}
|
||||
inline AstEdgeType (en _e) : m_e(_e) {}
|
||||
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -172,6 +204,7 @@ public:
|
||||
class AstAttrType {
|
||||
public:
|
||||
enum en {
|
||||
ILLEGAL,
|
||||
EXPR_BITS, // V3Const converts to constant
|
||||
//
|
||||
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
@@ -179,19 +212,23 @@ public:
|
||||
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
|
||||
VAR_PUBLIC, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_PUBLIC_FLAT, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
|
||||
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
|
||||
VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"EXPR_BITS", "VAR_BASE",
|
||||
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_PUBLIC_FLAT",
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SFORMAT"
|
||||
"%E-AT", "EXPR_BITS", "VAR_BASE",
|
||||
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstAttrType () {}
|
||||
inline AstAttrType () : m_e(ILLEGAL) {}
|
||||
inline AstAttrType (en _e) : m_e(_e) {}
|
||||
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -205,8 +242,9 @@ public:
|
||||
class AstBasicDTypeKwd {
|
||||
public:
|
||||
enum en {
|
||||
UNKNOWN,
|
||||
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
|
||||
REAL, REALTIME, SHORTINT, SHORTREAL, TIME,
|
||||
DOUBLE, SHORTINT, FLOAT, TIME,
|
||||
// Closer to a class type, but limited usage
|
||||
STRING,
|
||||
// Internal types for mid-steps
|
||||
@@ -217,8 +255,9 @@ public:
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"%E-unk",
|
||||
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
||||
"real", "realtime", "shortint", "shortreal", "time",
|
||||
"real", "shortint", "shortreal", "time",
|
||||
"string",
|
||||
"VerilatedScope*", "char*",
|
||||
"LOGIC_IMPLICIT"
|
||||
@@ -227,15 +266,16 @@ public:
|
||||
};
|
||||
const char* dpiType() const {
|
||||
static const char* names[] = {
|
||||
"%E-unk",
|
||||
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
||||
"double", "double", "short int", "float", "long long",
|
||||
"double", "short int", "float", "long long",
|
||||
"const char*",
|
||||
"dpiScope", "const char*",
|
||||
""
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstBasicDTypeKwd () {}
|
||||
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
|
||||
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
|
||||
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -248,6 +288,8 @@ public:
|
||||
case INTEGER: return 32;
|
||||
case LOGIC: return 1;
|
||||
case LONGINT: return 64;
|
||||
case DOUBLE: return 64;
|
||||
case FLOAT: return 32;
|
||||
case SHORTINT: return 16;
|
||||
case TIME: return 64;
|
||||
case STRING: return 64; // Just the pointer, for today
|
||||
@@ -262,7 +304,7 @@ public:
|
||||
}
|
||||
bool isZeroInit() const { // Otherwise initializes to X
|
||||
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|
||||
|| m_e==STRING);
|
||||
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isSloppy() const { // Don't be as anal about width warnings
|
||||
return !(m_e==LOGIC || m_e==BIT);
|
||||
@@ -271,10 +313,13 @@ public:
|
||||
return (m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
bool isDpiUnsupported() const {
|
||||
return (m_e==LOGIC || m_e==TIME || m_e==REALTIME);
|
||||
return (m_e==LOGIC || m_e==TIME);
|
||||
}
|
||||
bool isOpaque() const { // IE not a simple number we can bit optimize
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR);
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isDouble() const {
|
||||
return (m_e==DOUBLE);
|
||||
}
|
||||
};
|
||||
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
@@ -313,7 +358,7 @@ public:
|
||||
XTEMP
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstVarType () {}
|
||||
inline AstVarType () : m_e(UNKNOWN) {}
|
||||
inline AstVarType (en _e) : m_e(_e) {}
|
||||
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -371,7 +416,7 @@ public:
|
||||
CT_CASEZ
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstCaseType () {}
|
||||
inline AstCaseType () : m_e(CT_CASE) {}
|
||||
inline AstCaseType (en _e) : m_e(_e) {}
|
||||
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -393,7 +438,7 @@ public:
|
||||
DT_FATAL
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstDisplayType () {}
|
||||
inline AstDisplayType () : m_e(DT_DISPLAY) {}
|
||||
inline AstDisplayType (en _e) : m_e(_e) {}
|
||||
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -603,7 +648,7 @@ public:
|
||||
AstNRelinker() { m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
|
||||
void relink(AstNode* newp);
|
||||
AstNode* oldp() const { return m_oldp; }
|
||||
void dump(ostream& str=cout);
|
||||
void dump(ostream& str=cout) const;
|
||||
};
|
||||
inline ostream& operator<<(ostream& os, AstNRelinker& rhs) { rhs.dump(os); return os;}
|
||||
|
||||
@@ -681,7 +726,9 @@ class AstNode {
|
||||
static int s_cloneCntGbl; // Count of which userp is set
|
||||
|
||||
// Attributes
|
||||
bool m_signed:1; // Node is signed
|
||||
uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
|
||||
bool m_didWidth:1; // Did V3Width computation
|
||||
bool m_doingWidth:1; // Inside V3Width
|
||||
// // Space for more bools here
|
||||
|
||||
int m_width; // Bit width of operation
|
||||
@@ -714,6 +761,7 @@ class AstNode {
|
||||
void deleteTreeIter();
|
||||
void deleteNode();
|
||||
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
|
||||
// cppcheck-suppress functionConst
|
||||
void debugTreeChange(const char* prefix, int lineno, bool next);
|
||||
|
||||
protected:
|
||||
@@ -777,6 +825,9 @@ public:
|
||||
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
|
||||
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
|
||||
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
|
||||
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
|
||||
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
|
||||
static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do triganomics
|
||||
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
|
||||
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
|
||||
|
||||
@@ -804,10 +855,18 @@ public:
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
void width(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); signedFrom(fromp); }
|
||||
void signedFrom(AstNode* fromp) { if (fromp) { m_signed=fromp->m_signed; }}
|
||||
void isSigned(bool flag) { m_signed=flag; }
|
||||
bool isSigned() const { return m_signed; }
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
|
||||
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
|
||||
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
|
||||
AstNumeric numeric() const { return AstNumeric(m_numeric); }
|
||||
bool isDouble() const { return numeric().isDouble(); }
|
||||
bool isSigned() const { return numeric().isSigned(); }
|
||||
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
|
||||
bool isUnsigned() const { return numeric().isUnsigned(); }
|
||||
void didWidth(bool flag) { m_didWidth=flag; }
|
||||
bool didWidth() const { return m_didWidth; }
|
||||
void doingWidth(bool flag) { m_doingWidth=flag; }
|
||||
bool doingWidth() const { return m_doingWidth; }
|
||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||
|
||||
@@ -819,6 +878,7 @@ public:
|
||||
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; }
|
||||
int user1() const { return user1p()->castInt(); }
|
||||
void user1(int val) { user1p(AstNUser::fromInt(val)); }
|
||||
int user1Inc() { int v=user1(); user1(v+1); return v; }
|
||||
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
||||
|
||||
AstNUser* user2p() const {
|
||||
@@ -827,6 +887,7 @@ public:
|
||||
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; }
|
||||
int user2() const { return user2p()->castInt(); }
|
||||
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
||||
int user2Inc() { int v=user2(); user2(v+1); return v; }
|
||||
static void user2ClearTree() { AstUser2InUse::clear(); }
|
||||
|
||||
AstNUser* user3p() const {
|
||||
@@ -835,6 +896,7 @@ public:
|
||||
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; }
|
||||
int user3() const { return user3p()->castInt(); }
|
||||
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
||||
int user3Inc() { int v=user3(); user3(v+1); return v; }
|
||||
static void user3ClearTree() { AstUser3InUse::clear(); }
|
||||
|
||||
AstNUser* user4p() const {
|
||||
@@ -843,6 +905,7 @@ public:
|
||||
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; }
|
||||
int user4() const { return user4p()->castInt(); }
|
||||
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
||||
int user4Inc() { int v=user4(); user4(v+1); return v; }
|
||||
static void user4ClearTree() { AstUser4InUse::clear(); }
|
||||
|
||||
AstNUser* user5p() const {
|
||||
@@ -851,6 +914,7 @@ public:
|
||||
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; }
|
||||
int user5() const { return user5p()->castInt(); }
|
||||
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
||||
int user5Inc() { int v=user5(); user5(v+1); return v; }
|
||||
static void user5ClearTree() { AstUser5InUse::clear(); }
|
||||
|
||||
vluint64_t editCount() const { return m_editCount; }
|
||||
@@ -890,7 +954,7 @@ public:
|
||||
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
|
||||
void deleteTree(); // Always deletes the next link
|
||||
void checkTree(); // User Interface version
|
||||
void dumpPtrs(ostream& str=cout);
|
||||
void dumpPtrs(ostream& str=cout) const;
|
||||
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTreeFile(const string& filename, bool append=false);
|
||||
@@ -957,6 +1021,7 @@ struct AstNodeTermop : public AstNodeMath {
|
||||
ASTNODE_BASE_FUNCS(NodeTermop)
|
||||
// Know no children, and hot function, so skip iterator for speed
|
||||
// See checkTreeIter also that asserts no children
|
||||
// cppcheck-suppress functionConst
|
||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
||||
};
|
||||
|
||||
@@ -968,10 +1033,13 @@ struct AstNodeUniop : public AstNodeMath {
|
||||
setOp1p(lhsp); }
|
||||
ASTNODE_BASE_FUNCS(NodeUniop)
|
||||
AstNode* lhsp() const { return op1p()->castNode(); }
|
||||
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
||||
// METHODS
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
|
||||
virtual bool cleanLhs() = 0;
|
||||
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
||||
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
||||
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
@@ -994,6 +1062,7 @@ struct AstNodeBiop : public AstNodeMath {
|
||||
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
||||
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
|
||||
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
||||
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
@@ -1215,6 +1284,7 @@ public:
|
||||
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
||||
// Know no children, and hot function, so skip iterator for speed
|
||||
// See checkTreeIter also that asserts no children
|
||||
// cppcheck-suppress functionConst
|
||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
||||
};
|
||||
|
||||
@@ -1266,7 +1336,6 @@ private:
|
||||
string m_name; // Name of task
|
||||
string m_cname; // Name of task if DPI import
|
||||
bool m_taskPublic:1; // Public task
|
||||
bool m_didSigning:1; // V3Signed completed; can skip iteration
|
||||
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
|
||||
bool m_prototype:1; // Just a prototype
|
||||
bool m_dpiExport:1; // DPI exported
|
||||
@@ -1277,7 +1346,7 @@ private:
|
||||
public:
|
||||
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||
: AstNode(fileline)
|
||||
, m_name(name), m_taskPublic(false), m_didSigning(false)
|
||||
, m_name(name), m_taskPublic(false)
|
||||
, m_attrIsolateAssign(false), m_prototype(false)
|
||||
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
|
||||
, m_dpiTask(false), m_pure(false) {
|
||||
@@ -1304,8 +1373,6 @@ public:
|
||||
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
||||
void taskPublic(bool flag) { m_taskPublic=flag; }
|
||||
bool taskPublic() const { return m_taskPublic; }
|
||||
void didSigning(bool flag) { m_didSigning=flag; }
|
||||
bool didSigning() const { return m_didSigning; }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
void prototype(bool flag) { m_prototype = flag; }
|
||||
|
||||
+64
-13
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -70,7 +70,7 @@ bool AstVar::isScQuad() const {
|
||||
}
|
||||
|
||||
bool AstVar::isScBv() const {
|
||||
return (isSc() && width() >= v3Global.opt.pinsBv());
|
||||
return ((isSc() && width() >= v3Global.opt.pinsBv()) || m_attrScBv);
|
||||
}
|
||||
|
||||
void AstVar::combineType(AstVarType type) {
|
||||
@@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
||||
arg += "const char*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
||||
arg += "const VerilatedScope*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
|
||||
arg += "double";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
|
||||
arg += "float";
|
||||
} else if (strtype) {
|
||||
if (isInOnly()) arg += "const ";
|
||||
arg += "string";
|
||||
@@ -137,6 +141,43 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
||||
return arg;
|
||||
}
|
||||
|
||||
string AstVar::vlEnumType() const {
|
||||
string arg;
|
||||
AstBasicDType* bdtypep = basicp();
|
||||
bool strtype = bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::STRING;
|
||||
if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::CHARPTR) {
|
||||
return "VLVT_PTR";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
||||
return "VLVT_PTR";
|
||||
} else if (strtype) {
|
||||
arg += "VLVT_STRING";
|
||||
} else if (widthMin() <= 8) {
|
||||
arg += "VLVT_UINT8";
|
||||
} else if (widthMin() <= 16) {
|
||||
arg += "VLVT_UINT16";
|
||||
} else if (widthMin() <= VL_WORDSIZE) {
|
||||
arg += "VLVT_UINT32";
|
||||
} else if (isQuad()) {
|
||||
arg += "VLVT_UINT64";
|
||||
} else if (isWide()) {
|
||||
arg += "VLVT_WDATA";
|
||||
}
|
||||
// else return "VLVT_UNKNOWN"
|
||||
return arg;
|
||||
}
|
||||
|
||||
string AstVar::vlEnumDir() const {
|
||||
if (isInout()) {
|
||||
return "VLVD_INOUT";
|
||||
} else if (isInOnly()) {
|
||||
return "VLVD_IN";
|
||||
} else if (isOutOnly()) {
|
||||
return "VLVD_OUT";
|
||||
} else {
|
||||
return "VLVD_NODIR";
|
||||
}
|
||||
}
|
||||
|
||||
string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||
if (forReturn) named=false;
|
||||
string arg;
|
||||
@@ -148,7 +189,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||
} else if (isWide()) {
|
||||
arg += "uint32_t"; // []'s added later
|
||||
} else {
|
||||
arg += "uint64_t";
|
||||
arg += "vluint64_t";
|
||||
}
|
||||
if (isWide()) {
|
||||
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
|
||||
@@ -165,7 +206,6 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
if (forReturn) named=false;
|
||||
string arg;
|
||||
if (!basicp()) arg = "UNKNOWN";
|
||||
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
|
||||
if (basicp()->isBitLogic()) {
|
||||
if (widthMin() == 1) {
|
||||
arg = "unsigned char";
|
||||
@@ -201,7 +241,7 @@ string AstVar::scType() const {
|
||||
return "uint32_t";
|
||||
}
|
||||
} else {
|
||||
return "uint64_t";
|
||||
return "vluint64_t";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,13 +298,15 @@ uint32_t AstVar::arrayElements() const {
|
||||
return entries;
|
||||
}
|
||||
|
||||
uint32_t AstVar::dimensions() const {
|
||||
// How many array dimensions does this Var have?
|
||||
uint32_t dim = 0;
|
||||
pair<uint32_t,uint32_t> AstVar::dimensions() const {
|
||||
// How many array dimensions (packed,unpacked) does this Var have?
|
||||
uint32_t packed = 0;
|
||||
uint32_t unpacked = 0;
|
||||
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
|
||||
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
||||
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
||||
dim += 1;
|
||||
if (adtypep->isPacked()) packed += 1;
|
||||
else unpacked += 1;
|
||||
dtypep = adtypep->dtypep();
|
||||
}
|
||||
else {
|
||||
@@ -272,7 +314,7 @@ uint32_t AstVar::dimensions() const {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return dim;
|
||||
return make_pair(packed, unpacked);
|
||||
}
|
||||
|
||||
// Special operators
|
||||
@@ -348,6 +390,8 @@ string AstScopeName::scopeSymName() const {
|
||||
out += textp->text();
|
||||
}
|
||||
if (out.substr(0,10) == "__DOT__TOP") out.replace(0,10,"");
|
||||
if (out.substr(0,7) == "__DOT__") out.replace(0,7,"");
|
||||
if (out.substr(0,1) == ".") out.replace(0,1,"");
|
||||
string::size_type pos;
|
||||
while ((pos=out.find(".")) != string::npos) {
|
||||
out.replace(pos, 1, "__");
|
||||
@@ -457,13 +501,18 @@ void AstNode::dump(ostream& os) {
|
||||
//<<" "<<(void*)this->m_backp
|
||||
<<" <e"<<dec<<editCount()
|
||||
<<((editCount()>=editCountLast())?"#>":">")
|
||||
<<" {"<<dec<<fileline()->lineno()<<"}"
|
||||
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
|
||||
<<" "<<(isSigned()?"s":"")
|
||||
<<(isDouble()?"d":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) os<<"/"<<widthMin();
|
||||
if (name()!="") os<<" "<<AstNode::quoteName(name());
|
||||
}
|
||||
|
||||
void AstArrayDType::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
if (isPacked()) str<<" [PACKED]";
|
||||
}
|
||||
void AstArraySel::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
|
||||
@@ -477,7 +526,7 @@ void AstBasicDType::dump(ostream& str) {
|
||||
str<<" ["<<keyword().ascii()<<"]";
|
||||
if (implicit()) str<<" [IMPLICIT]";
|
||||
}
|
||||
void AstCast::dump(ostream& str) {
|
||||
void AstCCast::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" sz"<<size();
|
||||
}
|
||||
@@ -564,8 +613,10 @@ void AstVar::dump(ostream& str) {
|
||||
else if (isInput()) str<<" [I]";
|
||||
else if (isOutput()) str<<" [O]";
|
||||
}
|
||||
if (isUsedClock()) str<<" [C]";
|
||||
if (isConst()) str<<" [CONST]";
|
||||
if (isUsedClock()) str<<" [CLK]";
|
||||
if (isSigPublic()) str<<" [P]";
|
||||
if (isUsedLoopIdx()) str<<" [LOOP]";
|
||||
if (attrClockEn()) str<<" [aCLKEN]";
|
||||
if (attrIsolateAssign()) str<<" [aISO]";
|
||||
if (attrFileDescr()) str<<" [aFD]";
|
||||
|
||||
+558
-58
File diff suppressed because it is too large
Load Diff
+18
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -53,6 +53,7 @@ private:
|
||||
string m_namedScope; // Name of begin blocks above us
|
||||
string m_unnamedScope; // Name of begin blocks, including unnamed blocks
|
||||
int m_repeatNum; // Repeat counter
|
||||
int m_ifDepth; // Current if depth
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -152,6 +153,21 @@ private:
|
||||
// any BEGINs, but V3Coverage adds them all under the module itself.
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
// VISITORS - LINT CHECK
|
||||
virtual void visit(AstIf* nodep, AstNUser*) { // Note not AstNodeIf; other types don't get covered
|
||||
// Check IFDEPTH warning - could be in other transform files if desire
|
||||
int prevIfDepth = m_ifDepth;
|
||||
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
|
||||
} else if (nodep->uniquePragma() || nodep->unique0Pragma() || nodep->priorityPragma()) {
|
||||
m_ifDepth = -1;
|
||||
} else if (++m_ifDepth > v3Global.opt.ifDepth()) {
|
||||
nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic");
|
||||
nodep->fileline()->modifyWarnOff(V3ErrorCode::IFDEPTH, true); // Warn only once
|
||||
m_ifDepth = -1;
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
m_ifDepth = prevIfDepth;
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
@@ -161,6 +177,7 @@ public:
|
||||
m_modp = NULL;
|
||||
m_ftaskp = NULL;
|
||||
m_repeatNum = 0;
|
||||
m_ifDepth = 0;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~BeginVisitor() {}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+9
-5
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -148,17 +148,19 @@ private:
|
||||
|
||||
bool isCaseTreeFast(AstCase* nodep) {
|
||||
int width = 0;
|
||||
bool opaque = false;
|
||||
m_caseItems = 0;
|
||||
m_caseNoOverlapsAllCovered = true;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||
if (icondp->width() > width) width = icondp->width();
|
||||
if (icondp->isDouble()) opaque = true;
|
||||
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
|
||||
m_caseItems++;
|
||||
}
|
||||
}
|
||||
m_caseWidth = width;
|
||||
if (width==0 || width > CASE_OVERLAP_WIDTH) {
|
||||
if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
return false; // Too wide for analysis
|
||||
}
|
||||
@@ -348,7 +350,9 @@ private:
|
||||
and1p = cexprp->cloneTree(false);
|
||||
and2p = icondp;
|
||||
}
|
||||
AstEq* condp = new AstEq(itemp->fileline(), and1p, and2p);
|
||||
AstNodeBiop* condp = (and1p->isDouble()
|
||||
? (new AstEqD(itemp->fileline(), and1p, and2p))->castNodeBiop()
|
||||
: (new AstEq(itemp->fileline(), and1p, and2p))->castNodeBiop());
|
||||
if (!ifexprp) {
|
||||
ifexprp = condp;
|
||||
} else {
|
||||
@@ -448,10 +452,10 @@ private:
|
||||
if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) {
|
||||
// It's a simple priority encoder or complete statement
|
||||
// we can make a tree of statements to avoid extra comparisons
|
||||
m_statCaseFast++;
|
||||
++m_statCaseFast;
|
||||
replaceCaseFast(nodep); nodep=NULL;
|
||||
} else {
|
||||
m_statCaseSlow++;
|
||||
++m_statCaseSlow;
|
||||
replaceCaseComplicated(nodep); nodep=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+7
-7
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -77,7 +77,7 @@ private:
|
||||
AstNRelinker relinkHandle;
|
||||
nodep->unlinkFrBack(&relinkHandle);
|
||||
//
|
||||
AstCast* castp = new AstCast (nodep->fileline(), nodep, needsize);
|
||||
AstCCast* castp = new AstCCast (nodep->fileline(), nodep, needsize);
|
||||
castp->width(needsize, nodep->widthMin());
|
||||
relinkHandle.relink(castp);
|
||||
//if (debug()>8) castp->dumpTree(cout,"-castins: ");
|
||||
@@ -97,13 +97,13 @@ private:
|
||||
insertCast(nodep, castSize(nodep->backp()));
|
||||
}
|
||||
}
|
||||
void insureLower32Cast(AstCast* nodep) {
|
||||
void insureLower32Cast(AstCCast* nodep) {
|
||||
// If we have uint64 = CAST(uint64(x)) then the upcasting
|
||||
// really needs to be CAST(uint64(CAST(uint32(x))).
|
||||
// Otherwise a (uint64)(a>b) would return wrong value, as
|
||||
// less than has undeterministic signedness.
|
||||
if (nodep->isQuad() && !nodep->lhsp()->isQuad()
|
||||
&& !nodep->lhsp()->castCast()) {
|
||||
&& !nodep->lhsp()->castCCast()) {
|
||||
insertCast(nodep->lhsp(), VL_WORDSIZE);
|
||||
}
|
||||
}
|
||||
@@ -130,12 +130,12 @@ private:
|
||||
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
|
||||
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
||||
virtual void visit(AstCCast* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
insureLower32Cast(nodep);
|
||||
nodep->user1(1);
|
||||
}
|
||||
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
||||
virtual void visit(AstNegate* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
if (nodep->lhsp()->widthMin()==1) {
|
||||
@@ -149,7 +149,7 @@ private:
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (!nodep->lvalue()
|
||||
&& !nodep->backp()->castCast()
|
||||
&& !nodep->backp()->castCCast()
|
||||
&& nodep->backp()->castNodeMath()
|
||||
&& nodep->backp()->width()
|
||||
&& castSize(nodep) != castSize(nodep->varp())) {
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2004-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2004-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+49
-17
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -46,6 +46,8 @@
|
||||
#include "V3EmitV.h"
|
||||
#include "V3File.h"
|
||||
|
||||
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
|
||||
|
||||
//######################################################################
|
||||
|
||||
class CdcBaseVisitor : public AstNVisitor {
|
||||
@@ -65,9 +67,9 @@ class CdcEitherVertex : public V3GraphVertex {
|
||||
AstNode* m_nodep;
|
||||
AstSenTree* m_srcDomainp;
|
||||
AstSenTree* m_dstDomainp;
|
||||
bool m_srcDomainSet;
|
||||
bool m_dstDomainSet;
|
||||
bool m_asyncPath;
|
||||
bool m_srcDomainSet:1;
|
||||
bool m_dstDomainSet:1;
|
||||
bool m_asyncPath:1;
|
||||
public:
|
||||
CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep)
|
||||
: V3GraphVertex(graphp), m_scopep(scopep), m_nodep(nodep)
|
||||
@@ -109,11 +111,12 @@ public:
|
||||
};
|
||||
|
||||
class CdcLogicVertex : public CdcEitherVertex {
|
||||
bool m_hazard;
|
||||
bool m_isFlop;
|
||||
bool m_hazard:1;
|
||||
bool m_isFlop:1;
|
||||
public:
|
||||
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
|
||||
: CdcEitherVertex(graphp,scopep,nodep), m_hazard(false), m_isFlop(false)
|
||||
: CdcEitherVertex(graphp,scopep,nodep)
|
||||
, m_hazard(false), m_isFlop(false)
|
||||
{ srcDomainp(sensenodep); dstDomainp(sensenodep); }
|
||||
virtual ~CdcLogicVertex() {}
|
||||
// Accessors
|
||||
@@ -132,7 +135,7 @@ class CdcDumpVisitor : public CdcBaseVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
//Entire netlist:
|
||||
// {statement}Node::user3p -> bool, indicating not hazard
|
||||
// {statement}Node::user3 -> bool, indicating not hazard
|
||||
ofstream* m_ofp; // Output file
|
||||
string m_prefix;
|
||||
|
||||
@@ -290,9 +293,12 @@ private:
|
||||
void setNodeHazard(AstNode* nodep) {
|
||||
// Need to not clear if warnings are off (rather than when report it)
|
||||
// as bypassing this warning may turn up another path that isn't warning off'ed.
|
||||
// We can't modifyWarnOff here, as one instantiation might not be an issue until we find a hitting flop
|
||||
// Furthermore, a module like a "Or" module would only get flagged once,
|
||||
// even though the signals feeding it are radically different.
|
||||
if (!m_domainp || m_domainp->hasCombo()) { // Source flop logic in a posedge block is OK for reset (not async though)
|
||||
if (m_logicVertexp && !nodep->fileline()->warnIsOff(V3ErrorCode::CDCRSTLOGIC)) {
|
||||
UINFO(9,"Set hazard "<<nodep<<endl);
|
||||
UINFO(8,"Set hazard "<<nodep<<endl);
|
||||
m_logicVertexp->setHazard(nodep);
|
||||
}
|
||||
}
|
||||
@@ -310,7 +316,9 @@ private:
|
||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||
//if (debug()>6) m_graph.dump();
|
||||
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre");
|
||||
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
||||
//
|
||||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights
|
||||
//
|
||||
m_graph.dumpDotFilePrefixed("cdc_simp");
|
||||
//
|
||||
analyzeReset();
|
||||
@@ -335,7 +343,7 @@ private:
|
||||
if (CdcVarVertex* vvertexp = dynamic_cast<CdcVarVertex*>(itp)) {
|
||||
if (vvertexp->cntAsyncRst()) {
|
||||
m_userGeneration++; // Effectively a userClearVertices()
|
||||
UINFO(9, " Trace One async: "<<vvertexp<<endl);
|
||||
UINFO(8, " Trace One async: "<<vvertexp<<endl);
|
||||
// Twice, as we need to detect, then propagate
|
||||
CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false);
|
||||
if (markp) { // Mark is non-NULL if something bad on this path
|
||||
@@ -351,7 +359,8 @@ private:
|
||||
}
|
||||
|
||||
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
||||
// Return vertex of any hazardous stuff attached, or NULL if OK
|
||||
// First pass: Return vertex of any hazardous stuff attached, or NULL if OK
|
||||
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
|
||||
if (vertexp->user()>=m_userGeneration) return false; // Processed - prevent loop
|
||||
vertexp->user(m_userGeneration);
|
||||
|
||||
@@ -406,12 +415,15 @@ private:
|
||||
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
|
||||
if (!eToVertexp) targetp = eToVertexp;
|
||||
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) {
|
||||
if (vvertexp->isFlop()) {
|
||||
if (vvertexp->isFlop() // IE the target flop that is upsetting us
|
||||
&& edgep->weight() >= CDC_WEIGHT_ASYNC) { // And this signal feeds an async reset line
|
||||
targetp = eToVertexp;
|
||||
//UINFO(9," targetasync "<<targetp->name()<<" "<<" from "<<vertexp->name()<<endl);
|
||||
break;
|
||||
}
|
||||
} // else it might be random logic that's not relevant
|
||||
}
|
||||
//UINFO(9," finalflop "<<targetp->name()<<" "<<targetp->nodep()->fileline()<<endl);
|
||||
warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
|
||||
dumpAsyncRecurse(targetp, "", " ",0);
|
||||
}
|
||||
@@ -464,6 +476,12 @@ private:
|
||||
|
||||
void edgeReport() {
|
||||
// Make report of all signal names and what clock edges they have
|
||||
//
|
||||
// Due to flattening, many interesting direct-connect signals are
|
||||
// lost, so we can't make a report showing I/Os for a low level
|
||||
// module. Disabling flattening though makes us consider each
|
||||
// signal in it's own unique clock domain.
|
||||
|
||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||
|
||||
// Trace all sources and sinks
|
||||
@@ -493,6 +511,10 @@ private:
|
||||
|
||||
ostringstream os;
|
||||
os.setf(ios::left);
|
||||
// Module name - doesn't work due to flattening having lost the original
|
||||
// so we assume the modulename matches the filebasename
|
||||
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
|
||||
os<<" "<<setw(20)<<fname;
|
||||
os<<" "<<setw(8)<<whatp;
|
||||
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
|
||||
os<<" SRC=";
|
||||
@@ -613,8 +635,9 @@ private:
|
||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
||||
CdcVarVertex* varvertexp = makeVarVertex(varscp);
|
||||
UINFO(5," VARREF to "<<varscp<<endl);
|
||||
// We use weight of one; if we ref the var more than once, when we simplify,
|
||||
// the weight will increase
|
||||
// We use weight of one for normal edges,
|
||||
// Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting)
|
||||
// When simplify we'll take the MAX weight
|
||||
if (nodep->lvalue()) {
|
||||
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
||||
if (m_inDly) {
|
||||
@@ -623,7 +646,13 @@ private:
|
||||
varvertexp->srcDomainSet(true);
|
||||
}
|
||||
} else {
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||
if (varvertexp->cntAsyncRst()) {
|
||||
//UINFO(9," edgeasync "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, CDC_WEIGHT_ASYNC);
|
||||
} else {
|
||||
//UINFO(9," edgena "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -642,6 +671,9 @@ private:
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
iterateNewStmt(nodep);
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
|
||||
// CDC doesn't care about public variables
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep, AstNUser*) {
|
||||
iterateNewStmt(nodep);
|
||||
}
|
||||
@@ -717,7 +749,7 @@ public:
|
||||
|
||||
nodep->accept(*this);
|
||||
analyze();
|
||||
//edgeReport(); // Not useful at the moment
|
||||
if (debug()>=1) edgeReport(); // Not useful to users at the moment
|
||||
|
||||
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+2
-3
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -128,8 +128,7 @@ private:
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
if (nodep->isCircular()) {
|
||||
UINFO(8," CIRC "<<nodep<<endl);
|
||||
if (!nodep->user1()) {
|
||||
nodep->user1(true);
|
||||
if (!nodep->user1Inc()) {
|
||||
genChangeDet(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+4
-4
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2008-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2008-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -315,6 +315,7 @@ public:
|
||||
m_exprp = exprp;
|
||||
m_original = original;
|
||||
m_state = STATE_UNKNOWN;
|
||||
m_cloning = false;
|
||||
if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: ");
|
||||
nodep->bodysp()->iterateAndNext(*this);
|
||||
if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: ");
|
||||
@@ -696,7 +697,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
// Blow old statements from new body
|
||||
GaterBodyVisitor(alwp,exprp,false);
|
||||
|
||||
m_statGaters++;
|
||||
++m_statGaters;
|
||||
if (debug()>=9) alwp->dumpTree(cout," new: ");
|
||||
}
|
||||
|
||||
@@ -704,8 +705,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
if (debug()>=9) cout<<endl<<endl<<endl;
|
||||
UINFO(5, "Gater: ALWAYS: "<<nodep<<endl);
|
||||
if (nodep->user4()) return;
|
||||
nodep->user4(1);
|
||||
if (nodep->user4Inc()) return;
|
||||
|
||||
clear();
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+7
-5
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -70,8 +70,8 @@ protected:
|
||||
virtual ~CombBaseVisitor() {}
|
||||
|
||||
//***** optimization levels
|
||||
bool emptyFunctionDeletion() { return true; }
|
||||
bool duplicateFunctionCombine() { return true; }
|
||||
static bool emptyFunctionDeletion() { return true; }
|
||||
static bool duplicateFunctionCombine() { return true; }
|
||||
// Note this is disabled, it still needed work
|
||||
// Also repair it for DPI functions; when make __common need to insure proper
|
||||
// flags get inherited from the old to new AstCFunc, and that AstText doesn't
|
||||
@@ -146,7 +146,9 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
CombCallVisitor() {}
|
||||
CombCallVisitor() {
|
||||
m_find = false;
|
||||
}
|
||||
virtual ~CombCallVisitor() {}
|
||||
void main(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
@@ -257,7 +259,7 @@ private:
|
||||
UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl);
|
||||
UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl);
|
||||
// Mark user3p on entire old tree, so we don't process it more
|
||||
m_statCombs++;
|
||||
++m_statCombs;
|
||||
CombMarkVisitor visitor(oldfuncp);
|
||||
m_call.replaceFunc(oldfuncp, newfuncp);
|
||||
oldfuncp->unlinkFrBack();
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+30
-17
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -60,7 +60,8 @@ class V3ConfigIgnores {
|
||||
IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number
|
||||
IgnLines::const_iterator m_lastEnd; // Point with end()
|
||||
|
||||
IgnFiles m_ignFiles; // Ignores for each filename
|
||||
IgnFiles m_ignWilds; // Ignores for each wildcarded filename
|
||||
IgnFiles m_ignFiles; // Ignores for each non-wildcarded filename
|
||||
|
||||
static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow)
|
||||
|
||||
@@ -68,13 +69,13 @@ class V3ConfigIgnores {
|
||||
~V3ConfigIgnores() {}
|
||||
|
||||
// METHODS
|
||||
inline IgnLines* findLines(const string& filename) {
|
||||
IgnFiles::iterator it = m_ignFiles.find(filename);
|
||||
if (it != m_ignFiles.end()) {
|
||||
inline IgnLines* findWilds(const string& wildname) {
|
||||
IgnFiles::iterator it = m_ignWilds.find(wildname);
|
||||
if (it != m_ignWilds.end()) {
|
||||
return &(it->second);
|
||||
} else {
|
||||
m_ignFiles.insert(make_pair(filename, IgnLines()));
|
||||
it = m_ignFiles.find(filename);
|
||||
m_ignWilds.insert(make_pair(wildname, IgnLines()));
|
||||
it = m_ignWilds.find(wildname);
|
||||
return &(it->second);
|
||||
}
|
||||
}
|
||||
@@ -82,23 +83,35 @@ class V3ConfigIgnores {
|
||||
// Given a filename, find all wildcard matches against it and build
|
||||
// hash with the specific filename. This avoids having to wildmatch
|
||||
// more than once against any filename.
|
||||
IgnLines* linesp = findLines(filename);
|
||||
m_lastIt = linesp->begin();
|
||||
m_lastEnd = linesp->end();
|
||||
IgnFiles::iterator it = m_ignFiles.find(filename);
|
||||
if (it == m_ignFiles.end()) {
|
||||
// Haven't seen this filename before
|
||||
m_ignFiles.insert(make_pair(filename, IgnLines()));
|
||||
it = m_ignFiles.find(filename);
|
||||
// Make new list for this file of all matches
|
||||
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
|
||||
if (V3Options::wildmatch(filename.c_str(), fnit->first.c_str())) {
|
||||
for (IgnLines::iterator lit = fnit->second.begin(); lit != fnit->second.end(); ++lit) {
|
||||
it->second.insert(*lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastIt = it->second.begin();
|
||||
m_lastEnd = it->second.end();
|
||||
}
|
||||
|
||||
public:
|
||||
inline static V3ConfigIgnores& singleton() { return s_singleton; }
|
||||
|
||||
void addIgnore(V3ErrorCode code, string filename, int lineno, bool on) {
|
||||
void addIgnore(V3ErrorCode code, string wildname, int lineno, bool on) {
|
||||
// Insert
|
||||
IgnLines* linesp = findLines(filename);
|
||||
UINFO(9,"config addIgnore "<<filename<<":"<<lineno<<", "<<code<<", "<<on<<endl);
|
||||
IgnLines* linesp = findWilds(wildname);
|
||||
UINFO(9,"config addIgnore "<<wildname<<":"<<lineno<<", "<<code<<", "<<on<<endl);
|
||||
linesp->insert(V3ConfigLine(code, lineno, on));
|
||||
if (m_lastFilename == filename) {
|
||||
// Flush the match cache, due to a change in the rules.
|
||||
m_lastFilename = " ";
|
||||
}
|
||||
// Flush the match cache, due to a change in the rules.
|
||||
m_ignFiles.clear();
|
||||
m_lastFilename = " ";
|
||||
}
|
||||
inline void applyIgnores(FileLine* filelinep) {
|
||||
// HOT routine, called each parsed token line
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2010-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+382
-220
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "V3Const.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3Width.h"
|
||||
#include "V3Signed.h"
|
||||
#include "V3Simulate.h"
|
||||
|
||||
//######################################################################
|
||||
@@ -93,7 +92,7 @@ public:
|
||||
class ConstVisitor : public AstNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// ** only when m_warn/m_expensive is set. If state is needed other times,
|
||||
// ** only when m_warn/m_doExpensive is set. If state is needed other times,
|
||||
// ** must track down everywhere V3Const is called and make sure no overlaps.
|
||||
// AstVar::user4p -> Used by ConstVarMarkVisitor/ConstVarFindVisitor
|
||||
// AstJumpLabel::user4 -> bool. Set when AstJumpGo uses this label
|
||||
@@ -103,8 +102,9 @@ private:
|
||||
bool m_required; // If true, must become a constant
|
||||
bool m_wremove; // Inside scope, no assignw removal
|
||||
bool m_warn; // Output warnings
|
||||
bool m_cpp; // C++ conversions only
|
||||
bool m_expensive; // Enable computationally expensive optimizations
|
||||
bool m_doExpensive; // Enable computationally expensive optimizations
|
||||
bool m_doNConst; // Enable non-constant-child simplifications
|
||||
bool m_doV; // Verilog, not C++ conversion
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNode* m_scopep; // Current scope
|
||||
|
||||
@@ -289,13 +289,61 @@ private:
|
||||
// SEL(EXTEND(any,width,...),(width-1),0) -> ...
|
||||
// Since select's return unsigned, this is always an extend
|
||||
AstExtend* extendp = nodep->fromp()->castExtend();
|
||||
return (!m_cpp
|
||||
&& extendp
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
||||
);
|
||||
if (!(m_doV
|
||||
&& extendp
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
&& (int)nodep->widthConst()==extendp->lhsp()->width()
|
||||
)) return false;
|
||||
replaceWChild(nodep, extendp->lhsp()); nodep=NULL;
|
||||
return true;
|
||||
}
|
||||
bool operandSelBiLower(AstSel* nodep) {
|
||||
// SEL(ADD(a,b),(width-1),0) -> ADD(SEL(a),SEL(b))
|
||||
// Add or any operation which doesn't care if we discard top bits
|
||||
AstNodeBiop* bip = nodep->fromp()->castNodeBiop();
|
||||
if (!(m_doV
|
||||
&& bip
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
)) return false;
|
||||
if (debug()>=9) nodep->dumpTree(cout,"SEL(BI)-in:");
|
||||
AstNode* bilhsp = bip->lhsp()->unlinkFrBack();
|
||||
AstNode* birhsp = bip->rhsp()->unlinkFrBack();
|
||||
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
|
||||
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
|
||||
if (debug()>=9) bip->dumpTree(cout,"SEL(BI)-ou:");
|
||||
replaceWChild(nodep, bip); nodep=NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operandBiExtendConst(AstNodeBiop* nodep) {
|
||||
// Loop unrolling likes standalone compares
|
||||
// EQ(EXTEND(xx{width3}), const{width32}) -> EQ(xx{3},const{3})
|
||||
// Beware that the constant must have zero bits (+ 1 if signed) or compare
|
||||
// would be incorrect
|
||||
AstExtend* extendp = nodep->lhsp()->castExtend();
|
||||
if (!extendp) return false;
|
||||
AstNode* smallerp = extendp->lhsp();
|
||||
int subsize = smallerp->width();
|
||||
AstConst* constp = nodep->rhsp()->castConst();
|
||||
if (!constp) return false;
|
||||
if (!constp->num().isBitsZero(constp->width()-1, subsize)) return false;
|
||||
//
|
||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-in:");
|
||||
smallerp->unlinkFrBack();
|
||||
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
|
||||
nodep->lhsp(smallerp);
|
||||
|
||||
constp->unlinkFrBack();
|
||||
V3Number num (constp->fileline(), subsize);
|
||||
num.opAssign(constp->num());
|
||||
nodep->rhsp(new AstConst(constp->fileline(), num));
|
||||
constp->deleteTree(); constp=NULL;
|
||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
|
||||
return true;
|
||||
}
|
||||
|
||||
AstNode* afterComment(AstNode* nodep) {
|
||||
@@ -724,7 +772,7 @@ private:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (!m_cpp && nodep->lhsp()->castConcat()) {
|
||||
else if (m_doV && nodep->lhsp()->castConcat()) {
|
||||
bool need_temp = false;
|
||||
if (m_warn && !nodep->castAssignDly()) { // Is same var on LHS and RHS?
|
||||
// Note only do this (need user4) when m_warn, which is
|
||||
@@ -773,7 +821,9 @@ private:
|
||||
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
||||
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1ap);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn2ap);
|
||||
} else {
|
||||
if (!m_modp) nodep->v3fatalSrc("Not under module");
|
||||
@@ -804,12 +854,16 @@ private:
|
||||
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
// This order matters
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1ap);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn2ap);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1bp);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn2bp);
|
||||
}
|
||||
if (debug()>=9) newp->dumpTreeAndNext(cout," _new: ");
|
||||
if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: ");
|
||||
nodep->addNextHere(newp);
|
||||
// Cleanup
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
@@ -855,10 +909,10 @@ private:
|
||||
// Run it - may be unoptimizable due to large for loop, etc
|
||||
simvis.mainParamEmulate(nodep);
|
||||
if (!simvis.optimizable()) {
|
||||
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
|
||||
AstNode* errorp = simvis.whyNotNodep(); if (!errorp) errorp = nodep;
|
||||
nodep->v3error("Expecting expression to be constant, but can't determine constant for "
|
||||
<<nodep->prettyTypeName()<<endl
|
||||
<<V3Error::msgPrefix()<<errorp->fileline()<<"... Location of non-constant "
|
||||
<<V3Error::msgPrefix(V3ErrorCode::EC_ERROR,false)<<errorp->fileline()<<"... Location of non-constant "
|
||||
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
|
||||
replaceZero(nodep); nodep=NULL;
|
||||
} else {
|
||||
@@ -1060,16 +1114,50 @@ private:
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
void replaceSelIntoBiop(AstSel* nodep) {
|
||||
// SEL(BUFIF1(a,b),1,bit) => BUFIF1(SEL(a,1,bit),SEL(b,1,bit))
|
||||
AstNodeBiop* fromp = nodep->fromp()->unlinkFrBack()->castNodeBiop();
|
||||
if (!fromp) nodep->v3fatalSrc("Called on non biop");
|
||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||
//
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
AstNode* birhsp = fromp->rhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->rhsp(new AstSel(nodep->fileline(),
|
||||
birhsp, lsbp, widthp));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
void replaceSelIntoUniop(AstSel* nodep) {
|
||||
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
|
||||
AstNodeUniop* fromp = nodep->fromp()->unlinkFrBack()->castNodeUniop();
|
||||
if (!fromp) nodep->v3fatalSrc("Called on non biop");
|
||||
AstNode* lsbp = nodep->lsbp()->unlinkFrBack();
|
||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||
//
|
||||
AstNode* bilhsp = fromp->lhsp()->unlinkFrBack();
|
||||
//
|
||||
fromp->lhsp(new AstSel(nodep->fileline(),
|
||||
bilhsp, lsbp->cloneTree(true), widthp->cloneTree(true)));
|
||||
fromp->widthSignedFrom(nodep);
|
||||
nodep->replaceWith(fromp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (!nodep->varp()) nodep->v3fatalSrc("Not linked");
|
||||
bool did=false;
|
||||
if (!m_cpp && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
|
||||
if (m_doV && nodep->varp()->hasSimpleInit() && !nodep->backp()->castAttrOf()) {
|
||||
//if (debug()) nodep->varp()->valuep()->dumpTree(cout," visitvaref: ");
|
||||
nodep->varp()->valuep()->iterateAndNext(*this);
|
||||
if (operandConst(nodep->varp()->valuep())
|
||||
&& !nodep->lvalue()
|
||||
&& ((v3Global.opt.oConst() && !m_params // Can reduce constant wires into equations
|
||||
&& ((!m_params // Can reduce constant wires into equations
|
||||
&& m_doNConst
|
||||
&& v3Global.opt.oConst()
|
||||
&& !nodep->varp()->isSigPublic())
|
||||
|| nodep->varp()->isParam())) {
|
||||
AstConst* constp = nodep->varp()->valuep()->castConst();
|
||||
@@ -1106,7 +1194,7 @@ private:
|
||||
// Someday if lower is constant, convert to quoted "string".
|
||||
|
||||
virtual void visit(AstAttrOf* nodep, AstNUser*) {
|
||||
// Don't iterate children, don't want to loose VarRef.
|
||||
// Don't iterate children, don't want to lose VarRef.
|
||||
if (nodep->attrType()==AstAttrType::EXPR_BITS) {
|
||||
if (!nodep->fromp() || !nodep->fromp()->widthMin()) nodep->v3fatalSrc("Unsized expression");
|
||||
V3Number num (nodep->fileline(), 32, nodep->fromp()->widthMin());
|
||||
@@ -1121,8 +1209,9 @@ private:
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->sensp()->castConst()
|
||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam())) {
|
||||
if (m_doNConst
|
||||
&& (nodep->sensp()->castConst()
|
||||
|| (nodep->varrefp() && nodep->varrefp()->varp()->isParam()))) {
|
||||
// Constants in sensitivity lists may be removed (we'll simplify later)
|
||||
if (nodep->isClocked()) { // A constant can never get a pos/negexge
|
||||
if (onlySenItemInSenTree(nodep)) {
|
||||
@@ -1135,7 +1224,7 @@ private:
|
||||
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
} else if (nodep->sensp()->castNot()) {
|
||||
} else if (m_doNConst && nodep->sensp()->castNot()) {
|
||||
// V3Gate may propagate NOTs into clocks... Just deal with it
|
||||
AstNode* sensp = nodep->sensp();
|
||||
AstNode* lastSensp = sensp;
|
||||
@@ -1202,7 +1291,7 @@ private:
|
||||
|
||||
virtual void visit(AstSenTree* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_expensive) {
|
||||
if (m_doExpensive) {
|
||||
//cout<<endl; nodep->dumpTree(cout,"ssin: ");
|
||||
// Optimize ideas for the future:
|
||||
// SENTREE(... SENGATE(x,a), SENGATE(SENITEM(x),b) ...) => SENGATE(x,OR(a,b))
|
||||
@@ -1305,22 +1394,21 @@ private:
|
||||
// Zero elimination
|
||||
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
replaceNodeAssign(nodep);
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep, AstNUser*) {
|
||||
// Don't perform any optimizations, keep the alias around
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (replaceNodeAssign(nodep)) return;
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
AstNodeVarRef* varrefp = nodep->lhsp()->castVarRef(); // Not VarXRef, as different refs may set different values to each hierarchy
|
||||
if (m_wremove
|
||||
if (m_wremove && !m_params && m_doNConst
|
||||
&& m_modp && operandConst(nodep->rhsp())
|
||||
&& !nodep->rhsp()->castConst()->num().isFourState()
|
||||
&& varrefp // Don't do messes with BITREFs/ARRAYREFs
|
||||
&& !varrefp->varp()->valuep() // Not already constified
|
||||
&& !varrefp->varScopep() // Not scoped (or each scope may have different initial value)
|
||||
&& !m_params) {
|
||||
&& !varrefp->varScopep()) { // Not scoped (or each scope may have different initial value)
|
||||
// ASSIGNW (VARREF, const) -> INITIAL ( ASSIGN (VARREF, const) )
|
||||
UINFO(4,"constAssignW "<<nodep<<endl);
|
||||
// Make a initial assignment
|
||||
@@ -1340,77 +1428,79 @@ private:
|
||||
|
||||
virtual void visit(AstNodeIf* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (AstConst* constp = nodep->condp()->castConst()) {
|
||||
AstNode* keepp = NULL;
|
||||
if (constp->isZero()) {
|
||||
UINFO(4,"IF(0,{any},{x}) => {x}: "<<nodep<<endl);
|
||||
keepp = nodep->elsesp();
|
||||
} else {
|
||||
UINFO(4,"IF(!0,{x},{any}) => {x}: "<<nodep<<endl);
|
||||
keepp = nodep->ifsp();
|
||||
if (m_doNConst) {
|
||||
if (AstConst* constp = nodep->condp()->castConst()) {
|
||||
AstNode* keepp = NULL;
|
||||
if (constp->isZero()) {
|
||||
UINFO(4,"IF(0,{any},{x}) => {x}: "<<nodep<<endl);
|
||||
keepp = nodep->elsesp();
|
||||
} else {
|
||||
UINFO(4,"IF(!0,{x},{any}) => {x}: "<<nodep<<endl);
|
||||
keepp = nodep->ifsp();
|
||||
}
|
||||
if (keepp) {
|
||||
keepp->unlinkFrBackWithNext();
|
||||
nodep->replaceWith(keepp);
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
if (keepp) {
|
||||
keepp->unlinkFrBackWithNext();
|
||||
nodep->replaceWith(keepp);
|
||||
} else {
|
||||
nodep->unlinkFrBack();
|
||||
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
|
||||
// Empty block, remove it
|
||||
// Note if we support more C++ then there might be side effects in the condition itself
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (!afterComment(nodep->ifsp())) {
|
||||
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
|
||||
AstNode* condp = nodep->condp();
|
||||
AstNode* elsesp = nodep->elsesp();
|
||||
condp->unlinkFrBackWithNext();
|
||||
elsesp->unlinkFrBackWithNext();
|
||||
if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment
|
||||
nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible
|
||||
nodep->addIfsp(elsesp);
|
||||
}
|
||||
else if (((nodep->condp()->castNot() && nodep->condp()->width()==1)
|
||||
|| (nodep->condp()->castLogNot()))
|
||||
&& nodep->ifsp() && nodep->elsesp()) {
|
||||
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
|
||||
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
|
||||
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
||||
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||
ifp->branchPred(nodep->branchPred().invert());
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (ifSameAssign(nodep)) {
|
||||
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
|
||||
AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign();
|
||||
AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign();
|
||||
ifp->unlinkFrBack();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* truep = ifp->rhsp()->unlinkFrBack();
|
||||
AstNode* falsep = elsep->rhsp()->unlinkFrBack();
|
||||
ifp->rhsp(new AstCond(truep->fileline(),
|
||||
condp, truep, falsep));
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
||||
&& operandIfIf(nodep)) {
|
||||
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
||||
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
|
||||
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
|
||||
condp, lowerCondp));
|
||||
lowerIfp->replaceWith(lowerIfsp);
|
||||
lowerIfp->deleteTree(); lowerIfp=NULL;
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
}
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
|
||||
// Empty block, remove it
|
||||
// Note if we support more C++ then there might be side effects in the condition itself
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (!afterComment(nodep->ifsp())) {
|
||||
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
|
||||
AstNode* condp = nodep->condp();
|
||||
AstNode* elsesp = nodep->elsesp();
|
||||
condp->unlinkFrBackWithNext();
|
||||
elsesp->unlinkFrBackWithNext();
|
||||
if (nodep->ifsp()) { nodep->ifsp()->unlinkFrBackWithNext()->deleteTree(); } // Must have been comment
|
||||
nodep->condp(new AstLogNot(condp->fileline(), condp)); // LogNot, as C++ optimization also possible
|
||||
nodep->addIfsp(elsesp);
|
||||
}
|
||||
else if (((nodep->condp()->castNot() && nodep->condp()->width()==1)
|
||||
|| (nodep->condp()->castLogNot()))
|
||||
&& nodep->ifsp() && nodep->elsesp()) {
|
||||
UINFO(4,"IF(NOT {x}) => IF(x) swapped if/else"<<nodep<<endl);
|
||||
AstNode* condp = nodep->condp()->castNot()->lhsp()->unlinkFrBackWithNext();
|
||||
AstNode* ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
||||
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||
ifp->branchPred(nodep->branchPred().invert());
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (ifSameAssign(nodep)) {
|
||||
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
|
||||
AstNodeAssign* ifp = nodep->ifsp()->castNodeAssign();
|
||||
AstNodeAssign* elsep = nodep->elsesp()->castNodeAssign();
|
||||
ifp->unlinkFrBack();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* truep = ifp->rhsp()->unlinkFrBack();
|
||||
AstNode* falsep = elsep->rhsp()->unlinkFrBack();
|
||||
ifp->rhsp(new AstCond(truep->fileline(),
|
||||
condp, truep, falsep));
|
||||
nodep->replaceWith(ifp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
|
||||
&& operandIfIf(nodep)) {
|
||||
UINFO(0,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
||||
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
|
||||
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
|
||||
condp, lowerCondp));
|
||||
lowerIfp->replaceWith(lowerIfsp);
|
||||
lowerIfp->deleteTree(); lowerIfp=NULL;
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1423,7 +1513,7 @@ private:
|
||||
for (AstNode* argp = nodep->exprsp(); argp; argp=argp->nextp()) {
|
||||
if (argp->castConst()) { anyconst=true; break; }
|
||||
}
|
||||
if (anyconst) {
|
||||
if (m_doNConst && anyconst) {
|
||||
//UINFO(9," Display in "<<nodep->text()<<endl);
|
||||
string dispout = "";
|
||||
string fmt = "";
|
||||
@@ -1434,7 +1524,7 @@ private:
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
fmt = ch;
|
||||
} else if (inPct && isdigit(ch)) {
|
||||
} else if (inPct && (isdigit(ch) || ch=='.')) {
|
||||
fmt += ch;
|
||||
} else if (inPct) {
|
||||
inPct = false;
|
||||
@@ -1450,7 +1540,7 @@ private:
|
||||
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++) {
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
||||
if (*pos == '%') fmt += '%';
|
||||
fmt += *pos;
|
||||
}
|
||||
@@ -1486,14 +1576,16 @@ private:
|
||||
|
||||
virtual void visit(AstWhile* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->condp()->isZero()) {
|
||||
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
||||
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
if (m_doNConst) {
|
||||
if (nodep->condp()->isZero()) {
|
||||
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
||||
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
|
||||
else nodep->unlinkFrBack();
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1501,12 +1593,20 @@ private:
|
||||
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
|
||||
virtual void visit(AstNodePreSel* nodep, AstNUser*) {}
|
||||
|
||||
// Ignored, can eliminate early
|
||||
virtual void visit(AstSysIgnore* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_doNConst) {
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----
|
||||
// Jump elimination
|
||||
|
||||
virtual void visit(AstJumpGo* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (m_expensive) { nodep->labelp()->user4(true); }
|
||||
if (m_doExpensive) { nodep->labelp()->user4(true); }
|
||||
}
|
||||
|
||||
virtual void visit(AstJumpLabel* nodep, AstNUser*) {
|
||||
@@ -1515,7 +1615,7 @@ private:
|
||||
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
|
||||
nodep->iterateChildren(*this);
|
||||
// AstJumpGo's below here that point to this node will set user4
|
||||
if (m_expensive && !nodep->user4()) {
|
||||
if (m_doExpensive && !nodep->user4()) {
|
||||
UINFO(4,"JUMPLABEL => unused "<<nodep<<endl);
|
||||
AstNode* underp = NULL;
|
||||
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
@@ -1546,78 +1646,81 @@ private:
|
||||
|
||||
// Lint Checks
|
||||
// v--- *1* These ops are always first, as we warn before replacing
|
||||
// v--- *V* This op is a verilog op, ignore when in m_cpp mode
|
||||
// v--- *V* This op is a verilog op, only in m_doV mode
|
||||
// v--- *C* This op works on all constant children, allowed in m_doConst mode
|
||||
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
|
||||
// Generic constants on both side. Do this first to avoid other replacements
|
||||
TREEOP("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOP("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
// Zero on one side or the other
|
||||
TREEOP("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstDiv {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstDivS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstMul {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstMulS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstPow {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstPowS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
|
||||
TREEOP("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstMul {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP("AstMulS {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstSub {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstXor {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstXnor {$lhsp, $rhsp.isZero}", "AstNot{$lhsp}");
|
||||
TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstDiv {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstDivS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMul {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMulS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstPow {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstPowS {$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstOr {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstShiftL{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstShiftR{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
|
||||
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstMul {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstMulS {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstOr {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstShiftL{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstShiftR{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstShiftRS{$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstSub {$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
|
||||
TREEOP("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstOr {$lhsp.isAllOnes, $rhsp}", "replaceWLhs(nodep)"); //->allOnes
|
||||
TREEOP("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
||||
TREEOP("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
||||
TREEOP("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
|
||||
TREEOP("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
|
||||
TREEOP("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP ("AstAnd {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp.isNeqZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstOr {$lhsp.isAllOnes, $rhsp}", "replaceWLhs(nodep)"); //->allOnes
|
||||
TREEOP ("AstLogOr {$lhsp.isNeqZero, $rhsp}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isAllOnes}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isNeqZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstOr {$lhsp, $rhsp.isAllOnes}", "replaceWRhs(nodep)"); //->allOnes
|
||||
TREEOP ("AstLogOr {$lhsp, $rhsp.isNeqZero}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstXor {$lhsp.isAllOnes, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP ("AstXnor {$lhsp.isAllOnes, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstMul {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstMulS {$lhsp.isOne, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstDiv {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstDivS {$lhsp, $rhsp.isOne}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstMul {operandIsPowTwo($lhsp), $rhsp}", "replaceMulShift(nodep)"); // a*2^n -> a<<n
|
||||
TREEOP ("AstDiv {$lhsp, operandIsPowTwo($rhsp)}", "replaceDivShift(nodep)"); // a/2^n -> a>>n
|
||||
TREEOP ("AstPow {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
TREEOP ("AstPowS {operandIsTwo($lhsp), $rhsp}", "replacePowShift(nodep)"); // 2**a == 1<<a
|
||||
// Trinary ops
|
||||
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
|
||||
TREEOP("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOP("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOP("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
|
||||
TREEOP("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
|
||||
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstOr {$condp, $expr2p}"); // a?1:b == a|b
|
||||
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstAnd{$condp, $expr1p}"); // a?b:0 == a&b
|
||||
TREEOP("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~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.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOP ("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOPC("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOPC("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
|
||||
TREEOP ("AstCond{$condp->castNot(), $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstOr {$condp, $expr2p}"); // a?1:b == a|b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstAnd{$condp, $expr1p}"); // a?b:0 == a&b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~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())");
|
||||
// Prefer constants on left, since that often needs a shift, it lets constant red remove the shift
|
||||
TREEOP("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
||||
TREEOP("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
|
||||
TREEOP("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
||||
TREEOP("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
|
||||
TREEOP("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
|
||||
TREEOP ("AstNodeBiCom{!$lhsp.castConst, $rhsp.castConst}", "swapSides(nodep)");
|
||||
TREEOP ("AstNodeBiComAsv{operandAsvConst(nodep)}", "replaceAsv(nodep)");
|
||||
TREEOP ("AstNodeBiComAsv{operandAsvSame(nodep)}", "replaceAsv(nodep)");
|
||||
TREEOP ("AstNodeBiComAsv{operandAsvLUp(nodep)}", "replaceAsvLUp(nodep)");
|
||||
TREEOP ("AstNodeBiComAsv{operandAsvRUp(nodep)}", "replaceAsvRUp(nodep)");
|
||||
// v--- *1* as These ops are always first, as we warn before replacing
|
||||
TREEOP1("AstLt {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,0)");
|
||||
TREEOP1("AstGte {$lhsp, $rhsp.isZero}", "replaceNumSigned(nodep,1)");
|
||||
@@ -1666,33 +1769,46 @@ private:
|
||||
TREEOP ("AstShiftL{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
|
||||
// Compress out EXTENDs to appease loop unroller
|
||||
TREEOPV("AstEq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstNeq {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstGt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstGte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstLt {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstLte {$lhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
// 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)");
|
||||
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 ("AstEqD {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 ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqD {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
|
||||
// Comparison against 1'b0/1'b1; must be careful about widths.
|
||||
// These use Not, so must be Verilog only
|
||||
@@ -1743,18 +1859,33 @@ private:
|
||||
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
|
||||
// Next rule because AUTOINST puts the width of bits in
|
||||
// to pins, even when the widths are exactly the same across the hierarchy.
|
||||
TREEOPV("AstSel{operandSelExtend(nodep)}", "replaceWChild(nodep, nodep->fromp()->castExtend()->lhsp())");
|
||||
TREEOPV("AstSel{operandSelExtend(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{operandSelFull(nodep)}", "replaceWChild(nodep, nodep->fromp())");
|
||||
TREEOPV("AstSel{$fromp.castSel}", "replaceSelSel(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castAdd, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castAnd, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castOr, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPC("AstSel{$fromp.castConst, $lsbp.castConst, $widthp.castConst, }", "replaceConst(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castConcat, $lsbp.castConst, $widthp.castConst, }", "replaceSelConcat(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.isOne, }", "replaceSelReplicate(nodep)");
|
||||
// V3Tristate requires selects below BufIf1.
|
||||
// Also do additional operators that are bit-independent, but only definite
|
||||
// win if bit select is a constant (otherwise we may need to compute bit index several times)
|
||||
TREEOPV("AstSel{$fromp.castBufIf1}", "replaceSelIntoBiop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castNot}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castAnd,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castOr,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castXor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
TREEOPV("AstSel{$fromp.castXnor,$lhsp.castConst}", "replaceSelIntoUniop(nodep)");
|
||||
// Conversions
|
||||
TREEOPV("AstRedXnor{$lhsp}", "AstNot{AstRedXor{$lhsp}}"); // Just eliminate XNOR's
|
||||
TREEOPV("AstLogIf {$lhsp, $rhsp}", "AstLogOr{AstLogNot{$lhsp},$rhsp}");
|
||||
TREEOPV("AstLogIff{$lhsp, $rhsp}", "AstLogNot{AstXor{$lhsp,$rhsp}}");
|
||||
// Strings
|
||||
TREEOP ("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
|
||||
TREEOPC("AstCvtPackString{$lhsp.castConst}", "replaceConstString(nodep, nodep->lhsp()->castConst()->num().toString())");
|
||||
|
||||
|
||||
// Possible futures:
|
||||
@@ -1781,15 +1912,37 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
// Processing Mode Enum
|
||||
enum ProcMode {
|
||||
PROC_PARAMS,
|
||||
PROC_LIVE,
|
||||
PROC_V_WARN,
|
||||
PROC_V_NOWARN,
|
||||
PROC_V_EXPENSIVE,
|
||||
PROC_CPP
|
||||
};
|
||||
|
||||
// CONSTUCTORS
|
||||
ConstVisitor(bool params, bool expensive, bool warn, bool cpp) {
|
||||
m_params = params; m_required = params;
|
||||
m_expensive = expensive;
|
||||
m_warn = warn;
|
||||
m_cpp = cpp;
|
||||
m_wremove = true;
|
||||
ConstVisitor(ProcMode pmode) {
|
||||
m_params = false;
|
||||
m_required = false;
|
||||
m_doExpensive = false;
|
||||
m_doNConst = false;
|
||||
m_doV = false;
|
||||
m_warn = false;
|
||||
m_wremove = true; // Overridden in visitors
|
||||
m_modp = NULL;
|
||||
m_scopep = NULL;
|
||||
//
|
||||
switch (pmode) {
|
||||
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true; m_required = true; break;
|
||||
case PROC_LIVE: break;
|
||||
case PROC_V_WARN: m_doV = true; m_doNConst = true; m_warn = true; break;
|
||||
case PROC_V_NOWARN: m_doV = true; m_doNConst = true; break;
|
||||
case PROC_V_EXPENSIVE: m_doV = true; m_doNConst = true; m_doExpensive = true; break;
|
||||
case PROC_CPP: m_doV = false; m_doNConst = true; break;
|
||||
default: v3fatalSrc("Bad case"); break;
|
||||
}
|
||||
}
|
||||
virtual ~ConstVisitor() {}
|
||||
AstNode* mainAcceptEdit(AstNode* nodep) {
|
||||
@@ -1806,7 +1959,7 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
||||
// Resize even if the node already has a width, because burried in the treee we may
|
||||
// have a node we just created with signing, etc, that isn't sized yet.
|
||||
nodep = V3Width::widthParamsEdit(nodep); // Make sure we've sized everything first
|
||||
ConstVisitor visitor (true,false,false,false);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_PARAMS);
|
||||
if (AstVar* varp=nodep->castVar()) {
|
||||
// If a var wants to be constified, it's really a param, and
|
||||
// we want the value to be constant. We aren't passed just the
|
||||
@@ -1820,34 +1973,43 @@ AstNode* V3Const::constifyParamsEdit(AstNode* nodep) {
|
||||
return nodep;
|
||||
}
|
||||
|
||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (false,true,false,false);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
void V3Const::constifyAllLint(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (false,false,true,false);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
void V3Const::constifyCpp(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (false,false,false,true);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_CPP);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyEdit(AstNode* nodep) {
|
||||
ConstVisitor visitor (false,false,false,false);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_NOWARN);
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
return nodep;
|
||||
}
|
||||
|
||||
void V3Const::constifyAllLive(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
// This only pushes constants up, doesn't make any other edits
|
||||
// IE doesn't prune dead statements, as we need to do some usability checks after this
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
// Only call from Verilator.cpp, as it uses user#'s
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
|
||||
ConstVisitor visitor (false,true,false,false);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
|
||||
nodep = visitor.mainAcceptEdit(nodep);
|
||||
return nodep;
|
||||
}
|
||||
|
||||
+3
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -34,6 +34,8 @@ public:
|
||||
// Force this cell node's parameter list to become a constant
|
||||
// Return new node that may have replaced nodep
|
||||
static AstNode* constifyParamsEdit(AstNode* nodep);
|
||||
// Only do constant pushing, without removing dead logic
|
||||
static void constifyAllLive(AstNetlist* nodep);
|
||||
// Everything that's possible
|
||||
static void constifyAll(AstNetlist* nodep);
|
||||
// Also, warn
|
||||
|
||||
+7
-5
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -81,10 +81,12 @@ private:
|
||||
string prettyName = nodep->prettyName();
|
||||
if (!nodep->isToggleCoverable())
|
||||
return "Not relevant signal type";
|
||||
if (prettyName.c_str()[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
if (!v3Global.opt.coverageUnderscore()) {
|
||||
if (prettyName.c_str()[0] == '_')
|
||||
return "Leading underscore";
|
||||
if (prettyName.find("._") != string::npos)
|
||||
return "Inlined leading underscore";
|
||||
}
|
||||
if ((nodep->width()*nodep->arrayElements()) > 256) return "Wide bus/array > 256 bits";
|
||||
// We allow this, though tracing doesn't
|
||||
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -97,7 +97,7 @@ private:
|
||||
removep->unlinkFrBack(); pushDeletep(removep); removep=NULL;
|
||||
// Remove node from comparison so don't hit it again
|
||||
hashed.erase(dupit);
|
||||
m_statToggleJoins++;
|
||||
++m_statToggleJoins;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+15
-12
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -95,31 +95,37 @@ private:
|
||||
// VISITORS
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->modp()->user1(nodep->modp()->user1() + 1);
|
||||
nodep->modp()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->varScopep()) {
|
||||
nodep->varScopep()->user1(nodep->varScopep()->user1() + 1);
|
||||
nodep->varScopep()->varp()->user1(nodep->varScopep()->varp()->user1() + 1);
|
||||
nodep->varScopep()->user1Inc();
|
||||
nodep->varScopep()->varp()->user1Inc();
|
||||
}
|
||||
if (nodep->varp()) {
|
||||
nodep->varp()->user1(nodep->varp()->user1() + 1);
|
||||
nodep->varp()->user1Inc();
|
||||
}
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRefDType* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1(nodep->packagep()->user1() + 1);
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
@@ -145,13 +151,10 @@ private:
|
||||
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*) {
|
||||
if (nodep->isOutputter()) m_sideEffect=true;
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+3
-7
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -224,7 +224,6 @@ private:
|
||||
}
|
||||
//
|
||||
//=== Setting/not setting boolean: __Vdlyvset__
|
||||
bool sharedVset = false;
|
||||
AstVarScope* setvscp;
|
||||
|
||||
if (nodep->user3p()) {
|
||||
@@ -232,9 +231,8 @@ private:
|
||||
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
|
||||
// This is good for code like:
|
||||
// for (i=0; i<5; i++) vector[i] <= something;
|
||||
sharedVset = true;
|
||||
setvscp = nodep->user3p()->castNode()->castVarScope();
|
||||
m_statSharedSet++;
|
||||
++m_statSharedSet;
|
||||
} else { // Create new one
|
||||
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
|
||||
@@ -345,9 +343,7 @@ private:
|
||||
m_nextDlyp = NULL;
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep, AstNUser*) {
|
||||
if (!nodep->user2()) { // Not done yet
|
||||
nodep->user2(true);
|
||||
|
||||
if (!nodep->user2Inc()) { // Not done yet
|
||||
if (m_inDly && nodep->lvalue()) {
|
||||
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
|
||||
markVarUsage(nodep->varScopep(), VU_DLY);
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+65
-19
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
@@ -55,9 +55,9 @@ public:
|
||||
}
|
||||
|
||||
// ACCESSORS
|
||||
int splitFilenum() { return m_splitFilenum; }
|
||||
int splitFilenum() const { return m_splitFilenum; }
|
||||
int splitFilenumInc() { m_splitSize = 0; return ++m_splitFilenum; }
|
||||
int splitSize() { return m_splitSize; }
|
||||
int splitSize() const { return m_splitSize; }
|
||||
void splitSizeInc(AstNode* nodep) { m_splitSize += EmitCBaseCounterVisitor(nodep).count(); }
|
||||
bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit() > 1
|
||||
&& v3Global.opt.outputSplit() < splitSize()); }
|
||||
@@ -127,6 +127,7 @@ public:
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
} else if (nodep->isWide()
|
||||
&& nodep->lhsp()->castVarRef()
|
||||
&& !nodep->rhsp()->castCMath()
|
||||
&& !nodep->rhsp()->castVarRef()
|
||||
&& !nodep->rhsp()->castArraySel()) {
|
||||
// Wide functions assign into the array directly, don't need separate assign statement
|
||||
@@ -149,6 +150,8 @@ public:
|
||||
if (decind) ofp()->blockDec();
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic*, AstNUser*) {
|
||||
}
|
||||
virtual void visit(AstCCall* nodep, AstNUser*) {
|
||||
puts(nodep->hiername());
|
||||
puts(nodep->funcp()->name());
|
||||
@@ -341,13 +344,11 @@ public:
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFClose* nodep, AstNUser*) {
|
||||
puts("if (");
|
||||
puts("VL_FCLOSE_I(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fclose (VL_CVT_Q_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); ");
|
||||
puts("); ");
|
||||
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()) {
|
||||
@@ -355,11 +356,35 @@ public:
|
||||
} else {
|
||||
puts("if (");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fflush (VL_CVT_Q_FP(");
|
||||
puts(") { fflush (VL_CVT_I_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); }\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSystemT* nodep, AstNUser*) {
|
||||
puts("(void)VL_SYSTEM_I");
|
||||
emitIQW(nodep->lhsp());
|
||||
puts("(");
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
puts(cvtToStr(nodep->lhsp()->widthWords()));
|
||||
putbs(", ");
|
||||
}
|
||||
checkMaxWords(nodep->lhsp());
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstSystemF* nodep, AstNUser*) {
|
||||
puts("VL_SYSTEM_I");
|
||||
emitIQW(nodep->lhsp());
|
||||
puts("(");
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
puts(cvtToStr(nodep->lhsp()->widthWords()));
|
||||
putbs(", ");
|
||||
}
|
||||
checkMaxWords(nodep->lhsp());
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep, AstNUser*) {
|
||||
puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n");
|
||||
}
|
||||
@@ -473,7 +498,7 @@ public:
|
||||
}
|
||||
visit(nodep->castNodeBiop(), vup);
|
||||
}
|
||||
virtual void visit(AstCast* nodep, AstNUser*) {
|
||||
virtual void visit(AstCCast* nodep, AstNUser*) {
|
||||
// Extending a value of the same word width is just a NOP.
|
||||
if (nodep->size()>VL_WORDSIZE) {
|
||||
puts("(QData)(");
|
||||
@@ -541,17 +566,20 @@ public:
|
||||
}
|
||||
for (int word=VL_WORDS_I(nodep->num().minWidth())-1; word>0; word--) {
|
||||
// Only 32 bits - llx + long long here just to appease CPP format warning
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x", (long long)(nodep->num().dataWord(word)));
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
|
||||
}
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x)", (long long)(nodep->num().dataWord(0)));
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
|
||||
} else if (nodep->isDouble()) {
|
||||
ofp()->printf("%.17g", nodep->num().toDouble());
|
||||
} else if (nodep->isQuad()) {
|
||||
vluint64_t num = nodep->toUQuad();
|
||||
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", (long long)num);
|
||||
else ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", (long long)num);
|
||||
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
|
||||
else ofp()->printf("VL_ULL(0x%" VL_PRI64 "x)", num);
|
||||
} else {
|
||||
uint32_t num = nodep->toUInt();
|
||||
// Only 32 bits - llx + long long here just to appease CPP format warning
|
||||
if (num<10) puts(cvtToStr(num));
|
||||
else ofp()->printf("0x%" VL_PRI64 "x", (long long)num);
|
||||
else ofp()->printf("0x%" VL_PRI64 "x", (vluint64_t)num);
|
||||
//Unneeded-Causes %lx format warnings:
|
||||
// if (!nodep->num().isSigned() && (num & (1UL<<31))) puts("U");
|
||||
}
|
||||
@@ -826,6 +854,8 @@ class EmitCImp : EmitCStmts {
|
||||
public:
|
||||
EmitCImp() {
|
||||
m_modp = NULL;
|
||||
m_slow = false;
|
||||
m_fast = false;
|
||||
}
|
||||
virtual ~EmitCImp() {}
|
||||
void main(AstNodeModule* modp, bool slow, bool fast);
|
||||
@@ -1208,6 +1238,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
switch (tolower(pos[0])) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
// Digits, like %5d, etc.
|
||||
vfmt += pos[0];
|
||||
inPct = true; // Get more digits
|
||||
@@ -1226,6 +1257,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
case 'h':
|
||||
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
|
||||
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
|
||||
case 'e': displayArg(nodep,&elistp,isScan, vfmt,'e'); break;
|
||||
case 'f': displayArg(nodep,&elistp,isScan, vfmt,'f'); break;
|
||||
case 'g': displayArg(nodep,&elistp,isScan, vfmt,'g'); break;
|
||||
case 'm': {
|
||||
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||
string suffix = scopenamep->scopePrettyName();
|
||||
@@ -1416,6 +1450,7 @@ void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
|
||||
// Need implementation here. Be careful of alignment code; needs to be uniquified
|
||||
// with module name to avoid multiple symbols.
|
||||
//emitVarList(modp->stmtsp(), EVL_ALL, modp->name());
|
||||
puts(""); // NOP for cppcheck, otherwise const function
|
||||
}
|
||||
|
||||
void EmitCImp::emitTextSection(AstType type) {
|
||||
@@ -1616,7 +1651,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
|
||||
puts("#include \""+topClassName()+"__Inlines.h\"\n");
|
||||
}
|
||||
// No __Dpi.h needed, we've shimmed it all into the interface
|
||||
if (v3Global.dpi()) {
|
||||
// do this before including our main .h file so that any references to
|
||||
// types defined in svdpi.h are available
|
||||
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// Declare foreign instances up front to make C++ happy
|
||||
puts("class "+symClassName()+";\n");
|
||||
@@ -1794,8 +1834,10 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
|
||||
|
||||
// Us
|
||||
puts("#include \""+ symClassName() +".h\"\n");
|
||||
|
||||
if (v3Global.dpi()) {
|
||||
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
|
||||
puts("\n");
|
||||
puts("#include \"verilated_dpi.h\"\n");
|
||||
}
|
||||
|
||||
if (optSystemPerl() && (splitFilenum() || !m_fast)) {
|
||||
@@ -2000,7 +2042,9 @@ class EmitCTrace : EmitCStmts {
|
||||
return varp->isSc() && varp->isScBv();
|
||||
}
|
||||
void emitTraceInitOne(AstTraceDecl* nodep) {
|
||||
if (nodep->isWide()) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->declDouble");
|
||||
} else if (nodep->isWide()) {
|
||||
puts("vcdp->declArray");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->declQuad ");
|
||||
@@ -2029,7 +2073,9 @@ class EmitCTrace : EmitCStmts {
|
||||
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|
||||
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
|
||||
? "full":"chg");
|
||||
if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->"+full+"Double");
|
||||
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
puts("vcdp->"+full+"Array");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->"+full+"Quad ");
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2010 by Wilson Snyder. This program is free software; you can
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user