mirror of
https://github.com/verilator/verilator.git
synced 2026-10-03 16:44:11 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
132f61e900 | ||
|
|
0e9be8eea0 | ||
|
|
96f5f66c26 | ||
|
|
bbed4d50ab | ||
|
|
4b7ee8267b | ||
|
|
f6a745a4c2 | ||
|
|
a23a5505c4 | ||
|
|
21030f0a4f | ||
|
|
d21824cbae | ||
|
|
124786ad1b | ||
|
|
f81daac9c0 | ||
|
|
db8e8392fa | ||
|
|
5bc2f87d3e | ||
|
|
de35c90847 | ||
|
|
bc813fddcc | ||
|
|
13c91f5fce | ||
|
|
ac4690d74b | ||
|
|
a1a8f17617 | ||
|
|
12be852a43 | ||
|
|
440fbef79b | ||
|
|
e1c221a4d5 | ||
|
|
e1f1c82d4e | ||
|
|
3c1b82255e | ||
|
|
6bd47b54df | ||
|
|
3261a45ec1 | ||
|
|
0ac116bb4e | ||
|
|
221e4ff6fe | ||
|
|
fe80499f9c | ||
|
|
d3d1f3ab60 | ||
|
|
264b888ef2 | ||
|
|
ba270e09a4 | ||
|
|
8281ee1520 | ||
|
|
75aab4e9d2 | ||
|
|
b532a47e4a | ||
|
|
77a3d683e3 | ||
|
|
c132d0e1fe | ||
|
|
1a6348f113 | ||
|
|
89ac6ab594 | ||
|
|
3d1012b73b | ||
|
|
c98ad79e68 | ||
|
|
82460b0da3 | ||
|
|
0bdc57a14a | ||
|
|
33780a09df | ||
|
|
a9c9d5ca4b | ||
|
|
ab07dbdb9d | ||
|
|
6dd6750985 | ||
|
|
59aa0f43d5 | ||
|
|
04ca6a4307 | ||
|
|
c7cbe11ba4 | ||
|
|
4794093aba | ||
|
|
46e300b2c5 | ||
|
|
c693e52f6c | ||
|
|
4e2ec09f9a | ||
|
|
cdbae456d5 | ||
|
|
379177d2f4 | ||
|
|
fb193d6172 | ||
|
|
16234bb713 | ||
|
|
3f14e649b5 | ||
|
|
c2e8062f84 | ||
|
|
5d3fef21b0 | ||
|
|
b64e1b4a49 | ||
|
|
89f414b185 | ||
|
|
47e13cfdf4 | ||
|
|
48d3ce46d8 | ||
|
|
89c8449ec0 | ||
|
|
331fcb633e | ||
|
|
bffc2233a0 | ||
|
|
393b5d48b2 | ||
|
|
6006cdff2c | ||
|
|
d6b10465f3 | ||
|
|
b3cf5c4f5f | ||
|
|
3862f2f022 | ||
|
|
38ab22bf1d | ||
|
|
ce16f7689d | ||
|
|
b06a329466 | ||
|
|
c5b24f3850 | ||
|
|
103b956581 | ||
|
|
63361fc56e | ||
|
|
1e9e334929 | ||
|
|
f30d71b0c5 | ||
|
|
fee4aba9ec | ||
|
|
f1960273a0 | ||
|
|
778564e63b | ||
|
|
cf6a69da27 | ||
|
|
960b2ed023 | ||
|
|
74420550e6 | ||
|
|
cb5887b376 | ||
|
|
41b40157d8 | ||
|
|
b11b693c08 | ||
|
|
256eb4bba0 | ||
|
|
77804b4d38 | ||
|
|
8c9ca7a1b3 | ||
|
|
9d055f8c13 | ||
|
|
3dacd87dfb | ||
|
|
691fbb0c42 | ||
|
|
c28a6eef3b | ||
|
|
17fed3fedd |
@@ -1,3 +1,5 @@
|
||||
\#*
|
||||
.#*
|
||||
*~
|
||||
*.old
|
||||
*.gz
|
||||
@@ -20,8 +22,10 @@ configure
|
||||
dddrun*
|
||||
doxygen-doc
|
||||
gdbrun*
|
||||
gmon.out
|
||||
internals.txt
|
||||
verilator.txt
|
||||
verilator_bin*
|
||||
verilator_coverage_bin*
|
||||
verilator.pc
|
||||
**/obj_dir/*
|
||||
|
||||
@@ -2,6 +2,78 @@ Revision history for Verilator
|
||||
|
||||
The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
* Verilator 3.914 2017-10-14
|
||||
|
||||
** Added new examples/ directory with appropriate examples. This replaces the
|
||||
old test_c and test_sc directories.
|
||||
|
||||
*** Add --getenv option for simplifying Makefiles.
|
||||
|
||||
*** Add --x-initial option for specifying initial value assignment behavior.
|
||||
|
||||
*** Add --no-relative-cfuncs and related default optimization, bug1224. [John Coiner]
|
||||
|
||||
*** Add /*verilator tag*/ for XML extraction applications. [Chris Randall]
|
||||
|
||||
**** The internal test_verilated test directory is moved to be part of test_regress.
|
||||
|
||||
**** The experimental VL_THREADED setting (only, not normal mode) now requires C++11.
|
||||
|
||||
**** Fix over-aggressive inlining, bug1223. [John Coiner]
|
||||
|
||||
**** Fix Ubuntu 17.10 issues, bug1223 partial. [John Coiner]
|
||||
|
||||
**** Fix compiler warning when WIDTH warning ignored on large compare.
|
||||
|
||||
**** Fix memory leak in VerilatedVcd dumps, bug1222 partial. [Shareef Jalloq]
|
||||
|
||||
**** Fix unnecessary Vdly variables, bug1224 partial. [John Coiner]
|
||||
|
||||
**** Fix conditional slices and add related optimizations.
|
||||
|
||||
**** Fix `` expansion of `defines, bug1225, bug1227, bug1228. [Odd Magne Reitan]
|
||||
|
||||
**** Fix -E duplicating output, bug1226. [Odd Magne Reitan]
|
||||
|
||||
**** Fix float-conversion warning, bug1229. [Robert Henry]
|
||||
|
||||
**** Fix MacOS portability, bug1230, bug1231. [Jeff Bush]
|
||||
|
||||
|
||||
* Verilator 3.912 2017-09-23
|
||||
|
||||
** Verilated headers no longer "use namespace std;"
|
||||
User's code without "std::" prefixes may need "use namespace std;" to compile.
|
||||
|
||||
*** Support or/and/xor array intrinsic methods, bug1210. [Mike Popoloski]
|
||||
|
||||
*** Support package export, bug1217. [Usuario Eda]
|
||||
|
||||
*** Fix ordering of arrayed cell wide connections, bug1202 partial. [Mike Popoloski]
|
||||
|
||||
**** Support module port parameters without defaults, bug 1213. [Mike Popoloski]
|
||||
|
||||
**** Add performance information to --stats file.
|
||||
|
||||
**** Simplify VL_CONST_W macro generation for faster compiles.
|
||||
|
||||
**** Fix LITENDIAN warning on arrayed cells, bug1202. [Mike Popoloski]
|
||||
|
||||
**** Fix enum ranges without colons, bug1204. [Mike Popoloski]
|
||||
|
||||
**** Fix GCC noreturn compile error, bug1209. [Mike Popoloski]
|
||||
|
||||
**** Fix constant function default parameters, bug1211. [Mike Popoloski]
|
||||
|
||||
**** Fix non-colon array of interface modports, bug1212. [Mike Popoloski]
|
||||
|
||||
**** Fix .name connections on interfaces, bug1214. [Mike Popoloski]
|
||||
|
||||
**** Fix wide array indices causing compile error.
|
||||
|
||||
**** Better optimize Shift-And, and replication constructs.
|
||||
|
||||
|
||||
* Verilator 3.910 2017-09-07
|
||||
|
||||
*** SystemPerl mode (-sp-deprecated) has been removed.
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
/cov_work/
|
||||
/logs/
|
||||
^Makefile$
|
||||
bin/verilator_bin.*
|
||||
bin/verilator_coverage_bin.*
|
||||
src/Makefile$
|
||||
src/Makefile_obj$
|
||||
include/verilated.mk$
|
||||
@@ -39,5 +41,6 @@ nodist/
|
||||
/vc_hdrs.h$
|
||||
/csrc/
|
||||
doxygen-doc/.*
|
||||
obj_dir/.*
|
||||
TAGS
|
||||
.*~
|
||||
|
||||
+55
-43
@@ -101,7 +101,9 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
SUBDIRS = src test_verilated test_c test_sc test_regress
|
||||
SUBDIRS = src test_regress \
|
||||
examples/hello_world_c examples/hello_world_sc \
|
||||
examples/tracing_c examples/tracing_sc \
|
||||
|
||||
INFOS = README README.html README.pdf internals.txt internals.html \
|
||||
internals.pdf verilator.txt verilator.html verilator.pdf \
|
||||
@@ -114,7 +116,11 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
*.in *.ac \
|
||||
Changes TODO \
|
||||
MANIFEST.SKIP \
|
||||
bin/* \
|
||||
bin/verilator \
|
||||
bin/verilator_coverage \
|
||||
bin/verilator_difftree \
|
||||
bin/verilator_includer \
|
||||
bin/verilator_profcfunc \
|
||||
doxygen-mainpage doxygen.config veripool-logo.png \
|
||||
install-sh configure mkinstalldirs *.pod \
|
||||
include/*.[chv]* \
|
||||
@@ -127,9 +133,10 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
src/vlcovgen \
|
||||
src/.gdbinit \
|
||||
src/*.pl src/*.pod \
|
||||
examples/*/.*ignore examples/*/Makefile* \
|
||||
examples/*/*.[chv]* examples/*/*.pl \
|
||||
test_*/.*ignore test_*/Makefile* test_*/*.cpp \
|
||||
test_*/*.pl test_*/*.v test_*/*.vc test_*/*.vh \
|
||||
test_verilated/vgen*.pl \
|
||||
test_regress/t/t*/*.sv* \
|
||||
test_regress/t/t*/*.v* \
|
||||
test_regress/t/t*/*/*.sv* \
|
||||
@@ -153,9 +160,9 @@ INST_PROJ_FILES = \
|
||||
include/vltstd/*.[chv]* \
|
||||
|
||||
INST_PROJ_BIN_FILES = \
|
||||
verilator_bin \
|
||||
verilator_bin_dbg \
|
||||
verilator_coverage_bin_dbg \
|
||||
bin/verilator_bin \
|
||||
bin/verilator_bin_dbg \
|
||||
bin/verilator_coverage_bin_dbg \
|
||||
|
||||
DISTFILES := $(DISTFILES_INC)
|
||||
|
||||
@@ -182,33 +189,33 @@ verilator_exe verilator_bin verilator_bin_dbg verilator_coverage_bin_dbg:
|
||||
msg_test: all_nomsg
|
||||
@echo "Build complete!"
|
||||
@echo
|
||||
@echo "Type 'make test' to test."
|
||||
@echo "Now type 'make test' to test."
|
||||
@echo
|
||||
|
||||
.PHONY:test
|
||||
.PHONY: test
|
||||
ifeq ($(CFG_WITH_LONGTESTS),yes) # Local... Else don't burden users
|
||||
test: test_c test_sc test_verilated test_regress
|
||||
test: smoke-test examples test_regress
|
||||
else
|
||||
test: test_c test_sc
|
||||
test: smoke-test examples
|
||||
endif
|
||||
@echo "Tests passed!"
|
||||
@echo
|
||||
@echo "Type 'make install' to install documentation."
|
||||
@echo "Now type 'make install' to install."
|
||||
@echo "Or type 'make' inside an examples subdirectory."
|
||||
@echo
|
||||
|
||||
test_c: all_nomsg
|
||||
@(cd test_c && $(MAKE))
|
||||
test_c_debug: all_nomsg
|
||||
@(cd test_c && $(MAKE) test_debug)
|
||||
test_sc: all_nomsg
|
||||
@(cd test_sc && $(MAKE))
|
||||
test_sc_debug: all_nomsg
|
||||
@(cd test_sc && $(MAKE) test_debug)
|
||||
test_verilated: all_nomsg
|
||||
@(cd test_verilated && $(MAKE))
|
||||
smoke-test: all_nomsg
|
||||
test_regress/t/t_a_first_cc.pl
|
||||
test_regress/t/t_a_first_sc.pl
|
||||
|
||||
test_regress: all_nomsg
|
||||
@(cd test_regress && $(MAKE))
|
||||
|
||||
examples: all_nomsg
|
||||
for p in examples/* ; do \
|
||||
$(MAKE) -C $$p VERILATOR_ROOT=`pwd` ; \
|
||||
done
|
||||
|
||||
info: $(INFOS)
|
||||
|
||||
# Use --no-split to avoid creating filenames > 14 chars.
|
||||
@@ -281,18 +288,16 @@ VL_INST_INC_SRCDIR_FILES = \
|
||||
include/vltstd/*.[chv]* \
|
||||
|
||||
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 \
|
||||
examples/*/*.[chv]* examples/*/Makefile* \
|
||||
|
||||
installbin:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator $(DESTDIR)$(bindir)/verilator )
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_coverage $(DESTDIR)$(bindir)/verilator_coverage )
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_profcfunc $(DESTDIR)$(bindir)/verilator_profcfunc )
|
||||
( $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin )
|
||||
( $(INSTALL_PROGRAM) verilator_bin_dbg $(DESTDIR)$(bindir)/verilator_bin_dbg )
|
||||
( $(INSTALL_PROGRAM) verilator_coverage_bin_dbg $(DESTDIR)$(bindir)/verilator_coverage_bin_dbg )
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_bin $(DESTDIR)$(bindir)/verilator_bin )
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_bin_dbg $(DESTDIR)$(bindir)/verilator_bin_dbg )
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_coverage_bin_dbg $(DESTDIR)$(bindir)/verilator_coverage_bin_dbg )
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
||||
|
||||
@@ -314,12 +319,13 @@ installdata:
|
||||
; 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_v
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/hello_world_c
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/hello_world_sc
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/tracing_c
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/examples/tracing_sc
|
||||
cd $(srcdir) \
|
||||
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/$$p; \
|
||||
done
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgconfigdir)
|
||||
$(INSTALL_DATA) verilator.pc $(DESTDIR)$(pkgconfigdir)
|
||||
@@ -331,15 +337,15 @@ uninstall:
|
||||
-cd $(DESTDIR)$(mandir)/man1 && rm -f $(VL_INST_MAN_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)
|
||||
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_DATA_SRCDIR_FILES)
|
||||
-rm $(DESTDIR)$(pkgconfigdir)/verilator.pc
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/bin
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/include
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_c
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_sc
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_sp
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_v
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/hello_world_c
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/hello_world_sc
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/tracing_c
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/tracing_sc
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)
|
||||
-rmdir $(DESTDIR)$(pkgconfigdir)
|
||||
@@ -358,8 +364,8 @@ INST_PROJ_CVS = cp_if_cvs_diff
|
||||
|
||||
install-project: dist
|
||||
@echo "Install-project to $(DIRPROJECT)"
|
||||
strip verilator_bin*
|
||||
strip verilator_coverage_bin*
|
||||
strip bin/verilator_bin*
|
||||
strip bin/verilator_coverage_bin*
|
||||
$(MAKE) install-project-quick
|
||||
for p in $(VL_INST_MAN_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
|
||||
@@ -382,8 +388,8 @@ endif
|
||||
|
||||
install-cadtools: dist
|
||||
@echo "Install-project to $(CAD_DIR)"
|
||||
strip verilator_bin*
|
||||
strip verilator_coverage_bin*
|
||||
strip bin/verilator_bin*
|
||||
strip bin/verilator_coverage_bin*
|
||||
$(MAKE) install-cadtools-quick
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1
|
||||
for p in $(VL_INST_MAN_FILES) ; do \
|
||||
@@ -421,12 +427,15 @@ CPPCHECK_INC = -I$(srcdir)/include -I$(srcdir)/src/obj_dbg -I$(srcdir)/src
|
||||
|
||||
cppcheck: $(CPPCHECK_DEP)
|
||||
%.cppcheck: %.cpp
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 $(CPPCHECK_INC) $<
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $<
|
||||
|
||||
ftp: info
|
||||
|
||||
install-msg:
|
||||
@echo "Installed!"
|
||||
@echo
|
||||
@echo "Installed binaries to $(DESTDIR)$(bindir)/verilator"
|
||||
@echo "Installed man to $(DESTDIR)$(mandir)/man1"
|
||||
@echo "Installed examples to $(DESTDIR)$(pkgdatadir)/examples"
|
||||
@echo
|
||||
@echo "For documentation see 'man verilator' or 'verilator --help'"
|
||||
@echo "For forums and to report bugs see http://www.veripool.org/verilator"
|
||||
@@ -454,7 +463,7 @@ endif
|
||||
maintainer-clean::
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "rebuilding the deleted files requires makeinfo."
|
||||
rm -f *.info* $(INFOS) configure
|
||||
rm -f *.info* *.1 $(INFOS) configure
|
||||
|
||||
clean mostlyclean distclean maintainer-clean maintainer-copy::
|
||||
for dir in $(SUBDIRS); do \
|
||||
@@ -468,10 +477,13 @@ clean mostlyclean distclean maintainer-clean::
|
||||
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
||||
rm -f *.ev *.evs *.ov *.ovs *.cv *.cvs *.ma *.mas
|
||||
rm -f *.tex
|
||||
rm -rf test_*/obj_dir
|
||||
rm -rf examples/*/obj_dir examples/*/logs
|
||||
|
||||
distclean maintainer-clean::
|
||||
rm -f Makefile config.status config.cache config.log TAGS
|
||||
rm -f verilator_bin* verilator_coverage_bin*
|
||||
rm -f bin/verilator_bin* bin/verilator_coverage_bin*
|
||||
rm -f include/verilated.mk include/verilated_config.h
|
||||
|
||||
TAGFILES=${srcdir}/*/*.cpp ${srcdir}/*/*.h ${srcdir}/*/*.in \
|
||||
|
||||
+8
-5
@@ -51,7 +51,7 @@ output (not Verilator itself) compiles under MSVC++ 2008 and newer.
|
||||
|
||||
=head1 INSTALLATION
|
||||
|
||||
For more details see
|
||||
For more details see
|
||||
L<http://www.veripool.org/projects/verilator/wiki/Installing>.
|
||||
|
||||
If you will be modifying Verilator, you should use the "git" method as it
|
||||
@@ -169,6 +169,9 @@ 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.
|
||||
|
||||
You may now wish to consult the examples directory. Type C<make> inside any
|
||||
example directory to run the example.
|
||||
|
||||
=back
|
||||
|
||||
=head1 USAGE DOCUMENTATION
|
||||
@@ -190,10 +193,10 @@ The directories in the kit after de-taring are as follows:
|
||||
include/verilated.v => Stub defines for linting
|
||||
include/verilated.mk => Common makefile
|
||||
src/ => Translator source code
|
||||
test_v => Example Verilog code for other test dirs
|
||||
test_c => Example Verilog->C++ conversion
|
||||
test_sc => Example Verilog->SystemC conversion
|
||||
test_verilated => Internal tests
|
||||
examples/hello_world_c => Example simple Verilog->C++ conversion
|
||||
examples/hello_world_sc => Example simple Verilog->SystemC conversion
|
||||
examples/tracing_c => Example Verilog->C++ with tracing
|
||||
examples/tracing_sc => Example Verilog->SystemC with tracing
|
||||
test_regress => Internal tests
|
||||
|
||||
=head1 LIMITATIONS
|
||||
|
||||
@@ -41,7 +41,7 @@ Testing:
|
||||
* // verilator debug in code so can see only tree affecting those nodes
|
||||
|
||||
Usability:
|
||||
* Detect and pre-remove most UNOPTFLATs (4.000)
|
||||
* Detect and pre-remove most UNOPTFLATs (4.000)
|
||||
* Better reporting of unopt problems, including what lines of code
|
||||
* Report more errors (all of them?) before exiting [Eugene Weber]
|
||||
* Auto-create scons config files
|
||||
|
||||
+109
-41
@@ -182,7 +182,9 @@ sub run {
|
||||
warn "%Error: $command\n";
|
||||
}
|
||||
if ($status & 127) {
|
||||
if (($status & 127) == 8 || ($status & 127) == 11) { # SIGFPA or SIGSEGV
|
||||
if (($status & 127) == 4 # SIGILL
|
||||
|| ($status & 127) == 8 # SIGFPA
|
||||
|| ($status & 127) == 11) { # SIGSEGV
|
||||
warn "%Error: Verilator internal fault, sorry. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
} elsif (($status & 127) == 6) { # SIGABRT
|
||||
warn "%Error: Verilator aborted. Consider trying --debug --gdbbt\n" if !$Debug;
|
||||
@@ -284,6 +286,7 @@ descriptions in the next sections for more information.
|
||||
-G<name>=<value> Overwrite toplevel parameter
|
||||
--gdb Run Verilator under GDB interactively
|
||||
--gdbbt Run Verilator under GDB for backtrace
|
||||
--getenv <var> Get environment variable with defaults
|
||||
--help Display this help
|
||||
-I<dir> Directory to search for includes
|
||||
--if-depth <value> Tune IFDEPTH warning
|
||||
@@ -325,6 +328,7 @@ descriptions in the next sections for more information.
|
||||
--public Debugging; see docs
|
||||
-pvalue+<name>=<value> Overwrite toplevel parameter
|
||||
--relative-includes Resolve includes relative to current file
|
||||
--no-relative-cfuncs Disallow 'this->' in generated functions
|
||||
--report-unoptflat Extra diagnostics for UNOPTFLAT
|
||||
--savable Enable model save-restore
|
||||
--sc Create SystemC output
|
||||
@@ -349,13 +353,15 @@ descriptions in the next sections for more information.
|
||||
+verilog1995ext+<ext> Synonym for +1364-1995ext+<ext>
|
||||
+verilog2001ext+<ext> Synonym for +1364-2001ext+<ext>
|
||||
--vpi Enable VPI compiles
|
||||
-Werror-<message> Convert warning to error
|
||||
-Wall Enable all style warnings
|
||||
-Werror-<message> Convert warnings to errors
|
||||
-Wfuture-<message> Disable unknown message warnings
|
||||
-Wno-<message> Disable warning
|
||||
-Wno-lint Disable all lint warnings
|
||||
-Wno-style Disable all style warnings
|
||||
-Wno-fatal Disable fatal exit on warnings
|
||||
--x-assign <mode> Initially assign Xs to this value
|
||||
--x-assign <mode> Assign non-initial Xs to this value
|
||||
--x-initial <mode> Assign initial Xs to this value
|
||||
--x-initial-edge Enable initial X->0 and X->1 edge triggers
|
||||
-y <dir> Directory to search for modules
|
||||
|
||||
@@ -425,9 +431,6 @@ C<+1364-1995ext+> etc. specify both the syntax I<and> semantics to be used.
|
||||
|
||||
Enable all assertions.
|
||||
|
||||
See also --x-assign and --x-initial-edge; setting "--x-assign unique"
|
||||
and/or "--x-initial-edge" may be desirable.
|
||||
|
||||
=item --autoflush
|
||||
|
||||
After every $display or $fdisplay, flush the output stream. This insures
|
||||
@@ -759,6 +762,14 @@ backtrace on exit, then exit GDB immediately. Without --debug or if GDB
|
||||
doesn't seem to work, this flag is ignored. Intended for easy creation of
|
||||
backtraces by users; otherwise see the --gdb flag.
|
||||
|
||||
=item --getenv I<variable>
|
||||
|
||||
If the variable is declared in the environment, print it and exit
|
||||
immediately. Otherwise, if it's built into Verilator (e.g. VERILATOR_ROOT),
|
||||
print that and exit immediately. Otherwise, print a newline and exit
|
||||
immediately. This can be useful in makefiles. See also -V, and the various
|
||||
*.mk files.
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
@@ -870,6 +881,22 @@ change the ultimate model's performance, but may in some cases.
|
||||
|
||||
Backward compatible alias for "--pins-bv 33".
|
||||
|
||||
=item --no-relative-cfuncs
|
||||
|
||||
Disable 'this->' references in generated functions, and instead Verilator
|
||||
will generate absolute references starting from 'vlTOPp->'. This prevents
|
||||
V3Combine from merging functions from multiple instances of the same
|
||||
module, so it can grow the instruction stream.
|
||||
|
||||
This is a work around for old compilers. Don't set this if your C++
|
||||
compiler supports __restrict__ properly, as GCC 4.5.x and newer do. For
|
||||
older compilers, test if this switch gives you better performance or not.
|
||||
|
||||
Compilers which don't honor __restrict__ will suspect that 'this->'
|
||||
references and 'vlTOPp->' references may alias, and may write slow code
|
||||
with extra loads and stores to handle the (imaginary) aliasing. Using only
|
||||
'vlTOPp->' references allows these old compilers to produce tight code.
|
||||
|
||||
=item --no-skip-identical
|
||||
|
||||
Rarely needed. Disables skipping execution of Verilator if all source
|
||||
@@ -1178,7 +1205,7 @@ Setting it to "" disables matching.
|
||||
=item -V
|
||||
|
||||
Shows the verbose version, including configuration information compiled
|
||||
into Verilator. (Similar to perl -V.)
|
||||
into Verilator. (Similar to perl -V.) See also --getenv.
|
||||
|
||||
=item -v I<filename>
|
||||
|
||||
@@ -1198,8 +1225,9 @@ Enable use of VPI and linking against the verilated_vpi.cpp files.
|
||||
|
||||
=item -Wall
|
||||
|
||||
Enable all warnings, including code style warnings that are normally
|
||||
disabled by default.
|
||||
Enable all code style warnings, including code style warnings that are
|
||||
normally disabled by default. Equivelent to "-Wwarn-lint -Wwarn-style".
|
||||
Excludes some specialty warnings, i.e. IMPERFECTSCH.
|
||||
|
||||
=item -Werror-I<message>
|
||||
|
||||
@@ -1294,7 +1322,30 @@ enable rerunning with that same seed so you can reproduce bugs.
|
||||
B<Note.> This option applies only to variables which are explicitly assigned
|
||||
to X in the Verilog source code. Initial values of clocks are set to 0 unless
|
||||
--x-initial-edge is specified. Initial values of all other state holding
|
||||
variables are set as though --x-assign unique had been specified.
|
||||
variables are controlled with --x-initial.
|
||||
|
||||
=item --x-initial 0
|
||||
|
||||
=item --x-initial fast
|
||||
|
||||
=item --x-initial unique (default)
|
||||
|
||||
Controls the two-state value that is used to initialize variables that are
|
||||
not otherwise initialized.
|
||||
|
||||
--x-initial=0, initializes all otherwise uninitialized variables to zero.
|
||||
|
||||
--x-initial=unique, the default, initializes variables using a function,
|
||||
which determines the value to use each initialization. This gives greatest
|
||||
flexibility and allows finding reset bugs. See L</"Unknown states">
|
||||
|
||||
--x-initial=fast, is best for performance, and initializes all variables to
|
||||
a state Verilator determines is optimal. This may allow further code
|
||||
optimizations, but will likely hide any code bugs relating to missing
|
||||
resets.
|
||||
|
||||
B<Note.> This option applies only to initial values of variables. Initial
|
||||
values of clocks are set to 0 unless --x-initial-edge is specified.
|
||||
|
||||
=item --x-initial-edge
|
||||
|
||||
@@ -1356,7 +1407,7 @@ We'll compile this example into C++.
|
||||
cat <<EOF >sim_main.cpp
|
||||
#include "Vour.h"
|
||||
#include "verilated.h"
|
||||
int main(int argc, char **argv, char **env) {
|
||||
int main(int argc, char** argv, char** env) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
Vour* top = new Vour;
|
||||
while (!Verilated::gotFinish()) { top->eval(); }
|
||||
@@ -1405,8 +1456,8 @@ And we get as output
|
||||
|
||||
Really, you're better off writing a Makefile to do all this for you. Then,
|
||||
when your source changes it will automatically run all of these steps; to
|
||||
aid this Verilator can create a makefile dependency file. See the test_c
|
||||
directory in the distribution for an example.
|
||||
aid this Verilator can create a makefile dependency file. See the examples
|
||||
directory in the distribution.
|
||||
|
||||
|
||||
=head1 EXAMPLE SYSTEMC EXECUTION
|
||||
@@ -1483,15 +1534,16 @@ And we get the same output as the C++ example:
|
||||
|
||||
Really, you're better off using a Makefile to do all this for you. Then,
|
||||
when your source changes it will automatically run all of these steps. See
|
||||
the test_sc directory in the distribution for an example.
|
||||
the examples directory in the distribution.
|
||||
|
||||
|
||||
=head1 BENCHMARKING & OPTIMIZATION
|
||||
|
||||
For best performance, run Verilator with the "-O3 --x-assign=fast
|
||||
--noassert" flags. The -O3 flag will require longer compile times, and
|
||||
--x-assign=fast may increase the risk of reset bugs in trade for
|
||||
performance; see the above documentation for these flags.
|
||||
--x-initial=fast --noassert" flags. The -O3 flag will require longer
|
||||
compile times, and --x-assign=fast --x-initial=fast may increase the risk
|
||||
of reset bugs in trade for performance; see the above documentation for
|
||||
these flags.
|
||||
|
||||
Minor Verilog code changes can also give big wins. You should not have any
|
||||
UNOPTFLAT warnings from Verilator. Fixing these warnings can result in
|
||||
@@ -1969,7 +2021,7 @@ accesses the above signal "readme" would be:
|
||||
printf("Value of v: %d\n", v.value.integer); // Prints "readme"
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
int main(int argc, char** argv, char** env) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
Vour* top = new Vour;
|
||||
Verilated::internalsDump(); // See scopes to help debug
|
||||
@@ -2522,6 +2574,12 @@ indicate the function or task should pass all remaining arguments through
|
||||
$sformatf. This allows creation of DPI functions with $display like
|
||||
behavior. See the test_regress/t/t_dpi_display.v file for an example.
|
||||
|
||||
=item /*verilator tag <text...>*/
|
||||
|
||||
Attached after a variable or structure member to indicate opaque (to
|
||||
Verilator) text that should be passed through to the XML output as a tag,
|
||||
for use by downstream applications.
|
||||
|
||||
=item /*verilator tracing_off*/
|
||||
|
||||
Disable waveform tracing for all future signals that are declared in this
|
||||
@@ -2634,24 +2692,25 @@ value (see the --x-assign switch.) Thus if the value is actually used, the
|
||||
random value should cause downstream errors. Integers also randomize, even
|
||||
though the Verilog 2001 specification says they initialize to zero.
|
||||
|
||||
All variables are randomly initialized using a function. By running
|
||||
several random simulation runs you can determine that reset is working
|
||||
correctly. On the first run, the function initializes variables to zero.
|
||||
On the second, have it initialize variables to one. On the third and
|
||||
following runs have it initialize them randomly. If the results match,
|
||||
reset works. (Note this is what the hardware will really do.) In
|
||||
practice, just setting all variables to one at startup finds most problems.
|
||||
All variables, depending on --x-initial setting, are typically randomly
|
||||
initialized using a function. By running several random simulation runs
|
||||
you can determine that reset is working correctly. On the first run, the
|
||||
function initializes variables to zero. On the second, have it initialize
|
||||
variables to one. On the third and following runs have it initialize them
|
||||
randomly. If the results match, reset works. (Note this is what the
|
||||
hardware will really do.) In practice, just setting all variables to one
|
||||
at startup finds most problems (since typically control signals are
|
||||
active-high).
|
||||
|
||||
B<Note.> --x-assign applies to variables explicitly initialized or assigned to
|
||||
X. Uninitialized clocks are initialized to zero, while all other state holding
|
||||
variables are initialized to a random value.
|
||||
|
||||
Event driven simulators will generally trigger an edge on a transition from X
|
||||
to 1 (C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks
|
||||
are initialized to zero, Verilator will not trigger an initial negedge. Some
|
||||
code (particularly for reset) may rely on X->0 triggering an edge. Verilator
|
||||
provides a switch (see --x-initial-edge) to enable this behavior. Comparing
|
||||
runs with and without this switch will find such problems.
|
||||
--x-assign applies to variables explicitly initialized or assigned to
|
||||
X. Uninitialized clocks are initialized to zero, while all other state
|
||||
holding variables are initialized to a random value. Event driven
|
||||
simulators will generally trigger an edge on a transition from X to 1
|
||||
(C<posedge>) or X to 0 (C<negedge>). However, by default, since clocks are
|
||||
initialized to zero, Verilator will not trigger an initial negedge. Some
|
||||
code (particularly for reset) may rely on X->0 triggering an edge. The
|
||||
--x-initial-edge switch enables this behavior. Comparing runs with and
|
||||
without this switch will find such problems.
|
||||
|
||||
|
||||
=head2 Tri/Inout
|
||||
@@ -3154,8 +3213,8 @@ correctly.
|
||||
|
||||
Warns that the scheduling of the model is not absolutely perfect, and some
|
||||
manual code edits may result in faster performance. This warning defaults
|
||||
to off, and must be turned on explicitly before the top module statement is
|
||||
processed.
|
||||
to off, is not part of -Wall, and must be turned on explicitly before the
|
||||
top module statement is processed.
|
||||
|
||||
=item IMPLICIT
|
||||
|
||||
@@ -3205,6 +3264,11 @@ Warns that a packed vector is declared with little endian bit numbering
|
||||
and little numbering is now thus often due to simple oversight instead of
|
||||
intent.
|
||||
|
||||
Also warns that a cell is declared with little endian range (i.e. [0:7] or
|
||||
[7]) and is connected to a N-wide signal. Based on IEEE the bits will
|
||||
likely be backwards from what you expect (i.e. cell [0] will connect to
|
||||
signal bit [N-1] not bit [0]).
|
||||
|
||||
Ignoring this warning will only suppress the lint check, it will simulate
|
||||
correctly.
|
||||
|
||||
@@ -3662,7 +3726,7 @@ trace file if you want all data to land in the same output file.
|
||||
|
||||
#include "verilated_vcd_c.h"
|
||||
...
|
||||
int main(int argc, char **argv, char **env) {
|
||||
int main(int argc, char** argv, char** env) {
|
||||
...
|
||||
Verilated::traceEverOn(true);
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
@@ -3676,6 +3740,8 @@ trace file if you want all data to land in the same output file.
|
||||
tfp->close();
|
||||
}
|
||||
|
||||
Also see the examples/tracing_cc directory in the distribution.
|
||||
|
||||
=item How do I generate waveforms (traces) in SystemC?
|
||||
|
||||
Add the --trace switch to Verilator, and in your top level C sc_main code,
|
||||
@@ -3698,7 +3764,7 @@ trace file if you want all data to land in the same output file.
|
||||
|
||||
#include "verilated_vcd_sc.h"
|
||||
...
|
||||
int main(int argc, char **argv, char **env) {
|
||||
int main(int argc, char** argv, char** env) {
|
||||
...
|
||||
Verilated::traceEverOn(true);
|
||||
VerilatedVcdSc* tfp = new VerilatedVcdSc;
|
||||
@@ -3710,11 +3776,13 @@ trace file if you want all data to land in the same output file.
|
||||
tfp->close();
|
||||
}
|
||||
|
||||
Also see the examples/tracing_cc directory in the distribution.
|
||||
|
||||
=item How do I view waveforms (traces)?
|
||||
|
||||
Verilator makes standard VCD (Value Change Dump) files. They are viewable
|
||||
with the public domain Dinotrace or GtkWave programs, or any of the many
|
||||
commercial offerings.
|
||||
with the public domain GtkWave (recommended) or Dinotrace (legacy)
|
||||
programs, or any of the many commercial offerings.
|
||||
|
||||
=item How do I reduce the size of large waveform (trace) files?
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ use warnings;
|
||||
print "// DESCR"."IPTION: Generated by verilator_includer via makefile\n";
|
||||
foreach my $param (@ARGV) {
|
||||
if ($param =~ /^-D([^=]+)=(.*)/) {
|
||||
print "#define $1 $2\n"
|
||||
print "#define $1 $2\n"
|
||||
} else {
|
||||
print "#include \"$param\"\n"
|
||||
print "#include \"$param\"\n"
|
||||
}
|
||||
}
|
||||
|
||||
+84
-26
@@ -6,8 +6,9 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.910 2017-09-07])
|
||||
AC_INIT([Verilator],[3.914 2017-10-14])
|
||||
# When releasing, also update header of Changes file
|
||||
# and commit using "devel release" or "Version bump" message
|
||||
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc)
|
||||
@@ -42,7 +43,7 @@ AC_ARG_ENABLE([ccwarn],
|
||||
x) CFG_WITH_CCWARN=no ;;
|
||||
*) CFG_WITH_CCWARN=yes ;;
|
||||
esac]
|
||||
)
|
||||
)
|
||||
AC_SUBST(CFG_WITH_CCWARN)
|
||||
AC_MSG_RESULT($CFG_WITH_CCWARN)
|
||||
|
||||
@@ -60,7 +61,7 @@ AC_ARG_ENABLE([longtests],
|
||||
x) CFG_WITH_LONGTESTS=no ;;
|
||||
*) CFG_WITH_LONGTESTS=yes ;;
|
||||
esac]
|
||||
)
|
||||
)
|
||||
AC_SUBST(CFG_WITH_LONGTESTS)
|
||||
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
||||
|
||||
@@ -78,10 +79,10 @@ AC_PROG_INSTALL
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_MSG_CHECKING([that C++ compiler can compile simple program])
|
||||
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(yes))
|
||||
[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(yes))
|
||||
|
||||
AC_PATH_PROG(PERL,perl)
|
||||
if test "x$PERL" = "x" ; then
|
||||
@@ -105,49 +106,102 @@ AC_TYPE_SIZE_T
|
||||
# Checks for compiler characteristics.
|
||||
AC_C_INLINE
|
||||
|
||||
AC_DEFUN([_MY_CXX_CHECK_OPT],
|
||||
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([], [[int* a=new int; delete a; ]])],
|
||||
[], [AC_MSG_ERROR([$CXX does not seem to successfully compile a simple C++ program])])
|
||||
|
||||
AC_DEFUN([_MY_CXX_CHECK_FLAG],
|
||||
[# _MY_CXX_CHECK_FLAG(flag) -- Check if compiler supports specific options
|
||||
# Set $_my_result appropriately
|
||||
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
|
||||
# -Werror needed otherwise unknown -Wno-div-by-zero won't report problems
|
||||
CXXFLAGS="$CXXFLAGS $2 -Werror"
|
||||
AC_MSG_CHECKING([whether $CXX accepts $2])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([],[])],
|
||||
[_my_result=yes
|
||||
if test -s conftest.err; then
|
||||
if grep -e "$2" conftest.err >/dev/null; then
|
||||
_my_result=no
|
||||
fi
|
||||
fi],
|
||||
[_my_result=no])
|
||||
# new/delete is needed to find -faligned-new link problem on Darwin
|
||||
CXXFLAGS="$CXXFLAGS $1 -Werror"
|
||||
AC_MSG_CHECKING([whether $CXX accepts $1])
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([], [[int* a=new int; delete a; ]])],
|
||||
[_my_result=yes
|
||||
if test -s conftest.err; then
|
||||
if grep -e "$1" conftest.err >/dev/null; then
|
||||
_my_result=no
|
||||
fi
|
||||
fi],
|
||||
[_my_result=no])
|
||||
# GCC is annoying, trying to be helpful, it postpones unknown -Wno-
|
||||
# options if there's no error We want to see them regardless, so try
|
||||
# forcing an error and see if we get a gcc warning
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[an_error "intentional-error-for-test.h"
|
||||
]],[])],
|
||||
]],[])],
|
||||
[], # Ignore ok exit
|
||||
[if test -s conftest.err; then
|
||||
if grep -e "$2" conftest.err >/dev/null; then
|
||||
if grep -e "$1" conftest.err >/dev/null; then
|
||||
_my_result=no
|
||||
fi
|
||||
fi])
|
||||
AC_MSG_RESULT($_my_result)
|
||||
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
|
||||
])
|
||||
|
||||
AC_DEFUN([_MY_CXX_CHECK_SET],
|
||||
[# _MY_CXX_CHECK_SET(variable,flag) -- Check if compiler supports specific options
|
||||
# If it does, set variable to flag, only if not previously set
|
||||
if test "$$1" = ""; then
|
||||
_MY_CXX_CHECK_FLAG($2)
|
||||
if test "$_my_result" = "yes" ; then
|
||||
$1="$2"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([_MY_CXX_CHECK_OPT],
|
||||
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
|
||||
# If it does, append flag to variable
|
||||
_MY_CXX_CHECK_FLAG($2)
|
||||
if test "$_my_result" = "yes" ; then
|
||||
$1="$$1 $2"
|
||||
fi
|
||||
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
|
||||
])# _MY_CXX_CHECK_OPT
|
||||
])
|
||||
|
||||
# Flags for compiling Verilator internals including parser
|
||||
# Flag to select newest language standard supported
|
||||
# Macros work such that first option that passes is the one we take
|
||||
# gnu++14 is the newest that Verilator supports
|
||||
# std++03 is the oldest that Verilator supports
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++03)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++03)
|
||||
AC_SUBST(CFG_CXXFLAGS_STD_NEWEST)
|
||||
# And likewise oldest standard (same list above, backwards)
|
||||
# This is used for internal testing
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++03)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=std++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++03)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++11)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++14)
|
||||
_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_OLDEST,-std=gnu++17)
|
||||
AC_SUBST(CFG_CXXFLAGS_STD_OLDEST)
|
||||
|
||||
# Flags for compiling Verilator internals including parser, and Verilated files
|
||||
# These turn on extra warnings and are only used with 'configure --enable-ccwarn'
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wextra)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wfloat-conversion)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_WEXTRA,-Wlogical-op)
|
||||
AC_SUBST(CFG_CXXFLAGS_WEXTRA)
|
||||
|
||||
# Flags for compiling Verilator internals including parser always
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Qunused-arguments)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-faligned-new)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-delete-null-pointer-checks)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-undefined-bool-conversion)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-Wno-shadow)
|
||||
AC_SUBST(CFG_CXXFLAGS_SRC)
|
||||
|
||||
# Flags for compiling Verilator parser (in addition to above CFG_CXXFLAGS_SRC)
|
||||
# Flags for compiling Verilator parser always (in addition to above CFG_CXXFLAGS_SRC)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-char-subscripts)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-null-conversion)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_PARSER,-Wno-parentheses-equality)
|
||||
@@ -169,9 +223,13 @@ _MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-uninitialized)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-but-set-variable)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-unused-variable)
|
||||
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_NO_UNUSED,-Wno-shadow)
|
||||
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
|
||||
# Checks for library functions.
|
||||
AC_CHECK_MEMBER([struct stat.st_mtim.tv_nsec],
|
||||
[AC_DEFINE([HAVE_STAT_NSEC],[1],[Defined if struct stat has st_mtim.tv_nsec])],
|
||||
[], [#include <sys/stat.h>])
|
||||
|
||||
# Checks for system services
|
||||
|
||||
|
||||
+1
-2
@@ -635,8 +635,7 @@ INPUT = doxygen-mainpage \
|
||||
test_c \
|
||||
test_regress \
|
||||
test_sc \
|
||||
test_v \
|
||||
test_verilated
|
||||
test_v
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
*.csrc
|
||||
*.vcd
|
||||
obj_*
|
||||
project
|
||||
logs
|
||||
@@ -0,0 +1,52 @@
|
||||
######################################################################
|
||||
#
|
||||
# DESCRIPTION: Verilator Example: Small Makefile
|
||||
#
|
||||
# This calls the object directory makefile. That allows the objects to
|
||||
# be placed in the "current directory" which simplifies the Makefile.
|
||||
#
|
||||
# Copyright 2003-2017 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.
|
||||
#
|
||||
######################################################################
|
||||
# Check for sanity to avoid later confusion
|
||||
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
|
||||
# This is intended to be a minimal example. Before copying this to start a
|
||||
# real project, it is better to start with a more complete example,
|
||||
# e.g. examples/tracing_c.
|
||||
|
||||
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
|
||||
# package inatall, and verilator is in your path. Otherwise find the
|
||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||
ifeq ($(VERILATOR_ROOT),)
|
||||
VERILATOR = verilator
|
||||
else
|
||||
export VERILATOR_ROOT
|
||||
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||
endif
|
||||
|
||||
default:
|
||||
@echo "-- Verilator hello-world simple example"
|
||||
@echo "-- VERILATE ----------------"
|
||||
$(VERILATOR) -cc --exe top.v sim_main.cpp
|
||||
@echo "-- COMPILE -----------------"
|
||||
$(MAKE) -j 4 -C obj_dir -f Vtop.mk
|
||||
@echo "-- RUN ---------------------"
|
||||
obj_dir/Vtop
|
||||
@echo "-- DONE --------------------"
|
||||
@echo "Note: Once this example is understood, see examples/tracing_c."
|
||||
@echo "Note: Also see the EXAMPLE section in the verilator manpage/document."
|
||||
|
||||
######################################################################
|
||||
|
||||
maintainer-copy::
|
||||
clean mostlyclean distclean maintainer-clean::
|
||||
-rm -rf obj_dir *.log *.dmp *.vpd core
|
||||
@@ -0,0 +1,41 @@
|
||||
// DESCRIPTION: Verilator: Verilog example module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
//======================================================================
|
||||
|
||||
// Include common routines
|
||||
#include <verilated.h>
|
||||
|
||||
// Include model header, generated from Verilating "top.v"
|
||||
#include "Vtop.h"
|
||||
|
||||
int main(int argc, char** argv, char** env) {
|
||||
// See a similar example walkthrough in the verilator manpage.
|
||||
|
||||
// This is intended to be a minimal example. Before copying this to start a
|
||||
// real project, it is better to start with a more complete example,
|
||||
// e.g. examples/c_tracing.
|
||||
|
||||
// Prevent unused variable warnings
|
||||
if (0 && argc && argv && env) {}
|
||||
|
||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||
Vtop* top = new Vtop;
|
||||
|
||||
// Simulate until $finish
|
||||
while (!Verilated::gotFinish()) {
|
||||
|
||||
// Evaluate model
|
||||
top->eval();
|
||||
}
|
||||
|
||||
// Final model cleanup
|
||||
top->final();
|
||||
|
||||
// Destroy model
|
||||
delete top;
|
||||
|
||||
// Fin
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// DESCRIPTION: Verilator: Verilog example module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
|
||||
// See also the EXAMPLE section in the verilator manpage/document.
|
||||
module top;
|
||||
initial begin
|
||||
$display("Hello World!");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -1,8 +1,6 @@
|
||||
*.old
|
||||
*.dmp
|
||||
*.log
|
||||
*.csrc
|
||||
*.vcd
|
||||
obj_*
|
||||
logs
|
||||
project
|
||||
@@ -0,0 +1,67 @@
|
||||
######################################################################
|
||||
#
|
||||
# DESCRIPTION: Verilator Example: Small Makefile
|
||||
#
|
||||
# This calls the object directory makefile. That allows the objects to
|
||||
# be placed in the "current directory" which simplifies the Makefile.
|
||||
#
|
||||
# Copyright 2003-2017 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.
|
||||
#
|
||||
######################################################################
|
||||
# Check for sanity to avoid later confusion
|
||||
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
|
||||
# This is intended to be a minimal example. Before copying this to start a
|
||||
# real project, it is better to start with a more complete example,
|
||||
# e.g. examples/tracing_sc.
|
||||
|
||||
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
|
||||
# package inatall, and verilator is in your path. Otherwise find the
|
||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||
ifeq ($(VERILATOR_ROOT),)
|
||||
VERILATOR = verilator
|
||||
else
|
||||
export VERILATOR_ROOT
|
||||
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||
endif
|
||||
|
||||
# Check if SC exists via a verilator call (empty if not)
|
||||
SYSTEMC_EXISTS := $(shell $(VERILATOR) --getenv SYSTEMC_INCLUDE)
|
||||
|
||||
ifneq ($(SYSTEMC_EXISTS),)
|
||||
default: run
|
||||
else
|
||||
default: nosc
|
||||
endif
|
||||
|
||||
run:
|
||||
@echo "-- Verilator hello-world simple example"
|
||||
@echo "-- VERILATE ----------------"
|
||||
$(VERILATOR) -sc --exe top.v sc_main.cpp
|
||||
@echo "-- COMPILE -----------------"
|
||||
$(MAKE) -j 4 -C obj_dir -f Vtop.mk
|
||||
@echo "-- RUN ---------------------"
|
||||
obj_dir/Vtop
|
||||
@echo "-- DONE --------------------"
|
||||
@echo "Note: Once this example is understood, see examples/tracing_sc."
|
||||
@echo "Note: Also see the EXAMPLE section in the verilator manpage/document."
|
||||
|
||||
######################################################################
|
||||
|
||||
nosc:
|
||||
@echo
|
||||
@echo "%Skip: SYSTEMC_INCLUDE not in environment"
|
||||
@echo "(If you have SystemC see the README, and rebuild Verilator)"
|
||||
@echo
|
||||
|
||||
maintainer-copy::
|
||||
clean mostlyclean distclean maintainer-clean::
|
||||
-rm -rf obj_dir *.log *.dmp *.vpd core
|
||||
@@ -0,0 +1,51 @@
|
||||
// -*- SystemC -*-
|
||||
// DESCRIPTION: Verilator Example: Top level main for invoking SystemC model
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
//======================================================================
|
||||
|
||||
// SystemC global header
|
||||
#include <systemc.h>
|
||||
|
||||
// Include common routines
|
||||
#include <verilated.h>
|
||||
|
||||
// Include model header, generated from Verilating "top.v"
|
||||
#include "Vtop.h"
|
||||
|
||||
int sc_main(int argc, char* argv[]) {
|
||||
// See a similar example walkthrough in the verilator manpage.
|
||||
|
||||
// This is intended to be a minimal example. Before copying this to start a
|
||||
// real project, it is better to start with a more complete example,
|
||||
// e.g. examples/c_tracing.
|
||||
|
||||
// Prevent unused variable warnings
|
||||
if (0 && argc && argv) {}
|
||||
|
||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||
Vtop* top = new Vtop("top");
|
||||
|
||||
// Initialize SC model
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_start(1,SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
|
||||
// Simulate until $finish
|
||||
while (!Verilated::gotFinish()) {
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_start(1,SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Final model cleanup
|
||||
top->final();
|
||||
|
||||
// Fin
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// DESCRIPTION: Verilator: Verilog example module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
|
||||
// See also the EXAMPLE section in the verilator manpage/document.
|
||||
module top;
|
||||
initial begin
|
||||
$display("Hello World!");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,6 @@
|
||||
*.dmp
|
||||
*.log
|
||||
*.csrc
|
||||
*.vcd
|
||||
obj_*
|
||||
logs
|
||||
@@ -0,0 +1,96 @@
|
||||
######################################################################
|
||||
#
|
||||
# DESCRIPTION: Verilator Example: Small Makefile
|
||||
#
|
||||
# This calls the object directory makefile. That allows the objects to
|
||||
# be placed in the "current directory" which simplifies the Makefile.
|
||||
#
|
||||
# Copyright 2003-2017 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.
|
||||
#
|
||||
######################################################################
|
||||
# Check for sanity to avoid later confusion
|
||||
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# Set up variables
|
||||
|
||||
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
|
||||
# package inatall, and verilator is in your path. Otherwise find the
|
||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||
ifeq ($(VERILATOR_ROOT),)
|
||||
VERILATOR = verilator
|
||||
VERILATOR_COVERAGE = verilator_coverage
|
||||
else
|
||||
export VERILATOR_ROOT
|
||||
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||
endif
|
||||
|
||||
VERILATOR_FLAGS =
|
||||
# Generate C++ in executable form
|
||||
VERILATOR_FLAGS += -cc --exe
|
||||
# Generate makefile dependencies (not shown as complicates the Makefile)
|
||||
#VERILATOR_FLAGS += -MMD
|
||||
# Optimize
|
||||
VERILATOR_FLAGS += -O2 -x-assign 0
|
||||
# Warn abount lint issues; may not want this on less solid designs
|
||||
VERILATOR_FLAGS += -Wall
|
||||
# Make waveforms
|
||||
VERILATOR_FLAGS += --trace
|
||||
# Check SystemVerilog assertions
|
||||
VERILATOR_FLAGS += --assert
|
||||
# Generate coverage analysis
|
||||
VERILATOR_FLAGS += --coverage
|
||||
# Run Verilator in debug mode
|
||||
#VERILATOR_FLAGS += --debug
|
||||
# Add this trace to get a backtrace in gdb
|
||||
#VERILATOR_FLAGS += --gdbbt
|
||||
|
||||
######################################################################
|
||||
default: run
|
||||
|
||||
run:
|
||||
@echo
|
||||
@echo "-- Verilator tracing example"
|
||||
|
||||
@echo
|
||||
@echo "-- VERILATE ----------------"
|
||||
$(VERILATOR) $(VERILATOR_FLAGS) -f input.vc top.v sim_main.cpp
|
||||
|
||||
@echo
|
||||
@echo "-- COMPILE -----------------"
|
||||
# To compile, we can either just do what Verilator asks,
|
||||
# or call a submakefile where we can override the rules ourselves
|
||||
# $(MAKE) -j 4 -C obj_dir -f Vtop.mk
|
||||
$(MAKE) -j 4 -C obj_dir -f ../Makefile_obj
|
||||
|
||||
@echo
|
||||
@echo "-- RUN ---------------------"
|
||||
@mkdir -p logs
|
||||
obj_dir/Vtop | tee logs/sim.log
|
||||
|
||||
@echo
|
||||
@echo "-- COVERAGE ----------------"
|
||||
$(VERILATOR_COVERAGE) --annotate logs/annotated logs/coverage.dat
|
||||
|
||||
@echo
|
||||
@echo "-- DONE --------------------"
|
||||
@echo "To see waveforms, open vlt_dump.vcd in a waveform viewer"
|
||||
@echo
|
||||
|
||||
|
||||
######################################################################
|
||||
# Other targets
|
||||
|
||||
show-config:
|
||||
$(VERILATOR) -V
|
||||
|
||||
maintainer-copy::
|
||||
clean mostlyclean distclean maintainer-clean::
|
||||
-rm -rf obj_dir logs *.log *.dmp *.vpd coverage.dat core
|
||||
@@ -0,0 +1,55 @@
|
||||
# -*- Makefile -*-
|
||||
#######################################################################
|
||||
#
|
||||
# DESCRIPTION: Verilator Example: Makefile for inside object directory
|
||||
#
|
||||
# This is executed in the object directory, and called by ../Makefile
|
||||
#
|
||||
# Copyright 2003-2017 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.
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
default: Vtop
|
||||
|
||||
# Include the rules made by Verilator
|
||||
include Vtop.mk
|
||||
|
||||
#######################################################################
|
||||
# Compile flags
|
||||
|
||||
# Override some default compile flags
|
||||
CPPFLAGS += -MMD -MP
|
||||
CPPFLAGS += -DVL_DEBUG=1
|
||||
# Turn on some more flags (when configured appropriately)
|
||||
# For testing inside Verilator, "configure --enable-ccwarn" will do this
|
||||
# automatically; otherwise you may want this unconditionally enabled
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
USER_CPPFLAGS_WALL += -W -Werror -Wall
|
||||
endif
|
||||
|
||||
# See the benchmarking section of bin/verilator.
|
||||
# Support class optimizations. This includes the tracing and symbol table.
|
||||
# SystemC takes minutes to optimize, thus it is off by default.
|
||||
OPT_SLOW =
|
||||
# Fast path optimizations. Most time is spent in these classes.
|
||||
OPT_FAST = -O2 -fstrict-aliasing
|
||||
#OPT_FAST = -O
|
||||
#OPT_FAST =
|
||||
|
||||
#######################################################################
|
||||
# Linking final exe -- presumes have a sim_main.cpp
|
||||
|
||||
# Special compile rule
|
||||
sim_main.o: sim_main.cpp $(VM_PREFIX).h
|
||||
|
||||
######################################################################
|
||||
######################################################################
|
||||
# Automatically understand dependencies
|
||||
|
||||
DEPS := $(wildcard *.d)
|
||||
ifneq ($(DEPS),)
|
||||
include $(DEPS)
|
||||
endif
|
||||
@@ -0,0 +1,2 @@
|
||||
// This file typically lists flags required by a large project, e.g. include directories
|
||||
+librescan +libext+.v+.sv+.vh+.svh -y .
|
||||
@@ -0,0 +1,114 @@
|
||||
// DESCRIPTION: Verilator: Verilog example module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
//======================================================================
|
||||
|
||||
// Include common routines
|
||||
#include <verilated.h>
|
||||
|
||||
#include <sys/stat.h> // mkdir
|
||||
|
||||
// Include model header, generated from Verilating "top.v"
|
||||
#include "Vtop.h"
|
||||
|
||||
// If "verilator --trace" is used, include the tracing class
|
||||
#if VM_TRACE
|
||||
# include <verilated_vcd_c.h>
|
||||
#endif
|
||||
|
||||
// Current simulation time (64-bit unsigned)
|
||||
vluint64_t main_time = 0;
|
||||
// Called by $time in Verilog
|
||||
double sc_time_stamp () {
|
||||
return main_time; // Note does conversion to real, to match SystemC
|
||||
}
|
||||
|
||||
int main(int argc, char** argv, char** env) {
|
||||
// This is a more complicated example, please also see the simpler examples/hello_world_c.
|
||||
|
||||
// Prevent unused variable warnings
|
||||
if (0 && argc && argv && env) {}
|
||||
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
// Set debug level, 0 is off, 9 is highest presently used
|
||||
Verilated::debug(0);
|
||||
|
||||
// Randomization reset policy
|
||||
Verilated::randReset(2);
|
||||
|
||||
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
|
||||
Vtop* top = new Vtop; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
|
||||
|
||||
// If verilator was invoked with --trace, open trace
|
||||
#if VM_TRACE
|
||||
Verilated::traceEverOn(true); // Verilator must compute traced signals
|
||||
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
|
||||
VerilatedVcdC* tfp = new VerilatedVcdC;
|
||||
top->trace(tfp, 99); // Trace 99 levels of hierarchy
|
||||
mkdir("logs", 0777);
|
||||
tfp->open("logs/vlt_dump.vcd"); // Open the dump file
|
||||
#endif
|
||||
|
||||
// Set some inputs
|
||||
top->reset_l = !0;
|
||||
top->fastclk = 0;
|
||||
top->clk = 0;
|
||||
top->in_small = 1;
|
||||
top->in_quad = 0x1234;
|
||||
top->in_wide[0] = 0x1;
|
||||
top->in_wide[1] = 0x22222222;
|
||||
top->in_wide[2] = 0x33333333;
|
||||
|
||||
// Simulate until $finish
|
||||
while (!Verilated::gotFinish()) {
|
||||
main_time++; // Time passes...
|
||||
|
||||
// Toggle clocks and such
|
||||
top->fastclk = !top->fastclk;
|
||||
if ((main_time % 10) == 3) {
|
||||
top->clk = 1;
|
||||
}
|
||||
if ((main_time % 10) == 8) {
|
||||
top->clk = 0;
|
||||
}
|
||||
if (main_time > 1 && main_time < 10) {
|
||||
top->reset_l = !1; // Assert reset
|
||||
} else {
|
||||
top->reset_l = !0; // Deassert reset
|
||||
}
|
||||
|
||||
// Assign some other inputs
|
||||
top->in_quad += 0x12;
|
||||
|
||||
// Evaluate model
|
||||
top->eval();
|
||||
|
||||
// Read outputs
|
||||
VL_PRINTF ("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
|
||||
" -> oquad=%" VL_PRI64"x owide=%x_%08x_%08x\n",
|
||||
main_time, top->clk, top->reset_l, top->in_quad,
|
||||
top->out_quad, top->out_wide[2], top->out_wide[1], top->out_wide[0]);
|
||||
}
|
||||
|
||||
// Final model cleanup
|
||||
top->final();
|
||||
|
||||
// Close trace if opened
|
||||
#if VM_TRACE
|
||||
if (tfp) { tfp->close(); }
|
||||
#endif
|
||||
|
||||
// Coverage analysis (since test passed)
|
||||
#if VM_COVERAGE
|
||||
mkdir("logs", 0777);
|
||||
VerilatedCov::write("logs/coverage.dat");
|
||||
#endif
|
||||
|
||||
// Destroy model
|
||||
delete top; top = NULL;
|
||||
|
||||
// Fin
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// ======================================================================
|
||||
|
||||
module sub
|
||||
(
|
||||
input clk,
|
||||
input fastclk,
|
||||
input reset_l
|
||||
);
|
||||
|
||||
// Example counter/flop
|
||||
reg [31:0] count_f;
|
||||
always_ff @ (posedge fastclk) begin
|
||||
if (!reset_l) begin
|
||||
/*AUTORESET*/
|
||||
// Beginning of autoreset for uninitialized flops
|
||||
count_f <= 32'h0;
|
||||
// End of automatics
|
||||
end
|
||||
else begin
|
||||
count_f <= count_f + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Another example flop
|
||||
reg [31:0] count_c;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (!reset_l) begin
|
||||
/*AUTORESET*/
|
||||
// Beginning of autoreset for uninitialized flops
|
||||
count_c <= 32'h0;
|
||||
// End of automatics
|
||||
end
|
||||
else begin
|
||||
count_c <= count_c + 1;
|
||||
if (count_c >= 3) begin
|
||||
$display("[%0t] fastclk is %0d times faster than clk\n",
|
||||
$time, count_f/count_c);
|
||||
// This write is a magic value the Makefile uses to make sure the
|
||||
// test completes successfully.
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// An example assertion
|
||||
always_ff @ (posedge clk) begin
|
||||
AssertionExample: assert (!reset_l || count_c<100);
|
||||
end
|
||||
|
||||
// And example coverage analysis
|
||||
cover property (@(posedge clk) count_c==3);
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,42 @@
|
||||
// DESCRIPTION: Verilator: Verilog example module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// ======================================================================
|
||||
|
||||
// This is intended to be a complex example of several features, please also
|
||||
// see the simpler examples/hello_world_c.
|
||||
|
||||
module top
|
||||
(
|
||||
// Declare some signals so we can see how I/O works
|
||||
input clk,
|
||||
input fastclk,
|
||||
input reset_l,
|
||||
|
||||
output [1:0] out_small,
|
||||
output [39:0] out_quad,
|
||||
output [69:0] out_wide,
|
||||
input [1:0] in_small,
|
||||
input [39:0] in_quad,
|
||||
input [69:0] in_wide
|
||||
);
|
||||
|
||||
// Connect up the outputs, using some trivial logic
|
||||
wire [1:0] out_small = ~reset_l ? '0 : (in_small + 2'b1);
|
||||
wire [39:0] out_quad = ~reset_l ? '0 : (in_quad + 40'b1);
|
||||
wire [69:0] out_wide = ~reset_l ? '0 : (in_wide + 70'b1);
|
||||
|
||||
// And an example sub module. The submodule will print stuff.
|
||||
sub sub (/*AUTOINST*/
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.fastclk (fastclk),
|
||||
.reset_l (reset_l));
|
||||
|
||||
// Print some stuff as an example
|
||||
initial begin
|
||||
$display("[%0t] Model running...\n", $time);
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,6 @@
|
||||
*.dmp
|
||||
*.log
|
||||
*.csrc
|
||||
*.vcd
|
||||
obj_*
|
||||
logs
|
||||
@@ -0,0 +1,109 @@
|
||||
######################################################################
|
||||
#
|
||||
# DESCRIPTION: Verilator Example: Small Makefile
|
||||
#
|
||||
# This calls the object directory makefile. That allows the objects to
|
||||
# be placed in the "current directory" which simplifies the Makefile.
|
||||
#
|
||||
# Copyright 2003-2017 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.
|
||||
#
|
||||
######################################################################
|
||||
# Check for sanity to avoid later confusion
|
||||
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# Set up variables
|
||||
|
||||
# If $VERILATOR_ROOT isn't in the enviornment, we assume it is part of a
|
||||
# package inatall, and verilator is in your path. Otherwise find the
|
||||
# binary relative to $VERILATOR_ROOT (such as when inside the git sources).
|
||||
ifeq ($(VERILATOR_ROOT),)
|
||||
VERILATOR = verilator
|
||||
VERILATOR_COVERAGE = verilator_coverage
|
||||
else
|
||||
export VERILATOR_ROOT
|
||||
VERILATOR = $(VERILATOR_ROOT)/bin/verilator
|
||||
VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||
endif
|
||||
|
||||
VERILATOR_FLAGS =
|
||||
# Generate SystemC in executable form
|
||||
VERILATOR_FLAGS += -sc --exe
|
||||
# Generate makefile dependencies (not shown as complicates the Makefile)
|
||||
#VERILATOR_FLAGS += -MMD
|
||||
# Optimize
|
||||
VERILATOR_FLAGS += -O2 -x-assign 0
|
||||
# Warn abount lint issues; may not want this on less solid designs
|
||||
VERILATOR_FLAGS += -Wall
|
||||
# Make waveforms
|
||||
VERILATOR_FLAGS += --trace
|
||||
# Check SystemVerilog assertions
|
||||
VERILATOR_FLAGS += --assert
|
||||
# Generate coverage analysis
|
||||
VERILATOR_FLAGS += --coverage
|
||||
# Run Verilator in debug mode
|
||||
#VERILATOR_FLAGS += --debug
|
||||
# Add this trace to get a backtrace in gdb
|
||||
#VERILATOR_FLAGS += --gdbbt
|
||||
|
||||
# Check if SC exists via a verilator call (empty if not)
|
||||
SYSTEMC_EXISTS := $(shell $(VERILATOR) --getenv SYSTEMC_INCLUDE)
|
||||
|
||||
######################################################################
|
||||
|
||||
ifneq ($(SYSTEMC_EXISTS),)
|
||||
default: run
|
||||
else
|
||||
default: nosc
|
||||
endif
|
||||
|
||||
run:
|
||||
@echo
|
||||
@echo "-- Verilator tracing example"
|
||||
|
||||
@echo
|
||||
@echo "-- VERILATE ----------------"
|
||||
$(VERILATOR) $(VERILATOR_FLAGS) -f input.vc top.v sc_main.cpp
|
||||
|
||||
@echo
|
||||
@echo "-- COMPILE ----------------="
|
||||
# To compile, we can either just do what Verilator asks,
|
||||
# or call a submakefile where we can override the rules ourselves
|
||||
# $(MAKE) -j 4 -C obj_dir -f Vtop.mk
|
||||
$(MAKE) -j 4 -C obj_dir -f ../Makefile_obj
|
||||
|
||||
@echo
|
||||
@echo "-- RUN ---------------------"
|
||||
@mkdir -p logs
|
||||
obj_dir/Vtop | tee logs/sim.log
|
||||
|
||||
@echo
|
||||
@echo "-- COVERAGE ----------------"
|
||||
$(VERILATOR_COVERAGE) --annotate logs/annotated logs/coverage.dat
|
||||
|
||||
@echo
|
||||
@echo "-- DONE --------------------"
|
||||
@echo "To see waveforms, open vlt_dump.vcd in a waveform viewer"
|
||||
@echo
|
||||
|
||||
######################################################################
|
||||
# Other targets
|
||||
|
||||
nosc:
|
||||
@echo
|
||||
@echo "%Skip: SYSTEMC_INCLUDE not in environment"
|
||||
@echo "(If you have SystemC see the README, and rebuild Verilator)"
|
||||
@echo
|
||||
|
||||
show-config:
|
||||
$(VERILATOR) -V
|
||||
|
||||
maintainer-copy::
|
||||
clean mostlyclean distclean maintainer-clean::
|
||||
-rm -rf obj_dir logs *.log *.dmp *.vpd coverage.dat core
|
||||
@@ -0,0 +1,63 @@
|
||||
# -*- Makefile -*-
|
||||
#######################################################################
|
||||
#
|
||||
# DESCRIPTION: Verilator Example: Makefile for inside object directory
|
||||
#
|
||||
# This is executed in the object directory, and called by ../Makefile
|
||||
#
|
||||
# Copyright 2003-2017 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.
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
default: Vtop
|
||||
|
||||
# Include the rules made by Verilator
|
||||
include Vtop.mk
|
||||
|
||||
#######################################################################
|
||||
# Compile flags
|
||||
|
||||
# Override some default compile flags
|
||||
CPPFLAGS += -MMD -MP
|
||||
CPPFLAGS += -DVL_DEBUG=1
|
||||
# SystemC isn't too clean
|
||||
CPPFLAGS += -Wno-deprecated
|
||||
# Turn on some more flags (when configured appropriately)
|
||||
# For testing inside Verilator, "configure --enable-ccwarn" will do this
|
||||
# automatically; otherwise you may want this unconditionally enabled
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
USER_CPPFLAGS_WALL += -W -Werror -Wall
|
||||
endif
|
||||
|
||||
# If you build your own rules from scratch, note you need to include
|
||||
# SystemC as follows (Vtop.mk file includes verilated.mk with these
|
||||
# already).
|
||||
# CPPFLAGS += $(SYSTEMC_CXX_FLAGS) -I$(SYSTEMC_INCLUDE)
|
||||
# LDFLAGS += $(SYSTEMC_CXX_FLAGS) -L$(SYSTEMC_LIBDIR)
|
||||
|
||||
# See the benchmarking section of bin/verilator.
|
||||
# Support class optimizations. This includes the tracing and symbol table.
|
||||
# SystemC takes minutes to optimize, thus it is off by default.
|
||||
OPT_SLOW =
|
||||
# Fast path optimizations. Most time is spent in these classes.
|
||||
OPT_FAST = -O2 -fstrict-aliasing
|
||||
#OPT_FAST = -O
|
||||
#OPT_FAST =
|
||||
|
||||
#######################################################################
|
||||
# Linking final exe -- presumes have a sim_main.cpp
|
||||
|
||||
# Special compile rule
|
||||
sim_main.o: sim_main.cpp $(VM_PREFIX).h
|
||||
|
||||
######################################################################
|
||||
######################################################################
|
||||
# Automatically understand dependencies
|
||||
|
||||
DEPS := $(wildcard *.d)
|
||||
ifneq ($(DEPS),)
|
||||
include $(DEPS)
|
||||
endif
|
||||
@@ -0,0 +1,2 @@
|
||||
// This file typically lists flags required by a large project, e.g. include directories
|
||||
+librescan +libext+.v+.sv+.vh+.svh -y .
|
||||
@@ -0,0 +1,136 @@
|
||||
// -*- SystemC -*-
|
||||
// DESCRIPTION: Verilator Example: Top level main for invoking SystemC model
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
//======================================================================
|
||||
|
||||
// SystemC global header
|
||||
#include <systemc.h>
|
||||
|
||||
// Include common routines
|
||||
#include <verilated.h>
|
||||
#if VM_TRACE
|
||||
#include <verilated_vcd_sc.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h> // mkdir
|
||||
|
||||
// Include model header, generated from Verilating "top.v"
|
||||
#include "Vtop.h"
|
||||
|
||||
int sc_main(int argc, char* argv[]) {
|
||||
// This is a more complicated example, please also see the simpler examples/hello_world_c.
|
||||
|
||||
// Prevent unused variable warnings
|
||||
if (0 && argc && argv) {}
|
||||
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
|
||||
Verilated::commandArgs(argc, argv);
|
||||
|
||||
// Set debug level, 0 is off, 9 is highest presently used
|
||||
Verilated::debug(0);
|
||||
|
||||
// Randomization reset policy
|
||||
Verilated::randReset(2);
|
||||
|
||||
// General logfile
|
||||
ios::sync_with_stdio();
|
||||
|
||||
// Defaults time
|
||||
#if (SYSTEMC_VERSION>20011000)
|
||||
#else
|
||||
sc_time dut(1.0, sc_ns);
|
||||
sc_set_default_time_unit(dut);
|
||||
#endif
|
||||
|
||||
// Define clocks
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_clock clk ("clk", 10,SC_NS, 0.5, 3,SC_NS, true);
|
||||
sc_clock fastclk ("fastclk", 2,SC_NS, 0.5, 2,SC_NS, true);
|
||||
#else
|
||||
sc_clock clk ("clk", 10, 0.5, 3, true);
|
||||
sc_clock fastclk ("fastclk", 2, 0.5, 2, true);
|
||||
#endif
|
||||
|
||||
// Define interconnect
|
||||
sc_signal<bool> reset_l;
|
||||
sc_signal<vluint32_t> in_small;
|
||||
sc_signal<vluint64_t> in_quad;
|
||||
sc_signal<sc_bv<70> > in_wide;
|
||||
sc_signal<vluint32_t> out_small;
|
||||
sc_signal<vluint64_t> out_quad;
|
||||
sc_signal<sc_bv<70> > out_wide;
|
||||
|
||||
// Construct the Verilated model, from inside Vtop.h
|
||||
Vtop* top = new Vtop("top");
|
||||
// Attach signals to the model
|
||||
top->clk (clk);
|
||||
top->fastclk (fastclk);
|
||||
top->reset_l (reset_l);
|
||||
top->in_small (in_small);
|
||||
top->in_quad (in_quad);
|
||||
top->in_wide (in_wide);
|
||||
top->out_small (out_small);
|
||||
top->out_quad (out_quad);
|
||||
top->out_wide (out_wide);
|
||||
|
||||
#if VM_TRACE
|
||||
// Before any evaluation, need to know to calculate those signals only used for tracing
|
||||
Verilated::traceEverOn(true);
|
||||
#endif
|
||||
|
||||
// You must do one evaluation before enabling waves, in order to allow
|
||||
// SystemC to interconnect everything for testing.
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_start(1,SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
|
||||
// Turn on waves
|
||||
#if VM_TRACE
|
||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||
VerilatedVcdSc* tfp = new VerilatedVcdSc;
|
||||
top->trace (tfp, 99);
|
||||
mkdir("logs", 0777);
|
||||
tfp->open ("logs/vlt_dump.vcd");
|
||||
#endif
|
||||
|
||||
// Simulate until $finish
|
||||
while (!Verilated::gotFinish()) {
|
||||
#if VM_TRACE
|
||||
// Flush the wave files each cycle so we can immediately see the output
|
||||
// Don't do this in "real" programs, do it in an abort() handler instead
|
||||
if (tfp) tfp->flush();
|
||||
// Apply inputs
|
||||
if (VL_TIME_Q() > 1 && VL_TIME_Q() < 10) {
|
||||
reset_l = !1; // Assert reset
|
||||
} else if (VL_TIME_Q() > 1) {
|
||||
reset_l = !0; // Deassert reset
|
||||
}
|
||||
#endif
|
||||
// Simulate 1ns
|
||||
#if (SYSTEMC_VERSION>=20070314)
|
||||
sc_start(1,SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Close Waves
|
||||
#if VM_TRACE
|
||||
if (tfp) tfp->close();
|
||||
#endif
|
||||
|
||||
// Final model cleanup
|
||||
top->final();
|
||||
|
||||
// Coverage analysis (since test passed)
|
||||
#if VM_COVERAGE
|
||||
mkdir("logs", 0777);
|
||||
VerilatedCov::write("logs/coverage.dat");
|
||||
#endif
|
||||
|
||||
// Fin
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// ======================================================================
|
||||
|
||||
module sub
|
||||
(
|
||||
input clk,
|
||||
input fastclk,
|
||||
input reset_l
|
||||
);
|
||||
|
||||
// Example counter/flop
|
||||
reg [31:0] count_f;
|
||||
always_ff @ (posedge fastclk) begin
|
||||
if (!reset_l) begin
|
||||
/*AUTORESET*/
|
||||
// Beginning of autoreset for uninitialized flops
|
||||
count_f <= 32'h0;
|
||||
// End of automatics
|
||||
end
|
||||
else begin
|
||||
count_f <= count_f + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Another example flop
|
||||
reg [31:0] count_c;
|
||||
always_ff @ (posedge clk) begin
|
||||
if (!reset_l) begin
|
||||
/*AUTORESET*/
|
||||
// Beginning of autoreset for uninitialized flops
|
||||
count_c <= 32'h0;
|
||||
// End of automatics
|
||||
end
|
||||
else begin
|
||||
count_c <= count_c + 1;
|
||||
if (count_c >= 3) begin
|
||||
$display("[%0t] fastclk is %0d times faster than clk\n",
|
||||
$time, count_f/count_c);
|
||||
// This write is a magic value the Makefile uses to make sure the
|
||||
// test completes successfully.
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// An example assertion
|
||||
always_ff @ (posedge clk) begin
|
||||
AssertionExample: assert (!reset_l || count_c<100);
|
||||
end
|
||||
|
||||
// And example coverage analysis
|
||||
cover property (@(posedge clk) count_c==3);
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,42 @@
|
||||
// DESCRIPTION: Verilator: Verilog example module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// ======================================================================
|
||||
|
||||
// This is intended to be a complex example of several features, please also
|
||||
// see the simpler examples/hello_world_c.
|
||||
|
||||
module top
|
||||
(
|
||||
// Declare some signals so we can see how I/O works
|
||||
input clk,
|
||||
input fastclk,
|
||||
input reset_l,
|
||||
|
||||
output [1:0] out_small,
|
||||
output [39:0] out_quad,
|
||||
output [69:0] out_wide,
|
||||
input [1:0] in_small,
|
||||
input [39:0] in_quad,
|
||||
input [69:0] in_wide
|
||||
);
|
||||
|
||||
// Connect up the outputs, using some trivial logic
|
||||
wire [1:0] out_small = ~reset_l ? '0 : (in_small + 2'b1);
|
||||
wire [39:0] out_quad = ~reset_l ? '0 : (in_quad + 40'b1);
|
||||
wire [69:0] out_wide = ~reset_l ? '0 : (in_wide + 70'b1);
|
||||
|
||||
// And an example sub module. The submodule will print stuff.
|
||||
sub sub (/*AUTOINST*/
|
||||
// Inputs
|
||||
.clk (clk),
|
||||
.fastclk (fastclk),
|
||||
.reset_l (reset_l));
|
||||
|
||||
// Print some stuff as an example
|
||||
initial begin
|
||||
$display("[%0t] Model running...\n", $time);
|
||||
end
|
||||
|
||||
endmodule
|
||||
+107
-104
@@ -37,9 +37,9 @@ VerilatedVoidCb Verilated::s_flushCb = NULL;
|
||||
|
||||
// Keep below together in one cache line
|
||||
Verilated::Serialized Verilated::s_s;
|
||||
VL_THREAD const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
||||
VL_THREAD const char* Verilated::t_dpiFilename = "";
|
||||
VL_THREAD int Verilated::t_dpiLineno = 0;
|
||||
VL_THREAD_LOCAL const VerilatedScope* Verilated::t_dpiScopep = NULL;
|
||||
VL_THREAD_LOCAL const char* Verilated::t_dpiFilename = "";
|
||||
VL_THREAD_LOCAL int Verilated::t_dpiLineno = 0;
|
||||
struct Verilated::CommandArgValues Verilated::s_args = {0, NULL};
|
||||
|
||||
VerilatedImp VerilatedImp::s_s;
|
||||
@@ -194,9 +194,9 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
|
||||
if (vw == 1) { // Single divisor word breaks rest of algorithm
|
||||
vluint64_t k = 0;
|
||||
for (int j = uw-1; j >= 0; --j) {
|
||||
vluint64_t unw64 = ((k<<VL_ULL(32)) + (vluint64_t)(lwp[j]));
|
||||
owp[j] = unw64 / (vluint64_t)(rwp[0]);
|
||||
k = unw64 - (vluint64_t)(owp[j])*(vluint64_t)(rwp[0]);
|
||||
vluint64_t unw64 = ((k<<VL_ULL(32)) + static_cast<vluint64_t>(lwp[j]));
|
||||
owp[j] = unw64 / static_cast<vluint64_t>(rwp[0]);
|
||||
k = unw64 - static_cast<vluint64_t>(owp[j])*static_cast<vluint64_t>(rwp[0]);
|
||||
}
|
||||
if (is_modulus) {
|
||||
owp[0] = k;
|
||||
@@ -233,9 +233,9 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
|
||||
// Main loop
|
||||
for (int j = uw - vw; j >= 0; --j) {
|
||||
// Estimate
|
||||
vluint64_t unw64 = ((vluint64_t)(un[j+vw])<<VL_ULL(32) | (vluint64_t)(un[j+vw-1]));
|
||||
vluint64_t qhat = unw64 / (vluint64_t)(vn[vw-1]);
|
||||
vluint64_t rhat = unw64 - qhat*(vluint64_t)(vn[vw-1]);
|
||||
vluint64_t unw64 = (static_cast<vluint64_t>(un[j+vw])<<VL_ULL(32) | static_cast<vluint64_t>(un[j+vw-1]));
|
||||
vluint64_t qhat = unw64 / static_cast<vluint64_t>(vn[vw-1]);
|
||||
vluint64_t rhat = unw64 - qhat*static_cast<vluint64_t>(vn[vw-1]);
|
||||
|
||||
again:
|
||||
if (qhat >= VL_ULL(0x100000000)
|
||||
@@ -262,7 +262,7 @@ WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, boo
|
||||
owp[j]--;
|
||||
k = 0;
|
||||
for (int i=0; i<vw; ++i) {
|
||||
t = (vluint64_t)(un[i+j]) + (vluint64_t)(vn[i]) + k;
|
||||
t = static_cast<vluint64_t>(un[i+j]) + static_cast<vluint64_t>(vn[i]) + k;
|
||||
un[i+j] = t;
|
||||
k = t >> VL_ULL(32);
|
||||
}
|
||||
@@ -308,7 +308,7 @@ WDataOutP VL_POW_WWQ(int obits, int lbits, int rbits, WDataOutP owp, WDataInP lw
|
||||
WData rhsw[2]; VL_SET_WQ(rhsw, rhs);
|
||||
return VL_POW_WWW(obits,lbits,rbits,owp,lwp,rhsw);
|
||||
}
|
||||
QData VL_POW_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp) {
|
||||
QData VL_POW_QQW(int, int, int rbits, QData lhs, WDataInP rwp) {
|
||||
// Skip check for rhs == 0, as short-circuit doesn't save time
|
||||
if (VL_UNLIKELY(lhs==0)) return 0;
|
||||
QData power = lhs;
|
||||
@@ -364,7 +364,7 @@ QData VL_POWSS_QQW(int obits, int, int rbits, QData lhs, WDataInP rwp, bool lsig
|
||||
// Do a va_arg returning a quad, assuming input argument is anything less than wide
|
||||
#define _VL_VA_ARG_Q(ap, bits) (((bits) <= VL_WORDSIZE) ? va_arg(ap,IData) : va_arg(ap,QData))
|
||||
|
||||
void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
void _vl_vsformat(std::string& output, const char* formatp, va_list ap) {
|
||||
// Format a Verilog $write style format into the output list
|
||||
// The format must be pre-processed (and lower cased) by Verilator
|
||||
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||
@@ -372,8 +372,8 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Note uses a single buffer internally; presumes only one usage per printf
|
||||
// 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];
|
||||
static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD_LOCAL char tmpf[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const char* pctp = NULL; // Most recent %##.##g format
|
||||
bool inPct = false;
|
||||
bool widthSet = false;
|
||||
@@ -420,7 +420,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
}
|
||||
case '@': { // Verilog/C++ string
|
||||
va_arg(ap, int); // # bits is ignored
|
||||
const string* cstrp = va_arg(ap, const string*);
|
||||
const std::string* cstrp = va_arg(ap, const std::string*);
|
||||
output += *cstrp;
|
||||
break;
|
||||
}
|
||||
@@ -467,7 +467,8 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
}
|
||||
break;
|
||||
case 'd': { // Signed decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||
int digits = sprintf(tmp,"%" VL_PRI64 "d",
|
||||
static_cast<vlsint64_t>(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
@@ -498,8 +499,8 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||
} else if (VL_TIME_MULTIPLIER==1000) {
|
||||
digits=sprintf(tmp,"%" VL_PRI64 "u.%03" VL_PRI64 "u",
|
||||
(QData)(ld/VL_TIME_MULTIPLIER),
|
||||
(QData)(ld%VL_TIME_MULTIPLIER));
|
||||
static_cast<QData>(ld/VL_TIME_MULTIPLIER),
|
||||
static_cast<QData>(ld%VL_TIME_MULTIPLIER));
|
||||
} else {
|
||||
vl_fatal(__FILE__,__LINE__,"","Unsupported VL_TIME_MULTIPLIER");
|
||||
}
|
||||
@@ -529,20 +530,20 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
case 'u': // Packed 2-state
|
||||
output.reserve(output.size() + 4*VL_WORDS_I(lbits));
|
||||
for (int i=0; i<VL_WORDS_I(lbits); ++i) {
|
||||
output += (char)((lwp[i] ) & 0xff);
|
||||
output += (char)((lwp[i] >> 8) & 0xff);
|
||||
output += (char)((lwp[i] >> 16) & 0xff);
|
||||
output += (char)((lwp[i] >> 24) & 0xff);
|
||||
output += static_cast<char>((lwp[i] ) & 0xff);
|
||||
output += static_cast<char>((lwp[i] >> 8) & 0xff);
|
||||
output += static_cast<char>((lwp[i] >> 16) & 0xff);
|
||||
output += static_cast<char>((lwp[i] >> 24) & 0xff);
|
||||
}
|
||||
break;
|
||||
case 'z': // Packed 4-state
|
||||
output.reserve(output.size() + 8*VL_WORDS_I(lbits));
|
||||
for (int i=0; i<VL_WORDS_I(lbits); ++i) {
|
||||
output += (char)((lwp[i] ) & 0xff);
|
||||
output += (char)((lwp[i] >> 8) & 0xff);
|
||||
output += (char)((lwp[i] >> 16) & 0xff);
|
||||
output += (char)((lwp[i] >> 24) & 0xff);
|
||||
output += "\0\0\0\0"; // No tristate
|
||||
output += static_cast<char>((lwp[i] ) & 0xff);
|
||||
output += static_cast<char>((lwp[i] >> 8) & 0xff);
|
||||
output += static_cast<char>((lwp[i] >> 16) & 0xff);
|
||||
output += static_cast<char>((lwp[i] >> 24) & 0xff);
|
||||
output += "\0\0\0\0"; // No tristate
|
||||
}
|
||||
break;
|
||||
case 'v': // Strength; assume always strong
|
||||
@@ -559,7 +560,7 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
string msg = string("Unknown _vl_vsformat code: ")+pos[0];
|
||||
std::string msg = std::string("Unknown _vl_vsformat code: ")+pos[0];
|
||||
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||
break;
|
||||
} // switch
|
||||
@@ -577,7 +578,7 @@ static inline void _vl_vsss_advance(FILE* fp, int& floc) {
|
||||
if (fp) fgetc(fp);
|
||||
else floc -= 8;
|
||||
}
|
||||
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const string& fstr) {
|
||||
static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr) {
|
||||
// Get a character without advancing
|
||||
if (fp) {
|
||||
int data = fgetc(fp);
|
||||
@@ -594,14 +595,14 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp, const stri
|
||||
}
|
||||
}
|
||||
}
|
||||
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp, const string& fstr) {
|
||||
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr) {
|
||||
while (1) {
|
||||
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
if (c==EOF || !isspace(c)) return;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
}
|
||||
}
|
||||
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const string& fstr,
|
||||
static inline void _vl_vsss_read(FILE* fp, int& floc, WDataInP fromp, const std::string& fstr,
|
||||
char* tmpp, const char* acceptp) {
|
||||
// Read into tmp, consisting of characters from acceptp list
|
||||
char* cp = tmpp;
|
||||
@@ -622,10 +623,10 @@ static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits,
|
||||
VL_ASSIGNBIT_WI(0, lsb, owp, ld & 1);
|
||||
}
|
||||
}
|
||||
static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, int posstart, int posend) {
|
||||
static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp, size_t posstart, size_t posend) {
|
||||
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
|
||||
int lsb = 0;
|
||||
for (int i=0, pos=posend-1; i<obits && pos>=posstart; --pos) {
|
||||
for (int i=0, pos=static_cast<int>(posend)-1; i<obits && pos>=static_cast<int>(posstart); --pos) {
|
||||
switch (tolower (strp[pos])) {
|
||||
case 'x': case 'z': case '?': //FALLTHRU
|
||||
case '0': lsb += baseLog2; break;
|
||||
@@ -651,12 +652,12 @@ static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const
|
||||
|
||||
IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
int fbits, WDataInP fromp, // Else if a sscanf
|
||||
const string& fstr, // if a sscanf to string
|
||||
const std::string& fstr, // if a sscanf to string
|
||||
const char* formatp, va_list ap) {
|
||||
// Read a Verilog $sscanf/$fscanf style format into the output list
|
||||
// The format must be pre-processed (and lower cased) by Verilator
|
||||
// Arguments are in "width, arg-value (or WDataIn* if wide)" form
|
||||
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
int floc = fbits - 1;
|
||||
IData got = 0;
|
||||
bool inPct = false;
|
||||
@@ -706,10 +707,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
||||
_vl_vsss_read(fp,floc,fromp,fstr, tmp, NULL);
|
||||
if (!tmp[0]) goto done;
|
||||
int pos = ((int)strlen(tmp))-1;
|
||||
int lpos = (static_cast<int>(strlen(tmp)))-1;
|
||||
int lsb = 0;
|
||||
for (int i=0; i<obits && pos>=0; --pos) {
|
||||
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[pos]); lsb+=8;
|
||||
for (int i=0; i<obits && lpos>=0; --lpos) {
|
||||
_vl_vsss_setbit(owp,obits,lsb, 8, tmp[lpos]); lsb+=8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -748,25 +749,25 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
||||
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "01xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_based(owp,obits, 1, tmp, 0, (int)strlen(tmp));
|
||||
_vl_vsss_based(owp,obits, 1, tmp, 0, strlen(tmp));
|
||||
break;
|
||||
}
|
||||
case 'o': {
|
||||
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
||||
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "01234567xXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_based(owp,obits, 3, tmp, 0, (int)strlen(tmp));
|
||||
_vl_vsss_based(owp,obits, 3, tmp, 0, strlen(tmp));
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
_vl_vsss_skipspace(fp,floc,fromp,fstr);
|
||||
_vl_vsss_read(fp,floc,fromp,fstr, tmp, "0123456789abcdefABCDEFxXzZ?_");
|
||||
if (!tmp[0]) goto done;
|
||||
_vl_vsss_based(owp,obits, 4, tmp, 0, (int)strlen(tmp));
|
||||
_vl_vsss_based(owp,obits, 4, tmp, 0, strlen(tmp));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
string msg = string("Unknown _vl_vsscanf code: ")+pos[0];
|
||||
std::string msg = std::string("Unknown _vl_vsscanf code: ")+pos[0];
|
||||
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||
break;
|
||||
} // switch
|
||||
@@ -814,12 +815,12 @@ void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||
if (!start) while (isspace(*(destp-1)) && destp>destoutp) *--destp = '\0'; // Drop trailing spaces
|
||||
}
|
||||
|
||||
void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||
void _VL_STRING_TO_VINT(int obits, void* destp, size_t srclen, const char* srcp) {
|
||||
// Convert C string to Verilog format
|
||||
int bytes = VL_BYTES_I(obits);
|
||||
char* op = ((char*)(destp));
|
||||
size_t bytes = VL_BYTES_I(obits);
|
||||
char* op = reinterpret_cast<char*>(destp);
|
||||
if (srclen > bytes) srclen = bytes; // Don't overflow destination
|
||||
int i;
|
||||
size_t i;
|
||||
for (i=0; i<srclen; ++i) { *op++ = srcp[srclen-1-i]; }
|
||||
for (; i<bytes; ++i) { *op++ = 0; }
|
||||
}
|
||||
@@ -852,7 +853,7 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
|
||||
return got;
|
||||
}
|
||||
|
||||
IData VL_FOPEN_NI(const string& filename, IData mode) {
|
||||
IData VL_FOPEN_NI(const std::string& filename, IData mode) {
|
||||
char modez[5];
|
||||
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
|
||||
return VL_FOPEN_S(filename.c_str(), modez);
|
||||
@@ -880,61 +881,61 @@ void VL_FCLOSE_I(IData fdi) {
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, CData& destr, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, &destr, (int)output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, SData& destr, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, &destr, (int)output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, IData& destr, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, &destr, (int)output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, QData& destr, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, &destr, (int)output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, &destr, output.length(), output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
_vl_vsformat(output, formatp, ap);
|
||||
va_end(ap);
|
||||
|
||||
_VL_STRING_TO_VINT(obits, destp, (int)output.length(), output.c_str());
|
||||
_VL_STRING_TO_VINT(obits, destp, output.length(), output.c_str());
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) {
|
||||
void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, ...) {
|
||||
if (obits_ignored) {}
|
||||
output = "";
|
||||
va_list ap;
|
||||
@@ -943,8 +944,8 @@ void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...) {
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
std::string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
@@ -955,7 +956,7 @@ string VL_SFORMATF_NX(const char* formatp, ...) {
|
||||
}
|
||||
|
||||
void VL_WRITEF(const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
@@ -967,7 +968,7 @@ void VL_WRITEF(const char* formatp, ...) {
|
||||
}
|
||||
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||
VL_STATIC_OR_THREAD string output; // static only for speed
|
||||
static VL_THREAD_LOCAL std::string output; // static only for speed
|
||||
output = "";
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
@@ -1016,7 +1017,7 @@ IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) {
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
IData VL_SSCANF_INX(int, const string& ld, const char* formatp, ...) {
|
||||
IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
IData got = _vl_vsscanf(NULL, ld.length()*8, NULL, ld, formatp, ap);
|
||||
@@ -1034,12 +1035,12 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilenamep, void* memp, IData start, IData end) {
|
||||
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
|
||||
string ofilenames(ofilenamez);
|
||||
std::string ofilenames(ofilenamez);
|
||||
return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end);
|
||||
}
|
||||
|
||||
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const string& ofilenamep, void* memp, IData start, IData end) {
|
||||
const std::string& ofilenamep, void* memp, IData start, IData end) {
|
||||
if (fnwords) {}
|
||||
FILE* fp = fopen(ofilenamep.c_str(), "r");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
@@ -1088,32 +1089,34 @@ void VL_READMEM_N(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 (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) {
|
||||
if (VL_UNLIKELY(addr >= static_cast<IData>(depth+array_lsb)
|
||||
|| addr < static_cast<IData>(array_lsb))) {
|
||||
vl_fatal (ofilenamep.c_str(), linenum, "", "$readmem file address beyond bounds of array");
|
||||
} else {
|
||||
int entry = addr - array_lsb;
|
||||
QData shift = hex ? VL_ULL(4) : VL_ULL(1);
|
||||
// Shift value in
|
||||
if (width<=8) {
|
||||
CData* datap = &((CData*)(memp))[entry];
|
||||
CData* datap = &(reinterpret_cast<CData*>(memp))[entry];
|
||||
if (!innum) { *datap = 0; }
|
||||
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||
} else if (width<=16) {
|
||||
SData* datap = &((SData*)(memp))[entry];
|
||||
SData* datap = &(reinterpret_cast<SData*>(memp))[entry];
|
||||
if (!innum) { *datap = 0; }
|
||||
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||
} else if (width<=VL_WORDSIZE) {
|
||||
IData* datap = &((IData*)(memp))[entry];
|
||||
IData* datap = &(reinterpret_cast<IData*>(memp))[entry];
|
||||
if (!innum) { *datap = 0; }
|
||||
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
|
||||
} else if (width<=VL_QUADSIZE) {
|
||||
QData* datap = &((QData*)(memp))[entry];
|
||||
QData* datap = &(reinterpret_cast<QData*>(memp))[entry];
|
||||
if (!innum) { *datap = 0; }
|
||||
*datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width);
|
||||
*datap = ((*datap << static_cast<QData>(shift))
|
||||
+ static_cast<QData>(value)) & VL_MASK_Q(width);
|
||||
} else {
|
||||
WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ];
|
||||
WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))[ entry*VL_WORDS_I(width) ];
|
||||
if (!innum) { VL_ZERO_RESET_W(width, datap); }
|
||||
_VL_SHIFTL_INPLACE_W(width, datap, (IData)shift);
|
||||
_VL_SHIFTL_INPLACE_W(width, datap, static_cast<IData>(shift));
|
||||
datap[0] |= value;
|
||||
}
|
||||
if (VL_UNLIKELY(value>=(1<<shift))) {
|
||||
@@ -1150,13 +1153,13 @@ IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
|
||||
}
|
||||
|
||||
IData VL_TESTPLUSARGS_I(const char* formatp) {
|
||||
const string& match = VerilatedImp::argPlusMatch(formatp);
|
||||
const std::string& match = VerilatedImp::argPlusMatch(formatp);
|
||||
if (match == "") return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
IData VL_VALUEPLUSARGS_INW(int rbits, const string& ld, WDataOutP rwp) {
|
||||
string prefix;
|
||||
IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) {
|
||||
std::string prefix;
|
||||
bool inPct = false;
|
||||
bool done = false;
|
||||
char fmt = ' ';
|
||||
@@ -1179,29 +1182,29 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const string& ld, WDataOutP rwp) {
|
||||
}
|
||||
}
|
||||
|
||||
const string& match = VerilatedImp::argPlusMatch(prefix.c_str());
|
||||
const std::string& match = VerilatedImp::argPlusMatch(prefix.c_str());
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + prefix.length();
|
||||
if (match == "") return 0;
|
||||
|
||||
VL_ZERO_RESET_W(rbits, rwp);
|
||||
switch (tolower(fmt)) {
|
||||
case 'd':
|
||||
vlsint64_t ld;
|
||||
sscanf(dp,"%30" VL_PRI64 "d",&ld);
|
||||
VL_SET_WQ(rwp,ld);
|
||||
vlsint64_t lld;
|
||||
sscanf(dp,"%30" VL_PRI64 "d",&lld);
|
||||
VL_SET_WQ(rwp,lld);
|
||||
break;
|
||||
case 'b':
|
||||
_vl_vsss_based(rwp,rbits, 1, dp, 0, (int)strlen(dp));
|
||||
_vl_vsss_based(rwp,rbits, 1, dp, 0, strlen(dp));
|
||||
break;
|
||||
case 'o':
|
||||
_vl_vsss_based(rwp,rbits, 3, dp, 0, (int)strlen(dp));
|
||||
_vl_vsss_based(rwp,rbits, 3, dp, 0, strlen(dp));
|
||||
break;
|
||||
case 'h': //FALLTHRU
|
||||
case 'x':
|
||||
_vl_vsss_based(rwp,rbits, 4, dp, 0, (int)strlen(dp));
|
||||
_vl_vsss_based(rwp,rbits, 4, dp, 0, strlen(dp));
|
||||
break;
|
||||
case 's': // string/no conversion
|
||||
for (int i=0, lsb=0, posp=((int)strlen(dp))-1; i<rbits && posp>=0; --posp) {
|
||||
for (int i=0, lsb=0, posp=static_cast<int>(strlen(dp))-1; i<rbits && posp>=0; --posp) {
|
||||
_vl_vsss_setbit(rwp,rbits,lsb, 8, dp[posp]); lsb+=8;
|
||||
}
|
||||
break;
|
||||
@@ -1214,8 +1217,8 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const string& ld, WDataOutP rwp) {
|
||||
_VL_CLEAN_INPLACE_W(rbits,rwp);
|
||||
return 1;
|
||||
}
|
||||
IData VL_VALUEPLUSARGS_INN(int, const string& ld, string& rdr) {
|
||||
string prefix;
|
||||
IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) {
|
||||
std::string prefix;
|
||||
bool inPct = false;
|
||||
bool done = false;
|
||||
for (const char* posp = ld.c_str(); !done && *posp; ++posp) {
|
||||
@@ -1235,16 +1238,16 @@ IData VL_VALUEPLUSARGS_INN(int, const string& ld, string& rdr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
const string& match = VerilatedImp::argPlusMatch(prefix.c_str());
|
||||
const std::string& match = VerilatedImp::argPlusMatch(prefix.c_str());
|
||||
const char* dp = match.c_str() + 1 /*leading + */ + prefix.length();
|
||||
if (match == "") return 0;
|
||||
rdr = string(dp);
|
||||
rdr = std::string(dp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* vl_mc_scan_plusargs(const char* prefixp) {
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
if (match == "") return NULL;
|
||||
strncpy(outstr, match.c_str()+strlen(prefixp)+1, // +1 to skip the "+"
|
||||
VL_VALUE_STRING_MAX_WIDTH);
|
||||
@@ -1255,7 +1258,7 @@ const char* vl_mc_scan_plusargs(const char* prefixp) {
|
||||
//===========================================================================
|
||||
// Heavy functions
|
||||
|
||||
string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
|
||||
std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
|
||||
// See also _VL_VINT_TO_STRING
|
||||
char destout[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
int obits = lwords * VL_WORDSIZE;
|
||||
@@ -1272,7 +1275,7 @@ string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) {
|
||||
start = false; // Drop leading 0s
|
||||
}
|
||||
}
|
||||
return string(destout, len);
|
||||
return std::string(destout, len);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
@@ -1311,8 +1314,8 @@ void Verilated::commandArgs(int argc, const char** argv) {
|
||||
}
|
||||
|
||||
const char* Verilated::commandArgsPlusMatch(const char* prefixp) {
|
||||
const string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
if (match == "") return "";
|
||||
strncpy(outstr, match.c_str(), VL_VALUE_STRING_MAX_WIDTH);
|
||||
outstr[VL_VALUE_STRING_MAX_WIDTH-1] = '\0';
|
||||
@@ -1442,19 +1445,19 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap,
|
||||
} 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());
|
||||
vl_fatal(__FILE__,__LINE__,"",(std::string("Unsupported multi-dimensional public varInsert: ")+namep).c_str());
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
m_varsp->insert(make_pair(namep,var));
|
||||
m_varsp->insert(std::make_pair(namep,var));
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction // Used by applications
|
||||
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())) {
|
||||
if (VL_LIKELY(it != m_varsp->end())) {
|
||||
return &(it->second);
|
||||
}
|
||||
}
|
||||
@@ -1463,19 +1466,19 @@ VerilatedVar* VerilatedScope::varFind(const char* namep) const {
|
||||
|
||||
void* VerilatedScope::exportFindNullError(int funcnum) {
|
||||
// Slowpath - Called only when find has failed
|
||||
string msg = (string("Testbench C called '")
|
||||
+VerilatedImp::exportName(funcnum)
|
||||
+"' but scope wasn't set, perhaps due to dpi import call without 'context'");
|
||||
std::string msg = (std::string("Testbench C called '")
|
||||
+VerilatedImp::exportName(funcnum)
|
||||
+"' but scope wasn't set, perhaps due to dpi import call without 'context'");
|
||||
vl_fatal("unknown",0,"", msg.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* VerilatedScope::exportFindError(int funcnum) const {
|
||||
// Slowpath - Called only when find has failed
|
||||
string msg = (string("Testbench C called '")
|
||||
+VerilatedImp::exportName(funcnum)
|
||||
+"' but this DPI export function exists only in other scopes, not scope '"
|
||||
+name()+"'");
|
||||
std::string msg = (std::string("Testbench C called '")
|
||||
+VerilatedImp::exportName(funcnum)
|
||||
+"' but this DPI export function exists only in other scopes, not scope '"
|
||||
+name()+"'");
|
||||
vl_fatal("unknown",0,"", msg.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+101
-69
@@ -40,7 +40,6 @@
|
||||
// <iostream> avoided to reduce compile time
|
||||
// <map> avoided and instead in verilated_heavy.h to reduce compile time
|
||||
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
||||
using namespace std;
|
||||
|
||||
//=============================================================================
|
||||
// Switches
|
||||
@@ -235,9 +234,9 @@ class Verilated {
|
||||
Serialized();
|
||||
} s_s;
|
||||
|
||||
static VL_THREAD const VerilatedScope* t_dpiScopep; ///< DPI context scope
|
||||
static VL_THREAD const char* t_dpiFilename; ///< DPI context filename
|
||||
static VL_THREAD int t_dpiLineno; ///< DPI context line number
|
||||
static VL_THREAD_LOCAL const VerilatedScope* t_dpiScopep; ///< DPI context scope
|
||||
static VL_THREAD_LOCAL const char* t_dpiFilename; ///< DPI context filename
|
||||
static VL_THREAD_LOCAL int t_dpiLineno; ///< DPI context line number
|
||||
|
||||
// no need to be save-restored (serialized) the
|
||||
// assumption is that the restore is allowed to pass different arguments
|
||||
@@ -287,7 +286,7 @@ public:
|
||||
|
||||
/// Record command line arguments, for retrieval by $test$plusargs/$value$plusargs
|
||||
static void commandArgs(int argc, const char** argv);
|
||||
static void commandArgs(int argc, char** argv) { commandArgs(argc,(const char**)argv); }
|
||||
static void commandArgs(int argc, char** argv) { commandArgs(argc, const_cast<const char**>(argv)); }
|
||||
static void commandArgsAdd(int argc, const char** argv);
|
||||
static CommandArgValues* getCommandArgs() {return &s_args;}
|
||||
/// Match plusargs with a given prefix. Returns static char* valid only for a single call
|
||||
@@ -405,10 +404,10 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
|
||||
/// Create two 32-bit words from quadword
|
||||
/// WData is always at least 2 words; does not clean upper bits
|
||||
#define VL_SET_WQ(owp,data) { owp[0]=(IData)(data); owp[1]=(IData)((data)>>VL_WORDSIZE); }
|
||||
#define VL_SET_WI(owp,data) { owp[0]=(IData)(data); owp[1]=0; }
|
||||
#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) )
|
||||
#define VL_SET_WQ(owp,data) { owp[0]=static_cast<IData>(data); owp[1]=static_cast<IData>((data)>>VL_WORDSIZE); }
|
||||
#define VL_SET_WI(owp,data) { owp[0]=static_cast<IData>(data); owp[1]=0; }
|
||||
#define VL_SET_QW(lwp) ( (static_cast<QData>(lwp[0])) | (static_cast<QData>(lwp[1])<<(static_cast<QData>(VL_WORDSIZE)) ))
|
||||
#define _VL_SET_QII(ld,rd) ( (static_cast<QData>(ld)<<VL_ULL(32)) | static_cast<QData>(rd) )
|
||||
|
||||
/// Return FILE* from IData
|
||||
extern FILE* VL_CVT_I_FP(IData lhs);
|
||||
@@ -423,11 +422,11 @@ static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q
|
||||
/// 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))); }
|
||||
static inline double VL_ITOR_D_I(IData lhs) { return static_cast<double>(static_cast<vlsint32_t>(lhs)); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(VL_TRUNC(lhs))); }
|
||||
static inline IData VL_RTOI_I_D(double lhs) { return static_cast<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))); }
|
||||
static inline IData VL_RTOIROUND_I_D(double lhs) { return static_cast<vlsint32_t>(VL_ROUND(lhs)); }
|
||||
|
||||
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
||||
// (Requires clean input)
|
||||
@@ -442,7 +441,7 @@ static inline IData VL_EXTENDSIGN_I(int lbits, IData lhs) { return (-((lhs)&(VL
|
||||
static inline QData VL_EXTENDSIGN_Q(int lbits, QData lhs) { return (-((lhs)&(VL_ULL(1)<<(lbits-1)))); }
|
||||
|
||||
// Debugging prints
|
||||
void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
extern void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
|
||||
//=========================================================================
|
||||
// Pli macros
|
||||
@@ -456,13 +455,13 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
|
||||
/// Return current simulation time
|
||||
#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))
|
||||
# define VL_TIME_I() (static_cast<IData>(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() (static_cast<QData>(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() (static_cast<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))
|
||||
# define VL_TIME_I() (static_cast<IData>(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() (static_cast<QData>(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() (static_cast<double>(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
extern double sc_time_stamp();
|
||||
#endif
|
||||
|
||||
@@ -582,8 +581,8 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
od = (svar.read().get_word(0)) & VL_MASK_I(obits); \
|
||||
}
|
||||
#define VL_ASSIGN_QSW(obits,od,svar) { \
|
||||
od = (((QData)svar.read().get_word(1))<<VL_WORDSIZE | svar.read().get_word(0)) \
|
||||
& VL_MASK_Q(obits); \
|
||||
od = ((static_cast<QData>(svar.read().get_word(1)))<<VL_WORDSIZE | svar.read().get_word(0)) \
|
||||
& VL_MASK_Q(obits); \
|
||||
}
|
||||
#define VL_ASSIGN_WSW(obits,owp,svar) { \
|
||||
int words = VL_WORDS_I(obits); \
|
||||
@@ -617,8 +616,8 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
}
|
||||
#define VL_ASSIGN_SWQ(obits,svar,rd) { \
|
||||
sc_bv<obits> _bvtemp; \
|
||||
_bvtemp.set_word(0,(IData)(rd)); \
|
||||
_bvtemp.set_word(1,(IData)((rd)>>VL_WORDSIZE)); \
|
||||
_bvtemp.set_word(0, static_cast<IData>(rd)); \
|
||||
_bvtemp.set_word(1, static_cast<IData>((rd)>>VL_WORDSIZE)); \
|
||||
svar.write(_bvtemp); \
|
||||
}
|
||||
#define VL_ASSIGN_SWW(obits,svar,rwp) { \
|
||||
@@ -649,7 +648,7 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
// Right must be clean because otherwise size increase would pick up bad bits
|
||||
// EMIT_RULE: VL_EXTEND: oclean=clean; rclean==clean;
|
||||
#define VL_EXTEND_II(obits,lbits,lhs) ((lhs))
|
||||
#define VL_EXTEND_QI(obits,lbits,lhs) ((QData)(lhs))
|
||||
#define VL_EXTEND_QI(obits,lbits,lhs) (static_cast<QData>(lhs))
|
||||
#define VL_EXTEND_QQ(obits,lbits,lhs) ((lhs))
|
||||
|
||||
static inline WDataOutP VL_EXTEND_WI(int obits, int, WDataOutP owp, IData ld) {
|
||||
@@ -769,7 +768,7 @@ static inline IData VL_REDXOR_64(QData r) {
|
||||
return __builtin_parityll(r);
|
||||
#else
|
||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16)); r=(r^(r>>32));
|
||||
return (IData)r;
|
||||
return static_cast<IData>(r);
|
||||
#endif
|
||||
}
|
||||
static inline IData VL_REDXOR_W(int words, WDataInP lwp) {
|
||||
@@ -788,7 +787,7 @@ static inline IData VL_COUNTONES_I(IData lhs) {
|
||||
return r;
|
||||
}
|
||||
static inline IData VL_COUNTONES_Q(QData lhs) {
|
||||
return VL_COUNTONES_I((IData)lhs) + VL_COUNTONES_I((IData)(lhs>>32));
|
||||
return VL_COUNTONES_I(static_cast<IData>(lhs)) + VL_COUNTONES_I(static_cast<IData>(lhs>>32));
|
||||
}
|
||||
static inline IData VL_COUNTONES_W(int words, WDataInP lwp) {
|
||||
IData r = 0;
|
||||
@@ -1025,7 +1024,7 @@ static inline int _VL_CMPS_W(int lbits, WDataInP lwp, WDataInP rwp) {
|
||||
static inline WDataOutP VL_ADD_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; ++i) {
|
||||
carry = carry + (QData)(lwp[i]) + (QData)(rwp[i]);
|
||||
carry = carry + static_cast<QData>(lwp[i]) + static_cast<QData>(rwp[i]);
|
||||
owp[i] = (carry & VL_ULL(0xffffffff));
|
||||
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
||||
}
|
||||
@@ -1035,7 +1034,7 @@ static inline WDataOutP VL_ADD_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
|
||||
static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP rwp){
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; ++i) {
|
||||
carry = carry + (QData)(lwp[i]) + (QData)(IData)(~rwp[i]);
|
||||
carry = carry + static_cast<QData>(lwp[i]) + static_cast<QData>(static_cast<IData>(~rwp[i]));
|
||||
if (i==0) carry++; // Negation of temp2
|
||||
owp[i] = (carry & VL_ULL(0xffffffff));
|
||||
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
||||
@@ -1052,7 +1051,7 @@ static inline QData VL_NEGATE_Q(QData data) { return -data; }
|
||||
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]);
|
||||
carry = carry + static_cast<QData>(static_cast<IData>(~lwp[i]));
|
||||
if (i==0) carry++; // Negation of temp2
|
||||
owp[i] = (carry & VL_ULL(0xffffffff));
|
||||
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
||||
@@ -1064,9 +1063,9 @@ static inline WDataOutP VL_MUL_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
|
||||
for (int i=0; i<words; ++i) owp[i] = 0;
|
||||
for (int lword=0; lword<words; ++lword) {
|
||||
for (int rword=0; rword<words; ++rword) {
|
||||
QData mul = (QData)(lwp[lword]) * (QData)(rwp[rword]);
|
||||
QData mul = static_cast<QData>(lwp[lword]) * static_cast<QData>(rwp[rword]);
|
||||
for (int qword=lword+rword; qword<words; ++qword) {
|
||||
mul += (QData)(owp[qword]);
|
||||
mul += static_cast<QData>(owp[qword]);
|
||||
owp[qword] = (mul & VL_ULL(0xffffffff));
|
||||
mul = (mul >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
||||
}
|
||||
@@ -1112,7 +1111,7 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
|
||||
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]);
|
||||
carry = carry + static_cast<QData>(static_cast<IData>(~owp[i]));
|
||||
if (i==0) carry++; // Negation of temp2
|
||||
owp[i] = (carry & VL_ULL(0xffffffff));
|
||||
carry = (carry >> VL_ULL(32)) & VL_ULL(0xffffffff);
|
||||
@@ -1358,7 +1357,7 @@ static inline void _VL_INSERT_WQ(int obits, WDataOutP owp, QData ld, int hbit, i
|
||||
// EMIT_RULE: VL_REPLICATE: oclean=clean>width32, dirty<=width32; lclean=clean; rclean==clean;
|
||||
// RHS MUST BE CLEAN CONSTANT.
|
||||
#define VL_REPLICATE_IOI(obits,lbits,rbits, ld, rep) (-(ld)) // Iff lbits==1
|
||||
#define VL_REPLICATE_QOI(obits,lbits,rbits, ld, rep) (-((QData)ld)) // Iff lbits==1
|
||||
#define VL_REPLICATE_QOI(obits,lbits,rbits, ld, rep) (-(static_cast<QData>(ld))) // Iff lbits==1
|
||||
|
||||
static inline IData VL_REPLICATE_III(int, int lbits, int, IData ld, IData rep) {
|
||||
IData returndata = ld;
|
||||
@@ -1372,7 +1371,7 @@ static inline QData VL_REPLICATE_QII(int, int lbits, int, IData ld, IData rep) {
|
||||
QData returndata = ld;
|
||||
for (unsigned i=1; i < rep; ++i){
|
||||
returndata = returndata << lbits;
|
||||
returndata |= (QData)ld;
|
||||
returndata |= static_cast<QData>(ld);
|
||||
}
|
||||
return (returndata);
|
||||
}
|
||||
@@ -1498,7 +1497,7 @@ static inline QData VL_STREAML_QQI(int, int lbits, int, QData ld, IData rd) {
|
||||
static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WDataInP lwp, IData rd) {
|
||||
VL_ZERO_W(lbits, owp);
|
||||
// Slice size should never exceed the lhs width
|
||||
int ssize = (rd < (IData)lbits) ? rd : ((IData)lbits);
|
||||
int ssize = (rd < static_cast<IData>(lbits)) ? rd : (static_cast<IData>(lbits));
|
||||
for (int istart=0; istart<lbits; istart+=rd) {
|
||||
int ostart=lbits-rd-istart;
|
||||
ostart = ostart > 0 ? ostart : 0;
|
||||
@@ -1516,11 +1515,11 @@ static inline WDataOutP VL_STREAML_WWI(int, int lbits, int, WDataOutP owp, WData
|
||||
// Thus we specify inputs must be clean, so we don't need to clean the output.
|
||||
// Note the bit shifts are always constants, so the adds in these constify out.
|
||||
// Casts required, as args may be 8 bit entities, and need to shift to appropriate output size
|
||||
#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) ((IData)(ld)<<(rbits) | (IData)(rd))
|
||||
#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) ((QData)(ld)<<(rbits) | (QData)(rd))
|
||||
#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) ((QData)(ld)<<(rbits) | (QData)(rd))
|
||||
#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) ((QData)(ld)<<(rbits) | (QData)(rd))
|
||||
#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) ((QData)(ld)<<(rbits) | (QData)(rd))
|
||||
#define VL_CONCAT_III(obits,lbits,rbits,ld,rd) (static_cast<IData>(ld)<<(rbits) | static_cast<IData>(rd))
|
||||
#define VL_CONCAT_QII(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QIQ(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QQI(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
#define VL_CONCAT_QQQ(obits,lbits,rbits,ld,rd) (static_cast<QData>(ld)<<(rbits) | static_cast<QData>(rd))
|
||||
|
||||
static inline WDataOutP VL_CONCAT_WII(int obits,int lbits,int rbits,WDataOutP owp,IData ld,IData rd) {
|
||||
owp[0] = rd;
|
||||
@@ -1598,7 +1597,7 @@ static inline void _VL_SHIFTL_INPLACE_W(int obits,WDataOutP iowp,IData rd/*1 or
|
||||
static inline WDataOutP VL_SHIFTL_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||
int word_shift = VL_BITWORD_I(rd);
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
if (rd >= (IData)obits) { // rd may be huge with MSB set
|
||||
if (rd >= static_cast<IData>(obits)) { // rd may be huge with MSB set
|
||||
for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
} else if (bit_shift==0) { // Aligned word shift (<<0,<<32,<<64 etc)
|
||||
for (int i=0; i < word_shift; ++i) owp[i] = 0;
|
||||
@@ -1632,7 +1631,7 @@ static inline IData VL_SHIFTL_IIW(int obits,int,int rbits,IData lhs, WDataInP rw
|
||||
static inline WDataOutP VL_SHIFTR_WWI(int obits,int,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||
int word_shift = VL_BITWORD_I(rd); // Maybe 0
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
if (rd >= (IData)obits) { // rd may be huge with MSB set
|
||||
if (rd >= static_cast<IData>(obits)) { // rd may be huge with MSB set
|
||||
for (int i=0; i < VL_WORDS_I(obits); ++i) owp[i] = 0;
|
||||
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
||||
int copy_words = (VL_WORDS_I(obits)-word_shift);
|
||||
@@ -1687,14 +1686,14 @@ static inline QData VL_SHIFTRS_QQI(int obits, int lbits, int, QData lhs, IData r
|
||||
return (lhs >> rhs) | (sign & VL_CLEAN_QQ(obits,obits,signext));
|
||||
}
|
||||
static inline IData VL_SHIFTRS_IQI(int obits, int lbits, int rbits, QData lhs, IData rhs) {
|
||||
return (IData)(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs));
|
||||
return static_cast<IData>(VL_SHIFTRS_QQI(obits, lbits, rbits, lhs, rhs));
|
||||
}
|
||||
static inline WDataOutP VL_SHIFTRS_WWI(int obits,int lbits,int,WDataOutP owp,WDataInP lwp, IData rd) {
|
||||
int word_shift = VL_BITWORD_I(rd);
|
||||
int bit_shift = VL_BITBIT_I(rd);
|
||||
int lmsw = VL_WORDS_I(obits)-1;
|
||||
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
|
||||
if (rd >= (IData)obits) { // Shifting past end, sign in all of lbits
|
||||
if (rd >= static_cast<IData>(obits)) { // Shifting past end, sign in all of lbits
|
||||
for (int i=0; i <= lmsw; ++i) owp[i] = sign;
|
||||
owp[lmsw] &= VL_MASK_I(lbits);
|
||||
} else if (bit_shift==0) { // Aligned word shift (>>0,>>32,>>64 etc)
|
||||
@@ -1726,7 +1725,7 @@ static inline WDataOutP VL_SHIFTRS_WWW(int obits,int lbits,int rbits,WDataOutP o
|
||||
if (VL_UNLIKELY(rwp[i])) { // Huge shift 1>>32 or more
|
||||
int lmsw = VL_WORDS_I(obits)-1;
|
||||
IData sign = VL_SIGNONES_I(lbits,lwp[lmsw]);
|
||||
for (int i=0; i <= lmsw; ++i) owp[i] = sign;
|
||||
for (int j=0; j <= lmsw; ++j) owp[j] = sign;
|
||||
owp[lmsw] &= VL_MASK_I(lbits);
|
||||
return owp;
|
||||
}
|
||||
@@ -1767,11 +1766,11 @@ static inline QData VL_SHIFTRS_QQQ(int obits,int lbits,int rbits,QData lhs, QDat
|
||||
#define VL_BITSEL_IIII(obits,lbits,rbits,zbits,lhs,rhs) ((lhs)>>(rhs))
|
||||
#define VL_BITSEL_QIII(obits,lbits,rbits,zbits,lhs,rhs) ((lhs)>>(rhs))
|
||||
#define VL_BITSEL_QQII(obits,lbits,rbits,zbits,lhs,rhs) ((lhs)>>(rhs))
|
||||
#define VL_BITSEL_IQII(obits,lbits,rbits,zbits,lhs,rhs) ((IData)((lhs)>>(rhs)))
|
||||
#define VL_BITSEL_IQII(obits,lbits,rbits,zbits,lhs,rhs) (static_cast<IData>((lhs)>>(rhs)))
|
||||
|
||||
static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData rd) {
|
||||
int word = VL_BITWORD_I(rd);
|
||||
if (VL_UNLIKELY(rd>(IData)lbits)) {
|
||||
if (VL_UNLIKELY(rd > static_cast<IData>(lbits))) {
|
||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||
// We return all 1's as that's more likely to find bugs (?) than 0's.
|
||||
} else {
|
||||
@@ -1783,13 +1782,13 @@ static inline IData VL_BITSEL_IWII(int, int lbits, int, int, WDataInP lwp, IData
|
||||
// <msb> & <lsb> MUST BE CLEAN (currently constant)
|
||||
#define VL_SEL_IIII(obits,lbits,rbits,tbits,lhs,lsb,width) ((lhs)>>(lsb))
|
||||
#define VL_SEL_QQII(obits,lbits,rbits,tbits,lhs,lsb,width) ((lhs)>>(lsb))
|
||||
#define VL_SEL_IQII(obits,lbits,rbits,tbits,lhs,lsb,width) ((IData)((lhs)>>(lsb)))
|
||||
#define VL_SEL_IQII(obits,lbits,rbits,tbits,lhs,lsb,width) (static_cast<IData>((lhs)>>(lsb)))
|
||||
|
||||
static inline IData VL_SEL_IWII(int, int lbits, int, int, WDataInP lwp, IData lsb, IData width) {
|
||||
int msb = lsb+width-1;
|
||||
if (VL_UNLIKELY(msb>lbits)) {
|
||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I((int)lsb)) {
|
||||
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast<int>(lsb))) {
|
||||
return (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
|
||||
} else {
|
||||
// 32 bit extraction may span two words
|
||||
@@ -1803,9 +1802,9 @@ static inline QData VL_SEL_QWII(int, int lbits, int, int, WDataInP lwp, IData ls
|
||||
int msb = lsb+width-1;
|
||||
if (VL_UNLIKELY(msb>lbits)) {
|
||||
return ~0; // Spec says you can go outside the range of a array. Don't coredump if so.
|
||||
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I((int)lsb)) {
|
||||
} else if (VL_BITWORD_I(msb)==VL_BITWORD_I(static_cast<int>(lsb))) {
|
||||
return (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
|
||||
} else if (VL_BITWORD_I(msb)==1+VL_BITWORD_I((int)lsb)) {
|
||||
} else if (VL_BITWORD_I(msb)==1+VL_BITWORD_I(static_cast<int>(lsb))) {
|
||||
int nbitsfromlow = 32-VL_BITBIT_I(lsb);
|
||||
QData hi = (lwp[VL_BITWORD_I(msb)]);
|
||||
QData lo = (lwp[VL_BITWORD_I(lsb)]>>VL_BITBIT_I(lsb));
|
||||
@@ -1838,7 +1837,7 @@ static inline WDataOutP VL_SEL_WWII(int obits,int lbits,int,int,WDataOutP owp,WD
|
||||
for (int i=0; i<words; ++i) {
|
||||
owp[i] = lwp[i+word_shift]>>loffset;
|
||||
int upperword = i+word_shift+1;
|
||||
if (upperword <= (int)VL_BITWORD_I(msb)) {
|
||||
if (upperword <= static_cast<int>(VL_BITWORD_I(msb))) {
|
||||
owp[i] |= lwp[upperword]<< nbitsfromlow;
|
||||
}
|
||||
}
|
||||
@@ -1895,64 +1894,97 @@ static inline WDataOutP VL_COND_WIWW(int obits, int, int, int,
|
||||
// Constification
|
||||
|
||||
// VL_CONST_W_#X(int obits, WDataOutP owp, IData data0, .... IData data(#-1))
|
||||
// Sets wide vector words to specified constant words, zeros upper data.
|
||||
|
||||
// Sets wide vector words to specified constant words.
|
||||
// These macros are used when o might represent more words then are given as constants,
|
||||
// hence all upper words must be zeroed.
|
||||
// If changing the number of functions here, also change EMITCINLINES_NUM_CONSTW
|
||||
|
||||
#define _END(obits,wordsSet) \
|
||||
for(int i=(wordsSet);i<VL_WORDS_I(obits);++i) o[i] = (IData)0x0; \
|
||||
for(int i=(wordsSet);i<VL_WORDS_I(obits);++i) o[i] = 0; \
|
||||
return o
|
||||
|
||||
#define VL_HAVE_CONST_W_1X
|
||||
static inline WDataOutP VL_CONST_W_1X(int obits, WDataOutP o,
|
||||
IData d0) {
|
||||
o[0]=d0;
|
||||
_END(obits,1); }
|
||||
#define VL_HAVE_CONST_W_2X
|
||||
static inline WDataOutP VL_CONST_W_2X(int obits, WDataOutP o,
|
||||
IData d1,IData d0) {
|
||||
o[0]=d0; o[1]=d1;
|
||||
_END(obits,2); }
|
||||
#define VL_HAVE_CONST_W_3X
|
||||
static inline WDataOutP VL_CONST_W_3X(int obits, WDataOutP o,
|
||||
IData d2,IData d1,IData d0) {
|
||||
o[0]=d0; o[1]=d1; o[2]=d2;
|
||||
_END(obits,3); }
|
||||
#define VL_HAVE_CONST_W_4X
|
||||
static inline WDataOutP VL_CONST_W_4X(int obits, WDataOutP o,
|
||||
IData d3,IData d2,IData d1,IData d0) {
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
|
||||
_END(obits,4); }
|
||||
#define VL_HAVE_CONST_W_5X
|
||||
static inline WDataOutP VL_CONST_W_5X(int obits, WDataOutP o,
|
||||
IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
|
||||
_END(obits,5); }
|
||||
#define VL_HAVE_CONST_W_6X
|
||||
static inline WDataOutP VL_CONST_W_6X(int obits, WDataOutP o,
|
||||
IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
|
||||
_END(obits,6); }
|
||||
#define VL_HAVE_CONST_W_7X
|
||||
static inline WDataOutP VL_CONST_W_7X(int obits, WDataOutP o,
|
||||
IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
|
||||
_END(obits,7); }
|
||||
#define VL_HAVE_CONST_W_8X
|
||||
static inline WDataOutP VL_CONST_W_8X(int obits, WDataOutP o,
|
||||
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
||||
_END(obits,8); }
|
||||
#define VL_HAVE_CONST_W_9X
|
||||
static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
||||
IData d8,
|
||||
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
//
|
||||
static inline WDataOutP VL_CONSTHI_W_1X(int obits, int lsb, WDataOutP obase,
|
||||
IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0;
|
||||
_END(obits,1); }
|
||||
static inline WDataOutP VL_CONSTHI_W_2X(int obits, int lsb, WDataOutP obase,
|
||||
IData d1,IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1;
|
||||
_END(obits,2); }
|
||||
static inline WDataOutP VL_CONSTHI_W_3X(int obits, int lsb, WDataOutP obase,
|
||||
IData d2,IData d1,IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2;
|
||||
_END(obits,3); }
|
||||
static inline WDataOutP VL_CONSTHI_W_4X(int obits, int lsb, WDataOutP obase,
|
||||
IData d3,IData d2,IData d1,IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3;
|
||||
_END(obits,4); }
|
||||
static inline WDataOutP VL_CONSTHI_W_5X(int obits, int lsb, WDataOutP obase,
|
||||
IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4;
|
||||
_END(obits,5); }
|
||||
static inline WDataOutP VL_CONSTHI_W_6X(int obits, int lsb, WDataOutP obase,
|
||||
IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5;
|
||||
_END(obits,6); }
|
||||
static inline WDataOutP VL_CONSTHI_W_7X(int obits, int lsb, WDataOutP obase,
|
||||
IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6;
|
||||
_END(obits,7); }
|
||||
static inline WDataOutP VL_CONSTHI_W_8X(int obits, int lsb, WDataOutP obase,
|
||||
IData d7,IData d6,IData d5,IData d4,IData d3,IData d2,IData d1,IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7;
|
||||
o[8]=d8;
|
||||
_END(obits,9); }
|
||||
_END(obits,8); }
|
||||
|
||||
#undef _END
|
||||
|
||||
// Partial constant, lower words of vector wider than 8*32, starting at bit number lsb
|
||||
static inline void VL_CONSTLO_W_8X(int lsb, WDataOutP obase,
|
||||
IData d7, IData d6, IData d5, IData d4, IData d3, IData d2, IData d1, IData d0) {
|
||||
WDataOutP o = obase + VL_WORDS_I(lsb);
|
||||
o[0]=d0; o[1]=d1; o[2]=d2; o[3]=d3; o[4]=d4; o[5]=d5; o[6]=d6; o[7]=d7; }
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif /*_VERILATED_H_*/
|
||||
|
||||
@@ -16,8 +16,14 @@ RANLIB = ranlib
|
||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||
|
||||
# Select newest language
|
||||
CFG_CXXFLAGS_STD_NEWEST = @CFG_CXXFLAGS_STD_NEWEST@
|
||||
# Select oldest language (for Verilator internal testing only)
|
||||
CFG_CXXFLAGS_STD_OLDEST = @CFG_CXXFLAGS_STD_OLDEST@
|
||||
# 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@
|
||||
# Compiler flags that turn on extra warnings
|
||||
CFG_CXXFLAGS_WEXTRA = @CFG_CXXFLAGS_WEXTRA@
|
||||
|
||||
######################################################################
|
||||
# Programs
|
||||
@@ -48,8 +54,7 @@ VK_CPPFLAGS_ALWAYS += \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
VK_CPPFLAGS_WALL += -Wall \
|
||||
-Werror
|
||||
VK_CPPFLAGS_WALL += -Wall $(CFG_CXXFLAGS_WEXTRA) -Werror
|
||||
endif
|
||||
|
||||
CPPFLAGS += -I. $(VK_CPPFLAGS_WALL) $(VK_CPPFLAGS_ALWAYS)
|
||||
|
||||
+46
-46
@@ -90,9 +90,9 @@ public:
|
||||
class VerilatedCovImp : VerilatedCovImpBase {
|
||||
private:
|
||||
// TYPES
|
||||
typedef map<string,int> ValueIndexMap;
|
||||
typedef map<int,string> IndexValueMap;
|
||||
typedef deque<VerilatedCovImpItem*> ItemList;
|
||||
typedef std::map<std::string,int> ValueIndexMap;
|
||||
typedef std::map<int,std::string> IndexValueMap;
|
||||
typedef std::deque<VerilatedCovImpItem*> ItemList;
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
@@ -119,18 +119,18 @@ public:
|
||||
|
||||
private:
|
||||
// PRIVATE METHODS
|
||||
int valueIndex(const string& value) {
|
||||
int valueIndex(const std::string& value) {
|
||||
static int nextIndex = KEY_UNDEF+1;
|
||||
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
||||
if (iter != m_valueIndexes.end()) return iter->second;
|
||||
nextIndex++; assert(nextIndex>0);
|
||||
m_valueIndexes.insert(make_pair(value, nextIndex));
|
||||
m_indexValues.insert(make_pair(nextIndex, value));
|
||||
m_valueIndexes.insert(std::make_pair(value, nextIndex));
|
||||
m_indexValues.insert(std::make_pair(nextIndex, value));
|
||||
return nextIndex;
|
||||
}
|
||||
string dequote(const string& text) {
|
||||
static std::string dequote(const std::string& text) {
|
||||
// Quote any special characters
|
||||
string rtn;
|
||||
std::string rtn;
|
||||
for (const char* pos = text.c_str(); *pos; ++pos) {
|
||||
if (!isprint(*pos) || *pos=='%' || *pos=='"') {
|
||||
char hex[10]; sprintf(hex,"%%%02X",pos[0]);
|
||||
@@ -141,7 +141,7 @@ private:
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
bool legalKey(const string& key) {
|
||||
static bool legalKey(const std::string& key) {
|
||||
// Because we compress long keys to a single letter, and
|
||||
// don't want applications to either get confused if they use
|
||||
// a letter differently, nor want them to rely on our compression...
|
||||
@@ -150,17 +150,17 @@ private:
|
||||
if (key.length()==2 && isdigit(key[1])) return false;
|
||||
return true;
|
||||
}
|
||||
string keyValueFormatter (const string& key, const string& value) {
|
||||
string name;
|
||||
static std::string keyValueFormatter (const std::string& key, const std::string& value) {
|
||||
std::string name;
|
||||
if (key.length()==1 && isalpha(key[0])) {
|
||||
name += string("\001")+key;
|
||||
name += std::string("\001")+key;
|
||||
} else {
|
||||
name += string("\001")+dequote(key);
|
||||
name += std::string("\001")+dequote(key);
|
||||
}
|
||||
name += string("\002")+dequote(value);
|
||||
name += std::string("\002")+dequote(value);
|
||||
return name;
|
||||
}
|
||||
string combineHier (const string& old, const string& add) {
|
||||
static std::string combineHier (const std::string& old, const std::string& add) {
|
||||
// (foo.a.x, foo.b.x) => foo.*.x
|
||||
// (foo.a.x, foo.b.y) => foo.*
|
||||
// (foo.a.x, foo.b) => foo.*
|
||||
@@ -178,7 +178,7 @@ private:
|
||||
|
||||
// We used to backup and split on only .'s but it seems better to be verbose
|
||||
// and not assume . is the separator
|
||||
string prefix = string(a,apre-a);
|
||||
std::string prefix = std::string(a,apre-a);
|
||||
|
||||
// Scan backward to last mismatch
|
||||
const char* apost = a+strlen(a)-1;
|
||||
@@ -187,26 +187,26 @@ private:
|
||||
&& apost>apre && bpost>bpre) { apost--; bpost--; }
|
||||
|
||||
// Forward to . so we have a whole word
|
||||
string suffix = *bpost ? string(bpost+1) : "";
|
||||
std::string suffix = *bpost ? std::string(bpost+1) : "";
|
||||
|
||||
string out = prefix+"*"+suffix;
|
||||
std::string out = prefix+"*"+suffix;
|
||||
|
||||
//cout << "\nch pre="<<prefix<<" s="<<suffix<<"\nch a="<<old<<"\nch b="<<add<<"\nch o="<<out<<endl;
|
||||
return out;
|
||||
}
|
||||
bool itemMatchesString(VerilatedCovImpItem* itemp, const string& match) {
|
||||
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match) {
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
// We don't compare keys, only values
|
||||
string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (string::npos != val.find(match)) { // Found
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (std::string::npos != val.find(match)) { // Found
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void selftest() {
|
||||
static void selftest() {
|
||||
// Little selftest
|
||||
if (combineHier ("a.b.c","a.b.c") !="a.b.c") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
if (combineHier ("a.b.c","a.b") !="a.b*") vl_fatal(__FILE__,__LINE__,"","%Error: selftest\n");
|
||||
@@ -221,7 +221,7 @@ private:
|
||||
public:
|
||||
// PUBLIC METHODS
|
||||
void clear() {
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
delete itemp;
|
||||
}
|
||||
@@ -244,7 +244,7 @@ public:
|
||||
}
|
||||
}
|
||||
void zero() {
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
(*it)->zero();
|
||||
}
|
||||
}
|
||||
@@ -263,18 +263,18 @@ public:
|
||||
assert(m_insertp);
|
||||
// First two key/vals are filename
|
||||
ckeyps[0]="filename"; valps[0]=m_insertFilenamep;
|
||||
string linestr = vlCovCvtToStr(m_insertLineno);
|
||||
std::string linestr = vlCovCvtToStr(m_insertLineno);
|
||||
ckeyps[1]="lineno"; valps[1]=linestr.c_str();
|
||||
// Default page if not specified
|
||||
const char* fnstartp = m_insertFilenamep;
|
||||
while (const char* foundp = strchr(fnstartp,'/')) fnstartp=foundp+1;
|
||||
const char* fnendp = fnstartp;
|
||||
while (*fnendp && *fnendp!='.') fnendp++;
|
||||
string page_default = "sp_user/"+string(fnstartp,fnendp-fnstartp);
|
||||
std::string page_default = "sp_user/"+std::string(fnstartp,fnendp-fnstartp);
|
||||
ckeyps[2]="page"; valps[2]=page_default.c_str();
|
||||
|
||||
// Keys -> strings
|
||||
string keys[MAX_KEYS];
|
||||
std::string keys[MAX_KEYS];
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (ckeyps[i] && ckeyps[i][0]) {
|
||||
keys[i] = ckeyps[i];
|
||||
@@ -294,15 +294,15 @@ public:
|
||||
// Insert the values
|
||||
int addKeynum=0;
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
const string key = keys[i];
|
||||
const std::string key = keys[i];
|
||||
if (keys[i]!="") {
|
||||
const string val = valps[i];
|
||||
const std::string val = valps[i];
|
||||
//cout<<" "<<__FUNCTION__<<" "<<key<<" = "<<val<<endl;
|
||||
m_insertp->m_keys[addKeynum] = valueIndex(key);
|
||||
m_insertp->m_vals[addKeynum] = valueIndex(val);
|
||||
addKeynum++;
|
||||
if (!legalKey(key)) {
|
||||
string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
|
||||
std::string msg = "%Error: Coverage keys of one character, or letter+digit are illegal: "+key;
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
}
|
||||
}
|
||||
@@ -318,27 +318,27 @@ public:
|
||||
#endif
|
||||
selftest();
|
||||
|
||||
ofstream os (filename);
|
||||
std::ofstream os (filename);
|
||||
if (os.fail()) {
|
||||
string msg = (string)"%Error: Can't write '"+filename+"'";
|
||||
std::string msg = std::string("%Error: Can't write '")+filename+"'";
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
return;
|
||||
}
|
||||
os << "# SystemC::Coverage-3\n";
|
||||
|
||||
// Build list of events; totalize if collapsing hierarchy
|
||||
typedef map<string,pair<string,vluint64_t> > EventMap;
|
||||
EventMap eventCounts;
|
||||
typedef std::map<std::string,std::pair<std::string,vluint64_t> > EventMap;
|
||||
EventMap eventCounts;
|
||||
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
string name;
|
||||
string hier;
|
||||
std::string name;
|
||||
std::string hier;
|
||||
bool per_instance = false;
|
||||
|
||||
for (int i=0; i<MAX_KEYS; ++i) {
|
||||
if (itemp->m_keys[i] != KEY_UNDEF) {
|
||||
string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
||||
string val = m_indexValues[itemp->m_vals[i]];
|
||||
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
|
||||
std::string val = m_indexValues[itemp->m_vals[i]];
|
||||
if (key == VL_CIK_PER_INSTANCE) {
|
||||
if (val != "0") per_instance = true;
|
||||
}
|
||||
@@ -363,21 +363,21 @@ public:
|
||||
// Find or insert the named event
|
||||
EventMap::iterator cit = eventCounts.find(name);
|
||||
if (cit != eventCounts.end()) {
|
||||
const string& oldhier = cit->second.first;
|
||||
const std::string& oldhier = cit->second.first;
|
||||
cit->second.second += itemp->count();
|
||||
cit->second.first = combineHier(oldhier, hier);
|
||||
} else {
|
||||
eventCounts.insert(make_pair(name, make_pair(hier,itemp->count())));
|
||||
eventCounts.insert(std::make_pair(name, make_pair(hier,itemp->count())));
|
||||
}
|
||||
}
|
||||
|
||||
// Output body
|
||||
for (EventMap::iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
|
||||
os<<"C '"<<dec;
|
||||
for (EventMap::const_iterator it=eventCounts.begin(); it!=eventCounts.end(); ++it) {
|
||||
os<<"C '"<<std::dec;
|
||||
os<<it->first;
|
||||
if (it->second.first != "") os<<keyValueFormatter(VL_CIK_HIER,it->second.first);
|
||||
os<<"' "<<it->second.second;
|
||||
os<<endl;
|
||||
os<<std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -441,9 +441,9 @@ void VerilatedCov::_insertp (A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),
|
||||
}
|
||||
// Backward compatibility for Verilator
|
||||
void VerilatedCov::_insertp (A(0), A(1), K(2),int val2, K(3),int val3,
|
||||
K(4),const string& val4, A(5),A(6)) {
|
||||
string val2str = vlCovCvtToStr(val2);
|
||||
string val3str = vlCovCvtToStr(val3);
|
||||
K(4),const std::string& val4, A(5),A(6)) {
|
||||
std::string val2str = vlCovCvtToStr(val2);
|
||||
std::string val3str = vlCovCvtToStr(val3);
|
||||
_insertp(C(0),C(1),
|
||||
key2,val2str.c_str(), key3,val3str.c_str(), key4, val4.c_str(),
|
||||
C(5),C(6),N(7),N(8),N(9),
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//=============================================================================
|
||||
/// Conditionally compile coverage code
|
||||
@@ -75,7 +74,7 @@ using namespace std;
|
||||
/// Convert VL_COVER_INSERT value arguments to strings
|
||||
|
||||
template< class T> std::string vlCovCvtToStr (const T& t) {
|
||||
ostringstream os; os<<t; return os.str();
|
||||
std::ostringstream os; os<<t; return os.str();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@@ -115,7 +114,7 @@ public:
|
||||
,A(20),D(21),D(22),D(23),D(24),D(25),D(26),D(27),D(28),D(29));
|
||||
// Backward compatibility for Verilator
|
||||
static void _insertp (A(0), A(1), K(2),int val2, K(3),int val3,
|
||||
K(4),const string& val4, A(5),A(6));
|
||||
K(4),const std::string& val4, A(5),A(6));
|
||||
|
||||
#undef K
|
||||
#undef A
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//=============================================================================
|
||||
// Data used to edit below file, using vlcovgen
|
||||
@@ -105,7 +104,7 @@ VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr
|
||||
|
||||
class VerilatedCovKey {
|
||||
public:
|
||||
static string shortKey(const string& key) {
|
||||
static std::string shortKey(const std::string& key) {
|
||||
// VLCOVGEN_SHORT_AUTO_EDIT_BEGIN
|
||||
if (key == "col0") return VL_CIK_COL0;
|
||||
if (key == "col0_name") return VL_CIK_COL0_NAME;
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
|
||||
// On MSVC++ we need svdpi.h to declare exports, not imports
|
||||
#define DPI_PROTOTYPES
|
||||
#undef XXTERN
|
||||
#define XXTERN DPI_EXTERN DPI_DLLESPEC
|
||||
#undef EETERN
|
||||
#define EETERN DPI_EXTERN DPI_DLLESPEC
|
||||
|
||||
#include "vltstd/svdpi.h"
|
||||
@@ -40,7 +42,7 @@
|
||||
|
||||
// Not supported yet
|
||||
#define _VL_SVDPI_UNIMP() \
|
||||
vl_fatal(__FILE__,__LINE__,"",(string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
|
||||
vl_fatal(__FILE__,__LINE__,"",(std::string("%%Error: Unsupported DPI function: ")+VL_FUNC).c_str())
|
||||
|
||||
// Function requires a "context" in the import declaration
|
||||
#define _VL_SVDPI_CONTEXT_WARN() \
|
||||
@@ -261,13 +263,13 @@ svScope svGetScope() {
|
||||
|
||||
svScope svSetScope(const svScope scope) {
|
||||
const VerilatedScope* prevScopep = Verilated::dpiScope();
|
||||
const VerilatedScope* vscopep = (const VerilatedScope*)(scope);
|
||||
const VerilatedScope* vscopep = reinterpret_cast<const VerilatedScope*>(scope);
|
||||
Verilated::dpiScope(vscopep);
|
||||
return (svScope)prevScopep;
|
||||
}
|
||||
|
||||
const char* svGetNameFromScope(const svScope scope) {
|
||||
const VerilatedScope* vscopep = (const VerilatedScope*)(scope);
|
||||
const VerilatedScope* vscopep = reinterpret_cast<const VerilatedScope*>(scope);
|
||||
return vscopep->name();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
/// \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.
|
||||
/// 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
|
||||
///
|
||||
|
||||
+21
-21
@@ -16,10 +16,10 @@
|
||||
/// \file
|
||||
/// \brief Verilator: String include for all Verilated C files
|
||||
///
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all C++ files it generates. It is used when strings or other
|
||||
/// heavyweight types are required; these contents are not part of
|
||||
/// verilated.h to save compile time when such types aren't used.
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all C++ files it generates. It is used when strings or other
|
||||
/// heavyweight types are required; these contents are not part of
|
||||
/// verilated.h to save compile time when such types aren't used.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
@@ -36,49 +36,49 @@
|
||||
//======================================================================
|
||||
// Conversion functions
|
||||
|
||||
extern string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp);
|
||||
inline string VL_CVT_PACK_STR_NQ(QData lhs) {
|
||||
extern std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp);
|
||||
inline std::string VL_CVT_PACK_STR_NQ(QData lhs) {
|
||||
WData lw[2]; VL_SET_WQ(lw, lhs);
|
||||
return VL_CVT_PACK_STR_NW(2, lw);
|
||||
}
|
||||
inline string VL_CVT_PACK_STR_NN(const string& lhs) {
|
||||
inline std::string VL_CVT_PACK_STR_NN(const std::string& lhs) {
|
||||
return lhs;
|
||||
}
|
||||
inline string VL_CVT_PACK_STR_NI(IData lhs) {
|
||||
inline std::string VL_CVT_PACK_STR_NI(IData lhs) {
|
||||
WData lw[1]; lw[0] = lhs;
|
||||
return VL_CVT_PACK_STR_NW(1, lw);
|
||||
}
|
||||
inline string VL_CONCATN_NNN(const string& lhs, const string& rhs) {
|
||||
inline std::string VL_CONCATN_NNN(const std::string& lhs, const std::string& rhs) {
|
||||
return lhs+rhs;
|
||||
}
|
||||
inline string VL_REPLICATEN_NNQ(int,int,int, const string& lhs, IData rep) {
|
||||
string out; out.reserve(lhs.length() * rep);
|
||||
inline std::string VL_REPLICATEN_NNQ(int,int,int, const std::string& lhs, IData rep) {
|
||||
std::string out; out.reserve(lhs.length() * rep);
|
||||
for (unsigned times=0; times<rep; ++times) out += lhs;
|
||||
return out;
|
||||
}
|
||||
inline string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const string& lhs, IData rep) {
|
||||
inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits, const std::string& lhs, IData rep) {
|
||||
return VL_REPLICATEN_NNQ(obits,lbits,rbits,lhs,rep);
|
||||
}
|
||||
|
||||
extern IData VL_FOPEN_NI(const string& filename, IData mode);
|
||||
extern IData VL_FOPEN_NI(const std::string& filename, IData mode);
|
||||
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const string& ofilename, void* memp, IData start, IData end);
|
||||
extern IData VL_SSCANF_INX(int lbits, const string& ld, const char* formatp, ...);
|
||||
extern void VL_SFORMAT_X(int obits_ignored, string &output, const char* formatp, ...);
|
||||
extern string VL_SFORMATF_NX(const char* formatp, ...);
|
||||
extern IData VL_VALUEPLUSARGS_INW(int rbits, const string& ld, WDataOutP rdp);
|
||||
inline IData VL_VALUEPLUSARGS_INI(int rbits, const string& ld, IData& rdr) {
|
||||
const std::string& ofilename, void* memp, IData start, IData end);
|
||||
extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp, ...);
|
||||
extern void VL_SFORMAT_X(int obits_ignored, std::string &output, const char* formatp, ...);
|
||||
extern std::string VL_SFORMATF_NX(const char* formatp, ...);
|
||||
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rdp);
|
||||
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, IData& rdr) {
|
||||
WData rwp[2]; // WData must always be at least 2
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
|
||||
if (got) rdr = rwp[0];
|
||||
return got;
|
||||
}
|
||||
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const string& ld, QData& rdr) {
|
||||
inline IData VL_VALUEPLUSARGS_INQ(int rbits, const std::string& ld, QData& rdr) {
|
||||
WData rwp[2];
|
||||
IData got = VL_VALUEPLUSARGS_INW(rbits,ld,rwp);
|
||||
if (got) rdr = VL_SET_QW(rwp);
|
||||
return got;
|
||||
}
|
||||
extern IData VL_VALUEPLUSARGS_INN(int, const string& ld, string& rdr);
|
||||
extern IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr);
|
||||
|
||||
#endif // Guard
|
||||
|
||||
+22
-22
@@ -47,9 +47,9 @@ class VerilatedImp {
|
||||
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||
|
||||
// TYPES
|
||||
typedef vector<string> ArgVec;
|
||||
typedef map<pair<const void*,void*>,void*> UserMap;
|
||||
typedef map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||
typedef std::vector<std::string> ArgVec;
|
||||
typedef std::map<std::pair<const void*,void*>,void*> UserMap;
|
||||
typedef std::map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||
|
||||
// MEMBERS
|
||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
||||
@@ -65,8 +65,8 @@ class VerilatedImp {
|
||||
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)
|
||||
std::vector<FILE*> m_fdps; ///< File descriptors
|
||||
std::deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
@@ -80,7 +80,7 @@ public: // But only for verilated*.cpp
|
||||
static void internalsDump() {
|
||||
VL_PRINTF("internalsDump:\n");
|
||||
VL_PRINTF(" Argv:");
|
||||
for (ArgVec::iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
VL_PRINTF(" %s",it->c_str());
|
||||
}
|
||||
VL_PRINTF("\n");
|
||||
@@ -100,7 +100,7 @@ public: // But only for verilated*.cpp
|
||||
for (int i=0; i<argc; ++i) s_s.m_argVec.push_back(argv[i]);
|
||||
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||
}
|
||||
static string argPlusMatch(const char* prefixp) {
|
||||
static std::string argPlusMatch(const char* prefixp) {
|
||||
// Note prefixp does not include the leading "+"
|
||||
size_t len = strlen(prefixp);
|
||||
if (VL_UNLIKELY(!s_s.m_argVecLoaded)) {
|
||||
@@ -109,7 +109,7 @@ public: // But only for verilated*.cpp
|
||||
"%Error: Verilog called $test$plusargs or $value$plusargs without"
|
||||
" testbench C first calling Verilated::commandArgs(argc,argv).");
|
||||
}
|
||||
for (ArgVec::iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
for (ArgVec::const_iterator it=s_s.m_argVec.begin(); it!=s_s.m_argVec.end(); ++it) {
|
||||
if ((*it)[0]=='+') {
|
||||
if (0==strncmp(prefixp, it->c_str()+1, len)) return *it;
|
||||
}
|
||||
@@ -122,13 +122,13 @@ public: // But only for verilated*.cpp
|
||||
// There's often many more scopes than userdata's and thus having a ~48byte
|
||||
// per map overhead * N scopes would take much more space and cache thrashing.
|
||||
static inline void userInsert(const void* scopep, void* userKey, void* userData) {
|
||||
UserMap::iterator it=s_s.m_userMap.find(make_pair(scopep,userKey));
|
||||
UserMap::iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
|
||||
if (it != s_s.m_userMap.end()) it->second = userData;
|
||||
// When we support VL_THREADs, we need a lock around this insert, as it's runtime
|
||||
else s_s.m_userMap.insert(it, make_pair(make_pair(scopep,userKey),userData));
|
||||
else s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep,userKey),userData));
|
||||
}
|
||||
static inline void* userFind(const void* scopep, void* userKey) {
|
||||
UserMap::iterator it=s_s.m_userMap.find(make_pair(scopep,userKey));
|
||||
UserMap::const_iterator it=s_s.m_userMap.find(std::make_pair(scopep,userKey));
|
||||
if (VL_LIKELY(it != s_s.m_userMap.end())) return it->second;
|
||||
else return NULL;
|
||||
}
|
||||
@@ -146,7 +146,7 @@ private:
|
||||
}
|
||||
static void userDump() {
|
||||
bool first = true;
|
||||
for (UserMap::iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
|
||||
for (UserMap::const_iterator it=s_s.m_userMap.begin(); it!=s_s.m_userMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF(" userDump:\n"); first=false; }
|
||||
VL_PRINTF(" DPI_USER_DATA scope %p key %p: %p\n",
|
||||
it->first.first, it->first.second, it->second);
|
||||
@@ -159,11 +159,11 @@ public: // But only for verilated*.cpp
|
||||
// Slow ok - called once/scope at construction
|
||||
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(scopep->name());
|
||||
if (it == s_s.m_nameMap.end()) {
|
||||
s_s.m_nameMap.insert(it, make_pair(scopep->name(),scopep));
|
||||
s_s.m_nameMap.insert(it, std::make_pair(scopep->name(),scopep));
|
||||
}
|
||||
}
|
||||
static inline const VerilatedScope* scopeFind(const char* namep) {
|
||||
VerilatedScopeNameMap::iterator it=s_s.m_nameMap.find(namep);
|
||||
VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.find(namep);
|
||||
if (VL_LIKELY(it != s_s.m_nameMap.end())) return it->second;
|
||||
else return NULL;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ public: // But only for verilated*.cpp
|
||||
}
|
||||
static void scopesDump() {
|
||||
VL_PRINTF(" scopesDump:\n");
|
||||
for (VerilatedScopeNameMap::iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
|
||||
for (VerilatedScopeNameMap::const_iterator it=s_s.m_nameMap.begin(); it!=s_s.m_nameMap.end(); ++it) {
|
||||
const VerilatedScope* scopep = it->second;
|
||||
scopep->scopeDump();
|
||||
}
|
||||
@@ -198,30 +198,30 @@ public: // But only for verilated*.cpp
|
||||
// Slow ok - called once/function at creation
|
||||
ExportNameMap::iterator it=s_s.m_exportMap.find(namep);
|
||||
if (it == s_s.m_exportMap.end()) {
|
||||
s_s.m_exportMap.insert(it, make_pair(namep, s_s.m_exportNext++));
|
||||
s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++));
|
||||
return s_s.m_exportNext++;
|
||||
} else {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
static int exportFind(const char* namep) {
|
||||
ExportNameMap::iterator it=s_s.m_exportMap.find(namep);
|
||||
ExportNameMap::const_iterator it=s_s.m_exportMap.find(namep);
|
||||
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
|
||||
string msg = (string("%Error: Testbench C called ")+namep
|
||||
+" but no such DPI export function name exists in ANY model");
|
||||
std::string msg = (std::string("%Error: Testbench C called ")+namep
|
||||
+" but no such DPI export function name exists in ANY model");
|
||||
vl_fatal("unknown",0,"", msg.c_str());
|
||||
return -1;
|
||||
}
|
||||
static const char* exportName(int funcnum) {
|
||||
// Slowpath; find name for given export; errors only so no map to reverse-map it
|
||||
for (ExportNameMap::iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
|
||||
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
|
||||
if (it->second == funcnum) return it->first;
|
||||
}
|
||||
return "*UNKNOWN*";
|
||||
}
|
||||
static void exportsDump() {
|
||||
bool first = true;
|
||||
for (ExportNameMap::iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
|
||||
for (ExportNameMap::const_iterator it=s_s.m_exportMap.begin(); it!=s_s.m_exportMap.end(); ++it) {
|
||||
if (first) { VL_PRINTF(" exportDump:\n"); first=false; }
|
||||
VL_PRINTF(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
|
||||
}
|
||||
@@ -238,7 +238,7 @@ public: // But only for verilated*.cpp
|
||||
// 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);
|
||||
for (size_t i=start; i<start*2; ++i) s_s.m_fdFree.push_back(static_cast<IData>(i));
|
||||
}
|
||||
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
|
||||
s_s.m_fdps[idx] = fp;
|
||||
|
||||
+11
-11
@@ -40,8 +40,8 @@
|
||||
#endif
|
||||
|
||||
// CONSTANTS
|
||||
static const char* VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file
|
||||
static const char* VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
|
||||
static const char* const VLTSAVE_HEADER_STR = "verilatorsave01\n"; ///< Value of first bytes of each file
|
||||
static const char* const VLTSAVE_TRAILER_STR = "vltsaved"; ///< Value of last bytes of each file
|
||||
|
||||
//=============================================================================
|
||||
//=============================================================================
|
||||
@@ -60,8 +60,8 @@ bool VerilatedDeserialize::readDiffers (const void* __restrict datap, size_t siz
|
||||
|
||||
VerilatedDeserialize& VerilatedDeserialize::readAssert (const void* __restrict datap, size_t size) {
|
||||
if (VL_UNLIKELY(readDiffers(datap,size))) {
|
||||
string fn = filename();
|
||||
string msg = (string)"Can't deserialize save-restore file as was made from different model";
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize save-restore file as was made from different model");
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
@@ -81,8 +81,8 @@ void VerilatedSerialize::header() {
|
||||
void VerilatedDeserialize::header() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR)))) {
|
||||
string fn = filename();
|
||||
string msg = (string)"Can't deserialize; file has wrong header signature";
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize; file has wrong header signature");
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
@@ -98,8 +98,8 @@ void VerilatedSerialize::trailer() {
|
||||
void VerilatedDeserialize::trailer() {
|
||||
VerilatedDeserialize& os = *this; // So can cut and paste standard >> code below
|
||||
if (VL_UNLIKELY(os.readDiffers(VLTSAVE_TRAILER_STR, strlen(VLTSAVE_TRAILER_STR)))) {
|
||||
string fn = filename();
|
||||
string msg = (string)"Can't deserialize; file has wrong end-of-file signature";
|
||||
std::string fn = filename();
|
||||
std::string msg = std::string("Can't deserialize; file has wrong end-of-file signature");
|
||||
vl_fatal(fn.c_str(), 0, "", msg.c_str());
|
||||
close();
|
||||
}
|
||||
@@ -187,7 +187,7 @@ void VerilatedSave::flush() {
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = string(__FUNCTION__)+": "+strerror(errno);
|
||||
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
@@ -204,7 +204,7 @@ void VerilatedRestore::fill() {
|
||||
for (vluint8_t* sp=m_cp; sp < m_endp;) *rp++ = *sp++; // Overlaps
|
||||
m_endp = m_bufp + (m_endp - m_cp);
|
||||
m_cp = m_bufp; // Reset buffer
|
||||
// Read into buffer starting at m_endp
|
||||
// Read into buffer starting at m_endp
|
||||
while (1) {
|
||||
ssize_t remaining = (m_bufp+bufferSize() - m_endp);
|
||||
if (remaining==0) break;
|
||||
@@ -215,7 +215,7 @@ void VerilatedRestore::fill() {
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = string(__FUNCTION__)+": "+strerror(errno);
|
||||
std::string msg = std::string(__FUNCTION__)+": "+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
close();
|
||||
break;
|
||||
|
||||
+50
-42
@@ -25,66 +25,40 @@
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialBase - internal base class for common code between VerilatedSerialize and VerilatedDeserialize
|
||||
// VerilatedSerialize - convert structures to a stream representation
|
||||
|
||||
class VerilatedSerialBase {
|
||||
class VerilatedSerialize {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
string m_filename;
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSerialBase() {
|
||||
VerilatedSerialize() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
private:
|
||||
VerilatedSerialBase(const VerilatedSerialBase& ); ///< N/A, no copy constructor
|
||||
public:
|
||||
// CREATORS
|
||||
virtual ~VerilatedSerialBase() {
|
||||
virtual ~VerilatedSerialize() {
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
string filename() const { return m_filename; }
|
||||
std::string filename() const { return m_filename; }
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedSerialize - convert structures to a stream representation
|
||||
|
||||
class VerilatedSerialize : public VerilatedSerialBase {
|
||||
protected:
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedSerialize() {}
|
||||
virtual ~VerilatedSerialize() { close(); }
|
||||
// METHODS
|
||||
VerilatedSerialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
|
||||
flush();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
inline VerilatedSerialize& write (const void* __restrict datap, size_t size) {
|
||||
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
@@ -96,22 +70,54 @@ public:
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
private:
|
||||
VerilatedSerialize(const VerilatedSerialize& ); ///< N/A, no copy constructor
|
||||
VerilatedSerialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_cp > (m_bufp+(bufferSize()-bufferInsertSize())))) {
|
||||
flush();
|
||||
}
|
||||
return *this; // For function chaining
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedDeserial - load structures from a stream representation
|
||||
|
||||
class VerilatedDeserialize : public VerilatedSerialBase {
|
||||
class VerilatedDeserialize {
|
||||
protected:
|
||||
// MEMBERS
|
||||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
|
||||
virtual void fill() = 0;
|
||||
void header();
|
||||
void trailer();
|
||||
public:
|
||||
// CREATORS
|
||||
VerilatedDeserialize() { m_endp = NULL; }
|
||||
virtual ~VerilatedDeserialize() { close(); }
|
||||
VerilatedDeserialize() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t [bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
m_endp = NULL;
|
||||
}
|
||||
virtual ~VerilatedDeserialize() {
|
||||
close();
|
||||
if (m_bufp) { delete m_bufp; m_bufp=NULL; }
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
std::string filename() const { return m_filename; }
|
||||
virtual void close() { flush(); }
|
||||
virtual void flush() {}
|
||||
inline VerilatedDeserialize& read (void* __restrict datap, size_t size) {
|
||||
vluint8_t* __restrict dp = (vluint8_t* __restrict)datap;
|
||||
while (size) {
|
||||
@@ -127,6 +133,8 @@ public:
|
||||
bool readDiffers (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (const void* __restrict datap, size_t size);
|
||||
VerilatedDeserialize& readAssert (vluint64_t data) { return readAssert(&data, sizeof(data)); }
|
||||
private:
|
||||
VerilatedDeserialize(const VerilatedDeserialize& ); ///< N/A, no copy constructor
|
||||
VerilatedDeserialize& bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
@@ -150,7 +158,7 @@ public:
|
||||
virtual ~VerilatedSave() { close(); }
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const string& filename) { open(filename.c_str()); }
|
||||
void open(const std::string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush();
|
||||
};
|
||||
@@ -169,7 +177,7 @@ public:
|
||||
|
||||
// METHODS
|
||||
void open(const char* filenamep); ///< Open the file; call isOpen() to see if errors
|
||||
void open(const string& filename) { open(filename.c_str()); }
|
||||
void open(const std::string& filename) { open(filename.c_str()); }
|
||||
virtual void close();
|
||||
virtual void flush() {}
|
||||
virtual void fill();
|
||||
@@ -219,12 +227,12 @@ inline VerilatedSerialize& operator<<(VerilatedSerialize& os, float& rhs) {
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
|
||||
return os.read(&rhs, sizeof(rhs));
|
||||
}
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, string& rhs) {
|
||||
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, std::string& rhs) {
|
||||
vluint32_t len=rhs.length();
|
||||
os<<len;
|
||||
return os.write(rhs.data(), len);
|
||||
}
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, string& rhs) {
|
||||
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& rhs) {
|
||||
vluint32_t len=0;
|
||||
os>>len;
|
||||
rhs.resize(len);
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
/// \file
|
||||
/// \brief Verilator: Common include for all Verilated SystemC files
|
||||
///
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all SystemC files it generates.
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all SystemC files it generates.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
@@ -39,9 +39,9 @@
|
||||
#define VL_SC_BV_DATAP(bv) (VlScBvExposer::sp_datap(bv))
|
||||
class VlScBvExposer : public sc_bv_base {
|
||||
public:
|
||||
static vluint32_t* sp_datap(const sc_bv_base& base) {
|
||||
return static_cast<const VlScBvExposer*>(&base)->sp_datatp(); }
|
||||
vluint32_t* sp_datatp() const { return (vluint32_t*)(m_data); }
|
||||
static const vluint32_t* sp_datap(const sc_bv_base& base) {
|
||||
return static_cast<const VlScBvExposer*>(&base)->sp_datatp(); }
|
||||
const vluint32_t* sp_datatp() const { return reinterpret_cast<vluint32_t*>(m_data); }
|
||||
// Above reads this protected element in sc_bv_base:
|
||||
// sc_digit* m_data; // data array
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
/// Verilator range
|
||||
|
||||
// See also V3Ast::VNumRange
|
||||
class VerilatedRange {
|
||||
class VerilatedRange {
|
||||
int m_left;
|
||||
int m_right;
|
||||
protected:
|
||||
@@ -71,7 +71,7 @@ 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); }
|
||||
VerilatedVarFlags vldir() const { return static_cast<VerilatedVarFlags>(static_cast<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; }
|
||||
@@ -91,13 +91,14 @@ struct VerilatedCStrCmp {
|
||||
};
|
||||
|
||||
class VerilatedScopeNameMap
|
||||
: public map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
|
||||
: public std::map<const char*, const VerilatedScope*, VerilatedCStrCmp> {
|
||||
public:
|
||||
VerilatedScopeNameMap() {}
|
||||
~VerilatedScopeNameMap() {}
|
||||
};
|
||||
|
||||
class VerilatedVarNameMap : public map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||
class VerilatedVarNameMap
|
||||
: public std::map<const char*, VerilatedVar, VerilatedCStrCmp> {
|
||||
public:
|
||||
VerilatedVarNameMap() {}
|
||||
~VerilatedVarNameMap() {}
|
||||
|
||||
+60
-37
@@ -47,9 +47,32 @@
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
// Global
|
||||
// VerilatedVcdImp
|
||||
/// Base class to hold some static state
|
||||
/// This is an internally used class
|
||||
|
||||
vector<VerilatedVcd*> VerilatedVcd::s_vcdVecp; ///< List of all created traces
|
||||
class VerilatedVcdSingleton {
|
||||
private:
|
||||
typedef std::vector<VerilatedVcd*> VcdVec;
|
||||
struct Singleton {
|
||||
VcdVec s_vcdVecp; ///< List of all created traces
|
||||
};
|
||||
static Singleton& singleton() { static Singleton s; return s; }
|
||||
public:
|
||||
static void pushVcd(VerilatedVcd* vcdp) {
|
||||
singleton().s_vcdVecp.push_back(vcdp);
|
||||
}
|
||||
static void removeVcd(const VerilatedVcd* vcdp) {
|
||||
VcdVec::iterator pos = find(singleton().s_vcdVecp.begin(), singleton().s_vcdVecp.end(), vcdp);
|
||||
if (pos != singleton().s_vcdVecp.end()) { singleton().s_vcdVecp.erase(pos); }
|
||||
}
|
||||
static void flush_all() {
|
||||
for (VcdVec::const_iterator it=singleton().s_vcdVecp.begin(); it!=singleton().s_vcdVecp.end(); ++it) {
|
||||
VerilatedVcd* vcdp = *it;
|
||||
vcdp->flush();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// VerilatedVcdCallInfo
|
||||
@@ -72,6 +95,7 @@ protected:
|
||||
VerilatedVcdCallback_t changecb,
|
||||
void* ut, vluint32_t code)
|
||||
: m_initcb(icb), m_fullcb(fcb), m_changecb(changecb), m_userthis(ut), m_code(code) {};
|
||||
~VerilatedVcdCallInfo() {}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
@@ -79,7 +103,7 @@ protected:
|
||||
//=============================================================================
|
||||
// VerilatedVcdFile
|
||||
|
||||
bool VerilatedVcdFile::open(const string& name) {
|
||||
bool VerilatedVcdFile::open(const std::string& name) {
|
||||
m_fd = ::open(name.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_LARGEFILE|O_NONBLOCK, 0666);
|
||||
return (m_fd>=0);
|
||||
}
|
||||
@@ -121,7 +145,7 @@ void VerilatedVcd::open (const char* filename) {
|
||||
|
||||
// Set member variables
|
||||
m_filename = filename;
|
||||
s_vcdVecp.push_back(this);
|
||||
VerilatedVcdSingleton::pushVcd(this);
|
||||
|
||||
// SPDIFF_OFF
|
||||
// Set callback so an early exit will flush us
|
||||
@@ -150,7 +174,7 @@ void VerilatedVcd::openNext (bool incFilename) {
|
||||
closePrev(); // Close existing
|
||||
if (incFilename) {
|
||||
// Find _0000.{ext} in filename
|
||||
string name = m_filename;
|
||||
std::string name = m_filename;
|
||||
size_t pos=name.rfind(".");
|
||||
if (pos>8 && 0==strncmp("_cat",name.c_str()+pos-8,4)
|
||||
&& isdigit(name.c_str()[pos-4])
|
||||
@@ -204,19 +228,19 @@ void VerilatedVcd::makeNameMap() {
|
||||
// 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 string& hiername = it->first;
|
||||
for (NameMap::const_iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||
const std::string& hiername = it->first;
|
||||
if (hiername.size() >= 1 && 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");
|
||||
for (NameMap::const_iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||
const std::string& hiername = it->first;
|
||||
const std::string& decl = it->second;
|
||||
std::string newname = std::string("top");
|
||||
if (hiername[0] != '\t') newname += ' ';
|
||||
newname += hiername;
|
||||
newmapp->insert(make_pair(newname,decl));
|
||||
newmapp->insert(std::make_pair(newname,decl));
|
||||
}
|
||||
deleteNameMap();
|
||||
m_namemapp = newmapp;
|
||||
@@ -233,9 +257,11 @@ VerilatedVcd::~VerilatedVcd() {
|
||||
if (m_sigs_oldvalp) { delete[] m_sigs_oldvalp; m_sigs_oldvalp=NULL; }
|
||||
deleteNameMap();
|
||||
if (m_filep && m_fileNewed) { delete m_filep; m_filep = NULL; }
|
||||
// Remove from list of traces
|
||||
vector<VerilatedVcd*>::iterator pos = find(s_vcdVecp.begin(), s_vcdVecp.end(), this);
|
||||
if (pos != s_vcdVecp.end()) { s_vcdVecp.erase(pos); }
|
||||
for (CallbackVec::const_iterator it=m_callbacks.begin(); it!=m_callbacks.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
m_callbacks.clear();
|
||||
VerilatedVcdSingleton::removeVcd(this);
|
||||
}
|
||||
|
||||
void VerilatedVcd::closePrev () {
|
||||
@@ -326,7 +352,7 @@ void VerilatedVcd::bufferFlush () {
|
||||
} else if (got < 0) {
|
||||
if (errno != EAGAIN && errno != EINTR) {
|
||||
// write failed, presume error (perhaps out of disk space)
|
||||
string msg = (string)"VerilatedVcd::bufferFlush: "+strerror(errno);
|
||||
std::string msg = std::string("VerilatedVcd::bufferFlush: ")+strerror(errno);
|
||||
vl_fatal("",0,"",msg.c_str());
|
||||
closeErr();
|
||||
break;
|
||||
@@ -354,7 +380,7 @@ void VerilatedVcd::set_time_resolution (const char* unitp) {
|
||||
double VerilatedVcd::timescaleToDouble (const char* unitp) {
|
||||
char* endp;
|
||||
double value = strtod(unitp, &endp);
|
||||
if (!value) value=1; // On error so we allow just "ns" to return 1e-9.
|
||||
if (value==0.0 && endp==unitp) value=1; // On error so we allow just "ns" to return 1e-9.
|
||||
unitp=endp;
|
||||
while (*unitp && isspace(*unitp)) unitp++;
|
||||
switch (*unitp) {
|
||||
@@ -369,7 +395,7 @@ double VerilatedVcd::timescaleToDouble (const char* unitp) {
|
||||
return value;
|
||||
}
|
||||
|
||||
string VerilatedVcd::doubleToTimescale (double value) {
|
||||
std::string VerilatedVcd::doubleToTimescale (double value) {
|
||||
const char* suffixp = "s";
|
||||
if (value>=1e0) { suffixp="s"; value *= 1e0; }
|
||||
else if (value>=1e-3 ) { suffixp="ms"; value *= 1e3; }
|
||||
@@ -398,7 +424,7 @@ void VerilatedVcd::dumpHeader () {
|
||||
printStr("$date "); printStr(ctime(&time_str)); printStr(" $end\n");
|
||||
|
||||
printStr("$timescale ");
|
||||
const string& timeResStr = doubleToTimescale(m_timeRes);
|
||||
const std::string& timeResStr = doubleToTimescale(m_timeRes);
|
||||
printStr(timeResStr.c_str());
|
||||
printStr(" $end\n");
|
||||
|
||||
@@ -416,9 +442,9 @@ void VerilatedVcd::dumpHeader () {
|
||||
|
||||
// Print the signal names
|
||||
const char* lastName = "";
|
||||
for (NameMap::iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||
const string& hiernamestr = it->first;
|
||||
const string& decl = it->second;
|
||||
for (NameMap::const_iterator it=m_namemapp->begin(); it!=m_namemapp->end(); ++it) {
|
||||
const std::string& hiernamestr = it->first;
|
||||
const std::string& decl = it->second;
|
||||
|
||||
// Determine difference between the old and new names
|
||||
const char* hiername = hiernamestr.c_str();
|
||||
@@ -472,7 +498,7 @@ void VerilatedVcd::dumpHeader () {
|
||||
deleteNameMap();
|
||||
}
|
||||
|
||||
void VerilatedVcd::module (const string& name) {
|
||||
void VerilatedVcd::module (const std::string& name) {
|
||||
m_modName = name;
|
||||
}
|
||||
|
||||
@@ -485,7 +511,7 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
|
||||
if (tri) codesNeeded *= 2; // Space in change array for __en signals
|
||||
|
||||
// Make sure array is large enough
|
||||
m_nextCode = max(nextCode(), code+codesNeeded);
|
||||
m_nextCode = std::max(nextCode(), code+codesNeeded);
|
||||
if (m_sigs.capacity() <= m_nextCode) {
|
||||
m_sigs.reserve(m_nextCode*2); // Power-of-2 allocation speeds things up
|
||||
}
|
||||
@@ -503,10 +529,10 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
|
||||
// Tab separates final scope from signal name
|
||||
// Tab sorts before spaces, so signals nicely will print before scopes
|
||||
// Note the hiername may be nothing, if so we'll add "\t{name}"
|
||||
string nameasstr = name;
|
||||
std::string nameasstr = name;
|
||||
if (m_modName!="") { nameasstr = m_modName+m_scopeEscape+nameasstr; } // Optional ->module prefix
|
||||
string hiername;
|
||||
string basename;
|
||||
std::string hiername;
|
||||
std::string basename;
|
||||
for (const char* cp=nameasstr.c_str(); *cp; cp++) {
|
||||
if (isScopeEscape(*cp)) {
|
||||
// Ahh, we've just read a scope, not a basename
|
||||
@@ -520,7 +546,7 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
|
||||
hiername += "\t"+basename;
|
||||
|
||||
// Print reference
|
||||
string decl = "$var ";
|
||||
std::string decl = "$var ";
|
||||
if (m_evcd) decl += "port"; else decl += wirep; // usually "wire"
|
||||
char buf [1000];
|
||||
sprintf(buf, " %2d ", bits);
|
||||
@@ -543,7 +569,7 @@ void VerilatedVcd::declare (vluint32_t code, const char* name, const char* wirep
|
||||
decl += buf;
|
||||
}
|
||||
decl += " $end\n";
|
||||
m_namemapp->insert(make_pair(hiername,decl));
|
||||
m_namemapp->insert(std::make_pair(hiername,decl));
|
||||
}
|
||||
|
||||
void VerilatedVcd::declBit (vluint32_t code, const char* name, int arraynum)
|
||||
@@ -571,7 +597,7 @@ void VerilatedVcd::declDouble (vluint32_t code, const char* name, int arraynum
|
||||
|
||||
void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
(*((double*)&m_sigs_oldvalp[code])) = newval;
|
||||
(*(reinterpret_cast<double*>(&m_sigs_oldvalp[code]))) = newval;
|
||||
// Buffer can't overflow before sprintf; we sized during declaration
|
||||
sprintf(m_writep, "r%.16g", newval);
|
||||
m_writep += strlen(m_writep);
|
||||
@@ -580,9 +606,9 @@ void VerilatedVcd::fullDouble (vluint32_t code, const double newval) {
|
||||
}
|
||||
void VerilatedVcd::fullFloat (vluint32_t code, const float newval) {
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
(*((float*)&m_sigs_oldvalp[code])) = newval;
|
||||
(*(reinterpret_cast<float*>(&m_sigs_oldvalp[code]))) = newval;
|
||||
// Buffer can't overflow before sprintf; we sized during declaration
|
||||
sprintf(m_writep, "r%.16g", (double)newval);
|
||||
sprintf(m_writep, "r%.16g", static_cast<double>(newval));
|
||||
m_writep += strlen(m_writep);
|
||||
*m_writep++=' '; printCode(code); *m_writep++='\n';
|
||||
bufferCheck();
|
||||
@@ -596,7 +622,7 @@ void VerilatedVcd::addCallback (
|
||||
void* userthis)
|
||||
{
|
||||
if (VL_UNLIKELY(isOpen())) {
|
||||
string msg = (string)"Internal: "+__FILE__+"::"+__FUNCTION__+" called with already open file";
|
||||
std::string msg = std::string("Internal: ")+__FILE__+"::"+__FUNCTION__+" called with already open file";
|
||||
vl_fatal(__FILE__,__LINE__,"",msg.c_str());
|
||||
}
|
||||
VerilatedVcdCallInfo* vci = new VerilatedVcdCallInfo(initcb, fullcb, changecb, userthis, nextCode());
|
||||
@@ -647,10 +673,7 @@ void VerilatedVcd::dumpDone () {
|
||||
// Static members
|
||||
|
||||
void VerilatedVcd::flush_all() {
|
||||
for (vluint32_t ent = 0; ent< s_vcdVecp.size(); ent++) {
|
||||
VerilatedVcd* vcdp = s_vcdVecp[ent];
|
||||
vcdp->flush();
|
||||
}
|
||||
VerilatedVcdSingleton::flush_all();
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
+39
-39
@@ -28,7 +28,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
using namespace std;
|
||||
|
||||
class VerilatedVcd;
|
||||
class VerilatedVcdCallInfo;
|
||||
@@ -45,7 +44,7 @@ public:
|
||||
// METHODS
|
||||
VerilatedVcdFile() : m_fd(0) {}
|
||||
virtual ~VerilatedVcdFile() {}
|
||||
virtual bool open(const string& name);
|
||||
virtual bool open(const std::string& name);
|
||||
virtual void close();
|
||||
virtual ssize_t write(const char* bufp, ssize_t len);
|
||||
};
|
||||
@@ -80,13 +79,13 @@ private:
|
||||
bool m_fileNewed; ///< m_filep needs destruction
|
||||
bool m_isOpen; ///< True indicates open file
|
||||
bool m_evcd; ///< True for evcd format
|
||||
string m_filename; ///< Filename we're writing to (if open)
|
||||
std::string m_filename; ///< Filename we're writing to (if open)
|
||||
vluint64_t m_rolloverMB; ///< MB of file size to rollover at
|
||||
char m_scopeEscape; ///< Character to separate scope components
|
||||
int m_modDepth; ///< Depth of module hierarchy
|
||||
bool m_fullDump; ///< True indicates dump ignoring if changed
|
||||
vluint32_t m_nextCode; ///< Next code number to assign
|
||||
string m_modName; ///< Module name being traced now
|
||||
std::string m_modName; ///< Module name being traced now
|
||||
double m_timeRes; ///< Time resolution (ns/ms etc)
|
||||
double m_timeUnit; ///< Time units (ns/ms etc)
|
||||
vluint64_t m_timeLastDump; ///< Last time we did a dump
|
||||
@@ -97,12 +96,13 @@ private:
|
||||
vluint64_t m_wrChunkSize; ///< Output buffer size
|
||||
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
|
||||
|
||||
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
|
||||
vector<VerilatedVcdSig> m_sigs; ///< Pointer to signal information
|
||||
vector<VerilatedVcdCallInfo*> m_callbacks; ///< Routines to perform dumping
|
||||
typedef map<string,string> NameMap;
|
||||
NameMap* m_namemapp; ///< List of names for the header
|
||||
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
|
||||
vluint32_t* m_sigs_oldvalp; ///< Pointer to old signal values
|
||||
typedef std::vector<VerilatedVcdSig> SigVec;
|
||||
SigVec m_sigs; ///< Pointer to signal information
|
||||
typedef std::vector<VerilatedVcdCallInfo*> CallbackVec;
|
||||
CallbackVec m_callbacks; ///< Routines to perform dumping
|
||||
typedef std::map<std::string,std::string> NameMap;
|
||||
NameMap* m_namemapp; ///< List of names for the header
|
||||
|
||||
void bufferResize(vluint64_t minsize);
|
||||
void bufferFlush();
|
||||
@@ -131,17 +131,17 @@ private:
|
||||
// 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));
|
||||
if (code>=(94*94)) *m_writep++ = ((char)((code/94/94)%94+33));
|
||||
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
|
||||
*m_writep++ = ((char)((code)%94+33));
|
||||
if (code>=(94*94*94)) *m_writep++ = static_cast<char>((code/94/94/94)%94+33);
|
||||
if (code>=(94*94)) *m_writep++ = static_cast<char>((code/94/94)%94+33);
|
||||
if (code>=(94)) *m_writep++ = static_cast<char>((code/94)%94+33);
|
||||
*m_writep++ = static_cast<char>((code)%94+33);
|
||||
}
|
||||
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));
|
||||
if (code>=(94)) out += ((char)((code/94)%94+33));
|
||||
return out + ((char)((code)%94+33));
|
||||
static std::string stringCode (vluint32_t code) {
|
||||
std::string out;
|
||||
if (code>=(94*94*94)) out += static_cast<char>((code/94/94/94)%94+33);
|
||||
if (code>=(94*94)) out += static_cast<char>((code/94/94)%94+33);
|
||||
if (code>=(94)) out += static_cast<char>((code/94)%94+33);
|
||||
return out + static_cast<char>((code)%94+33);
|
||||
}
|
||||
|
||||
VerilatedVcd(const VerilatedVcd& ); ///< N/A, no copy constructor
|
||||
@@ -175,18 +175,18 @@ public:
|
||||
void close (); ///< Close the file
|
||||
|
||||
void set_time_unit (const char* unit); ///< Set time units (s/ms, defaults to ns)
|
||||
void set_time_unit (const string& unit) { set_time_unit(unit.c_str()); }
|
||||
void set_time_unit (const std::string& unit) { set_time_unit(unit.c_str()); }
|
||||
|
||||
void set_time_resolution (const char* unit); ///< Set time resolution (s/ms, defaults to ns)
|
||||
void set_time_resolution (const string& unit) { set_time_resolution(unit.c_str()); }
|
||||
void set_time_resolution (const std::string& unit) { set_time_resolution(unit.c_str()); }
|
||||
|
||||
double timescaleToDouble (const char* unitp);
|
||||
string doubleToTimescale (double value);
|
||||
std::string doubleToTimescale (double value);
|
||||
|
||||
/// Inside dumping routines, called each cycle to make the dump
|
||||
void dump (vluint64_t timeui);
|
||||
/// Call dump with a absolute unscaled time in seconds
|
||||
void dumpSeconds (double secs) { dump((vluint64_t)(secs * m_timeRes)); }
|
||||
void dumpSeconds (double secs) { dump(static_cast<vluint64_t>(secs * m_timeRes)); }
|
||||
|
||||
/// Inside dumping routines, declare callbacks for tracings
|
||||
void addCallback (VerilatedVcdCallback_t init, VerilatedVcdCallback_t full,
|
||||
@@ -194,7 +194,7 @@ public:
|
||||
void* userthis);
|
||||
|
||||
/// Inside dumping routines, declare a module
|
||||
void module (const string& name);
|
||||
void module (const std::string& name);
|
||||
/// Inside dumping routines, declare a signal
|
||||
void declBit (vluint32_t code, const char* name, int arraynum);
|
||||
void declBus (vluint32_t code, const char* name, int arraynum, int msb, int lsb);
|
||||
@@ -212,7 +212,7 @@ public:
|
||||
void fullBit (vluint32_t code, const vluint32_t newval) {
|
||||
// Note the &1, so we don't require clean input -- makes more common no change case faster
|
||||
m_sigs_oldvalp[code] = newval;
|
||||
*m_writep++=('0'+(char)(newval&1)); printCode(code); *m_writep++='\n';
|
||||
*m_writep++=('0'+static_cast<char>(newval&1)); printCode(code); *m_writep++='\n';
|
||||
bufferCheck();
|
||||
}
|
||||
void fullBus (vluint32_t code, const vluint32_t newval, int bits) {
|
||||
@@ -225,7 +225,7 @@ public:
|
||||
bufferCheck();
|
||||
}
|
||||
void fullQuad (vluint32_t code, const vluint64_t newval, int bits) {
|
||||
(*((vluint64_t*)&m_sigs_oldvalp[code])) = newval;
|
||||
(*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) = newval;
|
||||
*m_writep++='b';
|
||||
for (int bit=bits-1; bit>=0; --bit) {
|
||||
*m_writep++=((newval&(1ULL<<bit))?'1':'0');
|
||||
@@ -264,8 +264,8 @@ public:
|
||||
bufferCheck();
|
||||
}
|
||||
void fullTriQuad (vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits) {
|
||||
(*((vluint64_t*)&m_sigs_oldvalp[code])) = newval;
|
||||
(*((vluint64_t*)&m_sigs_oldvalp[code+1])) = newtri;
|
||||
(*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) = newval;
|
||||
(*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code+1]))) = newtri;
|
||||
*m_writep++='b';
|
||||
for (int bit=bits-1; bit>=0; --bit) {
|
||||
*m_writep++ = "01zz"[((newval >> bit)&1ULL)
|
||||
@@ -329,7 +329,7 @@ public:
|
||||
}
|
||||
}
|
||||
inline void chgQuad (vluint32_t code, const vluint64_t newval, int bits) {
|
||||
vluint64_t diff = (*((vluint64_t*)&m_sigs_oldvalp[code])) ^ newval;
|
||||
vluint64_t diff = (*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) ^ newval;
|
||||
if (VL_UNLIKELY(diff)) {
|
||||
if (VL_UNLIKELY(bits==64 || (diff & ((1ULL<<bits)-1) ))) {
|
||||
fullQuad(code, newval, bits);
|
||||
@@ -364,8 +364,8 @@ public:
|
||||
}
|
||||
}
|
||||
inline void chgTriQuad (vluint32_t code, const vluint64_t newval, const vluint32_t newtri, int bits) {
|
||||
vluint64_t diff = ( ((*((vluint64_t*)&m_sigs_oldvalp[code])) ^ newval)
|
||||
| ((*((vluint64_t*)&m_sigs_oldvalp[code+1])) ^ newtri));
|
||||
vluint64_t diff = ( ((*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code]))) ^ newval)
|
||||
| ((*(reinterpret_cast<vluint64_t*>(&m_sigs_oldvalp[code+1]))) ^ newtri));
|
||||
if (VL_UNLIKELY(diff)) {
|
||||
if (VL_UNLIKELY(bits==64 || (diff & ((1ULL<<bits)-1) ))) {
|
||||
fullTriQuad(code, newval, newtri, bits);
|
||||
@@ -383,13 +383,13 @@ public:
|
||||
}
|
||||
inline void chgDouble (vluint32_t code, const double newval) {
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
if (VL_UNLIKELY((*((double*)&m_sigs_oldvalp[code])) != newval)) {
|
||||
if (VL_UNLIKELY((*(reinterpret_cast<double*>(&m_sigs_oldvalp[code]))) != newval)) {
|
||||
fullDouble (code, newval);
|
||||
}
|
||||
}
|
||||
inline void chgFloat (vluint32_t code, const float newval) {
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
if (VL_UNLIKELY((*((float*)&m_sigs_oldvalp[code])) != newval)) {
|
||||
if (VL_UNLIKELY((*(reinterpret_cast<float*>(&m_sigs_oldvalp[code]))) != newval)) {
|
||||
fullFloat (code, newval);
|
||||
}
|
||||
}
|
||||
@@ -427,17 +427,17 @@ public:
|
||||
void dump (vluint64_t timeui) { m_sptrace.dump(timeui); }
|
||||
/// Write one cycle of dump data - backward compatible and to reduce
|
||||
/// conversion warnings. It's better to use a vluint64_t time instead.
|
||||
void dump (double timestamp) { dump((vluint64_t)timestamp); }
|
||||
void dump (vluint32_t timestamp) { dump((vluint64_t)timestamp); }
|
||||
void dump (int timestamp) { dump((vluint64_t)timestamp); }
|
||||
void dump (double timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
||||
void dump (vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
||||
void dump (int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
|
||||
/// Set time units (s/ms, defaults to ns)
|
||||
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
|
||||
void set_time_unit (const char* unit) { m_sptrace.set_time_unit(unit); }
|
||||
void set_time_unit (const string& unit) { set_time_unit(unit.c_str()); }
|
||||
void set_time_unit (const std::string& unit) { set_time_unit(unit.c_str()); }
|
||||
/// Set time resolution (s/ms, defaults to ns)
|
||||
/// See also VL_TIME_PRECISION, and VL_TIME_MULTIPLIER in verilated.h
|
||||
void set_time_resolution (const char* unit) { m_sptrace.set_time_resolution(unit); }
|
||||
void set_time_resolution (const string& unit) { set_time_resolution(unit.c_str()); }
|
||||
void set_time_resolution (const std::string& unit) { set_time_resolution(unit.c_str()); }
|
||||
|
||||
/// Internal class access
|
||||
inline VerilatedVcd* spTrace () { return &m_sptrace; };
|
||||
|
||||
+53
-49
@@ -52,7 +52,7 @@ VerilatedVpiError* VerilatedVpi::error_info() {
|
||||
// VerilatedVpiError Methods
|
||||
|
||||
const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
static const char* const names[] = {
|
||||
"*undefined*",
|
||||
"vpiBinStrVal",
|
||||
"vpiOctStrVal",
|
||||
@@ -77,7 +77,7 @@ const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) {
|
||||
return names[(vpiVal<=vpiRawFourStateVal)?vpiVal:0];
|
||||
}
|
||||
const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
static const char* const names[] = {
|
||||
"*undefined*",
|
||||
"vpiAlways",
|
||||
"vpiAssignStmt",
|
||||
@@ -219,7 +219,7 @@ const char* VerilatedVpiError::strFromVpiObjType(PLI_INT32 vpiVal) {
|
||||
return names[(vpiVal<=vpiGenVar)?vpiVal:0];
|
||||
}
|
||||
const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
static const char* const names[] = {
|
||||
"vpiCondition",
|
||||
"vpiDelay",
|
||||
"vpiElseStmt",
|
||||
@@ -262,7 +262,7 @@ const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) {
|
||||
}
|
||||
|
||||
const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
static const char* const names[] = {
|
||||
"*undefined*",
|
||||
"cbValueChange",
|
||||
"cbStmt",
|
||||
@@ -301,7 +301,7 @@ const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) {
|
||||
}
|
||||
|
||||
const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) {
|
||||
static const char *names[] = {
|
||||
static const char* const names[] = {
|
||||
"*undefined or other*",
|
||||
"vpiType",
|
||||
"vpiName",
|
||||
@@ -386,7 +386,7 @@ const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) {
|
||||
|
||||
#define CHECK_RESULT_CSTR(got, exp) \
|
||||
if (strcmp((got),(exp))) { \
|
||||
string msg = string("%Error: ") \
|
||||
std::string msg = std::string("%Error: ") \
|
||||
+ "GOT = '"+((got)?(got):"<null>")+"'" \
|
||||
+ " EXP = '"+((exp)?(exp):"<null>")+"'"; \
|
||||
vl_fatal(__FILE__,__LINE__,"",msg.c_str()); \
|
||||
@@ -502,9 +502,9 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
|
||||
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope);
|
||||
const VerilatedVar* varp;
|
||||
const VerilatedScope* scopep;
|
||||
string scopeAndName = namep;
|
||||
std::string scopeAndName = namep;
|
||||
if (voScopep) {
|
||||
scopeAndName = string(voScopep->fullname()) + "." + namep;
|
||||
scopeAndName = std::string(voScopep->fullname()) + "." + namep;
|
||||
namep = (PLI_BYTE8*)scopeAndName.c_str();
|
||||
}
|
||||
{
|
||||
@@ -514,11 +514,11 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
|
||||
return (new VerilatedVpioScope(scopep))->castVpiHandle();
|
||||
}
|
||||
const char* baseNamep = scopeAndName.c_str();
|
||||
string scopename;
|
||||
std::string scopename;
|
||||
const char* dotp = strrchr(namep, '.');
|
||||
if (VL_LIKELY(dotp)) {
|
||||
baseNamep = dotp+1;
|
||||
scopename = string(namep,dotp-namep);
|
||||
scopename = std::string(namep,dotp-namep);
|
||||
}
|
||||
scopep = Verilated::scopeFind(scopename.c_str());
|
||||
if (!scopep) return NULL;
|
||||
@@ -721,9 +721,9 @@ void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) {
|
||||
// value processing
|
||||
|
||||
void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
static VL_THREAD char outStr[1+VL_MULS_MAX_WORDS*32]; // Maximum required size is for binary string, one byte per bit plus null termination
|
||||
static VL_THREAD_LOCAL char outStr[1+VL_MULS_MAX_WORDS*32]; // Maximum required size is for binary string, one byte per bit plus null termination
|
||||
// cppcheck-suppress variableScope
|
||||
static VL_THREAD int outStrSz = sizeof(outStr)-1;
|
||||
static VL_THREAD_LOCAL int outStrSz = sizeof(outStr)-1;
|
||||
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object););
|
||||
_VL_VPI_ERROR_RESET(); // reset vpi error status
|
||||
if (VL_UNLIKELY(!value_p)) return;
|
||||
@@ -733,19 +733,19 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
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];
|
||||
static VL_THREAD_LOCAL 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].aval = *(reinterpret_cast<CData*>(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT16:
|
||||
out[0].aval = *((SData*)(vop->varDatap()));
|
||||
out[0].aval = *(reinterpret_cast<SData*>(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_UINT32:
|
||||
out[0].aval = *((IData*)(vop->varDatap()));
|
||||
out[0].aval = *(reinterpret_cast<IData*>(vop->varDatap()));
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
case VLVT_WDATA: {
|
||||
@@ -753,7 +753,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
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()));
|
||||
WDataInP datap = (reinterpret_cast<IData*>(vop->varDatap()));
|
||||
for (int i=0; i<words; ++i) {
|
||||
out[i].aval = datap[i];
|
||||
out[i].bval = 0;
|
||||
@@ -761,10 +761,10 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
return;
|
||||
}
|
||||
case VLVT_UINT64: {
|
||||
QData data = *((QData*)(vop->varDatap()));
|
||||
out[1].aval = (IData)(data>>VL_ULL(32));
|
||||
QData data = *(reinterpret_cast<QData*>(vop->varDatap()));
|
||||
out[1].aval = static_cast<IData>(data>>VL_ULL(32));
|
||||
out[1].bval = 0;
|
||||
out[0].aval = (IData)(data);
|
||||
out[0].aval = static_cast<IData>(data);
|
||||
out[0].bval = 0;
|
||||
return;
|
||||
}
|
||||
@@ -783,7 +783,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int bits = vop->varp()->range().elements();
|
||||
CData* datap = ((CData*)(vop->varDatap()));
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
int i;
|
||||
if (bits > outStrSz) {
|
||||
// limit maximum size of output to size of buffer to prevent overrun.
|
||||
@@ -813,7 +813,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
case VLVT_WDATA: {
|
||||
int chars = (vop->varp()->range().elements()+2)/3;
|
||||
int bytes = VL_BYTES_I(vop->varp()->range().elements());
|
||||
CData* datap = ((CData*)(vop->varDatap()));
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
int i;
|
||||
if (chars > outStrSz) {
|
||||
// limit maximum size of output to size of buffer to prevent overrun.
|
||||
@@ -855,10 +855,14 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
value_p->value.str = outStr;
|
||||
switch (vop->varp()->vltype()) {
|
||||
// outStrSz does not include NULL termination so add one
|
||||
case VLVT_UINT8 : VL_SNPRINTF(outStr, outStrSz+1, "%hhu", (unsigned char )*((CData*)(vop->varDatap()))); return;
|
||||
case VLVT_UINT16: VL_SNPRINTF(outStr, outStrSz+1, "%hu", (unsigned short)*((SData*)(vop->varDatap()))); return;
|
||||
case VLVT_UINT32: VL_SNPRINTF(outStr, outStrSz+1, "%u", (unsigned int )*((IData*)(vop->varDatap()))); return;
|
||||
case VLVT_UINT64: VL_SNPRINTF(outStr, outStrSz+1, "%llu", (unsigned long long)*((QData*)(vop->varDatap()))); return;
|
||||
case VLVT_UINT8 : VL_SNPRINTF(outStr, outStrSz+1, "%hhu",
|
||||
static_cast<unsigned char>(*(reinterpret_cast<CData*>(vop->varDatap())))); return;
|
||||
case VLVT_UINT16: VL_SNPRINTF(outStr, outStrSz+1, "%hu",
|
||||
static_cast<unsigned short>(*(reinterpret_cast<SData*>(vop->varDatap())))); return;
|
||||
case VLVT_UINT32: VL_SNPRINTF(outStr, outStrSz+1, "%u",
|
||||
static_cast<unsigned int>(*(reinterpret_cast<IData*>(vop->varDatap())))); return;
|
||||
case VLVT_UINT64: VL_SNPRINTF(outStr, outStrSz+1, "%llu",
|
||||
static_cast<unsigned long long>(*(reinterpret_cast<QData*>(vop->varDatap())))); return;
|
||||
default:
|
||||
strcpy(outStr, "-1");
|
||||
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits",
|
||||
@@ -874,7 +878,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int chars = (vop->varp()->range().elements()+3)>>2;
|
||||
CData* datap = ((CData*)(vop->varDatap()));
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
int i;
|
||||
if (chars > outStrSz) {
|
||||
// limit maximum size of output to size of buffer to prevent overrun.
|
||||
@@ -884,7 +888,6 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
}
|
||||
for (i=0; i<chars; ++i) {
|
||||
char val = (datap[i>>1]>>((i&1)<<2))&15;
|
||||
static char hex[] = "0123456789abcdef";
|
||||
if (i==(chars-1)) {
|
||||
// most signifcant char, mask off non existant bits when vector
|
||||
// size is not a multiple of 4
|
||||
@@ -894,7 +897,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
val &= (1<<rem)-1;
|
||||
}
|
||||
}
|
||||
outStr[chars-i-1] = hex[static_cast<int>(val)];
|
||||
outStr[chars-i-1] = "0123456789abcdef"[static_cast<int>(val)];
|
||||
}
|
||||
outStr[i]=0; // NULL terminate
|
||||
return;
|
||||
@@ -913,7 +916,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int bytes = VL_BYTES_I(vop->varp()->range().elements());
|
||||
CData* datap = ((CData*)(vop->varDatap()));
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
int i;
|
||||
if (bytes > outStrSz) {
|
||||
// limit maximum size of output to size of buffer to prevent overrun.
|
||||
@@ -938,13 +941,13 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
} else if (value_p->format == vpiIntVal) {
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
value_p->value.integer = *((CData*)(vop->varDatap()));
|
||||
value_p->value.integer = *(reinterpret_cast<CData*>(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_UINT16:
|
||||
value_p->value.integer = *((SData*)(vop->varDatap()));
|
||||
value_p->value.integer = *(reinterpret_cast<SData*>(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_UINT32:
|
||||
value_p->value.integer = *((IData*)(vop->varDatap()));
|
||||
value_p->value.integer = *(reinterpret_cast<IData*>(vop->varDatap()));
|
||||
return;
|
||||
case VLVT_WDATA: // FALLTHRU
|
||||
case VLVT_UINT64: // FALLTHRU
|
||||
@@ -995,17 +998,17 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
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 & vop->mask();
|
||||
*(reinterpret_cast<CData*>(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask();
|
||||
return object;
|
||||
case VLVT_UINT16:
|
||||
*((SData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask();
|
||||
*(reinterpret_cast<SData*>(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask();
|
||||
return object;
|
||||
case VLVT_UINT32:
|
||||
*((IData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask();
|
||||
*(reinterpret_cast<IData*>(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask();
|
||||
return object;
|
||||
case VLVT_WDATA: {
|
||||
int words = VL_WORDS_I(vop->varp()->range().elements());
|
||||
WDataOutP datap = ((IData*)(vop->varDatap()));
|
||||
WDataOutP datap = (reinterpret_cast<IData*>(vop->varDatap()));
|
||||
for (int i=0; i<words; ++i) {
|
||||
datap[i] = value_p->value.vector[i].aval;
|
||||
if (i==(words-1)) {
|
||||
@@ -1015,7 +1018,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
return object;
|
||||
}
|
||||
case VLVT_UINT64: {
|
||||
*((QData*)(vop->varDatap())) = _VL_SET_QII(
|
||||
*(reinterpret_cast<QData*>(vop->varDatap())) = _VL_SET_QII(
|
||||
value_p->value.vector[1].aval & vop->mask(),
|
||||
value_p->value.vector[0].aval);
|
||||
return object;
|
||||
@@ -1035,7 +1038,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
case VLVT_WDATA: {
|
||||
int bits = vop->varp()->range().elements();
|
||||
int len = strlen(value_p->value.str);
|
||||
CData* datap = ((CData*)(vop->varDatap()));
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
for (int i=0; i<bits; ++i) {
|
||||
char set = (i < len)?(value_p->value.str[len-i-1]=='1'):0;
|
||||
// zero bits 7:1 of byte when assigning to bit 0, else
|
||||
@@ -1063,7 +1066,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
int chars = (vop->varp()->range().elements()+2)/3;
|
||||
int bytes = VL_BYTES_I(vop->varp()->range().elements());
|
||||
int len = strlen(value_p->value.str);
|
||||
CData* datap = ((CData*)(vop->varDatap()));
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
div_t idx;
|
||||
datap[0] = 0; // reset zero'th byte
|
||||
for (int i=0; i<chars; ++i) {
|
||||
@@ -1128,10 +1131,11 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
VL_FUNC, remainder, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname());
|
||||
}
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8 : *((CData*)(vop->varDatap())) = val & vop->mask(); break;
|
||||
case VLVT_UINT16: *((SData*)(vop->varDatap())) = val & vop->mask(); break;
|
||||
case VLVT_UINT32: *((IData*)(vop->varDatap())) = val & vop->mask(); break;
|
||||
case VLVT_UINT64: *((QData*)(vop->varDatap())) = val; ((IData*)(vop->varDatap()))[1] &= vop->mask(); break;
|
||||
case VLVT_UINT8 : *(reinterpret_cast<CData*>(vop->varDatap())) = val & vop->mask(); break;
|
||||
case VLVT_UINT16: *(reinterpret_cast<SData*>(vop->varDatap())) = val & vop->mask(); break;
|
||||
case VLVT_UINT32: *(reinterpret_cast<IData*>(vop->varDatap())) = val & vop->mask(); break;
|
||||
case VLVT_UINT64: *(reinterpret_cast<QData*>(vop->varDatap())) = val;
|
||||
(reinterpret_cast<IData*>(vop->varDatap()))[1] &= vop->mask(); break;
|
||||
case VLVT_WDATA:
|
||||
default:
|
||||
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits",
|
||||
@@ -1147,7 +1151,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
case VLVT_UINT64:
|
||||
case VLVT_WDATA: {
|
||||
int chars = (vop->varp()->range().elements()+3)>>2;
|
||||
CData* datap = ((CData*)(vop->varDatap()));
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
char* val = value_p->value.str;
|
||||
// skip hex ident if one is detected at the start of the string
|
||||
if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X')) {
|
||||
@@ -1195,7 +1199,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
case VLVT_WDATA: {
|
||||
int bytes = VL_BYTES_I(vop->varp()->range().elements());
|
||||
int len = strlen(value_p->value.str);
|
||||
CData* datap = ((CData*)(vop->varDatap()));
|
||||
CData* datap = (reinterpret_cast<CData*>(vop->varDatap()));
|
||||
for (int i=0; i<bytes; ++i) {
|
||||
datap[i] = (i < len)?value_p->value.str[len-i-1]:0; // prepend with 0 values before placing string the least signifcant bytes
|
||||
}
|
||||
@@ -1209,13 +1213,13 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
} else if (value_p->format == vpiIntVal) {
|
||||
switch (vop->varp()->vltype()) {
|
||||
case VLVT_UINT8:
|
||||
*((CData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
*(reinterpret_cast<CData*>(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_UINT16:
|
||||
*((SData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
*(reinterpret_cast<SData*>(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_UINT32:
|
||||
*((IData*)(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
*(reinterpret_cast<IData*>(vop->varDatap())) = vop->mask() & value_p->value.integer;
|
||||
return object;
|
||||
case VLVT_WDATA: // FALLTHRU
|
||||
case VLVT_UINT64: // FALLTHRU
|
||||
|
||||
+39
-36
@@ -83,7 +83,7 @@ public:
|
||||
return newp+8;
|
||||
} else {
|
||||
// +8: 8 bytes for next
|
||||
vluint8_t* newp = (vluint8_t*)(::operator new(chunk+8));
|
||||
vluint8_t* newp = reinterpret_cast<vluint8_t*>(::operator new(chunk+8));
|
||||
return newp+8;
|
||||
}
|
||||
}
|
||||
@@ -94,12 +94,12 @@ public:
|
||||
}
|
||||
// MEMBERS
|
||||
static inline VerilatedVpio* castp(vpiHandle h) { return dynamic_cast<VerilatedVpio*>((VerilatedVpio*)h); }
|
||||
inline vpiHandle castVpiHandle() { return (vpiHandle)(this); }
|
||||
inline vpiHandle castVpiHandle() { return reinterpret_cast<vpiHandle>(this); }
|
||||
// ACCESSORS
|
||||
virtual const char* name() { return "<null>"; }
|
||||
virtual const char* fullname() { return "<null>"; }
|
||||
virtual const char* defname() { return "<null>"; }
|
||||
virtual vluint32_t type() { return 0; }
|
||||
virtual const char* name() const { return "<null>"; }
|
||||
virtual const char* fullname() const { return "<null>"; }
|
||||
virtual const char* defname() const { return "<null>"; }
|
||||
virtual vluint32_t type() const { return 0; }
|
||||
virtual vluint32_t size() const { return 0; }
|
||||
virtual const VerilatedRange* rangep() const { return NULL; }
|
||||
virtual vpiHandle dovpi_scan() { return 0; }
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
}
|
||||
virtual ~VerilatedVpioCb() {}
|
||||
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() { return vpiCallback; }
|
||||
virtual vluint32_t type() const { return vpiCallback; }
|
||||
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); }
|
||||
@@ -133,7 +133,7 @@ public:
|
||||
explicit VerilatedVpioConst(vlsint32_t num) : m_num(num) {}
|
||||
virtual ~VerilatedVpioConst() {}
|
||||
static inline VerilatedVpioConst* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioConst*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() { return vpiUndefined; }
|
||||
virtual vluint32_t type() const { return vpiUndefined; }
|
||||
vlsint32_t num() const { return m_num; }
|
||||
};
|
||||
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
explicit VerilatedVpioRange(const VerilatedRange* range) : m_range(range), m_iteration(0) {}
|
||||
virtual ~VerilatedVpioRange() {}
|
||||
static inline VerilatedVpioRange* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioRange*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() { return vpiRange; }
|
||||
virtual vluint32_t type() const { return vpiRange; }
|
||||
virtual vluint32_t size() const { return m_range->elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return m_range; }
|
||||
int iteration() const { return m_iteration; }
|
||||
@@ -167,10 +167,10 @@ public:
|
||||
: m_scopep(scopep) {}
|
||||
virtual ~VerilatedVpioScope() {}
|
||||
static inline VerilatedVpioScope* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioScope*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() { return vpiScope; }
|
||||
virtual vluint32_t type() const { return vpiScope; }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
virtual const char* name() { return m_scopep->name(); }
|
||||
virtual const char* fullname() { return m_scopep->name(); }
|
||||
virtual const char* name() const { return m_scopep->name(); }
|
||||
virtual const char* fullname() const { return m_scopep->name(); }
|
||||
};
|
||||
|
||||
class VerilatedVpioVar : public VerilatedVpio {
|
||||
@@ -207,16 +207,16 @@ public:
|
||||
vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; }
|
||||
vluint32_t entSize() const { return m_entSize; }
|
||||
vluint32_t index() { return m_index; }
|
||||
virtual vluint32_t type() {
|
||||
virtual vluint32_t type() const {
|
||||
if (varp()->vldir() != vpiNoDirection) return vpiPort;
|
||||
return (varp()->dims()>1) ? vpiMemory : vpiReg; /* but might be wire, logic */
|
||||
}
|
||||
virtual vluint32_t size() const { return get_range().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &get_range(); }
|
||||
virtual const char* name() { return m_varp->name(); }
|
||||
virtual const char* fullname() {
|
||||
VL_STATIC_OR_THREAD string out;
|
||||
out = string(m_scopep->name())+"."+name();
|
||||
virtual const char* name() const { return m_varp->name(); }
|
||||
virtual const char* fullname() const {
|
||||
static VL_THREAD_LOCAL std::string out;
|
||||
out = std::string(m_scopep->name())+"."+name();
|
||||
return out.c_str();
|
||||
}
|
||||
void* prevDatap() const { return m_prevDatap; }
|
||||
@@ -239,27 +239,27 @@ public:
|
||||
}
|
||||
virtual ~VerilatedVpioMemoryWord() {}
|
||||
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWord*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() { return vpiMemoryWord; }
|
||||
virtual vluint32_t type() const { return vpiMemoryWord; }
|
||||
virtual vluint32_t size() const { return varp()->range().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &(varp()->range()); }
|
||||
virtual const char* fullname() {
|
||||
VL_STATIC_OR_THREAD string out;
|
||||
virtual const char* fullname() const {
|
||||
static VL_THREAD_LOCAL std::string out;
|
||||
char num[20]; sprintf(num,"%d",m_index);
|
||||
out = string(scopep()->name())+"."+name()+"["+num+"]";
|
||||
out = std::string(scopep()->name())+"."+name()+"["+num+"]";
|
||||
return out.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedVpioVarIter : public VerilatedVpio {
|
||||
const VerilatedScope* m_scopep;
|
||||
VerilatedVarNameMap::iterator m_it;
|
||||
VerilatedVarNameMap::const_iterator m_it;
|
||||
bool m_started;
|
||||
public:
|
||||
explicit 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 vluint32_t type() { return vpiIterator; }
|
||||
virtual vluint32_t type() const { return vpiIterator; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
if (VL_LIKELY(m_scopep->varsp())) {
|
||||
VerilatedVarNameMap* varsp = m_scopep->varsp();
|
||||
@@ -286,8 +286,10 @@ public:
|
||||
: m_handle(handle), m_varp(varp), m_iteration(varp->array().right()), m_direction(VL_LIKELY(varp->array().left()>varp->array().right())?1:-1), m_done(false) { }
|
||||
virtual ~VerilatedVpioMemoryWordIter() {}
|
||||
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioMemoryWordIter*>((VerilatedVpio*)h); }
|
||||
virtual vluint32_t type() { return vpiIterator; }
|
||||
void iterationInc() { if (!(m_done = (m_iteration == m_varp->array().left()))) m_iteration+=m_direction; }
|
||||
virtual vluint32_t type() const { return vpiIterator; }
|
||||
void iterationInc() {
|
||||
if (!(m_done = (m_iteration == m_varp->array().left()))) m_iteration+=m_direction;
|
||||
}
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
vpiHandle result;
|
||||
if (m_done) return 0;
|
||||
@@ -301,8 +303,8 @@ public:
|
||||
|
||||
struct VerilatedVpiTimedCbsCmp {
|
||||
/// Ordering sets keyed by time, then callback descriptor
|
||||
bool operator() (const pair<QData,VerilatedVpioCb*>& a,
|
||||
const pair<QData,VerilatedVpioCb*>& b) const {
|
||||
bool operator() (const std::pair<QData,VerilatedVpioCb*>& a,
|
||||
const std::pair<QData,VerilatedVpioCb*>& b) const {
|
||||
if (a.first < b.first) return 1;
|
||||
if (a.first > b.first) return 0;
|
||||
return a.second < b.second;
|
||||
@@ -313,8 +315,8 @@ class VerilatedVpiError;
|
||||
|
||||
class VerilatedVpi {
|
||||
enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime+1 }; // Maxium callback reason
|
||||
typedef list<VerilatedVpioCb*> VpioCbList;
|
||||
typedef set<pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
|
||||
typedef std::list<VerilatedVpioCb*> VpioCbList;
|
||||
typedef std::set<std::pair<QData,VerilatedVpioCb*>,VerilatedVpiTimedCbsCmp > VpioTimedCbs;
|
||||
|
||||
struct product_info {
|
||||
PLI_BYTE8* product;
|
||||
@@ -339,7 +341,7 @@ public:
|
||||
s_s.m_cbObjLists[vop->reason()].push_back(vop);
|
||||
}
|
||||
static void cbTimedAdd(VerilatedVpioCb* vop) {
|
||||
s_s.m_timedCbs.insert(make_pair(vop->time(), vop));
|
||||
s_s.m_timedCbs.insert(std::make_pair(vop->time(), vop));
|
||||
}
|
||||
static void cbReasonRemove(VerilatedVpioCb* cbp) {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()];
|
||||
@@ -350,7 +352,7 @@ public:
|
||||
}
|
||||
}
|
||||
static void cbTimedRemove(VerilatedVpioCb* cbp) {
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(make_pair(cbp->time(),cbp));
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.find(std::make_pair(cbp->time(),cbp));
|
||||
if (VL_LIKELY(it != s_s.m_timedCbs.end())) {
|
||||
s_s.m_timedCbs.erase(it);
|
||||
}
|
||||
@@ -368,7 +370,7 @@ public:
|
||||
}
|
||||
}
|
||||
static QData cbNextDeadline() {
|
||||
VpioTimedCbs::iterator it=s_s.m_timedCbs.begin();
|
||||
VpioTimedCbs::const_iterator it=s_s.m_timedCbs.begin();
|
||||
if (VL_LIKELY(it!=s_s.m_timedCbs.end())) {
|
||||
return it->first;
|
||||
} else {
|
||||
@@ -389,7 +391,8 @@ public:
|
||||
}
|
||||
static void callValueCbs() {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
|
||||
set<VerilatedVpioVar*> update; // set of objects to update after callbacks
|
||||
typedef std::set<VerilatedVpioVar*> VpioVarSet;
|
||||
VpioVarSet update; // set of objects to update after callbacks
|
||||
for (VpioCbList::iterator it=cbObjList.begin(); it!=cbObjList.end();) {
|
||||
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
|
||||
it = cbObjList.erase(it);
|
||||
@@ -411,7 +414,7 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
for (set<VerilatedVpioVar*>::iterator it=update.begin(); it!=update.end(); ++it) {
|
||||
for (VpioVarSet::const_iterator it=update.begin(); it!=update.end(); ++it) {
|
||||
memcpy((*it)->prevDatap(), (*it)->varDatap(), (*it)->entSize());
|
||||
}
|
||||
}
|
||||
@@ -462,8 +465,8 @@ public:
|
||||
m_errorInfo.level = level;
|
||||
return this;
|
||||
}
|
||||
void setMessage(string file, PLI_INT32 line, string message, ...) {
|
||||
static VL_THREAD string filehold;
|
||||
void setMessage(std::string file, PLI_INT32 line, std::string message, ...) {
|
||||
static VL_THREAD_LOCAL std::string filehold;
|
||||
_VL_VPI_ERROR_SET;
|
||||
m_errorInfo.state = vpiPLI;
|
||||
filehold = file;
|
||||
|
||||
+18
-9
@@ -46,6 +46,7 @@
|
||||
# define VL_FUNC __func__
|
||||
# define VL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
# define VL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
# define VL_UNREACHABLE __builtin_unreachable();
|
||||
# define VL_PREFETCH_RD(p) __builtin_prefetch((p),0)
|
||||
# define VL_PREFETCH_RW(p) __builtin_prefetch((p),1)
|
||||
#elif defined(_MSC_VER)
|
||||
@@ -57,6 +58,7 @@
|
||||
# define VL_FUNC __FUNCTION__
|
||||
# define VL_LIKELY(x) (!!(x))
|
||||
# define VL_UNLIKELY(x) (!!(x))
|
||||
# define VL_UNREACHABLE
|
||||
# define VL_PREFETCH_RD(p)
|
||||
# define VL_PREFETCH_RW(p)
|
||||
#else
|
||||
@@ -68,23 +70,25 @@
|
||||
# define VL_FUNC "__func__" ///< Name of current function for error macros
|
||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||
# define VL_UNREACHABLE ///< Point that may never be reached
|
||||
# define VL_PREFETCH_RD(p) ///< Prefetch data with read intent
|
||||
# define VL_PREFETCH_RW(p) ///< Prefetch data with read/write intent
|
||||
#endif
|
||||
|
||||
#ifdef VL_THREADED
|
||||
# ifdef __GNUC__
|
||||
# define VL_THREAD __thread ///< Storage class for thread-local storage
|
||||
# if (__cplusplus < 201103L) && !defined(VL_THREADED_NO_C11_WARNING)
|
||||
# error "VL_THREADED support plans to move to C++-11 and later only; use newer --std to be ready"
|
||||
# endif
|
||||
# else
|
||||
# error "Unsupported compiler for VL_THREADED: No thread-local declarator"
|
||||
# endif
|
||||
# define VL_STATIC_OR_THREAD ///< Static if unthreaded, as some strings can be faster
|
||||
// ///< if non-dynamic and can't do "static VL_THREAD string"
|
||||
# define VL_THREAD_LOCAL thread_local ///< Use new C++ static local thread
|
||||
#else
|
||||
# define VL_THREAD ///< Storage class for thread-local storage
|
||||
# define VL_STATIC_OR_THREAD static ///< Static if unthreaded, as some strings can be faster
|
||||
// ///< if non-dynamic and can't do "static VL_THREAD string"
|
||||
# define VL_THREAD_LOCAL ///< Use new C++ static local thread
|
||||
#endif
|
||||
#define VL_THREAD ///< Deprecated
|
||||
#define VL_STATIC_OR_THREAD static ///< Deprecated
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define VL_ULL(c) (c##ui64) ///< Add appropriate suffix to 64-bit constant
|
||||
@@ -93,7 +97,7 @@
|
||||
#endif
|
||||
|
||||
// This is not necessarily the same as #UL, depending on what the IData typedef is.
|
||||
#define VL_UL(c) ((IData)(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
||||
#define VL_UL(c) (static_cast<IData>(c##UL)) ///< Add appropriate suffix to 32-bit constant
|
||||
|
||||
#if defined(VL_CPPCHECK) || defined(__clang_analyzer__)
|
||||
# define VL_DANGLING(v)
|
||||
@@ -106,9 +110,14 @@
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# define VL_HAS_UNIQUE_PTR
|
||||
# define VL_UNIQUE_PTR unique_ptr
|
||||
# define VL_HAS_UNORDERED_MAP
|
||||
# define VL_UNIQUE_PTR std::unique_ptr
|
||||
# define VL_UNORDERED_MAP std::unordered_map
|
||||
# define VL_INCLUDE_UNORDERED_MAP <unordered_map>
|
||||
#else
|
||||
# define VL_UNIQUE_PTR auto_ptr
|
||||
# define VL_UNIQUE_PTR std::auto_ptr
|
||||
# define VL_UNORDERED_MAP std::map
|
||||
# define VL_INCLUDE_UNORDERED_MAP <map>
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
|
||||
@@ -105,10 +105,12 @@ typedef unsigned char PLI_UBYTE8;
|
||||
|
||||
/* object is defined imported by the application */
|
||||
|
||||
#undef XXTERN
|
||||
#define XXTERN PLI_EXTERN PLI_DLLISPEC
|
||||
|
||||
/* object is exported by the application */
|
||||
|
||||
#undef EETERN
|
||||
#define EETERN PLI_EXTERN PLI_DLLESPEC
|
||||
#endif
|
||||
|
||||
|
||||
+7
-7
@@ -124,7 +124,7 @@ if [ x"$dir_arg" != x ]; then
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
@@ -134,7 +134,7 @@ else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
@@ -162,7 +162,7 @@ dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
@@ -201,17 +201,17 @@ else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
@@ -242,7 +242,7 @@ else
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
+9
-9
@@ -237,10 +237,10 @@ implementation is not found, the system will look in turn for overloaded
|
||||
implementations up the inheritance hierarchy. For example calling C<accept>
|
||||
on C<AstIf> will look in turn for:
|
||||
|
||||
void visit (AstIf* nodep, AstNUser* vup)
|
||||
void visit (AstNodeIf* nodep, AstNUser* vup)
|
||||
void visit (AstNodeStmt* nodep, AstNUser* vup)
|
||||
void visit (AstNode* nodep, AstNUser* vup)
|
||||
void visit (AstIf* nodep)
|
||||
void visit (AstNodeIf* nodep)
|
||||
void visit (AstNodeStmt* nodep)
|
||||
void visit (AstNode* nodep)
|
||||
|
||||
There are three ways data is passed between visitor functions.
|
||||
|
||||
@@ -485,10 +485,10 @@ be warning free.
|
||||
|
||||
=item --enable-longtests
|
||||
|
||||
In addition to the standard C, SystemC tests also run the tests in the
|
||||
C<test_verilated> and C<test_regress> directories when using I<make test>.
|
||||
This is disabled by default as SystemC installation problems would
|
||||
otherwise falsely indicate a Verilator problem.
|
||||
In addition to the standard C, SystemC examples, also run the tests in the
|
||||
C<test_regress> directory when using I<make test>. This is disabled by
|
||||
default as SystemC installation problems would otherwise falsely indicate a
|
||||
Verilator problem.
|
||||
|
||||
=back
|
||||
|
||||
@@ -709,7 +709,7 @@ Start GDB, then C<start> with the remaining arguments.
|
||||
Temporary breakpoint 1, main (argc=13, argv=0xbfffefa4, env=0xbfffefdc)
|
||||
at ../Verilator.cpp:615
|
||||
615 ios::sync_with_stdio();
|
||||
(gdb)
|
||||
(gdb)
|
||||
|
||||
You can then continue execution with breakpoints as required.
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
eval `modulecmd perl add synopsys-vcs_mx`;
|
||||
eval `modulecmd perl add synopsys-sim`;
|
||||
exec('vcs',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
|
||||
+7
-7
@@ -48,25 +48,25 @@ obj_dbg:
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
.PHONY: ../verilator_bin ../verilator_bin_dbg ../verilator_coverage_bin_dbg
|
||||
.PHONY: ../bin/verilator_bin ../bin/verilator_bin_dbg ../bin/verilator_coverage_bin_dbg
|
||||
|
||||
opt: ../verilator_bin
|
||||
opt: ../bin/verilator_bin
|
||||
ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build
|
||||
../verilator_bin: ../verilator_bin_dbg
|
||||
../bin/verilator_bin: ../bin/verilator_bin_dbg
|
||||
-rm -rf $@ $@.exe
|
||||
-cp -p $<$(EXEEXT) $@$(EXEEXT)
|
||||
else
|
||||
../verilator_bin: obj_opt prefiles
|
||||
../bin/verilator_bin: obj_opt prefiles
|
||||
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_coverage_bin_dbg
|
||||
../verilator_bin_dbg: obj_dbg prefiles
|
||||
dbg: ../bin/verilator_bin_dbg ../bin/verilator_coverage_bin_dbg
|
||||
../bin/verilator_bin_dbg: obj_dbg prefiles
|
||||
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
|
||||
|
||||
../verilator_coverage_bin_dbg: obj_dbg prefiles
|
||||
../bin/verilator_coverage_bin_dbg: obj_dbg prefiles
|
||||
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 VL_VLCOV=1 -f ../Makefile_obj serial_vlcov
|
||||
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 VL_VLCOV=1 -f ../Makefile_obj
|
||||
|
||||
|
||||
+4
-2
@@ -64,6 +64,8 @@ LDFLAGS += @LDFLAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
CFG_CXXFLAGS_SRC = @CFG_CXXFLAGS_SRC@
|
||||
CFG_CXXFLAGS_PARSER = @CFG_CXXFLAGS_PARSER@
|
||||
# Compiler flags that turn on extra warnings
|
||||
CFG_CXXFLAGS_WEXTRA = @CFG_CXXFLAGS_WEXTRA@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
@@ -73,7 +75,7 @@ TGT = ../../verilator_bin
|
||||
#################
|
||||
ifeq ($(VL_DEBUG),)
|
||||
# Optimize
|
||||
COPT = -O
|
||||
COPT = -O2
|
||||
else
|
||||
# Debug
|
||||
COPT = -ggdb -DVL_DEBUG
|
||||
@@ -97,7 +99,7 @@ CPPFLAGS += -DYYDEBUG # Required to get nice error messages
|
||||
CPPFLAGS += $(COPT)
|
||||
CPPFLAGS += -MP # Only works on recent GCC versions
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_SRC) -Werror
|
||||
CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_WEXTRA) $(CFG_CXXFLAGS_SRC) -Werror
|
||||
#CPPFLAGS += -pedantic-errors
|
||||
else
|
||||
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
|
||||
|
||||
+2
-2
@@ -176,7 +176,7 @@ private:
|
||||
if (m_check == CT_INITIAL) {
|
||||
nodep->v3warn(INITIALDLY,"Delayed assignments (<=) in initial or final block; suggest blocking assignments (=).");
|
||||
} else if (m_check == CT_LATCH) {
|
||||
// Suppress. Shouldn't matter that the interior of the latch races
|
||||
// Suppress. Shouldn't matter that the interior of the latch races
|
||||
} else {
|
||||
nodep->v3warn(COMBDLY,"Delayed assignments (<=) in non-clocked (non flop or latch) block; suggest blocking assignments (=).");
|
||||
}
|
||||
@@ -438,5 +438,5 @@ public:
|
||||
void V3Active::activeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ActiveVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("active.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -160,5 +160,5 @@ public:
|
||||
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ActiveTopVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("activetop.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+6
-6
@@ -162,7 +162,7 @@ private:
|
||||
// Bye
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
|
||||
virtual void visit(AstIf* nodep) {
|
||||
if (nodep->user1SetOnce()) return;
|
||||
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||
@@ -177,12 +177,12 @@ private:
|
||||
|
||||
// Recurse into the true case.
|
||||
ifp->ifsp()->iterateAndNext(*this);
|
||||
|
||||
|
||||
// If the last else is not an else if, recurse into that too.
|
||||
if (ifp->elsesp() && !nextifp) {
|
||||
ifp->elsesp()->iterateAndNext(*this);
|
||||
}
|
||||
|
||||
|
||||
// Build a bitmask of the true predicates
|
||||
AstNode* predp = ifp->condp()->cloneTree(false);
|
||||
if (propp) {
|
||||
@@ -195,13 +195,13 @@ private:
|
||||
if (ifp->elsesp() && !nextifp) {
|
||||
hasDefaultElse = true;
|
||||
}
|
||||
|
||||
|
||||
ifp = nextifp;
|
||||
} while (ifp);
|
||||
|
||||
AstNode *newifp = nodep->cloneTree(false);
|
||||
bool allow_none = nodep->unique0Pragma();
|
||||
|
||||
|
||||
// Note: if this ends with an 'else', then we don't need to validate that one of the
|
||||
// predicates evaluates to true.
|
||||
AstNode* ohot = ((allow_none || hasDefaultElse)
|
||||
@@ -344,5 +344,5 @@ public:
|
||||
void V3Assert::assertAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
AssertVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("assert.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -137,5 +137,5 @@ public:
|
||||
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
AssertPreVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("assertpre.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+5
-1
@@ -716,6 +716,7 @@ void AstNode::deleteTree() {
|
||||
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
void* AstNode::operator new(size_t size) {
|
||||
// Optimization note: Aligning to cache line is a loss, due to lost packing
|
||||
AstNode* objp = static_cast<AstNode*>(::operator new(size));
|
||||
V3Broken::addNewed(objp);
|
||||
return objp;
|
||||
@@ -734,6 +735,7 @@ void AstNode::operator delete(void* objp, size_t size) {
|
||||
|
||||
void AstNode::iterateChildren(AstNVisitor& v) {
|
||||
// This is a very hot function
|
||||
// Optimization note: Grabbing m_op#p->m_nextp is a net loss
|
||||
ASTNODE_PREFETCH(m_op1p);
|
||||
ASTNODE_PREFETCH(m_op2p);
|
||||
ASTNODE_PREFETCH(m_op3p);
|
||||
@@ -766,11 +768,13 @@ void AstNode::iterateAndNext(AstNVisitor& v) {
|
||||
#ifdef VL_DEBUG // Otherwise too hot of a function for debug
|
||||
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
|
||||
#endif
|
||||
if (nodep) ASTNODE_PREFETCH(nodep->m_nextp);
|
||||
while (nodep) { // effectively: if (!this) return; // Callers rely on this
|
||||
if (nodep->m_nextp) ASTNODE_PREFETCH(nodep->m_nextp->m_nextp);
|
||||
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
|
||||
ASTNODE_PREFETCH(nodep->m_nextp);
|
||||
// Desirable check, but many places where multiple iterations are OK
|
||||
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
|
||||
// Optimization note: Doing PREFETCH_RW on m_iterpp is a net even
|
||||
// cppcheck-suppress nullPointer
|
||||
niterp->m_iterpp = &niterp;
|
||||
niterp->accept(v);
|
||||
|
||||
+17
-13
@@ -82,7 +82,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"UNSIGNED","SIGNED","NOSIGN"
|
||||
};
|
||||
return names[m_e];
|
||||
@@ -203,14 +203,14 @@ public:
|
||||
return AstEdgeType::ET_ILLEGAL;
|
||||
}
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"%E-edge", "ANY", "BOTH", "POS", "NEG", "HIGH", "LOW",
|
||||
"COMBO","INITIAL","SETTLE","NEVER"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
const char* verilogKwd() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"%E-edge", "[any]", "edge", "posedge", "negedge", "[high]","[low]",
|
||||
"*","[initial]","[settle]","[never]"
|
||||
};
|
||||
@@ -270,7 +270,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"%E-AT",
|
||||
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
||||
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
||||
@@ -315,7 +315,7 @@ public:
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"%E-unk",
|
||||
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
||||
"real", "shortint", "shortreal", "time",
|
||||
@@ -328,7 +328,7 @@ public:
|
||||
return names[m_e];
|
||||
};
|
||||
const char* dpiType() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"%E-unk",
|
||||
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
||||
"double", "short int", "float", "long long",
|
||||
@@ -446,7 +446,7 @@ public:
|
||||
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"?","GPARAM","LPARAM","GENVAR",
|
||||
"VAR","INPUT","OUTPUT","INOUT",
|
||||
"SUPPLY0","SUPPLY1","WIRE","WREAL","IMPLICITWIRE",
|
||||
@@ -489,7 +489,7 @@ public:
|
||||
else return m_e;
|
||||
}
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"","VL_LIKELY","VL_UNLIKELY"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
@@ -522,7 +522,7 @@ public:
|
||||
else return m_e;
|
||||
}
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"","clker","non_clker"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
@@ -548,7 +548,7 @@ public:
|
||||
explicit inline VAlwaysKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"always","always_ff","always_latch","always_comb"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
@@ -598,7 +598,7 @@ public:
|
||||
bool addNewline() const { return m_e!=DT_WRITE; }
|
||||
bool needScopeTracking() const { return m_e!=DT_DISPLAY && m_e!=DT_WRITE; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"display","write","info","error","warning","fatal"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
@@ -621,7 +621,7 @@ public:
|
||||
explicit inline AstParseRefExp (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
static const char* const names[] = {
|
||||
"","TEXT","PREDOT"};
|
||||
return names[m_e]; }
|
||||
};
|
||||
@@ -734,6 +734,7 @@ class VNUser {
|
||||
public:
|
||||
VNUser() {}
|
||||
// non-explicit:
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
VNUser(int i) { m_u.up = 0; m_u.ui = i; }
|
||||
explicit VNUser(void* p) { m_u.up = p; }
|
||||
~VNUser() {}
|
||||
@@ -1087,6 +1088,8 @@ public:
|
||||
// ACCESSORS
|
||||
virtual string name() const { return ""; }
|
||||
virtual void name(const string& name) { this->v3fatalSrc("name() called on object without name() method"); }
|
||||
virtual void tag(const string& text) {}
|
||||
virtual string tag() const { return ""; }
|
||||
virtual string verilogKwd() const { return ""; }
|
||||
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
||||
static string dedotName(const string& namein); // Name with dots removed
|
||||
@@ -1258,7 +1261,7 @@ public:
|
||||
|
||||
// METHODS - Iterate on a tree
|
||||
AstNode* cloneTree(bool cloneNextLink);
|
||||
bool gateTree() { return gateTreeIter(); } // Is tree gateOptimizable?
|
||||
bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable?
|
||||
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
|
||||
bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable
|
||||
void deleteTree(); // Always deletes the next link
|
||||
@@ -1458,6 +1461,7 @@ public:
|
||||
virtual bool sizeMattersLhs() { return false; } virtual bool sizeMattersRhs() { return false; }
|
||||
virtual bool sizeMattersThs() { return false; }
|
||||
virtual int instrCount() const { return instrCountBranch(); }
|
||||
virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0;
|
||||
};
|
||||
|
||||
class AstNodePreSel : public AstNode {
|
||||
|
||||
+5
-5
@@ -226,7 +226,7 @@ string AstVar::vlArgType(bool named, bool forReturn, bool forFunc) const {
|
||||
arg += "float";
|
||||
} else if (strtype) {
|
||||
if (isInOnly()) arg += "const ";
|
||||
arg += "string";
|
||||
arg += "std::string";
|
||||
} else if (widthMin() <= 8) {
|
||||
arg += "CData";
|
||||
} else if (widthMin() <= 16) {
|
||||
@@ -763,10 +763,6 @@ void AstAlways::dump(ostream& str) {
|
||||
if (keyword() != VAlwaysKwd::ALWAYS) str<<" ["<<keyword().ascii()<<"]";
|
||||
}
|
||||
|
||||
void AstArraySel::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" [start:"<<start()<<"] [length:"<<length()<<"]";
|
||||
}
|
||||
void AstAttrOf::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" ["<<attrType().ascii()<<"]";
|
||||
@@ -891,6 +887,10 @@ void AstNodeModule::dump(ostream& str) {
|
||||
if (inLibrary()) str<<" [LIB]";
|
||||
if (dead()) str<<" [DEAD]";
|
||||
}
|
||||
void AstPackageExport::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> "<<packagep();
|
||||
}
|
||||
void AstPackageImport::dump(ostream& str) {
|
||||
this->AstNode::dump(str);
|
||||
str<<" -> "<<packagep();
|
||||
|
||||
+54
-22
@@ -127,15 +127,18 @@ public:
|
||||
setOp2p(new AstConst(fl,range.hi())); setOp3p(new AstConst(fl,range.lo()));
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Range)
|
||||
AstNode* msbp() const { return op2p(); } // op2 = Msb expression
|
||||
AstNode* lsbp() const { return op3p(); } // op3 = Lsb expression
|
||||
AstNode* msbp() const { return op2p(); } // op2 = Msb expression
|
||||
AstNode* lsbp() const { return op3p(); } // op3 = Lsb expression
|
||||
AstNode* leftp() const { return littleEndian()?lsbp():msbp(); } // How to show a declaration
|
||||
AstNode* rightp() const { return littleEndian()?msbp():lsbp(); }
|
||||
int msbConst() const { AstConst* constp=msbp()->castConst(); return (constp?constp->toSInt():0); }
|
||||
int lsbConst() const { AstConst* constp=lsbp()->castConst(); return (constp?constp->toSInt():0); }
|
||||
int elementsConst() const { return (msbConst()>lsbConst()) ? msbConst()-lsbConst()+1 : lsbConst()-msbConst()+1; }
|
||||
bool littleEndian() const { return m_littleEndian; }
|
||||
void littleEndian(bool flag) { m_littleEndian=flag; }
|
||||
int msbConst() const { AstConst* constp=msbp()->castConst(); return (constp?constp->toSInt():0); }
|
||||
int lsbConst() const { AstConst* constp=lsbp()->castConst(); return (constp?constp->toSInt():0); }
|
||||
int elementsConst() const { return (msbConst()>lsbConst()) ? msbConst()-lsbConst()+1 : lsbConst()-msbConst()+1; }
|
||||
int leftConst() const { AstConst* constp=leftp()->castConst(); return (constp?constp->toSInt():0); }
|
||||
int rightConst() const { AstConst* constp=rightp()->castConst(); return (constp?constp->toSInt():0); }
|
||||
int leftToRightInc() const { return littleEndian()?1:-1; }
|
||||
bool littleEndian() const { return m_littleEndian; }
|
||||
void littleEndian(bool flag) { m_littleEndian=flag; }
|
||||
virtual void dump(ostream& str);
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
@@ -254,7 +257,7 @@ public:
|
||||
m_uniqueNum = uniqueNumInc();
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(DefImplicitDType)
|
||||
virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castDefImplicitDType()->m_uniqueNum; }
|
||||
virtual bool same(AstNode* samep) const { return m_uniqueNum==samep->castDefImplicitDType()->m_uniqueNum; }
|
||||
virtual bool similarDType(AstNodeDType* samep) const {
|
||||
return type()==samep->type() && same(samep); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); }
|
||||
@@ -406,8 +409,8 @@ public:
|
||||
void rangep(AstRange* nodep) { setNOp1p(nodep); }
|
||||
void setSignedState(VSignedState signst) {
|
||||
// Note NOSIGN does NOT change the state; this is required by the parser
|
||||
if (signst==signedst_UNSIGNED) numeric(VSignedState(signst));
|
||||
else if (signst==signedst_SIGNED) numeric(VSignedState(signst));
|
||||
if (signst==signedst_UNSIGNED) numeric(signst);
|
||||
else if (signst==signedst_SIGNED) numeric(signst);
|
||||
}
|
||||
// METHODS
|
||||
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
|
||||
@@ -607,6 +610,7 @@ class AstMemberDType : public AstNodeDType {
|
||||
private:
|
||||
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
||||
string m_name; // Name of variable
|
||||
string m_tag; // Holds the string of the verilator tag -- used in XML output.
|
||||
int m_lsb; // Within this level's packed struct, the LSB of the first bit of the member
|
||||
//UNSUP: int m_randType; // Randomization type (IEEE)
|
||||
public:
|
||||
@@ -647,6 +651,8 @@ public:
|
||||
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
||||
// METHODS
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
virtual void tag(const string& text) { m_tag = text;}
|
||||
virtual string tag() const { return m_tag; }
|
||||
int lsb() const { return m_lsb; }
|
||||
void lsb(int lsb) { m_lsb=lsb; }
|
||||
};
|
||||
@@ -763,8 +769,6 @@ class AstArraySel : public AstNodeSel {
|
||||
// Parents: math|stmt
|
||||
// Children: varref|arraysel, math
|
||||
private:
|
||||
unsigned m_start;
|
||||
unsigned m_length;
|
||||
void init(AstNode* fromp) {
|
||||
if (fromp && fromp->dtypep()->skipRefp()->castNodeArrayDType()) {
|
||||
// Strip off array to find what array references
|
||||
@@ -773,11 +777,11 @@ private:
|
||||
}
|
||||
public:
|
||||
AstArraySel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
||||
:AstNodeSel(fl, fromp, bitp), m_start(0), m_length(1) {
|
||||
:AstNodeSel(fl, fromp, bitp) {
|
||||
init(fromp);
|
||||
}
|
||||
AstArraySel(FileLine* fl, AstNode* fromp, int bit)
|
||||
:AstNodeSel(fl, fromp, new AstConst(fl,bit)), m_start(0), m_length(1) {
|
||||
:AstNodeSel(fl, fromp, new AstConst(fl,bit)) {
|
||||
init(fromp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ArraySel)
|
||||
@@ -789,18 +793,13 @@ public:
|
||||
virtual bool cleanOut() { return true; }
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isGateOptimizable() const { return true; } // esp for V3Const::ifSameAssign
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
unsigned length() const { return m_length; }
|
||||
void length(unsigned length) { m_length = length; }
|
||||
void start(unsigned start) { m_start = start; }
|
||||
unsigned start() const { return m_start; }
|
||||
// Special operators
|
||||
static AstNode* baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences?
|
||||
virtual void dump(ostream& str);
|
||||
};
|
||||
|
||||
class AstWordSel : public AstNodeSel {
|
||||
@@ -982,6 +981,7 @@ class AstVar : public AstNode {
|
||||
private:
|
||||
string m_name; // Name of variable
|
||||
string m_origName; // Original name before dot addition
|
||||
string m_tag; // Holds the string of the verilator tag -- used in XML output.
|
||||
AstVarType m_varType; // Type of variable
|
||||
bool m_input:1; // Input or inout
|
||||
bool m_output:1; // Output or inout
|
||||
@@ -1122,6 +1122,8 @@ public:
|
||||
void trace(bool flag) { m_trace=flag; }
|
||||
// METHODS
|
||||
virtual void name(const string& name) { m_name = name; }
|
||||
virtual void tag(const string& text) { m_tag = text;}
|
||||
virtual string tag() const { return m_tag; }
|
||||
virtual string directionName() const { return (isInout() ? "inout" : isInput() ? "input"
|
||||
: isOutput() ? "output" : varType().ascii()); }
|
||||
bool isInput() const { return m_input; }
|
||||
@@ -1505,6 +1507,32 @@ public:
|
||||
virtual string verilogKwd() const { return "primitive"; }
|
||||
};
|
||||
|
||||
class AstPackageExportStarStar : public AstNode {
|
||||
// A package export *::* declaration
|
||||
public:
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
AstPackageExportStarStar(FileLine* fl)
|
||||
: AstNode (fl) {}
|
||||
ASTNODE_NODE_FUNCS(PackageExportStarStar)
|
||||
};
|
||||
|
||||
class AstPackageExport : public AstNode {
|
||||
private:
|
||||
// A package export declaration
|
||||
string m_name;
|
||||
AstPackage* m_packagep; // Package hierarchy
|
||||
public:
|
||||
AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name)
|
||||
: AstNode (fl), m_name(name), m_packagep(packagep) {}
|
||||
ASTNODE_NODE_FUNCS(PackageExport)
|
||||
virtual const char* broken() const { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); return NULL; }
|
||||
virtual void cloneRelink() { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); }
|
||||
virtual void dump(ostream& str);
|
||||
virtual string name() const { return m_name; }
|
||||
AstPackage* packagep() const { return m_packagep; }
|
||||
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
||||
};
|
||||
|
||||
class AstPackageImport : public AstNode {
|
||||
private:
|
||||
// A package import declaration
|
||||
@@ -1794,7 +1822,7 @@ public:
|
||||
}}
|
||||
virtual bool same(AstNode* samep) const {
|
||||
return (m_packagep==samep->castPackageRef()->m_packagep); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_packagep)); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(m_packagep); }
|
||||
virtual void dump(ostream& str=cout);
|
||||
AstPackage* packagep() const { return m_packagep; }
|
||||
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
||||
@@ -1916,7 +1944,7 @@ public:
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(SenItem)
|
||||
virtual void dump(ostream& str);
|
||||
virtual V3Hash sameHash() const { return V3Hash(V3Hash(edgeType())); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(edgeType()); }
|
||||
virtual bool same(AstNode* samep) const {
|
||||
return edgeType()==samep->castSenItem()->edgeType(); }
|
||||
AstEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge
|
||||
@@ -2155,6 +2183,8 @@ public:
|
||||
AstCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeCond(fl, condp, expr1p, expr2p) {}
|
||||
ASTNODE_NODE_FUNCS(Cond)
|
||||
virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) {
|
||||
return new AstCond(this->fileline(), condp, expr1p, expr2p); }
|
||||
};
|
||||
|
||||
class AstCondBound : public AstNodeCond {
|
||||
@@ -2165,6 +2195,8 @@ public:
|
||||
AstCondBound(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeCond(fl, condp, expr1p, expr2p) {}
|
||||
ASTNODE_NODE_FUNCS(CondBound)
|
||||
virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) {
|
||||
return new AstCondBound(this->fileline(), condp, expr1p, expr2p); }
|
||||
};
|
||||
|
||||
class AstCoverDecl : public AstNodeStmt {
|
||||
|
||||
+1
-1
@@ -296,5 +296,5 @@ void V3Begin::debeginAll(AstNetlist* nodep) {
|
||||
if (state.anyFuncInBegin()) {
|
||||
BeginRelinkVisitor brvisitor (nodep,&state);
|
||||
}
|
||||
V3Global::dumpCheckGlobalTree("begin.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("begin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+7
-3
@@ -31,7 +31,7 @@
|
||||
#include <cstdarg>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3Broken.h"
|
||||
@@ -47,7 +47,7 @@ class BrokenTable : public AstNVisitor {
|
||||
private:
|
||||
// MEMBERS
|
||||
// For each node, we keep if it exists or not.
|
||||
typedef map<const AstNode*,int> NodeMap;
|
||||
typedef VL_UNORDERED_MAP<const AstNode*,int> NodeMap; // Performance matters (when --debug)
|
||||
static NodeMap s_nodes; // Set of all nodes that exist
|
||||
// BITMASK
|
||||
enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed
|
||||
@@ -66,12 +66,16 @@ public:
|
||||
}
|
||||
if (iter!=s_nodes.end()) s_nodes.erase(iter);
|
||||
}
|
||||
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
|
||||
// GCC 4.4.* compiler warning bug, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39390
|
||||
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif
|
||||
static void addNewed(const AstNode* nodep) {
|
||||
// Called by operator new on any node - only if VL_LEAK_CHECKS
|
||||
if (debug()>=9) cout<<"-nodeNew: "<<(void*)(nodep)<<endl;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
if (iter!=s_nodes.end() || (iter->second & FLAG_ALLOCATED)) {
|
||||
((AstNode*)(nodep))->v3fatalSrc("Newing AstNode object that is already allocated");
|
||||
nodep->v3fatalSrc("Newing AstNode object that is already allocated");
|
||||
}
|
||||
if (iter == s_nodes.end()) {
|
||||
int flags = FLAG_ALLOCATED; // This int needed to appease GCC 4.1.2
|
||||
|
||||
+24
-17
@@ -95,6 +95,8 @@ public:
|
||||
m_modp->addStmtp(m_tlFuncp);
|
||||
}
|
||||
~V3CCtorsVisitor() {}
|
||||
private:
|
||||
explicit V3CCtorsVisitor(const V3CCtorsVisitor&); ///< N/A, no copy constructor
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
@@ -102,22 +104,27 @@ public:
|
||||
void V3CCtors::cctorsAll() {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=modp->nextp()->castNodeModule()) {
|
||||
// Process each module in turn
|
||||
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
|
||||
V3CCtorsVisitor configure_coverage (modp, "_configure_coverage",
|
||||
EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first",
|
||||
"if (0 && vlSymsp && first) {} // Prevent unused\n");
|
||||
|
||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||
AstVar* varp = np->castVar();
|
||||
if (varp) var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true)));
|
||||
AstCoverDecl* coverp = np->castCoverDecl();
|
||||
if (coverp) {
|
||||
AstNode* backp = coverp->backp();
|
||||
coverp->unlinkFrBack();
|
||||
configure_coverage.add(coverp);
|
||||
np = backp;
|
||||
}
|
||||
}
|
||||
// Process each module in turn
|
||||
{
|
||||
V3CCtorsVisitor var_reset (modp, "_ctor_var_reset");
|
||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||
if (AstVar* varp = np->castVar()) {
|
||||
var_reset.add(new AstCReset(varp->fileline(), new AstVarRef(varp->fileline(), varp, true)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (v3Global.opt.coverage()) {
|
||||
V3CCtorsVisitor configure_coverage
|
||||
(modp, "_configure_coverage", EmitCBaseVisitor::symClassVar()+ ", bool first", "vlSymsp, first",
|
||||
"if (0 && vlSymsp && first) {} // Prevent unused\n");
|
||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||
if (AstCoverDecl* coverp = np->castCoverDecl()) {
|
||||
AstNode* backp = coverp->backp();
|
||||
coverp->unlinkFrBack();
|
||||
configure_coverage.add(coverp);
|
||||
np = backp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -489,7 +489,7 @@ public:
|
||||
void V3Case::caseAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CaseVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("case.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("case", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
void V3Case::caseLint(AstNodeCase* nodep) {
|
||||
UINFO(4,__FUNCTION__<<": "<<endl);
|
||||
|
||||
+1
-1
@@ -188,5 +188,5 @@ public:
|
||||
void V3Cast::castAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CastVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("cast.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("cast", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+4
-4
@@ -111,8 +111,8 @@ private:
|
||||
AstVarScope* m_vscp; // Original (non-change) variable we're change-detecting
|
||||
AstVarScope* m_newvscp; // New (change detect) variable we're change-detecting
|
||||
AstNode* m_varEqnp; // Original var's equation to get var value
|
||||
AstNode* m_newLvEqnp; // New var's equation to read value
|
||||
AstNode* m_newRvEqnp; // New var's equation to set value
|
||||
AstNode* m_newLvEqnp; // New var's equation to read value
|
||||
AstNode* m_newRvEqnp; // New var's equation to set value
|
||||
uint32_t m_detects; // # detects created
|
||||
|
||||
// CONSTANTS
|
||||
@@ -278,7 +278,7 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeMath* nodep) {
|
||||
// Short-circuit
|
||||
// Short-circuit
|
||||
}
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
@@ -302,5 +302,5 @@ void V3Changed::changedAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ChangedState state;
|
||||
ChangedVisitor visitor (nodep, &state);
|
||||
V3Global::dumpCheckGlobalTree("changed.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("changed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -297,5 +297,5 @@ public:
|
||||
void V3Clean::cleanAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CleanVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("clean.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("clean", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+2
-2
@@ -879,7 +879,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
explicit GaterVisitor(AstNode* nodep) {
|
||||
explicit GaterVisitor(AstNetlist* nodep) {
|
||||
// AstAlways visitor does the real work, so most zeroing needs to be in clear()
|
||||
clear();
|
||||
nodep->accept(*this);
|
||||
@@ -915,5 +915,5 @@ void V3ClkGater::clkGaterAll(AstNetlist* nodep) {
|
||||
// While the gater does well at some modules, it seems to slow down many others
|
||||
UINFO(5,"ClkGater is disabled due to performance issues\n");
|
||||
//GaterVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("clkgater.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("clkgater", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -413,5 +413,5 @@ public:
|
||||
void V3Clock::clockAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ClockVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("clock.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("clock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -474,5 +474,5 @@ public:
|
||||
void V3Combine::combineAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CombineVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("combine.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("combine", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+166
-31
@@ -305,8 +305,7 @@ private:
|
||||
return (nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
&& nodep->lsbConst()==0
|
||||
&& (int)nodep->widthConst()==nodep->fromp()->width()
|
||||
&& 1);
|
||||
&& (int)nodep->widthConst()==nodep->fromp()->width());
|
||||
}
|
||||
bool operandSelExtend(AstSel* nodep) {
|
||||
// A pattern created by []'s after offsets have been removed
|
||||
@@ -342,12 +341,39 @@ private:
|
||||
replaceWChild(nodep, bip); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
bool operandSelShiftLower(AstSel* nodep) {
|
||||
// AND({a}, SHIFTR({b}, {c})) is often shorthand in C for Verilog {b}[{c} :+ {a}]
|
||||
// becomes thought other optimizations
|
||||
// SEL(SHIFTR({a},{b}),{lsb},{width}) -> SEL({a},{lsb+b},{width})
|
||||
AstShiftR* shiftp = nodep->fromp()->castShiftR();
|
||||
if (!(m_doV
|
||||
&& shiftp
|
||||
&& shiftp->rhsp()->castConst()
|
||||
&& nodep->lsbp()->castConst()
|
||||
&& nodep->widthp()->castConst()
|
||||
)) return false;
|
||||
AstNode* ap = shiftp->lhsp();
|
||||
AstConst* bp = shiftp->rhsp()->castConst();
|
||||
AstConst* lp = nodep->lsbp()->castConst();
|
||||
if (bp->isWide() || bp->num().isFourState() || bp->num().isNegative()
|
||||
|| lp->isWide() || lp->num().isFourState() || lp->num().isNegative()) return false;
|
||||
int newLsb = lp->toSInt() + bp->toSInt();
|
||||
if (newLsb + nodep->widthConst() > ap->width()) return false;
|
||||
//
|
||||
UINFO(9, "SEL(SHIFTR(a,b),l,w) -> SEL(a,l+b,w)\n");
|
||||
if (debug()>=9) nodep->dumpTree(cout,"SEL(SH)-in:");
|
||||
AstSel* newp = new AstSel(nodep->fileline(), ap->unlinkFrBack(), newLsb, nodep->widthConst());
|
||||
newp->dtypeFrom(nodep);
|
||||
if (debug()>=9) newp->dumpTree(cout,"SEL(SH)-ou:");
|
||||
nodep->replaceWith(newp); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operandBiExtendConst(AstNodeBiop* nodep) {
|
||||
bool operandBiExtendConstShrink(AstNodeBiop* nodep) {
|
||||
// Loop unrolling favors standalone compares
|
||||
// EQ(const{width32}, EXTEND(xx{width3})) -> EQ(const{3}, xx{3})
|
||||
// Beware that the constant must have zero bits (+ 1 if signed) or compare
|
||||
// would be incorrect
|
||||
// The constant must have zero bits (+ 1 if signed) or compare
|
||||
// would be incorrect. See also operandBiExtendConst
|
||||
AstExtend* extendp = nodep->rhsp()->castExtend();
|
||||
if (!extendp) return false;
|
||||
AstNode* smallerp = extendp->lhsp();
|
||||
@@ -369,6 +395,19 @@ private:
|
||||
if (debug()>=9) nodep->dumpTree(cout,"BI(EXTEND)-ou:");
|
||||
return true;
|
||||
}
|
||||
bool operandBiExtendConstOver(AstNodeBiop* nodep) {
|
||||
// EQ(const{width32}, EXTEND(xx{width3})) -> constant
|
||||
// When the constant has non-zero bits above the extend it's a constant.
|
||||
// Avoids compiler warning
|
||||
AstExtend* extendp = nodep->rhsp()->castExtend();
|
||||
if (!extendp) return false;
|
||||
AstNode* smallerp = extendp->lhsp();
|
||||
int subsize = smallerp->width();
|
||||
AstConst* constp = nodep->lhsp()->castConst();
|
||||
if (!constp) return false;
|
||||
if (constp->num().isBitsZero(constp->width()-1, subsize)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
AstNode* afterComment(AstNode* nodep) {
|
||||
// Ignore comments, such as to determine if a AstIf is empty.
|
||||
@@ -446,11 +485,7 @@ private:
|
||||
if (!ifp || ifp->nextp()) return false; // Must be SINGLE statement
|
||||
if (!elsep || elsep->nextp()) return false;
|
||||
if (ifp->type() != elsep->type()) return false; // Can't mix an assigndly and an assign
|
||||
AstVarRef* ifvarp = ifp->lhsp()->castVarRef();
|
||||
AstVarRef* elsevarp = elsep->lhsp()->castVarRef();
|
||||
if (!ifvarp || !elsevarp) return false;
|
||||
if (ifvarp->isWide()) return false; // Would need temporaries, so not worth it
|
||||
if (!ifvarp->sameGateTree(elsevarp)) return false;
|
||||
if (!ifp->lhsp()->sameGateTree(elsep->lhsp())) return false;
|
||||
if (!ifp->rhsp()->gateTree()) return false;
|
||||
if (!elsep->rhsp()->gateTree()) return false;
|
||||
return true;
|
||||
@@ -1367,22 +1402,67 @@ private:
|
||||
}
|
||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
}
|
||||
|
||||
void replaceSelReplicate(AstSel* nodep) {
|
||||
// SEL(REPLICATE(a,b),1,bit) => SEL(a,1,bit)
|
||||
bool operandSelReplicate(AstSel* nodep) {
|
||||
// SEL(REPLICATE(from,rep),lsb,width) => SEL(from,0,width) as long as SEL's width <= b's width
|
||||
AstReplicate* repp = nodep->fromp()->castReplicate();
|
||||
AstNode* fromp = repp->lhsp()->unlinkFrBack();
|
||||
AstConst* lsbp = nodep->lsbp()->castConst();
|
||||
AstNode* widthp = nodep->widthp()->unlinkFrBack();
|
||||
AstNode* fromp = repp->lhsp();
|
||||
AstConst* lsbp = nodep->lsbp()->castConst(); if (!lsbp) return false;
|
||||
AstNode* widthp = nodep->widthp(); if (!widthp->castConst()) return false;
|
||||
if (!fromp->width()) nodep->v3fatalSrc("Not widthed");
|
||||
if ((lsbp->toUInt() / fromp->width())
|
||||
!= ((lsbp->toUInt()+nodep->width()-1) / fromp->width())) return false;
|
||||
//
|
||||
fromp->unlinkFrBack();
|
||||
widthp->unlinkFrBack();
|
||||
AstSel* newp = new AstSel(nodep->fileline(),
|
||||
fromp,
|
||||
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
|
||||
widthp);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
bool operandRepRep(AstReplicate* nodep) {
|
||||
// REPLICATE(REPLICATE2(from2,cnt2),cnt1) => REPLICATE(from2,(cnt1+cnt2))
|
||||
AstReplicate* rep2p = nodep->lhsp()->castReplicate();
|
||||
AstNode* from2p = rep2p->lhsp();
|
||||
AstConst* cnt1p = nodep->rhsp()->castConst(); if (!cnt1p) return false;
|
||||
AstConst* cnt2p = rep2p->rhsp()->castConst(); if (!cnt2p) return false;
|
||||
//
|
||||
from2p->unlinkFrBack();
|
||||
cnt1p->unlinkFrBack();
|
||||
cnt2p->unlinkFrBack();
|
||||
AstReplicate* newp = new AstReplicate(nodep->fileline(),
|
||||
from2p, cnt1p->toUInt()*cnt2p->toUInt());
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
bool operandConcatSame(AstConcat* nodep) {
|
||||
// CONCAT(fromp,fromp) -> REPLICATE(fromp,1+1)
|
||||
// CONCAT(REP(fromp,cnt1),fromp) -> REPLICATE(fromp,cnt1+1)
|
||||
// CONCAT(fromp,REP(fromp,cnt1)) -> REPLICATE(fromp,1+cnt1)
|
||||
// CONCAT(REP(fromp,cnt1),REP(fromp,cnt2)) -> REPLICATE(fromp,cnt1+cnt2)
|
||||
AstNode* from1p = nodep->lhsp(); uint32_t cnt1 = 1;
|
||||
AstNode* from2p = nodep->rhsp(); uint32_t cnt2 = 1;
|
||||
if (from1p->castReplicate()) {
|
||||
AstConst* cnt1p = from1p->castReplicate()->rhsp()->castConst(); if (!cnt1p) return false;
|
||||
from1p = from1p->castReplicate()->lhsp();
|
||||
cnt1 = cnt1p->toUInt();
|
||||
}
|
||||
if (from2p->castReplicate()) {
|
||||
AstConst* cnt2p = from2p->castReplicate()->rhsp()->castConst(); if (!cnt2p) return false;
|
||||
from2p = from2p->castReplicate()->lhsp();
|
||||
cnt2 = cnt2p->toUInt();
|
||||
}
|
||||
if (!operandsSame(from1p,from2p)) return false;
|
||||
//
|
||||
from1p->unlinkFrBack();
|
||||
AstReplicate* newp = new AstReplicate(nodep->fileline(), from1p, cnt1+cnt2);
|
||||
newp->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -1609,9 +1689,12 @@ private:
|
||||
// But might be same name with different scopes
|
||||
if (litemp->varrefp()->varScopep() < ritemp->varrefp()->varScopep()) return true;
|
||||
if (litemp->varrefp()->varScopep() > ritemp->varrefp()->varScopep()) return false;
|
||||
// Or rarely, different data types
|
||||
if (litemp->varrefp()->dtypep() < ritemp->varrefp()->dtypep()) return true;
|
||||
if (litemp->varrefp()->dtypep() > ritemp->varrefp()->dtypep()) return false;
|
||||
}
|
||||
// Sort by edge, AFTER variable, as we want multiple edges for same var adjacent
|
||||
// note the SenTree optimizer requires this order (more general firsst, less general last)
|
||||
// note the SenTree optimizer requires this order (more general first, less general last)
|
||||
if (litemp->edgeType() < ritemp->edgeType()) return true;
|
||||
if (litemp->edgeType() > ritemp->edgeType()) return false;
|
||||
}
|
||||
@@ -1822,7 +1905,7 @@ private:
|
||||
}
|
||||
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);
|
||||
UINFO(9,"IF({a}) IF({b}) => IF({a} && {b})"<<endl);
|
||||
AstNodeIf* lowerIfp = nodep->ifsp()->castNodeIf();
|
||||
AstNode* condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
|
||||
@@ -1838,6 +1921,49 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstDisplay* nodep) {
|
||||
// DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2))
|
||||
nodep->iterateChildren(*this);
|
||||
if (stmtDisplayDisplay(nodep)) return;
|
||||
}
|
||||
bool stmtDisplayDisplay(AstDisplay* nodep) {
|
||||
// DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2))
|
||||
if (!m_modp) return false; // Don't optimize under single statement
|
||||
if (!nodep->backp()) return false;
|
||||
AstDisplay* prevp = nodep->backp()->castDisplay();
|
||||
if (!prevp) return false;
|
||||
if (!((prevp->displayType() == nodep->displayType())
|
||||
|| (prevp->displayType() == AstDisplayType::DT_WRITE
|
||||
&& nodep->displayType() == AstDisplayType::DT_DISPLAY)
|
||||
|| (prevp->displayType() == AstDisplayType::DT_DISPLAY
|
||||
&& nodep->displayType() == AstDisplayType::DT_WRITE)))
|
||||
return false;
|
||||
if ((prevp->filep() && !nodep->filep())
|
||||
|| (!prevp->filep() && nodep->filep())
|
||||
|| !prevp->filep()->sameTree(nodep->filep())) return false;
|
||||
if (!prevp->fmtp() || prevp->fmtp()->nextp()
|
||||
|| !nodep->fmtp() || nodep->fmtp()->nextp()) return false;
|
||||
AstSFormatF* pformatp = prevp->fmtp();
|
||||
if (!pformatp || pformatp->exprsp() || pformatp->scopeNamep()) return false;
|
||||
AstSFormatF* nformatp = nodep->fmtp();
|
||||
if (!nformatp || nformatp->exprsp() || nformatp->scopeNamep()) return false;
|
||||
//
|
||||
UINFO(9,"DISPLAY(SF({a})) DISPLAY(SF({b})) -> DISPLAY(SF({a}+{b}))"<<endl);
|
||||
// Convert DT_DISPLAY to DT_WRITE as may allow later optimizations
|
||||
if (prevp->displayType() == AstDisplayType::DT_DISPLAY) {
|
||||
prevp->displayType(AstDisplayType::DT_WRITE);
|
||||
pformatp->text(pformatp->text()+"\n");
|
||||
}
|
||||
// We can't replace prev() as the edit tracking iterators will get confused.
|
||||
// So instead we edit the prev note itself.
|
||||
if (prevp->addNewline()) pformatp->text(pformatp->text()+"\n");
|
||||
pformatp->text(pformatp->text()+nformatp->text());
|
||||
if (!prevp->addNewline() && nodep->addNewline()) {
|
||||
pformatp->text(pformatp->text()+"\n");
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
return true;
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep) {
|
||||
// Substitute constants into displays. The main point of this is to
|
||||
// simplify assertion methodologies which call functions with display's.
|
||||
@@ -1876,7 +2002,7 @@ private:
|
||||
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
|
||||
// fmt = out w/ replace % with %% as it must be literal.
|
||||
fmt = VString::quotePercent(out);
|
||||
argp->unlinkFrBack()->deleteTree();
|
||||
argp->unlinkFrBack()->deleteTree(); VL_DANGLING(argp);
|
||||
}
|
||||
argp=nextp;
|
||||
}
|
||||
@@ -2145,12 +2271,18 @@ private:
|
||||
TREEOP ("AstShiftR{operandShiftShift(nodep)}", "replaceShiftShift(nodep)");
|
||||
TREEOP ("AstWordSel{operandWordOOB(nodep)}", "replaceZero(nodep)");
|
||||
// Compress out EXTENDs to appease loop unroller
|
||||
TREEOPV("AstEq {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstNeq {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstGt {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstGte {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstLt {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstLte {$rhsp.castExtend,operandBiExtendConst(nodep)}", "DONE");
|
||||
TREEOPV("AstEq {$rhsp.castExtend,operandBiExtendConstShrink(nodep)}", "DONE");
|
||||
TREEOPV("AstNeq {$rhsp.castExtend,operandBiExtendConstShrink(nodep)}", "DONE");
|
||||
TREEOPV("AstGt {$rhsp.castExtend,operandBiExtendConstShrink(nodep)}", "DONE");
|
||||
TREEOPV("AstGte {$rhsp.castExtend,operandBiExtendConstShrink(nodep)}", "DONE");
|
||||
TREEOPV("AstLt {$rhsp.castExtend,operandBiExtendConstShrink(nodep)}", "DONE");
|
||||
TREEOPV("AstLte {$rhsp.castExtend,operandBiExtendConstShrink(nodep)}", "DONE");
|
||||
TREEOPV("AstEq {$rhsp.castExtend,operandBiExtendConstOver(nodep)}", "replaceZero(nodep)");
|
||||
TREEOPV("AstNeq {$rhsp.castExtend,operandBiExtendConstOver(nodep)}", "replaceNum(nodep,1)");
|
||||
TREEOPV("AstGt {$rhsp.castExtend,operandBiExtendConstOver(nodep)}", "replaceNum(nodep,1)");
|
||||
TREEOPV("AstGte {$rhsp.castExtend,operandBiExtendConstOver(nodep)}", "replaceNum(nodep,1)");
|
||||
TREEOPV("AstLt {$rhsp.castExtend,operandBiExtendConstOver(nodep)}", "replaceZero(nodep)");
|
||||
TREEOPV("AstLte {$rhsp.castExtend,operandBiExtendConstOver(nodep)}", "replaceZero(nodep)");
|
||||
// Identical operands on both sides
|
||||
// AstLogAnd/AstLogOr already converted to AstAnd/AstOr for these rules
|
||||
// AstAdd->ShiftL(#,1) but uncommon
|
||||
@@ -2242,6 +2374,8 @@ private:
|
||||
TREEOPV("AstExtendS{$lhsp.castExtendS}", "replaceExtend(nodep, nodep->lhsp()->castExtendS()->lhsp())");
|
||||
TREEOPV("AstReplicate{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
|
||||
TREEOPV("AstReplicateN{$lhsp, $rhsp.isOne, $lhsp->width()==nodep->width()}", "replaceWLhs(nodep)"); // {1{lhs}}->lhs
|
||||
TREEOPV("AstReplicate{$lhsp.castReplicate, operandRepRep(nodep)}", "DONE"); // {2{3{lhs}}}->{6{lhs}}
|
||||
TREEOPV("AstConcat{operandConcatSame(nodep)}", "DONE"); // {a,a}->{2{a}}, {a,2{a}}->{3{a}, etc
|
||||
// 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)}", "DONE");
|
||||
@@ -2253,9 +2387,10 @@ private:
|
||||
TREEOPV("AstSel{$fromp.castSub, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castXnor,operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castXor, operandSelBiLower(nodep)}", "DONE");
|
||||
TREEOPV("AstSel{$fromp.castShiftR, operandSelShiftLower(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)");
|
||||
TREEOPV("AstSel{$fromp.castReplicate, $lsbp.castConst, $widthp.castConst, operandSelReplicate(nodep) }", "DONE");
|
||||
// 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)
|
||||
@@ -2409,14 +2544,14 @@ void V3Const::constifyAllLint(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_WARN);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Const::constifyCpp(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_CPP);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("const_cpp.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("const_cpp", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyEdit(AstNode* nodep) {
|
||||
@@ -2432,7 +2567,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_LIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
@@ -2440,7 +2575,7 @@ void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ConstVisitor visitor (ConstVisitor::PROC_V_EXPENSIVE);
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
V3Global::dumpCheckGlobalTree("const.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
|
||||
|
||||
+2
-1
@@ -168,6 +168,7 @@ private:
|
||||
// Add signal to hold the old value
|
||||
string newvarname = (string)"__Vtogcov__"+nodep->shortName();
|
||||
AstVar* chgVarp = new AstVar (nodep->fileline(), AstVarType::MODULETEMP, newvarname, nodep);
|
||||
chgVarp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
|
||||
m_modp->addStmtp(chgVarp);
|
||||
|
||||
// Create bucket for each dimension * bit.
|
||||
@@ -395,5 +396,5 @@ public:
|
||||
void V3Coverage::coverage(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CoverageVisitor visitor (rootp);
|
||||
V3Global::dumpCheckGlobalTree("coverage.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
@@ -135,5 +135,5 @@ public:
|
||||
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
CoverageJoinVisitor visitor (rootp);
|
||||
V3Global::dumpCheckGlobalTree("coveragejoin.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+7
-7
@@ -338,8 +338,8 @@ private:
|
||||
if (vscp->user1() == 0) {
|
||||
UINFO(4," Dead "<<vscp<<endl);
|
||||
pair <AssignMap::iterator,AssignMap::iterator> eqrange = m_assignMap.equal_range(vscp);
|
||||
for (AssignMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||
AstNodeAssign* assp = it->second;
|
||||
for (AssignMap::iterator itr = eqrange.first; itr != eqrange.second; ++itr) {
|
||||
AstNodeAssign* assp = itr->second;
|
||||
UINFO(4," Dead assign "<<assp<<endl);
|
||||
assp->dtypep()->user1Inc(-1);
|
||||
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
|
||||
@@ -422,29 +422,29 @@ public:
|
||||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, false, false, false);
|
||||
V3Global::dumpCheckGlobalTree("deadModules.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
V3Global::dumpCheckGlobalTree("deadModules", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true, false, false);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypes.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypes", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, false, true, true, false);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypesScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true, false, true);
|
||||
V3Global::dumpCheckGlobalTree("deadAll.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deadAll", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DeadVisitor visitor (nodep, true, true, true, true);
|
||||
V3Global::dumpCheckGlobalTree("deadAllScoped.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+6
-6
@@ -77,7 +77,6 @@ private:
|
||||
// AstVarScope::user4p() -> AstAlwaysPost*. Post block for this variable
|
||||
// AstVarScope::user5() -> VarUsage. Tracks delayed vs non-delayed usage
|
||||
// AstVar::user2() -> bool. Set true if already made warning
|
||||
// AstVar::user4() -> int. Vector number, for assignment creation
|
||||
// AstVarRef::user2() -> bool. Set true if already processed
|
||||
// AstAlwaysPost::user2() -> ActActive*. Points to activity block of signal (valid when AstAlwaysPost::user4p is valid)
|
||||
// AstAlwaysPost::user4() -> AstIf*. Last IF (__Vdlyvset__) created under this AlwaysPost
|
||||
@@ -102,7 +101,8 @@ private:
|
||||
typedef std::map<pair<AstNodeModule*,string>,AstVar*> VarMap;
|
||||
VarMap m_modVarMap; // Table of new var names created under module
|
||||
V3Double0 m_statSharedSet;// Statistic tracking
|
||||
|
||||
typedef std::map<AstVarScope*,int> ScopeVecMap;
|
||||
ScopeVecMap m_scopeVecMap; // Next var number for each scope
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -195,7 +195,7 @@ private:
|
||||
arrayselp = lhsp->castArraySel();
|
||||
}
|
||||
if (!arrayselp) nodep->v3fatalSrc("No arraysel under bitsel?");
|
||||
if (arrayselp->length()!=1) nodep->v3fatalSrc("ArraySel with length!=1 should have been removed in V3Slice");
|
||||
if (arrayselp->dtypep()->skipRefp()->castUnpackArrayDType()) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
|
||||
|
||||
UINFO(4,"AssignDlyArray: "<<nodep<<endl);
|
||||
//
|
||||
@@ -211,7 +211,7 @@ private:
|
||||
if (!varrefp->varScopep()) varrefp->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp");
|
||||
varrefp->unlinkFrBack();
|
||||
AstVar* oldvarp = varrefp->varp();
|
||||
int modVecNum = oldvarp->user4(); oldvarp->user4(modVecNum+1);
|
||||
int modVecNum = m_scopeVecMap[varrefp->varScopep()]++;
|
||||
//
|
||||
deque<AstNode*> dimreadps; // Read value for each dimension of assignment
|
||||
for (unsigned dimension=0; dimension<dimvalp.size(); dimension++) {
|
||||
@@ -370,7 +370,7 @@ private:
|
||||
&& nodep->lhsp()->castSel()->fromp()->castArraySel())) {
|
||||
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
|
||||
AstNode* newlhsp = createDlyArray(nodep, lhsp);
|
||||
if (m_inLoop) nodep->v3warn(E_BLKLOOPINIT,"Unsupported: Delayed assignment to array inside for loops (non-delayed is ok - see docs)");
|
||||
if (m_inLoop) nodep->v3warn(BLKLOOPINIT,"Unsupported: Delayed assignment to array inside for loops (non-delayed is ok - see docs)");
|
||||
if (newlhsp) {
|
||||
nodep->lhsp(newlhsp);
|
||||
} else {
|
||||
@@ -471,5 +471,5 @@ public:
|
||||
void V3Delayed::delayedAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DelayedVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("delayed.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("delayed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -175,5 +175,5 @@ public:
|
||||
void V3Depth::depthAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DepthVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("depth.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
@@ -140,5 +140,5 @@ public:
|
||||
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DepthBlockVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("deepblock.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+94
-45
@@ -53,7 +53,8 @@ private:
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstScope* m_scopep; // Current scope
|
||||
bool m_needThis; // Add thisp to function
|
||||
bool m_modSingleton; // m_modp is only instanced once
|
||||
bool m_needThis; // Make function non-static
|
||||
FuncMmap m_modFuncs; // Name of public functions added
|
||||
|
||||
// METHODS
|
||||
@@ -63,41 +64,91 @@ private:
|
||||
return level;
|
||||
}
|
||||
|
||||
string descopedName(AstScope* scopep, bool& hierThisr, AstVar* varp=NULL) {
|
||||
static bool modIsSingleton(AstNodeModule* modp) {
|
||||
// True iff there's exactly one instance of this module in the design.
|
||||
int instances = 0;
|
||||
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
|
||||
if (stmtp->castScope()) {
|
||||
if (++instances > 1) { return false; }
|
||||
}
|
||||
}
|
||||
return (instances == 1);
|
||||
}
|
||||
|
||||
// Construct the best prefix to reference an object in 'scopep'
|
||||
// from a CFunc in 'm_scopep'. Result may be relative
|
||||
// ("this->[...]") or absolute ("vlTOPp->[...]").
|
||||
//
|
||||
// Using relative references allows V3Combine'ing
|
||||
// code across multiple instances of the same module.
|
||||
//
|
||||
// Sets 'hierThisr' true if the object is local to this scope
|
||||
// (and could be made into a function-local later in V3Localize),
|
||||
// false if the object is in another scope.
|
||||
string descopedName(const AstScope* scopep, bool& hierThisr,
|
||||
const AstVar* varp=NULL) {
|
||||
UASSERT(scopep, "Var/Func not scoped\n");
|
||||
hierThisr = true;
|
||||
hierThisr = (scopep == m_scopep);
|
||||
|
||||
// It's possible to disable relative references. This is a concession
|
||||
// to older compilers (gcc < 4.5.x) that don't understand __restrict__
|
||||
// well and emit extra ld/st to guard against pointer aliasing
|
||||
// when this-> and vlTOPp-> are mixed in the same function.
|
||||
//
|
||||
// "vlTOPp" is declared "restrict" so better compilers understand
|
||||
// that it won't alias with "this".
|
||||
bool relativeRefOk = v3Global.opt.relativeCFuncs();
|
||||
|
||||
// Use absolute refs in top-scoped routines, keep them static.
|
||||
// The DPI callback registration depends on representing top-level
|
||||
// static routines as plain function pointers. That breaks if those
|
||||
// become true OO routines.
|
||||
//
|
||||
// V3Combine wouldn't likely be able to combine top-level
|
||||
// routines anyway, so there's no harm in keeping these static.
|
||||
if (m_modp->isTop()) {
|
||||
relativeRefOk = false;
|
||||
}
|
||||
|
||||
// Use absolute refs if this scope is the only instance of the module.
|
||||
// Saves a bit of overhead on passing the 'this' pointer, and there's no
|
||||
// need to be nice to V3Combine when we have only a single instance.
|
||||
// The risk that this prevents combining identical logic from differently-
|
||||
// named but identical modules seems low.
|
||||
if (m_modSingleton) {
|
||||
relativeRefOk = false;
|
||||
}
|
||||
|
||||
if (varp && varp->isFuncLocal()) {
|
||||
hierThisr = true;
|
||||
return ""; // Relative to function, not in this
|
||||
} else if (scopep == m_scopep && m_modp->isTop()) {
|
||||
//return ""; // Reference to scope we're in, no need to HIER-> it
|
||||
return "vlTOPp->";
|
||||
} else if (scopep == m_scopep && !m_modp->isTop()
|
||||
&& 0) { // We no longer thisp-> as still get ambiguation problems
|
||||
m_needThis = true;
|
||||
return "thisp->"; // this-> but with restricted aliasing
|
||||
} else if (scopep->aboveScopep() && scopep->aboveScopep()==m_scopep
|
||||
&& 0 // DISABLED: GCC considers the pointers ambiguous, so goes ld/store crazy
|
||||
) {
|
||||
// Reference to scope of cell directly under this module, can just "cell->"
|
||||
string name = scopep->name();
|
||||
string::size_type pos;
|
||||
if ((pos = name.rfind(".")) != string::npos) {
|
||||
name.erase(0,pos+1);
|
||||
}
|
||||
hierThisr = false;
|
||||
return name+"->";
|
||||
} else {
|
||||
// Reference to something else, use global variable
|
||||
UINFO(8," Descope "<<scopep<<endl);
|
||||
UINFO(8," to "<<scopep->name()<<endl);
|
||||
UINFO(8," under "<<m_scopep->name()<<endl);
|
||||
hierThisr = false;
|
||||
if (!scopep->aboveScopep()) { // Top
|
||||
return "vlTOPp->"; // == "vlSymsp->TOPp->", but GCC would suspect aliases
|
||||
} else {
|
||||
return scopep->nameVlSym()+".";
|
||||
}
|
||||
}
|
||||
} else if (relativeRefOk && scopep == m_scopep) {
|
||||
m_needThis = true;
|
||||
return "this->";
|
||||
} else if (relativeRefOk && scopep->aboveScopep()
|
||||
&& scopep->aboveScopep()==m_scopep) {
|
||||
// Reference to scope of cell directly under this module, can just "cell->"
|
||||
string name = scopep->name();
|
||||
string::size_type pos;
|
||||
if ((pos = name.rfind(".")) != string::npos) {
|
||||
name.erase(0,pos+1);
|
||||
}
|
||||
m_needThis = true;
|
||||
return name+"->";
|
||||
} else {
|
||||
// Reference to something elsewhere, or relative refences
|
||||
// are disabled. Use global variable
|
||||
UINFO(8," Descope "<<scopep<<endl);
|
||||
UINFO(8," to "<<scopep->name()<<endl);
|
||||
UINFO(8," under "<<m_scopep->name()<<endl);
|
||||
if (!scopep->aboveScopep()) { // Top
|
||||
// We could also return "vlSymsp->TOPp->" here, but GCC would
|
||||
// suspect aliases.
|
||||
return "vlTOPp->";
|
||||
} else {
|
||||
return scopep->nameVlSym()+".";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void makePublicFuncWrappers() {
|
||||
@@ -166,7 +217,7 @@ private:
|
||||
}
|
||||
}
|
||||
// Not really any way the user could do this, and we'd need to come up with some return value
|
||||
//newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), AstDisplayType::DT_DISPLAY,
|
||||
//newfuncp->addStmtsp(new AstDisplay (newfuncp->fileline(), AstDisplayType::DT_WARNING,
|
||||
// string("%%Error: ")+name+"() called with bad scope", NULL));
|
||||
//newfuncp->addStmtsp(new AstStop (newfuncp->fileline()));
|
||||
if (debug()>=9) newfuncp->dumpTree(cout," newfunc: ");
|
||||
@@ -182,6 +233,7 @@ private:
|
||||
virtual void visit(AstNodeModule* nodep) {
|
||||
m_modp = nodep;
|
||||
m_modFuncs.clear();
|
||||
m_modSingleton = modIsSingleton(m_modp);
|
||||
nodep->iterateChildren(*this);
|
||||
makePublicFuncWrappers();
|
||||
m_modp = NULL;
|
||||
@@ -222,11 +274,7 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->user1(true);
|
||||
if (m_needThis) {
|
||||
nodep->v3fatalSrc("old code");
|
||||
// Really we should have more node types for backend optimization of this stuff
|
||||
string text = v3Global.opt.modPrefix() + "_" + m_modp->name()
|
||||
+"* thisp = &("+m_scopep->nameVlSym()+");\n";
|
||||
nodep->addInitsp(new AstCStmt(nodep->fileline(), text));
|
||||
nodep->isStatic(false);
|
||||
}
|
||||
// If it's under a scope, move it up to the top
|
||||
if (m_scopep) {
|
||||
@@ -248,11 +296,12 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DescopeVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_needThis = false;
|
||||
nodep->accept(*this);
|
||||
explicit DescopeVisitor(AstNetlist* nodep)
|
||||
: m_modp(NULL),
|
||||
m_scopep(NULL),
|
||||
m_modSingleton(false),
|
||||
m_needThis(false) {
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~DescopeVisitor() {}
|
||||
};
|
||||
@@ -263,5 +312,5 @@ public:
|
||||
void V3Descope::descopeAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
DescopeVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("descope.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+105
-53
@@ -36,6 +36,8 @@
|
||||
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 8192 // We use a static char array in VL_VALUE_STRING
|
||||
|
||||
#define EMITC_NUM_CONSTW 8 // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_8X is last)
|
||||
|
||||
//######################################################################
|
||||
// Emit statements and math operators
|
||||
|
||||
@@ -603,9 +605,9 @@ public:
|
||||
puts(nodep->hiername());
|
||||
puts(nodep->varp()->name());
|
||||
}
|
||||
void emitCvtPackStr(AstNode* nodep) {
|
||||
void emitCvtPackStr(AstNode* nodep) {
|
||||
if (AstConst* constp = nodep->castConst()) {
|
||||
putbs("string(");
|
||||
putbs("std::string(");
|
||||
putsQuoted(constp->num().toString());
|
||||
puts(")");
|
||||
} else {
|
||||
@@ -625,28 +627,68 @@ public:
|
||||
if (nodep->num().isFourState()) {
|
||||
nodep->v3error("Unsupported: 4-state numbers in this context");
|
||||
} else if (nodep->num().isString()) {
|
||||
putbs("string(");
|
||||
putbs("std::string(");
|
||||
putsQuoted(nodep->num().toString());
|
||||
puts(")");
|
||||
} else if (nodep->isWide()) {
|
||||
putbs("VL_CONST_W_");
|
||||
puts(cvtToStr(VL_WORDS_I(nodep->num().widthMin())));
|
||||
puts("X(");
|
||||
puts(cvtToStr(nodep->widthMin()));
|
||||
puts(",");
|
||||
if (!assigntop) {
|
||||
puts(assignString);
|
||||
} else if (assigntop->castVarRef()) {
|
||||
puts(assigntop->hiername());
|
||||
puts(assigntop->varp()->name());
|
||||
} else {
|
||||
assigntop->iterateAndNext(*this);
|
||||
int upWidth = nodep->num().widthMin();
|
||||
int chunks = 0;
|
||||
if (upWidth > EMITC_NUM_CONSTW*VL_WORDSIZE) {
|
||||
// Output e.g. 8 words in groups of e.g. 8
|
||||
chunks = (upWidth-1) / (EMITC_NUM_CONSTW*VL_WORDSIZE);
|
||||
upWidth %= (EMITC_NUM_CONSTW*VL_WORDSIZE);
|
||||
if (upWidth == 0) upWidth = (EMITC_NUM_CONSTW*VL_WORDSIZE);
|
||||
}
|
||||
for (int word=VL_WORDS_I(nodep->num().widthMin())-1; word>0; word--) {
|
||||
// Only 32 bits - llx + long long here just to appease CPP format warning
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
|
||||
{ // Upper e.g. 8 words
|
||||
if (chunks) {
|
||||
putbs("VL_CONSTHI_W_");
|
||||
puts(cvtToStr(VL_WORDS_I(upWidth)));
|
||||
puts("X(");
|
||||
puts(cvtToStr(nodep->widthMin()));
|
||||
puts(",");
|
||||
puts(cvtToStr(chunks*EMITC_NUM_CONSTW*VL_WORDSIZE));
|
||||
} else {
|
||||
putbs("VL_CONST_W_");
|
||||
puts(cvtToStr(VL_WORDS_I(upWidth)));
|
||||
puts("X(");
|
||||
puts(cvtToStr(nodep->widthMin()));
|
||||
}
|
||||
puts(",");
|
||||
if (!assigntop) {
|
||||
puts(assignString);
|
||||
} else if (assigntop->castVarRef()) {
|
||||
puts(assigntop->hiername());
|
||||
puts(assigntop->varp()->name());
|
||||
} else {
|
||||
assigntop->iterateAndNext(*this);
|
||||
}
|
||||
for (int word=VL_WORDS_I(upWidth)-1; word>=0; word--) {
|
||||
// Only 32 bits - llx + long long here just to appease CPP format warning
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word+chunks*EMITC_NUM_CONSTW)));
|
||||
}
|
||||
puts(")");
|
||||
}
|
||||
for (chunks--; chunks >= 0; chunks--) {
|
||||
puts(";\n");
|
||||
putbs("VL_CONSTLO_W_");
|
||||
puts(cvtToStr(EMITC_NUM_CONSTW));
|
||||
puts("X(");
|
||||
puts(cvtToStr(chunks*EMITC_NUM_CONSTW*VL_WORDSIZE));
|
||||
puts(",");
|
||||
if (!assigntop) {
|
||||
puts(assignString);
|
||||
} else if (assigntop->castVarRef()) {
|
||||
puts(assigntop->hiername());
|
||||
puts(assigntop->varp()->name());
|
||||
} else {
|
||||
assigntop->iterateAndNext(*this);
|
||||
}
|
||||
for (int word=EMITC_NUM_CONSTW-1; word>=0; word--) {
|
||||
// Only 32 bits - llx + long long here just to appease CPP format warning
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word+chunks*EMITC_NUM_CONSTW)));
|
||||
}
|
||||
puts(")");
|
||||
}
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
|
||||
} else if (nodep->isDouble()) {
|
||||
if (int(nodep->num().toDouble()) == nodep->num().toDouble()
|
||||
&& nodep->num().toDouble() < 1000
|
||||
@@ -1422,7 +1464,8 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
}
|
||||
bool zeroit = (varp->attrFileDescr() // Zero it out, so we don't core dump if never call $fopen
|
||||
|| (varp->basicp() && varp->basicp()->isZeroInit())
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero()));
|
||||
|| (varp->name().size()>=1 && varp->name()[0]=='_' && v3Global.opt.underlineZero())
|
||||
|| (v3Global.opt.xInitial() == "fast" || v3Global.opt.xInitial() == "0"));
|
||||
if (varp->isWide()) {
|
||||
// DOCUMENT: We randomize everything. If the user wants a _var to be zero,
|
||||
// there should be a initial statement. (Different from verilator2.)
|
||||
@@ -1516,8 +1559,8 @@ void EmitCImp::emitCoverageImp(AstNodeModule* modp) {
|
||||
puts( " \"filename\",filenamep,");
|
||||
puts( " \"lineno\",lineno,");
|
||||
puts( " \"column\",column,\n");
|
||||
//puts( "\"hier\",string(__VlSymsp->name())+hierp,"); // Need to move hier into scopes and back out if do this
|
||||
puts( "\"hier\",string(name())+hierp,");
|
||||
//puts( "\"hier\",std::string(__VlSymsp->name())+hierp,"); // Need to move hier into scopes and back out if do this
|
||||
puts( "\"hier\",std::string(name())+hierp,");
|
||||
puts( " \"page\",pagep,");
|
||||
puts( " \"comment\",commentp);\n");
|
||||
puts("}\n");
|
||||
@@ -1686,7 +1729,7 @@ void EmitCImp::emitSensitives() {
|
||||
|
||||
void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts("\nvoid "+modClassName(modp)+"::eval() {\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp; // Setup global symbol table\n");
|
||||
puts(EmitCBaseVisitor::symTopAssign()+"\n");
|
||||
putsDecoration("// Initialize\n");
|
||||
puts("if (VL_UNLIKELY(!vlSymsp->__Vm_didInit)) _eval_initial_loop(vlSymsp);\n");
|
||||
@@ -1696,14 +1739,16 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
putsDecoration("// Evaluate till stable\n");
|
||||
puts("VL_DEBUG_IF(VL_PRINTF(\"\\n----TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n");
|
||||
puts("int __VclockLoop = 0;\n");
|
||||
puts("QData __Vchange=1;\n");
|
||||
puts("QData __Vchange = 1;\n");
|
||||
puts("while (VL_LIKELY(__Vchange)) {\n");
|
||||
puts( "VL_DEBUG_IF(VL_PRINTF(\" Clock loop\\n\"););\n");
|
||||
puts( "vlSymsp->__Vm_activity = true;\n");
|
||||
if (v3Global.opt.trace()) {
|
||||
puts("vlSymsp->__Vm_activity = true;\n");
|
||||
}
|
||||
puts( "_eval(vlSymsp);\n");
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
|
||||
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+")) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
|
||||
puts("}\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
@@ -1712,15 +1757,17 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
||||
puts("\nvoid "+modClassName(modp)+"::_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+") {\n");
|
||||
puts("vlSymsp->__Vm_didInit = true;\n");
|
||||
puts("_eval_initial(vlSymsp);\n");
|
||||
puts( "vlSymsp->__Vm_activity = true;\n");
|
||||
if (v3Global.opt.trace()) {
|
||||
puts("vlSymsp->__Vm_activity = true;\n");
|
||||
}
|
||||
puts( "int __VclockLoop = 0;\n");
|
||||
puts( "QData __Vchange=1;\n");
|
||||
puts( "QData __Vchange = 1;\n");
|
||||
puts( "while (VL_LIKELY(__Vchange)) {\n");
|
||||
puts( "_eval_settle(vlSymsp);\n");
|
||||
puts( "_eval(vlSymsp);\n");
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
|
||||
puts( "if (VL_UNLIKELY(++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+")) vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
|
||||
puts( "}\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
@@ -1797,7 +1844,7 @@ void EmitCImp::emitIntFuncDecls(AstNodeModule* modp) {
|
||||
if (!funcp->dpiImport()) { // DPI is prototyped in __Dpi.h
|
||||
ofp()->putsPrivate(funcp->declPrivate());
|
||||
if (funcp->isStatic()) puts("static ");
|
||||
puts(funcp->rtnTypeVoid()); puts("\t");
|
||||
puts(funcp->rtnTypeVoid()); puts(" ");
|
||||
puts(funcp->name()); puts("("+cFuncArgs(funcp)+");\n");
|
||||
}
|
||||
}
|
||||
@@ -1829,8 +1876,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
// 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");
|
||||
}
|
||||
puts("\n");
|
||||
|
||||
// Declare foreign instances up front to make C++ happy
|
||||
puts("class "+symClassName()+";\n");
|
||||
@@ -1854,13 +1901,18 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
ofp()->resetPrivate();
|
||||
ofp()->putsPrivate(false); // public:
|
||||
|
||||
// Instantiated modules
|
||||
putsDecoration("// CELLS\n");
|
||||
if (modp->isTop()) puts("// Public to allow access to /*verilator_public*/ items;\n");
|
||||
if (modp->isTop()) puts("// otherwise the application code can consider these internals.\n");
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstCell* cellp=nodep->castCell()) {
|
||||
ofp()->putsCellDecl(modClassName(cellp->modp()), cellp->name());
|
||||
{ // Instantiated cells
|
||||
bool did = false;
|
||||
for (AstNode* nodep=modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
if (AstCell* cellp=nodep->castCell()) {
|
||||
if (!did) {
|
||||
did = true;
|
||||
putsDecoration("// CELLS\n");
|
||||
if (modp->isTop()) puts("// Public to allow access to /*verilator_public*/ items;\n");
|
||||
if (modp->isTop()) puts("// otherwise the application code can consider these internals.\n");
|
||||
}
|
||||
ofp()->putsCellDecl(modClassName(cellp->modp()), cellp->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1882,11 +1934,11 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
puts("\n// INTERNAL VARIABLES\n");
|
||||
if (modp->isTop()) puts("// Internals; generally not touched by application code\n");
|
||||
ofp()->putsPrivate(!modp->isTop()); // private: unless top
|
||||
puts(symClassName()+"*\t__VlSymsp;\t\t// Symbol table\n");
|
||||
puts(symClassName()+"* __VlSymsp; // Symbol table\n");
|
||||
ofp()->putsPrivate(false); // public:
|
||||
if (modp->isTop()) {
|
||||
if (v3Global.opt.inhibitSim()) {
|
||||
puts("bool\t__Vm_inhibitSim;\t///< Set true to disable evaluation of module\n");
|
||||
puts("bool __Vm_inhibitSim; ///< Set true to disable evaluation of module\n");
|
||||
}
|
||||
}
|
||||
emitCoverageDecl(modp); // may flip public/private
|
||||
@@ -1921,8 +1973,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
ofp()->resetPrivate();
|
||||
// We don't need a private copy constructor, as VerilatedModule has one for us.
|
||||
ofp()->putsPrivate(true);
|
||||
puts(modClassName(modp)+"& operator= (const "+modClassName(modp)+"&);\t///< Copying not allowed\n");
|
||||
puts(modClassName(modp)+"(const "+modClassName(modp)+"&);\t///< Copying not allowed\n");
|
||||
puts(modClassName(modp)+"& operator= (const "+modClassName(modp)+"&); ///< Copying not allowed\n");
|
||||
puts(modClassName(modp)+"(const "+modClassName(modp)+"&); ///< Copying not allowed\n");
|
||||
|
||||
ofp()->putsPrivate(false); // public:
|
||||
if (optSystemC() && modp->isTop()) {
|
||||
@@ -1950,7 +2002,6 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
}
|
||||
}
|
||||
|
||||
puts("\n// USER METHODS\n");
|
||||
emitTextSection(AstType::atScInt);
|
||||
|
||||
puts("\n// API METHODS\n");
|
||||
@@ -1962,7 +2013,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
if (!optSystemC()) puts("/// Simulation complete, run final blocks. Application must call on completion.\n");
|
||||
puts("void final();\n");
|
||||
if (v3Global.opt.inhibitSim()) {
|
||||
puts("void inhibitSim(bool flag) { __Vm_inhibitSim=flag; }\t///< Set true to disable evaluation of module\n");
|
||||
puts("void inhibitSim(bool flag) { __Vm_inhibitSim=flag; } ///< Set true to disable evaluation of module\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1995,13 +2046,13 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
|
||||
// Save/restore
|
||||
if (v3Global.opt.savable() && modp->isTop()) {
|
||||
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vserialize(os); return os;}\n");
|
||||
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "+modClassName(modp)+"& rhs) {rhs.__Vdeserialize(os); return os;}\n");
|
||||
puts("inline VerilatedSerialize& operator<<(VerilatedSerialize& os, "+modClassName(modp)+"& rhs) { rhs.__Vserialize(os); return os; }\n");
|
||||
puts("inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, "+modClassName(modp)+"& rhs) { rhs.__Vdeserialize(os); return os; }\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// finish up h-file
|
||||
puts("#endif /*guard*/\n");
|
||||
puts("#endif // guard\n");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -2017,6 +2068,7 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
|
||||
puts("\n");
|
||||
puts("#include \"verilated_dpi.h\"\n");
|
||||
}
|
||||
puts("\n");
|
||||
|
||||
emitTextSection(AstType::atScImpHdr);
|
||||
|
||||
@@ -2152,7 +2204,7 @@ class EmitCTrace : EmitCStmts {
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
putsDecoration("// Callback from vcd->open()\n");
|
||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts("if (!Verilated::calcUnusedSigs()) vl_fatal(__FILE__,__LINE__,__FILE__,\"Turning on wave traces requires Verilated::traceEverOn(true) call before time 0.\");\n");
|
||||
|
||||
puts("vcdp->scopeEscape(' ');\n");
|
||||
@@ -2165,7 +2217,7 @@ class EmitCTrace : EmitCStmts {
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
putsDecoration("// Callback from vcd->dump()\n");
|
||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts("t->traceFullThis (vlSymsp, vcdp, code);\n");
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
@@ -2180,7 +2232,7 @@ class EmitCTrace : EmitCStmts {
|
||||
+v3Global.opt.traceClassBase()+"* vcdp, void* userthis, uint32_t code) {\n");
|
||||
putsDecoration("// Callback from vcd->dump()\n");
|
||||
puts(topClassName()+"* t=("+topClassName()+"*)userthis;\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts(EmitCBaseVisitor::symClassVar()+" = t->__VlSymsp; // Setup global symbol table\n");
|
||||
puts("if (vlSymsp->getClearActivity()) {\n");
|
||||
puts("t->traceChgThis (vlSymsp, vcdp, code);\n");
|
||||
puts("}\n");
|
||||
@@ -2324,7 +2376,7 @@ class EmitCTrace : EmitCStmts {
|
||||
puts("int c=code;\n");
|
||||
puts("if (0 && vcdp && c) {} // Prevent unused\n");
|
||||
if (nodep->funcType() == AstCFuncType::TRACE_INIT) {
|
||||
puts("vcdp->module(vlSymsp->name()); // Setup signal names\n");
|
||||
puts("vcdp->module(vlSymsp->name()); // Setup signal names\n");
|
||||
} else if (nodep->funcType() == AstCFuncType::TRACE_INIT_SUB) {
|
||||
} else if (nodep->funcType() == AstCFuncType::TRACE_FULL) {
|
||||
} else if (nodep->funcType() == AstCFuncType::TRACE_FULL_SUB) {
|
||||
|
||||
+2
-40
@@ -32,30 +32,15 @@
|
||||
#include "V3EmitCBase.h"
|
||||
#include "V3Stats.h"
|
||||
|
||||
#define EMITCINLINES_NUM_CONSTW 10 // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_9X is last)
|
||||
|
||||
//######################################################################
|
||||
|
||||
class EmitCInlines : EmitCBaseVisitor {
|
||||
// STATE
|
||||
vector<V3Double0> m_wordWidths; // What sizes are used?
|
||||
|
||||
// METHODS
|
||||
void emitInt();
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstVar* nodep) {
|
||||
// All wide constants load into variables, so we can just hunt for them
|
||||
nodep->iterateChildren(*this);
|
||||
int words = nodep->widthWords();
|
||||
if (words >= EMITCINLINES_NUM_CONSTW ) {
|
||||
if (int(m_wordWidths.size()) <= words) {
|
||||
m_wordWidths.resize(words+5);
|
||||
}
|
||||
++ m_wordWidths.at(words);
|
||||
v3Global.needHInlines(true);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstBasicDType* nodep) {
|
||||
if (nodep->keyword() == AstBasicDTypeKwd::STRING) {
|
||||
v3Global.needHeavy(true); // #include <string> via verilated_heavy.h when we create symbol file
|
||||
@@ -94,33 +79,10 @@ void EmitCInlines::emitInt() {
|
||||
|
||||
puts("\n//======================\n\n");
|
||||
|
||||
for (unsigned words=0; words<m_wordWidths.size(); words++) {
|
||||
if (m_wordWidths.at(words)) {
|
||||
puts("#ifndef VL_HAVE_CONST_W_"+cvtToStr(words)+"X\n");
|
||||
puts("# define VL_HAVE_CONST_W_"+cvtToStr(words)+"X\n");
|
||||
puts("static inline WDataOutP VL_CONST_W_"+cvtToStr(words)+"X(int obits, WDataOutP o\n");
|
||||
puts("\t");
|
||||
for (int i=words-1; i>=0; --i) {
|
||||
puts(",IData d"+cvtToStr(i));
|
||||
if (i && (i % 8 == 0)) puts("\n\t");
|
||||
}
|
||||
puts(") {\n");
|
||||
puts(" ");
|
||||
for (int i=words-1; i>=0; --i) {
|
||||
puts(" o["+cvtToStr(i)+"]=d"+cvtToStr(i)+";");
|
||||
if (i && (i % 8 == 0)) puts("\n ");
|
||||
}
|
||||
puts("\n");
|
||||
puts(" for(int i="+cvtToStr(words)+";i<VL_WORDS_I(obits);i++) o[i] = (IData)0x0;\n");
|
||||
puts(" return o;\n");
|
||||
puts("}\n");
|
||||
puts("#endif\n");
|
||||
puts("\n");
|
||||
}
|
||||
}
|
||||
// Placeholder - v3Global.needHInlines(true) currently not used
|
||||
|
||||
puts("//======================\n\n");
|
||||
puts("#endif /*guard*/\n");
|
||||
puts("#endif // guard\n");
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
+42
-22
@@ -112,8 +112,8 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
// We didn'e have all m_scopes loaded when we encountered variables, so expand them now
|
||||
// It would be less code if each module inserted its own variables.
|
||||
// Someday. For now public isn't common.
|
||||
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||
AstScope* scopep = it->first; AstNodeModule* smodp = it->second;
|
||||
for (vector<ScopeModPair>::iterator itsc = m_scopes.begin(); itsc != m_scopes.end(); ++itsc) {
|
||||
AstScope* scopep = itsc->first; AstNodeModule* smodp = itsc->second;
|
||||
for (vector<ModVarPair>::iterator it = m_modVars.begin(); it != m_modVars.end(); ++it) {
|
||||
AstNodeModule* modp = it->first;
|
||||
AstVar* varp = it->second;
|
||||
@@ -124,10 +124,10 @@ class EmitCSyms : EmitCBaseVisitor {
|
||||
string scpName;
|
||||
string varBase;
|
||||
if (whole.substr(0,10) == "__DOT__TOP") whole.replace(0,10,"");
|
||||
string::size_type pos = whole.rfind("__DOT__");
|
||||
if (pos != string::npos) {
|
||||
scpName = whole.substr(0,pos);
|
||||
varBase = whole.substr(pos+strlen("__DOT__"));
|
||||
string::size_type dpos = whole.rfind("__DOT__");
|
||||
if (dpos != string::npos) {
|
||||
scpName = whole.substr(0,dpos);
|
||||
varBase = whole.substr(dpos+strlen("__DOT__"));
|
||||
} else {
|
||||
varBase = whole;
|
||||
}
|
||||
@@ -303,8 +303,10 @@ void EmitCSyms::emitSymHdr() {
|
||||
|
||||
puts("\n// LOCAL STATE\n");
|
||||
puts("const char* __Vm_namep;\n"); // Must be before subcells, as constructor order needed before _vlCoverInsert.
|
||||
puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n");
|
||||
puts("bool\t__Vm_didInit;\n");
|
||||
if (v3Global.opt.trace()) {
|
||||
puts("bool __Vm_activity; ///< Used by trace routines to determine change occurred\n");
|
||||
}
|
||||
puts("bool __Vm_didInit;\n");
|
||||
|
||||
puts("\n// SUBCELL STATE\n");
|
||||
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||
@@ -319,14 +321,20 @@ void EmitCSyms::emitSymHdr() {
|
||||
}
|
||||
}
|
||||
|
||||
puts("\n// COVERAGE\n");
|
||||
if (m_coverBins) {
|
||||
puts("uint32_t\t__Vcoverage["); puts(cvtToStr(m_coverBins)); puts("];\n");
|
||||
puts("\n// COVERAGE\n");
|
||||
puts("uint32_t __Vcoverage["); puts(cvtToStr(m_coverBins)); puts("];\n");
|
||||
}
|
||||
|
||||
puts("\n// SCOPE NAMES\n");
|
||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||
puts("VerilatedScope __Vscope_"+it->second.m_symName+";\n");
|
||||
{ // Scope names
|
||||
bool did = false;
|
||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||
if (!did) {
|
||||
did = true;
|
||||
puts("\n// SCOPE NAMES\n");
|
||||
}
|
||||
puts("VerilatedScope __Vscope_"+it->second.m_symName+";\n");
|
||||
}
|
||||
}
|
||||
|
||||
puts("\n// CREATORS\n");
|
||||
@@ -335,7 +343,9 @@ void EmitCSyms::emitSymHdr() {
|
||||
|
||||
puts("\n// METHODS\n");
|
||||
puts("inline const char* name() { return __Vm_namep; }\n");
|
||||
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r;}\n");
|
||||
if (v3Global.opt.trace()) {
|
||||
puts("inline bool getClearActivity() { bool r=__Vm_activity; __Vm_activity=false; return r; }\n");
|
||||
}
|
||||
if (v3Global.opt.savable() ) {
|
||||
puts("void __Vserialize(VerilatedSerialize& os);\n");
|
||||
puts("void __Vdeserialize(VerilatedDeserialize& os);\n");
|
||||
@@ -343,7 +353,7 @@ void EmitCSyms::emitSymHdr() {
|
||||
puts("\n");
|
||||
puts("} VL_ATTR_ALIGNED(64);\n");
|
||||
puts("\n");
|
||||
puts("#endif /*guard*/\n");
|
||||
puts("#endif // guard\n");
|
||||
}
|
||||
|
||||
void EmitCSyms::emitSymImp() {
|
||||
@@ -369,7 +379,9 @@ void EmitCSyms::emitSymImp() {
|
||||
puts(symClassName()+"::"+symClassName()+"("+topClassName()+"* topp, const char* namep)\n");
|
||||
puts("\t// Setup locals\n");
|
||||
puts("\t: __Vm_namep(namep)\n"); // No leak, as we get destroyed when the top is destroyed
|
||||
puts("\t, __Vm_activity(false)\n");
|
||||
if (v3Global.opt.trace()) {
|
||||
puts("\t, __Vm_activity(false)\n");
|
||||
}
|
||||
puts("\t, __Vm_didInit(false)\n");
|
||||
puts("\t// Setup submodule names\n");
|
||||
char comma=',';
|
||||
@@ -420,11 +432,17 @@ void EmitCSyms::emitSymImp() {
|
||||
}
|
||||
}
|
||||
|
||||
puts("// Setup scope names\n");
|
||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||
puts("__Vscope_"+it->second.m_symName+".configure(this,name(),");
|
||||
putsQuoted(it->second.m_prettyName);
|
||||
puts(");\n");
|
||||
{ // Setup scope names
|
||||
bool did = false;
|
||||
for (ScopeNames::iterator it = m_scopeNames.begin(); it != m_scopeNames.end(); ++it) {
|
||||
if (!did) {
|
||||
did = true;
|
||||
puts("// Setup scope names\n");
|
||||
}
|
||||
puts("__Vscope_"+it->second.m_symName+".configure(this,name(),");
|
||||
putsQuoted(it->second.m_prettyName);
|
||||
puts(");\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (v3Global.dpi()) {
|
||||
@@ -512,7 +530,9 @@ void EmitCSyms::emitSymImp() {
|
||||
puts("void "+symClassName()+"::"+funcname+"("+classname+"& os) {\n");
|
||||
puts( "// LOCAL STATE\n");
|
||||
// __Vm_namep presumably already correct
|
||||
puts( "os"+op+"__Vm_activity;\n");
|
||||
if (v3Global.opt.trace()) {
|
||||
puts( "os"+op+"__Vm_activity;\n");
|
||||
}
|
||||
puts( "os"+op+"__Vm_didInit;\n");
|
||||
puts( "// SUBCELL STATE\n");
|
||||
for (vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
|
||||
|
||||
@@ -68,6 +68,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
||||
if (tag=="") tag = VString::downcase(nodep->typeName());
|
||||
puts("<"+tag+" "+nodep->fileline()->xml());
|
||||
if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); }
|
||||
if (nodep->tag()!="") { puts(" tag="); putsQuoted(nodep->tag()); }
|
||||
}
|
||||
void outputChildrenEnd(AstNode* nodep, string tag) {
|
||||
if (tag=="") tag = VString::downcase(nodep->typeName());
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ string V3Error::lineStr (const char* filename, int lineno) {
|
||||
const char* fnslashp = strrchr (filename, '/');
|
||||
if (fnslashp) filename = fnslashp+1;
|
||||
out<<filename<<":"<<dec<<lineno<<":";
|
||||
const char* spaces = " ";
|
||||
const char* const spaces = " ";
|
||||
size_t numsp = out.str().length(); if (numsp>20) numsp = 20;
|
||||
out<<(spaces + numsp);
|
||||
return out.str();
|
||||
|
||||
+5
-5
@@ -48,7 +48,6 @@ public:
|
||||
I_LINT, // All lint messages
|
||||
I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE)
|
||||
// Error codes:
|
||||
E_BLKLOOPINIT, // Error: Delayed assignment to array inside for loops
|
||||
E_DETECTARRAY, // Error: Unsupported: Can't detect changes on arrayed variable
|
||||
E_MULTITOP, // Error: Multiple top level modules
|
||||
E_TASKNSVAR, // Error: Task I/O not simple
|
||||
@@ -60,6 +59,7 @@ public:
|
||||
ASSIGNDLY, // Assignment delays
|
||||
ASSIGNIN, // Assigning to input
|
||||
BLKANDNBLK, // Blocked and non-blocking assignments to same variable
|
||||
BLKLOOPINIT, // Delayed assignment to array inside for loops
|
||||
BLKSEQ, // Blocking assignments in sequential block
|
||||
CASEINCOMPLETE, // Case statement has missing values
|
||||
CASEOVERLAP, // Case statements overlap
|
||||
@@ -121,11 +121,11 @@ public:
|
||||
// Boolean
|
||||
" I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE",
|
||||
// Errors
|
||||
"BLKLOOPINIT", "DETECTARRAY", "MULTITOP", "TASKNSVAR",
|
||||
"DETECTARRAY", "MULTITOP", "TASKNSVAR",
|
||||
// Warnings
|
||||
" EC_FIRST_WARN",
|
||||
"ALWCOMBORDER", "ASSIGNDLY", "ASSIGNIN",
|
||||
"BLKANDNBLK", "BLKSEQ",
|
||||
"BLKANDNBLK", "BLKLOOPINIT", "BLKSEQ",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CLKDATA",
|
||||
"CMPCONST", "COMBDLY", "DEFPARAM", "DECLFILENAME",
|
||||
"ENDLABEL", "GENCLK",
|
||||
@@ -150,6 +150,7 @@ public:
|
||||
// Warnings we'll present to the user as errors
|
||||
// Later -Werror- options may make more of these.
|
||||
bool pretendError() const { return ( m_e==ASSIGNIN || m_e==BLKANDNBLK
|
||||
|| m_e==BLKLOOPINIT
|
||||
|| m_e==IMPURE || m_e==MODDUP); }
|
||||
// Warnings to mention manual
|
||||
bool mentionManual() const { return ( m_e==EC_FATALSRC || m_e==SYMRSVDWORD
|
||||
@@ -254,8 +255,7 @@ class V3Error {
|
||||
// Global versions, so that if the class doesn't define a operator, we get the functions anyways.
|
||||
inline int debug() { return V3Error::debugDefault(); }
|
||||
inline void v3errorEnd(ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
||||
inline void v3errorEndFatal(ostringstream& sstr) VL_ATTR_NORETURN;
|
||||
inline void v3errorEndFatal(ostringstream& sstr) { V3Error::v3errorEnd(sstr); assert(0); }
|
||||
inline void v3errorEndFatal(ostringstream& sstr) { V3Error::v3errorEnd(sstr); assert(0); VL_UNREACHABLE }
|
||||
|
||||
// Theses allow errors using << operators: v3error("foo"<<"bar");
|
||||
// Careful, you can't put () around msg, as you would in most macro definitions
|
||||
|
||||
+2
-2
@@ -243,7 +243,7 @@ private:
|
||||
}
|
||||
bool expandWide (AstNodeAssign* nodep, AstArraySel* rhsp) {
|
||||
UINFO(8," Wordize ASSIGN(ARRAYSEL) "<<nodep<<endl);
|
||||
if (rhsp->length()!=1) nodep->v3fatalSrc("ArraySel with length!=1 should have been removed in V3Slice");
|
||||
if (nodep->dtypep()->skipRefp()->castUnpackArrayDType()) nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
|
||||
for (int w=0; w<nodep->widthWords(); w++) {
|
||||
addWordAssign(nodep, w, newAstWordSelClone (rhsp, w));
|
||||
}
|
||||
@@ -937,5 +937,5 @@ public:
|
||||
void V3Expand::expandAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
ExpandVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("expand.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("expand", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+49
-22
@@ -34,6 +34,14 @@
|
||||
# define INFILTER_PIPE // Allow pipe filtering. Needs fork()
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STAT_NSEC // i.e. Linux 2.6, from configure
|
||||
# define VL_STAT_CTIME_NSEC(stat) ((stat).st_ctim.tv_nsec) // Nanoseconds
|
||||
# define VL_STAT_MTIME_NSEC(stat) ((stat).st_mtim.tv_nsec) // Nanoseconds
|
||||
#else
|
||||
# define VL_STAT_CTIME_NSEC(stat) (0)
|
||||
# define VL_STAT_MTIME_NSEC(stat) (0)
|
||||
#endif
|
||||
|
||||
#ifdef INFILTER_PIPE
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
@@ -62,6 +70,7 @@ class V3FileDependImp {
|
||||
public:
|
||||
DependFile(const string& filename, bool target)
|
||||
: m_target(target), m_filename(filename) {
|
||||
m_stat.st_ctime = 0;
|
||||
m_stat.st_mtime = 0;
|
||||
}
|
||||
~DependFile() {}
|
||||
@@ -69,7 +78,10 @@ class V3FileDependImp {
|
||||
bool target() const { return m_target; }
|
||||
off_t size() const { return m_stat.st_size; }
|
||||
ino_t ino() const { return m_stat.st_ino; }
|
||||
time_t mtime() const { return m_stat.st_mtime; }
|
||||
time_t cstime() const { return m_stat.st_ctime; } // Seconds
|
||||
time_t cnstime() const { return VL_STAT_CTIME_NSEC(m_stat); } // Nanoseconds
|
||||
time_t mstime() const { return m_stat.st_mtime; } // Seconds
|
||||
time_t mnstime() const { return VL_STAT_MTIME_NSEC(m_stat); } // Nanoseconds
|
||||
void loadStats() {
|
||||
if (!m_stat.st_mtime) {
|
||||
string fn = filename();
|
||||
@@ -178,7 +190,10 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm
|
||||
*ofp<<(iter->target()?"T":"S")<<" ";
|
||||
*ofp<<" "<<setw(8)<<showSize;
|
||||
*ofp<<" "<<setw(8)<<showIno;
|
||||
*ofp<<" "<<setw(11)<<iter->mtime();
|
||||
*ofp<<" "<<setw(11)<<iter->cstime();
|
||||
*ofp<<" "<<setw(11)<<iter->cnstime();
|
||||
*ofp<<" "<<setw(11)<<iter->mstime();
|
||||
*ofp<<" "<<setw(11)<<iter->mnstime();
|
||||
*ofp<<" \""<<iter->filename()<<"\"";
|
||||
*ofp<<endl;
|
||||
}
|
||||
@@ -209,31 +224,42 @@ inline bool V3FileDependImp::checkTimes(const string& filename, const string& cm
|
||||
off_t chkSize; *ifp>>chkSize;
|
||||
ino_t chkIno; *ifp>>chkIno;
|
||||
if (ifp->eof()) break; // Needed to read final whitespace before found eof
|
||||
time_t chkMtime; *ifp>>chkMtime;
|
||||
time_t chkCstime; *ifp>>chkCstime;
|
||||
time_t chkCnstime; *ifp>>chkCnstime;
|
||||
time_t chkMstime; *ifp>>chkMstime;
|
||||
time_t chkMnstime; *ifp>>chkMnstime;
|
||||
char quote; *ifp>>quote;
|
||||
string chkFilename; getline(*ifp, chkFilename, '"');
|
||||
//UINFO(9," got d="<<chkDir<<" s="<<chkSize<<" mt="<<chkMtime<<" fn = "<<chkFilename<<endl);
|
||||
|
||||
V3Options::fileNfsFlush(chkFilename);
|
||||
struct stat chkStat;
|
||||
int err = stat(chkFilename.c_str(), &chkStat);
|
||||
if (err!=0) {
|
||||
UINFO(2," --check-times failed: missing "<<chkFilename<<endl);
|
||||
return false;
|
||||
}
|
||||
if (filename != chkFilename) { // See above; we were writing it at the time...
|
||||
//UINFO(9," got d="<<chkDir<<" s="<<chkSize<<" ct="<<chkCstime<<"."<<chkCnstime<<" mt="<<chkMstime<<"."<<chkMnstime<<" fn = "<<chkFilename<<endl);
|
||||
//UINFO(9," nowSt s="<<chkStat.st_size<<" mt="<<chkStat.st_mtime<<" ct="<<chkStat.st_ctime<<" fn = "<<chkFilename<<endl);
|
||||
if (filename != chkFilename) { // Other then the .dat file itself, as we were writing it at the time...
|
||||
// We'd like this rule:
|
||||
//if (!(chkStat.st_size == chkSize
|
||||
// && chkStat.st_mtime == chkMtime) {
|
||||
// && chkStat.st_mtime == chkMstime) {
|
||||
// However NFS messes us up, as there might be some data outstanding when
|
||||
// we determined the original size. For safety, we know the creation time
|
||||
// must be within a few second window... call it 20 sec.
|
||||
if (!(chkStat.st_size >= chkSize
|
||||
&& chkStat.st_ino == chkIno
|
||||
&& chkStat.st_mtime >= chkMtime
|
||||
&& chkStat.st_mtime <= (chkMtime + 20))) {
|
||||
&& chkStat.st_ctime == chkCstime
|
||||
&& VL_STAT_CTIME_NSEC(chkStat) == chkCnstime
|
||||
&& chkStat.st_mtime <= (chkMstime + 20)
|
||||
// Not comparing chkMnstime
|
||||
)) {
|
||||
UINFO(2," --check-times failed: out-of-date "<<chkFilename
|
||||
<<"; "<<chkStat.st_size<<"=?"<<chkSize
|
||||
<<" "<<chkStat.st_mtime<<"=?"<<chkMtime<<endl);
|
||||
<<" "<<chkStat.st_ctime<<"."<<VL_STAT_CTIME_NSEC(chkStat)
|
||||
<<"=?"<<chkCstime<<"."<<chkCnstime
|
||||
<<" "<<chkStat.st_mtime<<"."<<VL_STAT_MTIME_NSEC(chkStat)
|
||||
<<"=?"<<chkMstime<<"."<<chkMnstime<<endl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -608,21 +634,22 @@ bool V3OutFormatter::tokenEnd(const char* cp) {
|
||||
|
||||
int V3OutFormatter::endLevels (const char *strg) {
|
||||
int levels=m_indentLevel;
|
||||
const char* cp=strg;
|
||||
while (isspace(*cp)) cp++;
|
||||
switch (*cp) {
|
||||
case '\n': // Newlines.. No need for whitespace before it
|
||||
return (0);
|
||||
case '#': // Preproc directive
|
||||
return (0);
|
||||
}
|
||||
{
|
||||
// label/public/private: Deindent by 2 spaces
|
||||
const char* mp=cp;
|
||||
for (; isalnum(*mp); mp++) ;
|
||||
if (mp[0]==':' && mp[1]!=':') return (levels-m_blockIndent/2);
|
||||
const char* cp=strg;
|
||||
while (isspace(*cp)) cp++;
|
||||
switch (*cp) {
|
||||
case '\n': // Newlines.. No need for whitespace before it
|
||||
return (0);
|
||||
case '#': // Preproc directive
|
||||
return (0);
|
||||
}
|
||||
{
|
||||
// label/public/private: Deindent by 2 spaces
|
||||
const char* mp=cp;
|
||||
for (; isalnum(*mp); mp++) ;
|
||||
if (mp[0]==':' && mp[1]!=':') return (levels-m_blockIndent/2);
|
||||
}
|
||||
}
|
||||
|
||||
// We want "} else {" to be one level to the left of normal
|
||||
for (const char* cp=strg; *cp; cp++) {
|
||||
switch (*cp) {
|
||||
|
||||
+3
-1
@@ -161,11 +161,13 @@ public:
|
||||
|
||||
// OPERATORS
|
||||
void v3errorEnd(ostringstream& str);
|
||||
void v3errorEndFatal(ostringstream& str) VL_ATTR_NORETURN;
|
||||
void v3errorEndFatal(ostringstream& str);
|
||||
string warnMore() const;
|
||||
inline bool operator==(FileLine rhs) const {
|
||||
return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno && m_warnOn==rhs.m_warnOn);
|
||||
}
|
||||
private:
|
||||
void v3errorEndFatalGuts(ostringstream& str);
|
||||
};
|
||||
ostream& operator<<(ostream& os, FileLine* fileline);
|
||||
|
||||
|
||||
+9
-6
@@ -437,9 +437,9 @@ private:
|
||||
if (m_inSenItem) varscp->user2(true);
|
||||
else if (m_activep && m_activep->hasClocked() && !nodep->lvalue()) {
|
||||
if (varscp->user2()) {
|
||||
if (!vvertexp->rstSyncNodep()) vvertexp->rstSyncNodep(nodep);
|
||||
} else {
|
||||
if (!vvertexp->rstAsyncNodep()) vvertexp->rstAsyncNodep(nodep);
|
||||
} else {
|
||||
if (!vvertexp->rstSyncNodep()) vvertexp->rstSyncNodep(nodep);
|
||||
}
|
||||
}
|
||||
// We use weight of one; if we ref the var more than once, when we simplify,
|
||||
@@ -864,6 +864,9 @@ void GateVisitor::optimizeElimVar(AstVarScope* varscp, AstNode* substp, AstNode*
|
||||
// optimizing away this assignment, etc.
|
||||
consumerp = V3Const::constifyEdit(consumerp);
|
||||
if (debug()>=5) consumerp->dumpTree(cout,"\telimUseDne: ");
|
||||
// Some previous input edges may have disappeared, perhaps all of them.
|
||||
// If we remove the edges we can further optimize
|
||||
// See e.g t_var_overzero.v.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1133,7 +1136,7 @@ void GateVisitor::dedupe() {
|
||||
|
||||
|
||||
//######################################################################
|
||||
// Recurse through the graph, try to merge assigns
|
||||
// Recurse through the graph, try to merge assigns
|
||||
|
||||
class GateMergeAssignsGraphVisitor : public GateGraphBaseVisitor {
|
||||
private:
|
||||
@@ -1145,7 +1148,7 @@ private:
|
||||
V3Double0 m_numMergedAssigns; // Statistic tracking
|
||||
|
||||
|
||||
// assemble two Sel into one if possible
|
||||
// assemble two Sel into one if possible
|
||||
AstSel* merge(AstSel* pre, AstSel* cur) {
|
||||
AstVarRef* preVarRefp = pre->fromp()->castVarRef();
|
||||
AstVarRef* curVarRefp = cur->fromp()->castVarRef();
|
||||
@@ -1201,7 +1204,7 @@ private:
|
||||
// update the graph
|
||||
{
|
||||
// delete all inedges to lvertexp
|
||||
if (!lvertexp->inEmpty()) {
|
||||
if (!lvertexp->inEmpty()) {
|
||||
for (V3GraphEdge* ledgep = lvertexp->inBeginp(); ledgep; ) {
|
||||
V3GraphEdge* oedgep = ledgep;
|
||||
ledgep = ledgep->inNextp();
|
||||
@@ -1488,5 +1491,5 @@ void V3Gate::gateAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
GateVisitor visitor (nodep);
|
||||
GateDeassignVisitor deassign (nodep);
|
||||
V3Global::dumpCheckGlobalTree("gate.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("gate", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -228,5 +228,5 @@ public:
|
||||
void V3GenClk::genClkAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
GenClkReadVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("genclk.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("genclk", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ public:
|
||||
// METHODS
|
||||
void readFiles();
|
||||
void checkTree();
|
||||
static void dumpCheckGlobalTree(const string& filename, int newNumber=0, bool doDump=true);
|
||||
static void dumpCheckGlobalTree(const string& stagename, int newNumber=0, bool doDump=true);
|
||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
|
||||
bool constRemoveXs() const { return m_constRemoveXs; }
|
||||
|
||||
+2
-2
@@ -121,7 +121,7 @@ uint32_t V3GraphVertex::outHash() const {
|
||||
ostream& operator<<(ostream& os, V3GraphVertex* vertexp) {
|
||||
os<<" VERTEX="<<vertexp->name();
|
||||
if (vertexp->rank()) os<<" r"<<vertexp->rank();
|
||||
if (vertexp->fanout()) os<<" f"<<vertexp->fanout();
|
||||
if (vertexp->fanout()!=0.0) os<<" f"<<vertexp->fanout();
|
||||
if (vertexp->color()) os<<" c"<<vertexp->color();
|
||||
return os;
|
||||
}
|
||||
@@ -327,7 +327,7 @@ void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) {
|
||||
<<"\t[fontsize=8 "
|
||||
<<"label=\""<<(vertexp->name()!="" ? vertexp->name() : "\\N");
|
||||
if (vertexp->rank()) *logp<<" r"<<vertexp->rank();
|
||||
if (vertexp->fanout()) *logp<<" f"<<vertexp->fanout();
|
||||
if (vertexp->fanout()!=0.0) *logp<<" f"<<vertexp->fanout();
|
||||
if (vertexp->color()) *logp<<"\\n c"<<vertexp->color();
|
||||
*logp<<"\"";
|
||||
*logp<<", color="<<vertexp->dotColor();
|
||||
|
||||
+4
-4
@@ -257,11 +257,11 @@ private:
|
||||
// Find epsilon closure of this nfa node, and destinations to work list
|
||||
for (V3GraphEdge* nfaEdgep = nfaStatep->outBeginp(); nfaEdgep; nfaEdgep=nfaEdgep->outNextp()) {
|
||||
DfaEdge* cNfaEdgep = static_cast<DfaEdge*>(nfaEdgep);
|
||||
DfaVertex* nfaStatep = static_cast<DfaVertex*>(nfaEdgep->top());
|
||||
DfaVertex* ecNfaStatep = static_cast<DfaVertex*>(nfaEdgep->top());
|
||||
//UINFO(9," Consider "<<nfaEdgep->top()<<" EP "<<cNfaEdgep->epsilon()<<endl);
|
||||
if (cNfaEdgep->epsilon()
|
||||
&& unseenNfaThisStep(nfaStatep)) { // Not processed?
|
||||
workps.push_back(nfaStatep);
|
||||
&& unseenNfaThisStep(ecNfaStatep)) { // Not processed?
|
||||
workps.push_back(ecNfaStatep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,7 +453,7 @@ private:
|
||||
DfaVertex* fromvertexp = static_cast<DfaVertex*>(edgep->fromp());
|
||||
if (fromvertexp != vertexp
|
||||
&& !fromvertexp->user()) {
|
||||
workps.push(static_cast<DfaVertex*>(fromvertexp));
|
||||
workps.push(fromvertexp);
|
||||
fromvertexp->user(1);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -251,7 +251,7 @@ public:
|
||||
// Outbound are cutable, as we may need to evaluate multiple times
|
||||
|
||||
{
|
||||
V3GraphTestVertex* n = new V3GraphTestVertex(gp,"c=a|b|i");
|
||||
n = new V3GraphTestVertex(gp,"c=a|b|i");
|
||||
new V3GraphEdge(gp, n, c, 1, true);
|
||||
new V3GraphEdge(gp, a, n, 1, false);
|
||||
new V3GraphEdge(gp, b, n, 1, false);
|
||||
|
||||
+89
-41
@@ -53,22 +53,34 @@ private:
|
||||
// NODE STATE
|
||||
// Output
|
||||
// AstNodeModule::user1() // OUTPUT: bool. User request to inline this module
|
||||
// Entire netlist (can be cleared after this visit completes)
|
||||
// Internal state (can be cleared after this visit completes)
|
||||
// AstNodeModule::user2() // CIL_*. Allowed to automatically inline module
|
||||
// AstNodeModule::user3() // int. Number of cells referencing this module
|
||||
AstUser1InUse m_inuser1;
|
||||
// AstNodeModule::user4() // int. Statements in module
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser3InUse m_inuser3;
|
||||
AstUser4InUse m_inuser4;
|
||||
|
||||
enum {CIL_NOTHARD=0, // For user2, inline not supported
|
||||
CIL_NOTSOFT, // For user2, don't inline unless user overrides
|
||||
CIL_MAYBE}; // For user2, might inline
|
||||
// For the user2 field:
|
||||
enum {CIL_NOTHARD=0, // Inline not supported
|
||||
CIL_NOTSOFT, // Don't inline unless user overrides
|
||||
CIL_MAYBE, // Might inline
|
||||
CIL_USER}; // Pragma suggests inlining
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Flattened cell's containing module
|
||||
int m_stmtCnt; // Statements in module
|
||||
AstNodeModule* m_modp; // Current module
|
||||
V3Double0 m_statUnsup; // Statistic tracking
|
||||
|
||||
typedef vector<AstNodeModule*> ModVec;
|
||||
ModVec m_allMods; // All modules, in top-down order.
|
||||
|
||||
// Within the context of a given module, LocalInstanceMap maps
|
||||
// from child modules to the count of each child's local instantiations.
|
||||
typedef map<AstNodeModule*, int> LocalInstanceMap;
|
||||
|
||||
// We keep a LocalInstanceMap for each module in the design
|
||||
map<AstNodeModule*, LocalInstanceMap> m_instances;
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
@@ -92,39 +104,23 @@ private:
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) {
|
||||
m_stmtCnt = 0;
|
||||
m_modp = nodep;
|
||||
m_allMods.push_back(nodep);
|
||||
m_modp->user2(CIL_MAYBE);
|
||||
m_modp->user4(0); // statement count
|
||||
if (m_modp->castIface()) {
|
||||
// Inlining an interface means we no longer have a cell handle to resolve to.
|
||||
// If inlining moves post-scope this can perhaps be relaxed.
|
||||
cantInline("modIface",true);
|
||||
}
|
||||
if (m_modp->modPublic()) cantInline("modPublic",false);
|
||||
//
|
||||
|
||||
nodep->iterateChildren(*this);
|
||||
//
|
||||
bool userinline = nodep->user1();
|
||||
int allowed = nodep->user2();
|
||||
int refs = nodep->user3();
|
||||
// Should we automatically inline this module?
|
||||
// inlineMult = 2000 by default. If a mod*#instances is < this # nodes, can inline it
|
||||
bool doit = ((allowed == CIL_NOTSOFT || allowed == CIL_MAYBE)
|
||||
&& (userinline
|
||||
|| ((allowed == CIL_MAYBE)
|
||||
&& (refs==1
|
||||
|| m_stmtCnt < INLINE_MODS_SMALLER
|
||||
|| v3Global.opt.inlineMult() < 1
|
||||
|| refs*m_stmtCnt < v3Global.opt.inlineMult()))));
|
||||
// Packages aren't really "under" anything so they confuse this algorithm
|
||||
if (nodep->castPackage()) doit = false;
|
||||
UINFO(4, " Inline="<<doit<<" Possible="<<allowed<<" Usr="<<userinline<<" Refs="<<refs<<" Stmts="<<m_stmtCnt
|
||||
<<" "<<nodep<<endl);
|
||||
nodep->user1(doit);
|
||||
m_modp = NULL;
|
||||
}
|
||||
virtual void visit(AstCell* nodep) {
|
||||
nodep->modp()->user3Inc();
|
||||
nodep->modp()->user3Inc(); // Inc refs
|
||||
m_instances[m_modp][nodep->modp()]++;
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstPragma* nodep) {
|
||||
@@ -132,8 +128,9 @@ private:
|
||||
//UINFO(0,"PRAG MARK "<<m_modp<<endl);
|
||||
if (!m_modp) {
|
||||
nodep->v3error("Inline pragma not under a module");
|
||||
} else {
|
||||
m_modp->user1(1);
|
||||
} else if (m_modp->user2() == CIL_MAYBE
|
||||
|| m_modp->user2() == CIL_NOTSOFT) {
|
||||
m_modp->user2(CIL_USER);
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); // Remove so don't propagate to upper cell...
|
||||
} else if (nodep->pragType() == AstPragmaType::NO_INLINE_MODULE) {
|
||||
@@ -156,30 +153,71 @@ private:
|
||||
if (!nodep->packagep()) nodep->taskp(NULL);
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
// Nop's to speed up the loop
|
||||
virtual void visit(AstAlways* nodep) {
|
||||
nodep->iterateChildren(*this);
|
||||
m_stmtCnt++;
|
||||
m_modp->user4Inc(); // statement count
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) {
|
||||
// Don't count assignments, as they'll likely flatten out
|
||||
// Still need to iterate though to nullify VarXRefs
|
||||
int oldcnt = m_stmtCnt;
|
||||
int oldcnt = m_modp->user4();
|
||||
nodep->iterateChildren(*this);
|
||||
m_stmtCnt = oldcnt;
|
||||
m_modp->user4(oldcnt);
|
||||
}
|
||||
virtual void visit(AstNetlist* nodep) {
|
||||
// Build user2, user3, and user4 for all modules.
|
||||
// Also build m_allMods and m_instances.
|
||||
nodep->iterateChildren(*this);
|
||||
|
||||
// Iterate through all modules in bottom-up order.
|
||||
// Make a final inlining decision for each.
|
||||
for (ModVec::reverse_iterator it=m_allMods.rbegin(); it!=m_allMods.rend(); ++it) {
|
||||
AstNodeModule* modp = *it;
|
||||
|
||||
// If we're going to inline some modules into this one,
|
||||
// update user4 (statement count) to reflect that:
|
||||
int statements = modp->user4();
|
||||
LocalInstanceMap& localsr = m_instances[modp];
|
||||
for (LocalInstanceMap::iterator it = localsr.begin(); it != localsr.end(); ++it) {
|
||||
AstNodeModule* childp = it->first;
|
||||
if (childp->user1()) { // inlining child
|
||||
statements += (childp->user4() * it->second);
|
||||
}
|
||||
}
|
||||
modp->user4(statements);
|
||||
|
||||
int allowed = modp->user2();
|
||||
int refs = modp->user3();
|
||||
|
||||
// Should we automatically inline this module?
|
||||
// inlineMult = 2000 by default.
|
||||
// If a mod*#refs is < this # nodes, can inline it
|
||||
bool doit = ((allowed == CIL_USER)
|
||||
|| ((allowed == CIL_MAYBE)
|
||||
&& (refs==1
|
||||
|| statements < INLINE_MODS_SMALLER
|
||||
|| v3Global.opt.inlineMult() < 1
|
||||
|| refs*statements < v3Global.opt.inlineMult())));
|
||||
// Packages aren't really "under" anything so they confuse this algorithm
|
||||
if (modp->castPackage()) doit = false;
|
||||
UINFO(4, " Inline="<<doit<<" Possible="<<allowed
|
||||
<<" Refs="<<refs<<" Stmts="<<statements<<" "<<modp<<endl);
|
||||
modp->user1(doit);
|
||||
}
|
||||
}
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstNode* nodep) {
|
||||
nodep->iterateChildren(*this);
|
||||
m_stmtCnt++;
|
||||
if (m_modp) {
|
||||
m_modp->user4Inc(); // Inc statement count
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
explicit InlineMarkVisitor(AstNode* nodep) {
|
||||
m_modp = NULL;
|
||||
m_stmtCnt = 0;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~InlineMarkVisitor() {
|
||||
@@ -187,6 +225,7 @@ public:
|
||||
// Done with these, are not outputs
|
||||
AstNode::user2ClearTree();
|
||||
AstNode::user3ClearTree();
|
||||
AstNode::user4ClearTree();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -443,11 +482,13 @@ private:
|
||||
// AstVar::user3() // bool Don't alias the user2, keep it as signal
|
||||
// AstCell::user4 // AstCell* of the created clone
|
||||
|
||||
AstUser4InUse m_inuser4;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser3InUse m_inuser3;
|
||||
AstUser4InUse m_inuser4;
|
||||
AstUser5InUse m_inuser5;
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNodeModule* m_modp; // Current module
|
||||
V3Double0 m_statCells; // Statistic tracking
|
||||
|
||||
static int debug() {
|
||||
@@ -575,8 +616,15 @@ public:
|
||||
|
||||
void V3Inline::inlineAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
InlineMarkVisitor mvisitor (nodep);
|
||||
InlineVisitor visitor (nodep);
|
||||
AstUser1InUse m_inuser1; // output of InlineMarkVisitor,
|
||||
// input to InlineVisitor.
|
||||
{
|
||||
// Scoped to clean up temp userN's
|
||||
InlineMarkVisitor mvisitor (nodep);
|
||||
}
|
||||
{
|
||||
InlineVisitor visitor (nodep);
|
||||
}
|
||||
// Remove all modules that were inlined
|
||||
// V3Dead will also clean them up, but if we have debug on, it's a good
|
||||
// idea to avoid dumping the hugely exploded tree.
|
||||
@@ -587,5 +635,5 @@ void V3Inline::inlineAll(AstNetlist* nodep) {
|
||||
modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp);
|
||||
}
|
||||
}
|
||||
V3Global::dumpCheckGlobalTree("inline.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("inline", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
+21
-18
@@ -203,7 +203,7 @@ public:
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
explicit InstDeModVarVisitor() {}
|
||||
void accept(AstNodeModule* nodep) {
|
||||
void main(AstNodeModule* nodep) {
|
||||
UINFO(8," dmMODULE "<<nodep<<endl);
|
||||
m_modVarNameMap.clear();
|
||||
nodep->accept(*this);
|
||||
@@ -218,8 +218,7 @@ class InstDeVisitor : public AstNVisitor {
|
||||
private:
|
||||
// STATE
|
||||
AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations
|
||||
int m_instNum; // Current instantiation number
|
||||
int m_instLsb; // Current instantiation number
|
||||
int m_instSelNum; // Current instantiation count 0..N-1
|
||||
InstDeModVarVisitor m_deModVars; // State of variables for current cell module
|
||||
|
||||
typedef map<string,AstVar*> VarNameMap;
|
||||
@@ -267,7 +266,7 @@ private:
|
||||
UINFO(4," CELL "<<nodep<<endl);
|
||||
// Find submodule vars
|
||||
if (!nodep->modp()) nodep->v3fatalSrc("Unlinked");
|
||||
m_deModVars.accept(nodep->modp());
|
||||
m_deModVars.main(nodep->modp());
|
||||
//
|
||||
if (nodep->rangep()) {
|
||||
m_cellRangep = nodep->rangep();
|
||||
@@ -278,8 +277,10 @@ private:
|
||||
&& ifaceVarp->dtypep()->castUnpackArrayDType()->subDTypep()->castIfaceRefDType();
|
||||
|
||||
// Make all of the required clones
|
||||
m_instLsb = m_cellRangep->lsbConst();
|
||||
for (m_instNum = m_instLsb; m_instNum<=m_cellRangep->msbConst(); m_instNum++) {
|
||||
for (int i = 0; i < m_cellRangep->elementsConst(); i++) {
|
||||
m_instSelNum = m_cellRangep->littleEndian() ? (m_cellRangep->elementsConst() - 1 - i) : i;
|
||||
int instNum = m_cellRangep->lsbConst() + i;
|
||||
|
||||
AstCell* newp = nodep->cloneTree(false);
|
||||
nodep->addNextHere(newp);
|
||||
// Remove ranging and fix name
|
||||
@@ -287,8 +288,8 @@ private:
|
||||
// Somewhat illogically, we need to rename the orignal name of the cell too.
|
||||
// as that is the name users expect for dotting
|
||||
// The spec says we add [x], but that won't work in C...
|
||||
newp->name(newp->name()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
|
||||
newp->origName(newp->origName()+"__BRA__"+cvtToStr(m_instNum)+"__KET__");
|
||||
newp->name(newp->name()+"__BRA__"+cvtToStr(instNum)+"__KET__");
|
||||
newp->origName(newp->origName()+"__BRA__"+cvtToStr(instNum)+"__KET__");
|
||||
UINFO(8," CELL loop "<<newp<<endl);
|
||||
|
||||
// If this AstCell is actually an interface instantiation, also clone the IfaceRef
|
||||
@@ -302,8 +303,8 @@ private:
|
||||
arrdtype->addNextHere(ifaceRefp);
|
||||
ifaceRefp->cellp(newp);
|
||||
ifaceRefp->cellName(newp->name());
|
||||
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(m_instNum) + "__KET__");
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(m_instNum) + "__KET__");
|
||||
varNewp->name(varNewp->name() + "__BRA__" + cvtToStr(instNum) + "__KET__");
|
||||
varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(instNum) + "__KET__");
|
||||
varNewp->dtypep(ifaceRefp);
|
||||
newp->addNextHere(varNewp);
|
||||
if (debug()==9) { varNewp->dumpTree(cout, "newintf: "); cout << endl; }
|
||||
@@ -343,12 +344,16 @@ private:
|
||||
// Connection to array, where array dimensions match the instant dimension
|
||||
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
||||
exprp = new AstArraySel (exprp->fileline(), exprp,
|
||||
(m_instNum-m_instLsb));
|
||||
m_instSelNum);
|
||||
nodep->exprp(exprp);
|
||||
} else if (expwidth == pinwidth) {
|
||||
// NOP: Arrayed instants: widths match so connect to each instance
|
||||
} else if (expwidth == pinwidth*m_cellRangep->elementsConst()) {
|
||||
// Arrayed instants: one bit for each of the instants (each assign is 1 pinwidth wide)
|
||||
if (m_cellRangep->littleEndian()) {
|
||||
nodep->v3warn(LITENDIAN,"Little endian cell range connecting to vector: MSB < LSB of cell range: "
|
||||
<<m_cellRangep->lsbConst()<<":"<<m_cellRangep->msbConst());
|
||||
}
|
||||
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
||||
bool inputPin = nodep->modVarp()->isInput();
|
||||
if (!inputPin && !exprp->castVarRef()
|
||||
@@ -358,7 +363,7 @@ private:
|
||||
// Note spec allows more complicated matches such as slices and such
|
||||
}
|
||||
exprp = new AstSel (exprp->fileline(), exprp,
|
||||
pinwidth*(m_instNum-m_instLsb),
|
||||
pinwidth*m_instSelNum,
|
||||
pinwidth);
|
||||
nodep->exprp(exprp);
|
||||
} else {
|
||||
@@ -457,8 +462,7 @@ public:
|
||||
// CONSTUCTORS
|
||||
explicit InstDeVisitor(AstNetlist* nodep) {
|
||||
m_cellRangep=NULL;
|
||||
m_instNum=0;
|
||||
m_instLsb=0;
|
||||
m_instSelNum=0;
|
||||
//
|
||||
nodep->accept(*this);
|
||||
}
|
||||
@@ -526,8 +530,7 @@ public:
|
||||
&& connBasicp->width() == pinBasicp->width()
|
||||
&& connBasicp->lsb() == pinBasicp->lsb()
|
||||
&& !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types
|
||||
&& connBasicp->width() == pinVarp->width()
|
||||
&& 1) {
|
||||
&& connBasicp->width() == pinVarp->width()) {
|
||||
// Done. One to one interconnect won't need a temporary variable.
|
||||
} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
|
||||
// Done. Constant.
|
||||
@@ -580,11 +583,11 @@ AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModu
|
||||
void V3Inst::instAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
InstVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("inst.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("inst", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
}
|
||||
|
||||
void V3Inst::dearrayAll(AstNetlist* nodep) {
|
||||
UINFO(2,__FUNCTION__<<": "<<endl);
|
||||
InstDeVisitor visitor (nodep);
|
||||
V3Global::dumpCheckGlobalTree("dearray.tree", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
V3Global::dumpCheckGlobalTree("dearray", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user