Compare commits

...
90 Commits
Author SHA1 Message Date
Wilson Snyder 4100f20a69 Version bump 2011-11-27 10:37:23 -05:00
Wilson Snyder bedf946fb2 Support V-AMS wreal 2011-11-27 10:31:06 -05:00
Wilson Snyder b9e67157c6 With "--language VAMS" support a touch of Verilog AMS. 2011-11-25 00:49:38 -05:00
Wilson Snyder b30b2a183b Support . 2011-11-20 02:01:48 -05:00
Wilson Snyder 9ab3bcdde3 Support with %g. 2011-11-20 01:01:02 -05:00
Wilson Snyder 5df3bbe188 Fix $display with %d following %g. 2011-11-20 00:45:59 -05:00
Wilson Snyder 8cf12416c0 Commentary 2011-11-18 13:33:31 -05:00
Wilson Snyder b7c2c83c88 Fix bad result with if-else-return optimization, bug420. 2011-11-12 08:07:30 -05:00
Wilson Snyder 3b6da93331 Reuse goto labels inside functions, bug420a 2011-11-10 19:13:32 -05:00
Wilson Snyder b4642d3fd4 Show examples with timestamps as 64 bits 2011-11-06 11:54:17 -05:00
Wilson Snyder 88a2b0b911 Support constants in sensitivity lists, bug412. 2011-11-02 18:34:17 -04:00
Wilson Snyder 954e127f1d Commentary: Report children node types 2011-11-01 19:33:11 -04:00
Wilson Snyder 7654add5e5 Indicate 'exiting due to errors' if errors, not warnings. 2011-10-31 21:39:15 -04:00
Wilson Snyder 85a37ea53f Search for user -y paths before default current directory. 2011-10-28 18:57:40 -04:00
Wilson Snyder b337acebcc When multiple tops, show example 2011-10-28 18:19:04 -04:00
Wilson Snyder fb9ca54c95 Fix reporting not found modules if generate-off, bug403. 2011-10-27 20:56:38 -04:00
Wilson Snyder 1a15d41523 Support jumps in program modules 2011-10-27 19:13:24 -04:00
Wilson Snyder e378cc5791 Add sc_bv attribute to force bit vectors, bug402. 2011-10-26 08:57:27 -04:00
Wilson Snyder 748c189c79 Devel version 2011-10-25 19:11:45 -04:00
Wilson Snyder b89be6c4b9 Version bump 2011-10-25 18:59:40 -04:00
Wilson Snyder df207807b6 Add ASSIGNIN as suppressable error. 2011-10-25 18:57:49 -04:00
Wilson Snyder 1f2b40cff1 Fix 3.823 constructor core dump on Debian, bug401. 2011-10-25 18:41:04 -04:00
Wilson Snyder 734400fd37 Fix version number mistake 2011-10-25 18:11:06 -04:00
Wilson Snyder f19979d928 Fix "always @ (* )", bug403, bug404. 2011-10-25 18:08:24 -04:00
Wilson Snyder 19be7a53da List unsupported on delays 2011-10-21 07:13:38 -04:00
Wilson Snyder e56af34fb0 Post release 2011-10-20 21:18:16 -04:00
Wilson Snyder 7737aa20e8 Version bump 2011-10-20 21:13:42 -04:00
Wilson Snyder ead046201c Fix make info tex warning 2011-10-20 21:13:33 -04:00
Wilson Snyder 0aa7c3f659 Add -Wall reporting ASSIGNDLY on assignment delays. 2011-10-20 20:50:42 -04:00
Wilson Snyder 4aa7222022 tests: use verilator_flags and skip more widely 2011-10-12 23:03:53 -04:00
Wilson Snyder 86e3c78776 configure: Test for compiler flags, and remove old config checks 2011-10-12 19:04:57 -04:00
Wilson Snyder 40076287ea Internals: In .tree files show filename as letter 2011-10-11 07:17:39 -04:00
Wilson Snyder ca81db8edf Remove dead node types; make report of node usage. No functional change 2011-10-10 18:13:42 -04:00
Wilson Snyder ae68a80e98 Fix fflush 2011-10-10 18:13:17 -04:00
Wilson Snyder beb7c58375 Fix DPI import false BLKSEQ warnings. 2011-10-07 20:04:15 -04:00
Wilson Snyder e080b9d565 Fix DPI import output of 64 bits, bug398. 2011-10-07 19:47:10 -04:00
Wilson Snyder ca2db37039 Fix UNDRIVEN warnings inside DPI import functions. 2011-10-07 08:29:34 -04:00
Wilson Snyder 194825f78e Add configure options for cc warnings and extended tests. 2011-10-07 06:48:40 -04:00
Wilson Snyder 55bd765ea0 Find config_rev when under git in remote config dir 2011-10-05 18:36:44 -04:00
Wilson Snyder b03d61e2cf Use EXEEXT to fix make warning 2011-10-05 17:07:10 -04:00
Wilson Snyder 6fc0e5167b Commentary 2011-10-05 17:06:08 -04:00
Wilson Snyder 0065be011f Fix errors when building from git outside of kit directory 2011-10-05 10:47:05 -04:00
Wilson Snyder 3f7cbce58c Move version to configure.ac 2011-10-05 09:50:14 -04:00
Wilson Snyder 246b62e322 Tests: Add runtime 2011-10-05 09:50:00 -04:00
Wilson Snyder 7c2fdd1ee9 Fix --help output to go to stderr, not stdout, bug397. 2011-10-04 10:08:16 -04:00
Wilson Snyder f77aa2623c Fix autoconf suggestions 2011-10-04 10:07:46 -04:00
Wilson Snyder 20847a3ff5 Fix autoconf warnings, bug396. 2011-10-04 08:48:37 -04:00
Wilson Snyder eb6d42acf9 Support $ceil, $floor, etc. 2011-09-28 21:35:26 -04:00
Wilson Snyder 094d676a8b Fix MSVC compile warning with trunc/round, bug394. 2011-09-21 09:08:05 -04:00
Wilson Snyder 71306ceb1d Devel version 2011-09-14 21:44:54 -04:00
Wilson Snyder 8bbfc7fc22 Version bump 2011-09-14 21:12:40 -04:00
Wilson Snyder 19baba12b1 Commentary 2011-09-14 21:11:14 -04:00
Wilson Snyder 15b8819136 Avoid warning on older flex/gcc systems (lion) 2011-09-12 20:26:34 -04:00
Wilson Snyder 3fae8ade05 Fix PowerPC runtime error, bug288 2011-08-22 21:02:09 -04:00
Wilson Snyder f9bbf31d65 Fix internal error on integer casts, bug374. 2011-08-09 19:56:22 -04:00
Wilson Snyder df1da3dda9 Internals: Fix cppcheck warnings; no functional change intended 2011-08-04 21:58:45 -04:00
Wilson Snyder c83f2a4abd Internals: Fix preincrements to reduce cppcheck warnings 2011-08-04 21:15:24 -04:00
Wilson Snyder ad53833040 Version bump 2011-07-28 19:53:54 -04:00
Wilson Snyder bc8c85668a Support coverage in -cc and -sc output modes. 2011-07-28 19:41:05 -04:00
Wilson Snyder d12a3dde45 Fix cast compile warning 2011-07-28 07:59:30 -04:00
Wilson Snyder 301c878c0f Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-28 07:56:44 -04:00
Wilson Snyder bd55bfa071 Support more vpi file functions 2011-07-28 07:05:40 -04:00
Wilson Snyder 6d2f09b579 Fix vpi_register_cb using bad s_cb_data, bug370. 2011-07-27 13:03:49 -04:00
Wilson Snyder 4bfea7f54d Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-26 18:30:25 -04:00
Wilson Snyder 55906486d8 Support 'real' numbers and related functions. 2011-07-24 15:01:51 -04:00
Wilson Snyder d5478e6e08 tests: Print status to stderr 2011-07-24 15:01:36 -04:00
Wilson Snyder d88d85c172 Internals: Real2: Create numeric class; no functional change intended 2011-07-23 19:58:34 -04:00
Wilson Snyder 59c3c536c7 Internals: Real1: properly lex doubles 2011-07-23 08:25:41 -04:00
Wilson Snyder a007458cb8 Internals: Rename float/double to match real branch. No functional change. 2011-07-21 22:10:25 -04:00
Wilson Snyder d051912f21 Internals: Rename functions to match real branch. No functional change. 2011-07-21 21:32:31 -04:00
Wilson Snyder a547158a50 bisonpre: Merge from Verilog-Perl 2011-07-21 20:34:33 -04:00
Wilson Snyder 95f2351aa0 Tests: %t formatting 2011-07-21 19:37:53 -04:00
Wilson Snyder 698aaffb0b Fix missing leading zeros in %0d, bug367 2011-07-14 07:39:11 -04:00
Wilson Snyder 73eccecbf8 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-07-11 08:10:28 -04:00
Wilson Snyder ae4a261463 Internals: Rename UnaryMin to Negate. No functional change. 2011-07-08 06:03:07 -04:00
Wilson Snyder c9f0d0cec2 Recognize pragma synthesys to match vhier 2011-07-07 13:30:27 -04:00
Wilson Snyder 4fa1e45d45 Internals: Move width internals to inside class; move WidthCommit. No functional change 2011-07-06 19:03:40 -04:00
Wilson Snyder 1b3d252bfe Internals: Cleanup Dead code 2011-07-06 18:46:41 -04:00
Wilson Snyder a9ba4a9fcd Internals: Cleanups in V3Signed towards reals; no functional change 2011-07-05 21:05:35 -04:00
Wilson Snyder 7f49619875 Fix VL_FCLOSE declaration, broke two commits ago, bug363 2011-07-05 20:42:33 -04:00
Wilson Snyder 696660639a Support 'const' variables in limited cases; similar to enums. 2011-07-02 12:45:26 -04:00
Wilson Snyder da4323062d Commentary 2011-07-01 15:23:09 -04:00
Wilson Snyder a901e171b2 Support $fopen and I/O with integer instead of `verilator_file_descriptor. 2011-07-01 13:41:21 -04:00
Wilson Snyder 6e41d532fe Use 'vluint64_t' for SystemC instead of (same sized) 'uint64' for MSVC++. 2011-06-29 19:19:01 -04:00
Wilson Snyder 4fc78ffb58 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-06-29 14:22:59 -04:00
Wilson Snyder 8137f41fc3 Support disable for loop escapes. 2011-06-28 21:26:49 -04:00
Wilson Snyder 2e9471797d Version to devel 2011-06-28 21:11:29 -04:00
Wilson Snyder 3fd2108b10 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-05-20 15:34:30 -04:00
Wilson Snyder 96e2a407f4 Merge branch 'master' of ssh://git-verilator-wsnyder/git/verilator 2011-05-20 13:40:18 -04:00
Wilson Snyder ca83fd6dc1 CDC: edge report under debug 2011-04-20 10:11:35 -04:00
281 changed files with 5490 additions and 2095 deletions
+227
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -24,6 +24,8 @@ src/Makefile_obj$
include/verilated.mk$ include/verilated.mk$
config.cache$ config.cache$
config.status$ config.status$
verilator.log
verilator.tex
verilator_bin.* verilator_bin.*
.vcsmx_rebuild$ .vcsmx_rebuild$
autom4te\.cache/ autom4te\.cache/
+36 -20
View File
@@ -88,7 +88,10 @@ pkgdatadir = @pkgdatadir@
datarootdir = @datarootdir@ datarootdir = @datarootdir@
# Compile options # Compile options
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@ CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
PACKAGE_VERSION = @PACKAGE_VERSION@
#### End of system configuration section. #### #### End of system configuration section. ####
###################################################################### ######################################################################
@@ -101,8 +104,6 @@ INFOS = README internals.txt verilator.txt verilator.html verilator.1 verilator.
# Files that can be generated, but should be up to date for a distribution. # Files that can be generated, but should be up to date for a distribution.
DISTDEP = info Makefile DISTDEP = info Makefile
# Files to distribute.
DISTBIN = $(wildcard bin/verilator-*)
DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
*.in *.ac \ *.in *.ac \
@@ -129,7 +130,6 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
test_regress/t/*.pl \ test_regress/t/*.pl \
test_regress/t/*.pf \ test_regress/t/*.pf \
test_regress/t/*.v* \ test_regress/t/*.v* \
verilator.* \
INST_PROJ_FILES = \ INST_PROJ_FILES = \
bin/verilator \ bin/verilator \
@@ -171,7 +171,7 @@ msg_test:
@echo @echo
.PHONY:test .PHONY:test
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users ifeq ($(CFG_WITH_LONGTESTS),yes) # Local... Else don't burden users
test: test_vcs test_c test_sc test_sp test_verilated test_regress test: test_vcs test_c test_sc test_sp test_verilated test_regress
else else
test: test_c test_sc test_sp test: test_c test_sc test_sp
@@ -203,17 +203,18 @@ test_regress: all_nomsg
info: $(INFOS) info: $(INFOS)
# Use --no-split to avoid creating filenames > 14 chars. # Use --no-split to avoid creating filenames > 14 chars.
verilator.1: bin/verilator verilator.1: ${srcdir}/bin/verilator
pod2man $< $@ pod2man $< $@
verilator.txt: bin/verilator verilator.txt: ${srcdir}/bin/verilator
$(POD2TEXT) $< $@ $(POD2TEXT) $< $@
verilator.html: bin/verilator verilator.html: ${srcdir}/bin/verilator
pod2html $< >$@ pod2html $< >$@
verilator.pdf: bin/verilator $(DISTCONFIG) # PDF needs DIST variables; but having configure.ac as dependency isn't detected
pod2latex --full --out verilator.tex bin/verilator verilator.pdf: ${srcdir}/bin/verilator Makefile
pod2latex --full --out verilator.tex ${srcdir}/bin/verilator
cat < verilator.tex \ cat < verilator.tex \
| sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \ | sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \
| sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \ | sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \
@@ -257,7 +258,7 @@ VL_INST_DATA_SRCDIR_FILES = \
test_v/*.[chv]* \ test_v/*.[chv]* \
test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \ test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \
test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \ test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \
test_sp/*.[chv]* test_sp/Makefile test_sp/Makefile_obj \ test_sp/Makefile test_sp/Makefile_obj \
installbin: installbin:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir) $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
@@ -268,9 +269,11 @@ installbin:
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer ) ( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
# Man files can either be part of the original kit, or built in current directory
# So important we use $< so VPATH is searched
installman: $(VL_INST_MAN_FILES) installman: $(VL_INST_MAN_FILES)
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1 $(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
for p in $(VL_INST_MAN_FILES) ; do \ for p in $< ; do \
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \ $(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
done done
@@ -315,6 +318,8 @@ install: all_nomsg installbin installman installdata install-msg
install-here: installman ftp install-here: installman ftp
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
DISTNAMEREV = $(shell sed -e '/DTVERSION/!d' -e 's/.*verilator_\([^"]*\).*/\1/' -e q ${srcdir}/src/config_rev.h)
DIRPROJECT := $(shell project_dir --project) DIRPROJECT := $(shell project_dir --project)
VERILATOR_CAD_DIR = $(CAD_DIR)/verilator/$(DISTNAMEREV)/$(DIRPROJECT_ARCH) VERILATOR_CAD_DIR = $(CAD_DIR)/verilator/$(DISTNAMEREV)/$(DIRPROJECT_ARCH)
INST_PROJ_CVS = cp_if_cvs_diff INST_PROJ_CVS = cp_if_cvs_diff
@@ -323,7 +328,7 @@ install-project: dist
@echo "Install-project to $(DIRPROJECT)" @echo "Install-project to $(DIRPROJECT)"
strip verilator_bin* strip verilator_bin*
$(MAKE) install-project-quick $(MAKE) install-project-quick
for p in verilator.1 ; do \ for p in $(VL_INST_MAN_FILES) ; do \
$(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \ $(INSTALL_DATA) $$p $(DIRPROJECT_PREFIX)/man/man1/$$p; \
done done
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz $(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
@@ -347,7 +352,7 @@ install-cadtools: dist
strip verilator_bin* strip verilator_bin*
$(MAKE) install-cadtools-quick $(MAKE) install-cadtools-quick
$(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1 $(SHELL) ${srcdir}/mkinstalldirs $(VERILATOR_CAD_DIR)/man/man1
for p in verilator.1 ; do \ for p in $(VL_INST_MAN_FILES) ; do \
$(INSTALL_DATA) $$p $(VERILATOR_CAD_DIR)/man/man1/$$p; \ $(INSTALL_DATA) $$p $(VERILATOR_CAD_DIR)/man/man1/$$p; \
done done
$(INST_PROJ_CVS) $(DISTNAME).tgz $(VERILATOR_CAD_DIR)/verilator.tgz $(INST_PROJ_CVS) $(DISTNAME).tgz $(VERILATOR_CAD_DIR)/verilator.tgz
@@ -371,6 +376,15 @@ endif
# VERILATOR_AUTHOR_SITE # VERILATOR_AUTHOR_SITE
endif endif
CPPCHECK = cppcheck
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
cppcheck: $(CPPCHECK_DEP)
%.cppcheck: %.cpp
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -I$(srcdir)/include -I$(srcdir)/src $<
ftp: info ftp: info
install-msg: install-msg:
@@ -391,8 +405,13 @@ Makefile: Makefile.in config.status $(IN_WILD)
src/Makefile: src/Makefile.in Makefile src/Makefile: src/Makefile.in Makefile
config.status: configure config.status: configure
./config.status --recheck ./config.status --recheck
configure: configure.ac configure: configure.ac
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
autoconf --warnings=all
else
autoconf autoconf
endif
maintainer-clean:: maintainer-clean::
@echo "This command is intended for maintainers to use;" @echo "This command is intended for maintainers to use;"
@@ -433,15 +452,12 @@ dist-file-list:
###################################################################### ######################################################################
# Distributions # Distributions
DISTCONFIG = ${srcdir}/src/config_build.h.in DISTTITLE := Verilator $(word 1,$(PACKAGE_VERSION))
DISTNAME := verilator-$(word 1,$(PACKAGE_VERSION))
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG)) DISTDATEPRE := $(word 2,$(PACKAGE_VERSION))
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG)) DISTDATE := $(subst /,-,$(DISTDATEPRE))
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([1-2][0-9][0-9][0-9].[0-9]*[0-9].[0-9]*[0-9]\).*/\1/' -e q $(DISTCONFIG))
DISTNAMEREV := $(shell sed -e '/DTVERSION/!d' -e 's/.*verilator_\([^"]*\).*/\1/' -e q src/config_rev.h)
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME))) DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
DISTDATE := $(subst /,-,$(DISTDATEPRE))
tag: tag:
svnorcvs tag $(DISTTAGNAME) svnorcvs tag $(DISTTAGNAME)
+119 -58
View File
@@ -70,7 +70,7 @@ if (! GetOptions (
# "version!" => \&version, # Also passthru'ed # "version!" => \&version, # Also passthru'ed
# Switches # Switches
"gdb=s" => \$opt_gdb, # Undocumented debugging "gdb=s" => \$opt_gdb, # Undocumented debugging
"gdbbt!" => \$opt_gdbbt, # Undocumented debugging "gdbbt!" => \$opt_gdbbt,
# Additional parameters # Additional parameters
"<>" => sub {}, # Ignored "<>" => sub {}, # Ignored
)) { )) {
@@ -99,7 +99,7 @@ if ($opt_gdbbt && !$opt_gdb && $Debug) {
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-exitstatus=>2, -verbose=>2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
} }
sub debug { sub debug {
@@ -125,7 +125,14 @@ sub verilator_bin {
$bin = "$dir/$basename"; # From pointing to kit directory $bin = "$dir/$basename"; # From pointing to kit directory
} }
} else { } else {
$bin = $basename; if (-x "$RealBin/$basename") {
$bin = "$RealBin/$basename"; # From path/to/verilator with verilator_bin installed
} else {
$bin = $basename; # Find in PATH
}
# Note we don't look under bin/$basename which would be right if running
# in the kit dir. Running that would likely break, since
# VERILATOR_ROOT wouldn't be set and Verilator won't find internal files.
} }
return $bin; return $bin;
} }
@@ -196,8 +203,9 @@ Verilator - Convert Verilog code to C++/SystemC
=head1 DESCRIPTION =head1 DESCRIPTION
Verilator converts synthesizable (not behavioral) Verilog code, plus some Verilator converts synthesizable (not behavioral) Verilog code, plus some
Synthesis, SystemVerilog and Sugar/PSL assertions, into C++, SystemC or Synthesis, SystemVerilog and a small subset of Verilog AMS and Sugar/PSL
SystemPerl code. It is not a complete simulator, just a compiler. assertions, into C++, SystemC or SystemPerl code. It is not a complete
simulator, just a compiler.
Verilator is invoked with parameters similar to GCC, Cadence Verilator is invoked with parameters similar to GCC, Cadence
Verilog-XL/NC-Verilog, or Synopsys's VCS. It reads the specified Verilog Verilog-XL/NC-Verilog, or Synopsys's VCS. It reads the specified Verilog
@@ -268,7 +276,7 @@ descriptions in the next sections for more information.
--MP Create phony dependency targets --MP Create phony dependency targets
--Mdir <directory> Name of output object directory --Mdir <directory> Name of output object directory
--mod-prefix <topname> Name to prepend to lower classes --mod-prefix <topname> Name to prepend to lower classes
--no-pins64 Don't use uint64_t's for 33-64 bit sigs --no-pins64 Don't use vluint64_t's for 33-64 bit sigs
--no-skip-identical Disable skipping identical output --no-skip-identical Disable skipping identical output
+notimingchecks Ignored +notimingchecks Ignored
-O0 Disable optimizations -O0 Disable optimizations
@@ -292,8 +300,8 @@ descriptions in the next sections for more information.
--top-module <topname> Name of top level input module --top-module <topname> Name of top level input module
--trace Enable waveform creation --trace Enable waveform creation
--trace-depth <levels> Depth of tracing --trace-depth <levels> Depth of tracing
--trace-max-array <bits> Maximum bit width for tracing --trace-max-array <depth> Maximum bit width for tracing
--trace-max-width <depth> Maximum array depth for tracing --trace-max-width <width> Maximum array depth for tracing
--trace-underscore Enable tracing of _signals --trace-underscore Enable tracing of _signals
-U<var> Undefine preprocessor define -U<var> Undefine preprocessor define
--unroll-count <loops> Tune maximum loop iterations --unroll-count <loops> Tune maximum loop iterations
@@ -562,10 +570,7 @@ Displays this message and program version and exits.
=item -II<dir> =item -II<dir>
Add the directory to the list of directories that should be searched for See -y.
include directories or libraries. Same as +incdir and -y; +incdir and -y
are fairly standard across Verilog tools while -I is an alias for GCC
compatibility.
=item --if-depth I<value> =item --if-depth I<value>
@@ -574,10 +579,7 @@ defaults to 0 which disables this warning.
=item +incdir+I<dir> =item +incdir+I<dir>
Add the directory to the list of directories that should be searched for See -y.
include directories or libraries. Same as -I and -y; +incdir and -y
are fairly standard across Verilog tools while -I is an alias for GCC
compatibility.
=item --inhibit-sim =item --inhibit-sim
@@ -609,9 +611,13 @@ in the Make variable LDLIBS, not LDFLAGS.)
Select the language to be used when first processing each Verilog file. Select the language to be used when first processing each Verilog file.
The language value must be "1364-1995", "1364-2001", "1364-2001", The language value must be "1364-1995", "1364-2001", "1364-2001",
"1364-2005", or "1800-2005". This should only be used for legacy code, as "1364-2005", "1800-2005", "VAMS-2.3". Verilator also allows the
the preferable option is to edit the code to repair new keywords, or add non-standard "1800+VAMS" to allow both the full SystemVerilog and
appropriate `begin_keywords. Verilog-AMS keywords.
The --language flag is only recommended for legacy code, as the preferable
option is to edit the code to repair new keywords, or add appropriate
`begin_keywords.
=item +libext+I<ext>+I<ext>... =item +libext+I<ext>+I<ext>...
@@ -713,9 +719,10 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
=item --pins-bv I<width> =item --pins-bv I<width>
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
wide should use sc_bv's instead of uint32/uint64_t's. The default is wide should use sc_bv's instead of uint32/vluint64_t's. The default is
"--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv "--pins-bv 65". Versions before Verilator 3.671 defaulted to "--pins-bv
33". The more sc_bv is used, the worse for performance. 33". The more sc_bv is used, the worse for performance. Use the
"/*verilator sc_bv*/" attribute to select specific ports to be sc_bv.
=item --pins-uint8 =item --pins-uint8
@@ -823,13 +830,13 @@ Specify the number of levels deep to enable tracing, for example
entire model. Using a small number will decrease visibility, but greatly entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size. improve runtime and trace file size.
=item --trace-max-array I<bits> =item --trace-max-array I<depth>
Rarely needed. Specify the maximum array depth of a signal that may be Rarely needed. Specify the maximum array depth of a signal that may be
traced. Defaults to 32, as tracing large arrays may greatly slow traced traced. Defaults to 32, as tracing large arrays may greatly slow traced
simulations. simulations.
=item --trace-max-width I<depth> =item --trace-max-width I<width>
Rarely needed. Specify the maximum bit width of a signal that may be Rarely needed. Specify the maximum bit width of a signal that may be
traced. Defaults to 256, as tracing large vectors may greatly slow traced traced. Defaults to 256, as tracing large vectors may greatly slow traced
@@ -930,14 +937,14 @@ Enables the specified warning message.
Enable all lint related warning messages (note by default they are already Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX "-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNSIGNED -Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-REALCVT
-Wwarn-WIDTH". -Wwarn-UNSIGNED -Wwarn-WIDTH".
=item -Wwarn-style =item -Wwarn-style
Enable all code style related warning messages. This is equivalent to Enable all code style related warning messages. This is equivalent to
"-Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH -Wwarn-SYNCASYNCNET "-Wwarn ASSIGNDLY -Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH
-Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN". -Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
=item -x-assign 0 =item -x-assign 0
@@ -965,9 +972,14 @@ enable rerunning with that same seed so you can reproduce bugs.
=item -y I<dir> =item -y I<dir>
Add the directory to the list of directories that should be searched for Add the directory to the list of directories that should be searched for
include directories or libraries. Same as +incdir and -I; +incdir and +y include files or libraries. The three flags -y, +incdir and -I have
are fairly standard across Verilog tools while -I is an alias for GCC similar effect; +incdir and +y are fairly standard across Verilog tools while -I
compatibility. is an alias for GCC compatibility.
Verilator defaults to the current directory ("-y .") and any specified
--Mdir, though these default paths are used after any user specified
directories. This allows '-y "$(pwd)"' to be used if absolute filenames
are desired for error messages instead of relative filenames.
=back =back
@@ -1226,11 +1238,6 @@ all runs of the C++ Compiler. For example, "objcache --read --write", or
"ccache". If using distcc, it would generally be run under either objcache "ccache". If using distcc, it would generally be run under either objcache
or ccache; see the documentation for those programs. or ccache; see the documentation for those programs.
=item OBJCACHE_JOBS
Optionally lists Make flags that specifies parallel make jobs. For example
a 4 CPU system may use "-j 6" to request 6 parallel compiles when making.
=item SYSTEMC =item SYSTEMC
Required for SystemC output mode. If set, specifies the directory Required for SystemC output mode. If set, specifies the directory
@@ -1306,10 +1313,13 @@ example:
Vtop *top; // Instantiation of module Vtop *top; // Instantiation of module
unsigned int main_time = 0; // Current simulation time vluint64_t main_time = 0; // Current simulation time
// This is a 64-bit integer to reduce wrap over issues and
// allow modulus. You can also use a double, if you wish.
double sc_time_stamp () { // Called by $time in Verilog double sc_time_stamp () { // Called by $time in Verilog
return main_time; return main_time; // converts to double, to match
// what SystemC does
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
@@ -1352,7 +1362,7 @@ will plug directly into a SystemC netlist.
The SC_MODULE gets the same pinout as the Verilog module, with the The SC_MODULE gets the same pinout as the Verilog module, with the
following type conversions: Pins of a single bit become bool. Pins 2-32 following type conversions: Pins of a single bit become bool. Pins 2-32
bits wide become uint32_t's. Pins 33-64 bits wide become sc_bv's or bits wide become uint32_t's. Pins 33-64 bits wide become sc_bv's or
uint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's. vluint64_t's depending on the --no-pins64 switch. Wider pins become sc_bv's.
(Uints simulate the fastest so are used where possible.) (Uints simulate the fastest so are used where possible.)
Lower modules are not pure SystemC code. This is a feature, as using the Lower modules are not pure SystemC code. This is a feature, as using the
@@ -1661,7 +1671,7 @@ please file a bug if a feature you need is missing.
Verilator supports ==? and !=? operators, ++ and -- in some contexts, Verilator supports ==? and !=? operators, ++ and -- in some contexts,
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0, $bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
$unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle, $unit, $warning, always_comb, always_ff, always_latch, bit, byte, chandle,
do-while, enum, export, final, import, int, logic, longint, package, const, do-while, enum, export, final, import, int, logic, longint, package,
program, shortint, time, typedef, var, void, priority case/if, and unique program, shortint, time, typedef, var, void, priority case/if, and unique
case/if. case/if.
@@ -1680,6 +1690,18 @@ Verilator currently has some support for SystemVerilog 2009 synthesis
constructs. As SystemVerilog features enter common usage they are added; constructs. As SystemVerilog features enter common usage they are added;
please file a bug if a feature you need is missing. please file a bug if a feature you need is missing.
=head2 Verilog AMS Support
Verilator implements a very small subset of Verilog AMS (Verilog Analog and
Mixed-Signal Extensions) with the subset corresponding to those VMS
keywords with near equivelents in the Verilog 2005 or SystemVerilog 2009
languages.
AMS parsing is enabled with "--language VAMS" or "--language 1800+VAMS".
At present Verilator implements ceil, exp, floor, ln, log, pow, sqrt,
string, and wreal.
=head2 Sugar/PSL Support =head2 Sugar/PSL Support
Most future work is being directed towards improving SystemVerilog Most future work is being directed towards improving SystemVerilog
@@ -1711,8 +1733,8 @@ assertion clocks.
=head2 Synthesis Directive Assertion Support =head2 Synthesis Directive Assertion Support
With the --assert switch, Verilator reads any "//synopsys full_case" or "// With the --assert switch, Verilator reads any "//synopsys full_case" or "//
synopsys parallel_case" directives. The same applies to any "//cadence" or synopsys parallel_case" directives. The same applies to any "// ambit
"// ambit synthesis" directives of the same form. synthesis", "//cadence" or "//pragma" directives of the same form.
When these synthesis directives are discovered, Verilator will either When these synthesis directives are discovered, Verilator will either
formally prove the directive to be true, or failing that, will insert the formally prove the directive to be true, or failing that, will insert the
@@ -2028,6 +2050,15 @@ should be declared in SystemC as a sc_clock instead of a bool. This was
needed in SystemC 1.1 and 1.2 only; versions 2.0 and later do not require needed in SystemC 1.1 and 1.2 only; versions 2.0 and later do not require
clock pins to be sc_clocks and this is no longer needed. clock pins to be sc_clocks and this is no longer needed.
=item /*verilator sc_bv*/
Used after a port declaration. It sets the port to be of sc_bv<I<width>>
type, instead of bool, vluint32_t or vluint64_t. This may be useful if
the port width is parametrized and different of such modules interface
a templated module (such as a transactor) or for other reasons. In general
you should avoid using this attribute when not necessary as with increasing
usage of sc_bv the performance increases significantly.
=item /*verilator sformat*/ =item /*verilator sformat*/
Attached to the final input of a function or task "input string" to Attached to the final input of a function or task "input string" to
@@ -2096,7 +2127,7 @@ that Verilator will print a list of known scopes to help your debugging.
=head2 Floating Point =head2 Floating Point
Floating Point numbers are not synthesizable, and so not supported. Floating Point (real) numbers are supported.
=head2 Latches =head2 Latches
@@ -2258,6 +2289,13 @@ not arrays nor structs.
Treated as a "longint"; does not yet warn about operations that are Treated as a "longint"; does not yet warn about operations that are
specified as illegal on chandles. specified as illegal on chandles.
=item disable
Disable statements may be used only if the block being disabled is a block
the disable statement itself is inside. This was commonly used to provide
loop break and continue functionality before SystemVerilog added the break
and continue keywords.
=item priority if, unique if =item priority if, unique if
Priority and unique if's are treated as normal ifs and not asserted to be Priority and unique if's are treated as normal ifs and not asserted to be
@@ -2306,11 +2344,6 @@ The rarely used optional parameter to $finish and $stop is ignored.
File descriptors passed to the file PLI calls must be file descriptors, not File descriptors passed to the file PLI calls must be file descriptors, not
MCDs, which includes the mode parameter to $fopen being mandatory. MCDs, which includes the mode parameter to $fopen being mandatory.
Verilator will convert the integer used to hold the file descriptor into a
internal FILE*. To prevent core dumps due to mis-use, and because integers
are 32 bits while FILE*s may be 64 bits, the descriptor must be stored in a
reg [63:0] rather than an integer. The define `verilator_file_descriptor in
verilated.v can be used to hide this difference.
=item $fscanf, $sscanf =item $fscanf, $sscanf
@@ -2334,10 +2367,6 @@ Read memory commands should work properly. Note Verilator and the Verilog
specification does not include support for readmem to multi-dimensional specification does not include support for readmem to multi-dimensional
arrays. arrays.
=item $realtime
Treated as $time.
=item $test$plusargs, $value$plusargs =item $test$plusargs, $value$plusargs
Supported, but the instantiating C++/SystemC testbench must call Supported, but the instantiating C++/SystemC testbench must call
@@ -2377,6 +2406,29 @@ List of all warnings:
=over 4 =over 4
=item ASSIGNIN
Error that an assignment is being made to an input signal. This is almost
certainly a mistake, though technically legal.
input a;
assign a = 1'b1;
Ignoring this warning will only suppress the lint check, it will simulate
correctly.
=item ASSIGNDLY
Warns that you have an assignment statement with a delayed time in front of
it, for example:
a <= #100 b;
assign #100 a = b;
Ignoring this warning may make Verilator simulations differ from other
simulators, however at one point this was a common style so disabled by
default as a code style warning.
=item BLKANDNBLK =item BLKANDNBLK
BLKANDNBLK is an error that a variable comes from a mix of blocked and BLKANDNBLK is an error that a variable comes from a mix of blocked and
@@ -2617,6 +2669,11 @@ not really needed. The best solution is to insure that each module is in a
unique file by the same name. Otherwise, make sure all library files are unique file by the same name. Otherwise, make sure all library files are
read in as libraries with -v, instead of automatically with -y. read in as libraries with -v, instead of automatically with -y.
=item REALCVT
Warns that a real number is being implicitly rounded to an integer, with
possible loss of precision.
=item REDEFMACRO =item REDEFMACRO
Warns that you have redefined the same macro with a different value, for Warns that you have redefined the same macro with a different value, for
@@ -2945,6 +3002,11 @@ One limit is that you cannot under either license release a commercial
Verilog simulation product incorporating Verilator without making the Verilog simulation product incorporating Verilator without making the
source code available. source code available.
As is standard with Open Source, contributions back to Verilator will be
placed under the Verilator copyright and LGPL/Artistic license. Small test
cases will be released into the public domain so they can be used anywhere,
large tests under the LGPL/Artistic, unless requested otherwise.
=item Why is Verilation so slow? =item Why is Verilation so slow?
Verilator needs more memory than the resulting simulator will require, as Verilator needs more memory than the resulting simulator will require, as
@@ -3051,8 +3113,8 @@ network disk. Network disks are generally far slower.
=item How do I do coverage analysis? =item How do I do coverage analysis?
Verilator supports both block (line) coverage and user inserted functional Verilator supports both block (line) coverage and user inserted functional
coverage. Both currently require SystemPerl output mode and the SystemPerl coverage. Both require the SystemPerl package to be installed but do not
package. require use of the SystemPerl output mode.
First, run verilator with the --coverage option. If you're using your own First, run verilator with the --coverage option. If you're using your own
makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if
@@ -3142,10 +3204,9 @@ Between GCC 3.0 to 3.3, each compiled progressively slower, thus if you can
use GCC 2.95, or GCC 3.4 you'll have faster builds. Two ways to cheat are use GCC 2.95, or GCC 3.4 you'll have faster builds. Two ways to cheat are
to compile on parallel machines and avoid compilations altogether. See the to compile on parallel machines and avoid compilations altogether. See the
--output-split option, and the web for the ccache, distcc and icecream --output-split option, and the web for the ccache, distcc and icecream
packages, and the Make::Cache package available from packages. ccache will skip GCC runs between identical source builds, even
L<http://www.veripool.org/>. Make::Cache will skip GCC runs between across different users. You can use the OBJCACHE environment variable to
identical source builds, even across different users. You can use the use these CC wrappers.
OBJCACHE environment variable to use these CC wrappers.
=item Why do so many files need to recompile when I add a signal? =item Why do so many files need to recompile when I add a signal?
@@ -3175,7 +3236,7 @@ as you would any other member variable.
Signals are the smallest of 8 bit chars, 16 bit shorts, 32 bit longs, or 64 Signals are the smallest of 8 bit chars, 16 bit shorts, 32 bit longs, or 64
bit long longs that fits the width of the signal. Generally, you can use bit long longs that fits the width of the signal. Generally, you can use
just uint32_t's for 1 to 32 bits, or uint64_t for 1 to 64 bits, and the just uint32_t's for 1 to 32 bits, or vluint64_t for 1 to 64 bits, and the
compiler will properly up-convert smaller entities. compiler will properly up-convert smaller entities.
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's. Signals wider than 64 bits are stored as an array of 32-bit uint32_t's.
+2 -2
View File
@@ -99,7 +99,7 @@ sub filter {
next if $line =~ / This=/; next if $line =~ / This=/;
$line =~ s/0x[a-f0-9]+/0x/g; $line =~ s/0x[a-f0-9]+/0x/g;
$line =~ s/<e[0-9]+\#?>/<e>/g; $line =~ s/<e[0-9]+\#?>/<e>/g;
$line =~ s/{\d+}/{}/g if !$Opt_Lineno; $line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
print $f2 $line; print $f2 $line;
} }
$f1->close; $f1->close;
@@ -109,7 +109,7 @@ sub filter {
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
+1 -1
View File
@@ -39,7 +39,7 @@ profcfunc($Opt_File);
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
+100 -31
View File
@@ -1,35 +1,83 @@
dnl DESCRIPTION: Process this file with autoconf to produce a configure script. # DESCRIPTION: Process this file with autoconf to produce a configure script.
dnl #
dnl Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can # Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
dnl redistribute it and/or modify it under the terms of either the GNU Lesser # redistribute it and/or modify it under the terms of either the GNU Lesser
dnl General Public License Version 3 or the Perl Artistic License Version 2.0. # General Public License Version 3 or the Perl Artistic License Version 2.0.
AC_INIT(src/Verilator.cpp) AC_INIT([Verilator],[3.830])
AC_CONFIG_HEADER(src/config_build.h) AC_CONFIG_HEADER(src/config_build.h)
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
dnl Special Substitutions AC_MSG_RESULT([configuring for $PACKAGE_STRING])
AC_ARG_ENABLE(defenv,
[AS_HELP_STRING([--disable-defenv], [disable hardcoded default environment variables])], # Special Substitutions - CFG_WITH_DEFENV
CFG_WITH_DEFENV=$enableval, AC_MSG_CHECKING(whether to disable hardcoded paths)
CFG_WITH_DEFENV=yes) AC_ARG_ENABLE([defenv],
[AS_HELP_STRING([--disable-defenv],
[disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])],
[case "${enableval}" in
yes) CFG_WITH_DEFENV=yes ;;
no) CFG_WITH_DEFENV=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --disable-defenv]) ;;
esac],
CFG_WITH_DEFENV=yes)
AC_SUBST(CFG_WITH_DEFENV) AC_SUBST(CFG_WITH_DEFENV)
AC_MSG_RESULT($CFG_WITH_DEFENV)
dnl Compiler flags # Special Substitutions - CFG_WITH_CCWARN
AC_MSG_CHECKING(whether to show and stop on compilation warnings)
AC_ARG_ENABLE([ccwarn],
[AS_HELP_STRING([--enable-ccwarn],
[enable showing and stopping on compilation warnings])],
[case "${enableval}" in
yes) CFG_WITH_CCWARN=yes ;;
no) CFG_WITH_CCWARN=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ccwarn]) ;;
esac],
[case "x${VERILATOR_AUTHOR_SITE}" in
x) CFG_WITH_CCWARN=no ;;
*) CFG_WITH_CCWARN=yes ;;
esac]
)
AC_SUBST(CFG_WITH_CCWARN)
AC_MSG_RESULT($CFG_WITH_CCWARN)
# Special Substitutions - CFG_WITH_LONGTESTS
AC_MSG_CHECKING(whether to run long tests)
AC_ARG_ENABLE([longtests],
[AS_HELP_STRING([--enable-longtests],
[enable running long developer tests])],
[case "${enableval}" in
yes) CFG_WITH_LONGTESTS=yes ;;
no) CFG_WITH_LONGTESTS=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-longtests]) ;;
esac],
[case "x${VERILATOR_AUTHOR_SITE}" in
x) CFG_WITH_LONGTESTS=no ;;
*) CFG_WITH_LONGTESTS=yes ;;
esac]
)
AC_SUBST(CFG_WITH_LONGTESTS)
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
# Compiler flags
CFLAGS=-I${includedir} CFLAGS=-I${includedir}
CPPFLAGS=-I${includedir} CPPFLAGS=-I${includedir}
CXXFLAGS=-I${includedir} CXXFLAGS=-I${includedir}
LDFLAGS=-L${libdir} LDFLAGS=-L${libdir}
dnl Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AC_PROG_CXX AC_PROG_CXX
AC_PROG_INSTALL AC_PROG_INSTALL
AC_LANG_PUSH(C++) AC_LANG_PUSH(C++)
AC_MSG_CHECKING([that C++ compiler can compile simple program]) AC_MSG_CHECKING([that C++ compiler can compile simple program])
AC_TRY_RUN([int main() { return 0; }], AC_RUN_IFELSE(
[AC_LANG_SOURCE([int main() { return 0; }])],
AC_MSG_RESULT(yes), AC_MSG_RESULT(yes),
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required])) AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]),
AC_MSG_RESULT(yes))
AC_PATH_PROG(PERL,perl) AC_PATH_PROG(PERL,perl)
if test "x$PERL" = "x" ; then if test "x$PERL" = "x" ; then
@@ -44,33 +92,54 @@ if test "x$YACC" = "x" ; then
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it]) AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
fi fi
dnl Checks for libraries. # Checks for libraries.
dnl Checks for header files. # Checks for typedefs, structures
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(fcntl.h unistd.h inttypes.h sys/file.h sys/time.h sys/un.h math.h stdint.h mingw/stdint.h)
dnl Checks for typedefs, structures
AC_CHECK_TYPE(size_t,unsigned int) AC_CHECK_TYPE(size_t,unsigned int)
AC_CHECK_TYPE(uint_t,unsigned int)
AC_CHECK_TYPE(ulong_t,unsigned long)
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
AC_STRUCT_TM
dnl Checks for compiler characteristics. # Checks for compiler characteristics.
AC_C_INLINE AC_C_INLINE
dnl Checks for library functions. AC_DEFUN([_MY_CXX_CHECK_OPT],
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
# -Werror needed otherwise unknown -Wno-div-by-zero won't report problems
CXXFLAGS="$CXXFLAGS $1 -Werror"
AC_MSG_CHECKING([whether $CXX accepts $1])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([],[])],
[_my_result=yes],
[_my_result=no])
AC_MSG_RESULT($_my_result)
if test "$_my_result" = "yes" ; then
CFG_CXXFLAGS_NO_UNUSED="$CFG_CXXFLAGS_NO_UNUSED $1"
fi
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
])# _MY_CXX_CHECK_OPT
dnl Checks for system services # For example, -Wno-div-by-zero isn't in 4.1.2
_MY_CXX_CHECK_OPT(-Wno-char-subscripts)
# Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn
# without this flag, even though there's a conditional to prevent the divide.
# We still don't add no-div-by-zero as it throws message to stdout, though doesn't die.
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
_MY_CXX_CHECK_OPT(-Wno-sign-compare)
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
dnl Other install directories # Checks for library functions.
# Checks for system services
# Other install directories
pkgdatadir=${datadir}/verilator pkgdatadir=${datadir}/verilator
AC_SUBST(pkgdatadir) AC_SUBST(pkgdatadir)
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk) AC_OUTPUT
AC_MSG_RESULT([]) AC_MSG_RESULT([])
AC_MSG_RESULT([Now type 'gmake']) AC_MSG_RESULT([Now type 'make' (or sometimes 'gmake') to build Verilator.])
AC_MSG_RESULT([]) AC_MSG_RESULT([])
+78 -12
View File
@@ -26,7 +26,6 @@
#define _VERILATED_CPP_ #define _VERILATED_CPP_
#include "verilated_imp.h" #include "verilated_imp.h"
#include <cctype> #include <cctype>
#include <vector>
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING #define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
@@ -285,12 +284,15 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
// Note also assumes variables < 64 are not wide, this assumption is // Note also assumes variables < 64 are not wide, this assumption is
// sometimes not true in low-level routines written here in verilated.cpp // 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 tmp[VL_VALUE_STRING_MAX_WIDTH];
static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH];
const char* pctp = NULL; // Most recent %##.##g format
bool inPct = false; bool inPct = false;
bool widthSet = false; bool widthSet = false;
int width = 0; int width = 0;
const char* pos = formatp; const char* pos = formatp;
for (; *pos; ++pos) { for (; *pos; ++pos) {
if (!inPct && pos[0]=='%') { if (!inPct && pos[0]=='%') {
pctp = pos;
inPct = true; inPct = true;
widthSet = false; widthSet = false;
width = 0; width = 0;
@@ -312,6 +314,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
widthSet = true; widthSet = true;
width = width*10 + (fmt - '0'); width = width*10 + (fmt - '0');
break; break;
case '.':
inPct = true; // Get more digits
break;
case '%': case '%':
output += '%'; output += '%';
break; break;
@@ -325,6 +330,18 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
output += cstrp; output += cstrp;
break; break;
} }
case 'e':
case 'f':
case 'g': {
const int lbits = va_arg(ap, int);
double d = va_arg(ap, double);
if (lbits) {} // UNUSED - always 64
strncpy(tmpf, pctp, pos-pctp+1);
tmpf[pos-pctp+1] = '\0';
sprintf(tmp, tmpf, d);
output += tmp;
break;
}
default: { default: {
// Deal with all read-and-print somethings // Deal with all read-and-print somethings
const int lbits = va_arg(ap, int); const int lbits = va_arg(ap, int);
@@ -358,14 +375,26 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
case 'd': { // Signed decimal 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",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
int needmore = width-digits; int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
output.append(needmore,'0'); // Pre-pad zero
} else {
output.append(needmore,' '); // Pre-pad spaces
}
}
output += tmp; output += tmp;
break; break;
} }
case 'u': { // Unsigned decimal case 'u': { // Unsigned decimal
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld); int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
int needmore = width-digits; int needmore = width-digits;
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { //%0
output.append(needmore,'0'); // Pre-pad zero
} else {
output.append(needmore,' '); // Pre-pad spaces
}
}
output += tmp; output += tmp;
break; break;
} }
@@ -569,6 +598,17 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
VL_SET_WQ(owp,ld); VL_SET_WQ(owp,ld);
break; break;
} }
case 'f':
case 'e':
case 'g': { // Real number
_vl_vsss_skipspace(fp,floc,fromp);
_vl_vsss_read(fp,floc,fromp, tmp, "+-.0123456789eE");
if (!tmp[0]) goto done;
union { double r; vlsint64_t ld; } u;
u.r = strtod(tmp, NULL);
VL_SET_WQ(owp,u.ld);
break;
}
case 't': // FALLTHRU // Time case 't': // FALLTHRU // Time
case 'u': { // Unsigned decimal case 'u': { // Unsigned decimal
_vl_vsss_skipspace(fp,floc,fromp); _vl_vsss_skipspace(fp,floc,fromp);
@@ -628,6 +668,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
//=========================================================================== //===========================================================================
// File I/O // File I/O
FILE* VL_CVT_I_FP(IData lhs) {
return VerilatedImp::fdToFp(lhs);
}
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) { void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
// See also VL_DATA_TO_STRING_NW // See also VL_DATA_TO_STRING_NW
int lsb=obits-1; int lsb=obits-1;
@@ -655,8 +699,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
for (; i<bytes; i++) { *op++ = 0; } for (; i<bytes; i++) { *op++ = 0; }
} }
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) { IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
// The string needs to be padded with 0's in unused spaces in front of // The string needs to be padded with 0's in unused spaces in front of
@@ -683,16 +727,26 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
return got; return got;
} }
QData VL_FOPEN_QI(QData filename, IData mode) { IData VL_FOPEN_QI(QData filename, IData mode) {
IData fnw[2]; VL_SET_WQ(fnw, filename); IData fnw[2]; VL_SET_WQ(fnw, filename);
return VL_FOPEN_WI(2, fnw, mode); return VL_FOPEN_WI(2, fnw, mode);
} }
QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) { IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep); _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
char modez[5]; char modez[5];
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode); _VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
return VL_CVT_FP_Q(fopen(filenamez,modez)); return VL_FOPEN_S(filenamez,modez);
}
IData VL_FOPEN_S(const char* filenamep, const char* modep) {
return VerilatedImp::fdNew(fopen(filenamep,modep));
}
void VL_FCLOSE_I(IData fdi) {
FILE* fp = VL_CVT_I_FP(fdi);
if (VL_UNLIKELY(!fp)) return;
fclose(fp);
VerilatedImp::fdDelete(fdi);
} }
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) { void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
@@ -726,8 +780,8 @@ void VL_WRITEF(const char* formatp, ...) {
VL_PRINTF("%s", output.c_str()); VL_PRINTF("%s", output.c_str());
} }
void VL_FWRITEF(QData fpq, const char* formatp, ...) { void VL_FWRITEF(IData fpi, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return; if (VL_UNLIKELY(!fp)) return;
va_list ap; va_list ap;
@@ -739,8 +793,8 @@ void VL_FWRITEF(QData fpq, const char* formatp, ...) {
fputs(output.c_str(), fp); fputs(output.c_str(), fp);
} }
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) { IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
FILE* fp = VL_CVT_Q_FP(fpq); FILE* fp = VL_CVT_I_FP(fpi);
if (VL_UNLIKELY(!fp)) return 0; if (VL_UNLIKELY(!fp)) return 0;
va_list ap; va_list ap;
@@ -883,6 +937,17 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
} }
} }
IData VL_SYSTEM_IQ(QData lhs) {
IData lhsw[2]; VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(2, lhsw);
}
IData VL_SYSTEM_IW(int lhswords, WDataInP filenamep) {
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
_VL_VINT_TO_STRING(lhswords*VL_WORDSIZE, filenamez, filenamep);
int code = system(filenamez);
return code >> 8; // Want exit status
}
IData VL_TESTPLUSARGS_I(const char* formatp) { IData VL_TESTPLUSARGS_I(const char* formatp) {
string match = VerilatedImp::argPlusMatch(formatp); string match = VerilatedImp::argPlusMatch(formatp);
if (match == "") return 0; if (match == "") return 0;
@@ -1038,6 +1103,7 @@ VerilatedScope::VerilatedScope() {
m_callbacksp = NULL; m_callbacksp = NULL;
m_namep = NULL; m_namep = NULL;
m_funcnumMax = 0; m_funcnumMax = 0;
m_symsp = NULL;
m_varsp = NULL; m_varsp = NULL;
} }
+42 -23
View File
@@ -35,6 +35,7 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <cmath>
// <iostream> avoided to reduce compile time // <iostream> avoided to reduce compile time
// <string> 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; using namespace std;
@@ -321,11 +322,14 @@ extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp); ///< Zero reset a
extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus); extern WDataOutP _vl_moddiv_w(int lbits, WDataOutP owp, WDataInP lwp, WDataInP rwp, bool is_modulus);
/// File I/O /// File I/O
extern IData VL_FGETS_IXQ(int obits, void* destp, QData fpq); extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode); extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
extern QData VL_FOPEN_QI(QData ofilename, IData mode); extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); } extern IData VL_FOPEN_QI(QData ofilename, IData mode);
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
extern void VL_FCLOSE_I(IData fdi);
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP ofilename, void* memp, IData start, IData end); WDataInP ofilename, void* memp, IData start, IData end);
@@ -336,15 +340,19 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); } VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
extern void VL_WRITEF(const char* formatp, ...); extern void VL_WRITEF(const char* formatp, ...);
extern void VL_FWRITEF(QData fpq, const char* formatp, ...); extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...); extern IData VL_FSCANF_IX(IData fpi, const char* formatp, ...);
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...); extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...); extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...); extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
extern void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...); extern void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...);
extern IData VL_SYSTEM_IW(int lhsnwords, WDataInP lhs);
extern IData VL_SYSTEM_IQ(QData lhs);
inline IData VL_SYSTEM_II(IData lhs) { return VL_SYSTEM_IQ(lhs); }
extern IData VL_TESTPLUSARGS_I(const char* formatp); extern IData VL_TESTPLUSARGS_I(const char* formatp);
extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp); extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp);
extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
@@ -364,15 +372,24 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
#define VL_SET_QW(lwp) ( ((QData)(lwp[0])) | ((QData)(lwp[1])<<((QData)(VL_WORDSIZE)) )) #define VL_SET_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_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
/// Return FILE* from IData
extern FILE* VL_CVT_I_FP(IData lhs);
// Use a union to avoid cast-to-different-size warnings // Use a union to avoid cast-to-different-size warnings
/// Return FILE* from QData
static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; }
/// Return void* from QData /// Return void* from QData
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; } static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
/// Return QData from FILE*
static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
/// Return QData from void* /// Return QData from void*
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; } static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
/// Return double from QData (bits, not numerically)
static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q=lhs; return u.d; }
/// Return QData from double (bits, not numerically)
static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.d=lhs; return u.q; }
/// Return double from QData (numeric)
static inline double VL_ITOR_D_I(IData lhs) { return ((double)((vlsint32_t)(lhs))); }
/// Return QData from double (numeric)
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(VL_TRUNC(lhs))); }
/// Return QData from double (numeric)
static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(VL_ROUND(lhs))); }
// Sign extend such that if MSB set, we get ffff_ffff, else 0s // Sign extend such that if MSB set, we get ffff_ffff, else 0s
// (Requires clean input) // (Requires clean input)
@@ -402,9 +419,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000) #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_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_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() ((double)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
#else #else
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER)) # 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_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
extern double sc_time_stamp(); extern double sc_time_stamp();
#endif #endif
@@ -947,11 +966,11 @@ static inline WDataOutP VL_SUB_W(int words, WDataOutP owp,WDataInP lwp,WDataInP
// Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround, // Optimization bug in GCC 2.96 and presumably all-pre GCC 3 versions need this workaround,
// we can't just // we can't just
//# define VL_UNARYMIN_I(data) (-(data)) //# define VL_NEGATE_I(data) (-(data))
static inline IData VL_UNARYMIN_I(IData data) { return -data; } static inline IData VL_NEGATE_I(IData data) { return -data; }
static inline QData VL_UNARYMIN_Q(QData data) { return -data; } static inline QData VL_NEGATE_Q(QData data) { return -data; }
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){ static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
QData carry = 0; QData carry = 0;
for (int i=0; i<words; i++) { for (int i=0; i<words; i++) {
carry = carry + (QData)(IData)(~lwp[i]); carry = carry + (QData)(IData)(~lwp[i]);
@@ -998,18 +1017,18 @@ static inline WDataOutP VL_MULS_WWW(int,int lbits,int, WDataOutP owp,WDataInP lw
IData lneg = VL_SIGN_I(lbits,lwp[words-1]); IData lneg = VL_SIGN_I(lbits,lwp[words-1]);
if (lneg) { // Negate lhs if (lneg) { // Negate lhs
lwusp = lwstore; lwusp = lwstore;
VL_UNARYMIN_W(words, lwstore, lwp); VL_NEGATE_W(words, lwstore, lwp);
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
} }
IData rneg = VL_SIGN_I(lbits,rwp[words-1]); IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
if (rneg) { // Negate rhs if (rneg) { // Negate rhs
rwusp = rwstore; rwusp = rwstore;
VL_UNARYMIN_W(words, rwstore, rwp); VL_NEGATE_W(words, rwstore, rwp);
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
} }
VL_MUL_W(words,owp,lwusp,rwusp); VL_MUL_W(words,owp,lwusp,rwusp);
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
if ((lneg ^ rneg) & 1) { // Negate output (not using UNARYMIN, as owp==lwp) if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
QData carry = 0; QData carry = 0;
for (int i=0; i<words; i++) { for (int i=0; i<words; i++) {
carry = carry + (QData)(IData)(~owp[i]); carry = carry + (QData)(IData)(~owp[i]);
@@ -1056,12 +1075,12 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
IData rwstore[VL_MULS_MAX_WORDS]; IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp; WDataInP ltup = lwp;
WDataInP rtup = rwp; WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); } if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); } if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if ((lsign && !rsign) || (!lsign && rsign)) { if ((lsign && !rsign) || (!lsign && rsign)) {
IData qNoSign[VL_MULS_MAX_WORDS]; IData qNoSign[VL_MULS_MAX_WORDS];
VL_DIV_WWW(lbits,qNoSign,ltup,rtup); VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign)); _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp; return owp;
} else { } else {
return VL_DIV_WWW(lbits,owp,ltup,rtup); return VL_DIV_WWW(lbits,owp,ltup,rtup);
@@ -1075,12 +1094,12 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
IData rwstore[VL_MULS_MAX_WORDS]; IData rwstore[VL_MULS_MAX_WORDS];
WDataInP ltup = lwp; WDataInP ltup = lwp;
WDataInP rtup = rwp; WDataInP rtup = rwp;
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); } if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); } if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
if (lsign) { // Only dividend sign matters for modulus if (lsign) { // Only dividend sign matters for modulus
IData qNoSign[VL_MULS_MAX_WORDS]; IData qNoSign[VL_MULS_MAX_WORDS];
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup); VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign)); _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
return owp; return owp;
} else { } else {
return VL_MODDIV_WWW(lbits,owp,ltup,rtup); return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
+12 -6
View File
@@ -13,6 +13,12 @@ LINK = @CXX@
AR = ar AR = ar
RANLIB = ranlib RANLIB = ranlib
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
# Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero
CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
###################################################################### ######################################################################
# Programs # Programs
@@ -38,13 +44,9 @@ VK_CPPFLAGS_ALWAYS += \
-DVM_TRACE=$(VM_TRACE) \ -DVM_TRACE=$(VM_TRACE) \
-DVM_COVERAGE=$(VM_COVERAGE) \ -DVM_COVERAGE=$(VM_COVERAGE) \
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
VK_CPPFLAGS_WALL += -Wall \ VK_CPPFLAGS_WALL += -Wall \
-Wno-char-subscripts \ $(CFG_CXXFLAGS_NO_UNUSED) \
-Wno-sign-compare \
-Wno-unused-parameter \
-Wno-unused-variable \
-Wno-uninitialized \
-Werror -Werror
endif endif
@@ -116,6 +118,10 @@ ifeq ($(VM_SP),1)
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \ $(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
--preproc $(VK_CLASSES_SP) --preproc $(VK_CLASSES_SP)
else else
ifeq ($(VM_COVERAGE),1)
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
VPATH += $(SYSTEMPERL_INCLUDE)
endif
preproc: preproc:
endif endif
+2 -6
View File
@@ -27,11 +27,7 @@
`define coverage_block_off `define coverage_block_off
`endif `endif
// Hide file descriptor difference // Hide file descriptor difference - deprecated - for older versions
`ifdef verilator `define verilator_file_descriptor integer
`define verilator_file_descriptor reg [63:0]
`else
`define verilator_file_descriptor integer
`endif
`endif // guard `endif // guard
+39 -1
View File
@@ -35,6 +35,7 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <deque>
#include <string> #include <string>
class VerilatedScope; class VerilatedScope;
@@ -62,9 +63,18 @@ class VerilatedImp {
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number> ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
int m_exportNext; ///< Next export funcnum int m_exportNext; ///< Next export funcnum
// File I/O
vector<FILE*> m_fdps; ///< File descriptors
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
public: // But only for verilated*.cpp public: // But only for verilated*.cpp
// CONSTRUCTORS // CONSTRUCTORS
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {} VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
m_fdps.resize(3);
m_fdps[0] = stdin;
m_fdps[1] = stdout;
m_fdps[2] = stderr;
}
~VerilatedImp() {} ~VerilatedImp() {}
// METHODS - arguments // METHODS - arguments
@@ -184,6 +194,34 @@ public: // But only for verilated*.cpp
} }
// We don't free up m_exportMap until the end, because we can't be sure // We don't free up m_exportMap until the end, because we can't be sure
// what other models are using the assigned funcnum's. // what other models are using the assigned funcnum's.
public: // But only for verilated*.cpp
// METHODS - file IO
static IData fdNew(FILE* fp) {
if (VL_UNLIKELY(!fp)) return 0;
// Bit 31 indicates it's a descriptor not a MCD
if (s_s.m_fdFree.empty()) {
// Need to create more space in m_fdps and m_fdFree
size_t start = s_s.m_fdps.size();
s_s.m_fdps.resize(start*2);
for (size_t i=start; i<start*2; i++) s_s.m_fdFree.push_back((IData)i);
}
IData idx = s_s.m_fdFree.back(); s_s.m_fdFree.pop_back();
s_s.m_fdps[idx] = fp;
return (idx | (1UL<<31)); // bit 31 indicates not MCD
}
static void fdDelete(IData fdi) {
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return;
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
s_s.m_fdps[idx] = NULL;
s_s.m_fdFree.push_back(idx);
}
static inline FILE* fdToFp(IData fdi) {
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(!(fdi & (1ULL<<31)) || idx >= s_s.m_fdps.size())) return NULL;
return s_s.m_fdps[idx];
}
}; };
#endif // Guard #endif // Guard
+6 -3
View File
@@ -86,8 +86,8 @@ private:
NameMap* m_namemapp; ///< List of names for the header NameMap* m_namemapp; ///< List of names for the header
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
inline size_t bufferSize() { return 256*1024; } // See below for slack calculation inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
inline size_t bufferInsertSize() { return 16*1024; } inline static size_t bufferInsertSize() { return 16*1024; }
void bufferFlush(); void bufferFlush();
void bufferCheck() { void bufferCheck() {
// Flush the write buffer if there's not enough space left for new information // Flush the write buffer if there's not enough space left for new information
@@ -110,6 +110,7 @@ private:
void dumpHeader(); void dumpHeader();
void dumpPrep (vluint64_t timeui); void dumpPrep (vluint64_t timeui);
void dumpFull (vluint64_t timeui); void dumpFull (vluint64_t timeui);
// cppcheck-suppress functionConst
void dumpDone (); void dumpDone ();
inline void printCode (vluint32_t code) { inline void printCode (vluint32_t code) {
if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33)); if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33));
@@ -117,7 +118,7 @@ private:
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33)); if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
*m_writep++ = ((char)((code)%94+33)); *m_writep++ = ((char)((code)%94+33));
} }
string stringCode (vluint32_t code) { static string stringCode (vluint32_t code) {
string out; string out;
if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33)); 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*94)) out += ((char)((code/94/94)%94+33));
@@ -141,6 +142,8 @@ public:
m_evcd = false; m_evcd = false;
m_scopeEscape = '.'; // Backward compatibility m_scopeEscape = '.'; // Backward compatibility
m_wroteBytes = 0; m_wroteBytes = 0;
m_fd = 0;
m_fullDump = true;
} }
~VerilatedVcd(); ~VerilatedVcd();
+42 -20
View File
@@ -95,9 +95,14 @@ typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
class VerilatedVpioCb : public VerilatedVpio { class VerilatedVpioCb : public VerilatedVpio {
t_cb_data m_cbData; t_cb_data m_cbData;
s_vpi_value m_value;
QData m_time; QData m_time;
public: public:
VerilatedVpioCb(const t_cb_data* cbDatap, QData time) : m_cbData(*cbDatap), m_time(time) {} // cppcheck-suppress uninitVar // m_value
VerilatedVpioCb(const t_cb_data* cbDatap, QData time)
: m_cbData(*cbDatap), m_time(time) {
m_cbData.value = &m_value;
}
virtual ~VerilatedVpioCb() {} virtual ~VerilatedVpioCb() {}
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); } static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
vluint32_t reason() const { return m_cbData.reason; } vluint32_t reason() const { return m_cbData.reason; }
@@ -326,6 +331,7 @@ public:
VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n", VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: value_callback %p %s v[0]=%d\n",
vop,varop->fullname(), *((CData*)newDatap));); vop,varop->fullname(), *((CData*)newDatap)););
memcpy(prevDatap, newDatap, varop->entSize()); memcpy(prevDatap, newDatap, varop->entSize());
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
(vop->cb_rtnp()) (vop->cb_datap()); (vop->cb_rtnp()) (vop->cb_datap());
} }
} }
@@ -735,19 +741,26 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
// I/O routines // I/O routines
//-PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *fileName) { PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
//- _VL_VPI_UNIMP(); return 0; return VL_FOPEN_S(filenamep,"wb");
//-} }
//-PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0; PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
//-} VL_FCLOSE_I(mcd); return 0;
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 cd) { }
//- _VL_VPI_UNIMP(); return 0;
//-} //-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
//-PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *format, ...) {
//- _VL_VPI_UNIMP(); return 0; //- _VL_VPI_UNIMP(); return 0;
//-} //-}
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
va_list ap;
va_start(ap,formatp);
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
va_end(ap);
return chars;
}
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) { PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
va_list ap; va_list ap;
va_start(ap,formatp); va_start(ap,formatp);
@@ -760,15 +773,24 @@ PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
return VL_VPRINTF(formatp, ap); return VL_VPRINTF(formatp, ap);
} }
//-PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) { PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
//- _VL_VPI_UNIMP(); return 0; FILE* fp = VL_CVT_I_FP(mcd);
//-} if (VL_UNLIKELY(!fp)) return 0;
//-PLI_INT32 vpi_flush(void) { int chars = vfprintf(fp, format, ap);
//- _VL_VPI_UNIMP(); return 0; return chars;
//-} }
//-PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
//- _VL_VPI_UNIMP(); return 0; PLI_INT32 vpi_flush(void) {
//-} Verilated::flushCall();
return 0;
}
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
FILE* fp = VL_CVT_I_FP(mcd);
if (VL_UNLIKELY(!fp)) return 1;
fflush(fp);
return 0;
}
// utility routines // utility routines
+12
View File
@@ -221,6 +221,18 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long #define VL_BITBIT_I(bit) ((bit)&VL_SIZEBITS_I) ///< Bit number for a bit in a long
#define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad #define VL_BITBIT_Q(bit) ((bit)&VL_SIZEBITS_Q) ///< Bit number for a bit in a quad
//=========================================================================
// Floating point
// #defines, to avoid requiring math.h on all compile runs
#ifdef _MSC_VER
# define VL_TRUNC(n) (((n)<0) ? ceil((n)) : floor((n)))
# define VL_ROUND(n) (((n)<0) ? ceil((n)-0.5) : floor((n)+0.5))
#else
# define VL_TRUNC(n) trunc(n)
# define VL_ROUND(n) round(n)
#endif
//========================================================================= //=========================================================================
#endif /*guard*/ #endif /*guard*/
+6 -5
View File
@@ -207,10 +207,10 @@ viewers let us know; ZGRViewer isn't great for large graphs.
Tree files are dumps of the AST Tree and are produced between every major Tree files are dumps of the AST Tree and are produced between every major
algorithmic stage. An example: algorithmic stage. An example:
NETLIST 0x90fb00 <e1> {0} w0 NETLIST 0x90fb00 <e1> {a0} w0
1: MODULE 0x912b20 <e8822> {8} w0 top L2 [P] 1: MODULE 0x912b20 <e8822> {a8} w0 top L2 [P]
*1:2: VAR 0x91a780 <e74#> {22} w70 out_wide [O] WIRE *1:2: VAR 0x91a780 <e74#> {a22} w70 out_wide [O] WIRE
1:2:1: BASICDTYPE 0x91a3c0 <e73> {22} w70 [logic] 1:2:1: BASICDTYPE 0x91a3c0 <e73> {a22} w70 [logic]
=over 4 =over 4
@@ -224,7 +224,8 @@ algorithmic stage. An example:
this node. A trailing # indicates this node changed since the last tree this node. A trailing # indicates this node changed since the last tree
dump was made. You can gdb break on this edit; see below. dump was made. You can gdb break on this edit; see below.
"{22}" indicates this node is related to line 22 in the source. "{a22}" indicates this node is related to line 22 in the source filename
"a", where "a" is the first file read, "z" the 36th, and "aa" the 37th.
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits. "w70" indicates the width is 70 bits. sw70 would be signed 70 bits.
+1 -1
View File
@@ -38,7 +38,7 @@ cwrite ("graph_export.cpp");
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
+1 -1
View File
@@ -43,7 +43,7 @@ dotwrite();
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
+55 -11
View File
@@ -12,12 +12,15 @@ use vars qw ($Debug);
#====================================================================== #======================================================================
# main # main
our $Opt_Stage = 0;
autoflush STDOUT 1; autoflush STDOUT 1;
autoflush STDERR 1; autoflush STDERR 1;
Getopt::Long::config ("no_auto_abbrev"); Getopt::Long::config ("no_auto_abbrev");
if (! GetOptions ( if (! GetOptions (
"debug" => sub { $Debug = 1; }, "debug" => sub { $Debug = 1; },
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; }, "<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
"stage=i" => \$Opt_Stage,
)) { )) {
die "%Error: Bad usage, try 'install_test --help'\n"; die "%Error: Bad usage, try 'install_test --help'\n";
} }
@@ -37,8 +40,10 @@ sub test {
my $srcdir = getcwd(); my $srcdir = getcwd();
my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld"; my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld";
my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix"; my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix";
my $testdir = $srcdir."/test_regress/obj_dir/install_test_test"; my $testdirp= $srcdir."/test_regress/obj_dir/install_test_testp";
if (1) { my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn";
if ($Opt_Stage <= 0) {
run("/bin/rm -rf $blddir"); run("/bin/rm -rf $blddir");
run("/bin/mkdir -p $blddir"); run("/bin/mkdir -p $blddir");
run("cd $blddir && $srcdir/configure --prefix $prefix"); run("cd $blddir && $srcdir/configure --prefix $prefix");
@@ -46,24 +51,63 @@ sub test {
} }
# Install it under the prefix # Install it under the prefix
if (1) { if ($Opt_Stage <= 1) {
run("/bin/rm -rf $prefix"); run("/bin/rm -rf $prefix");
run("/bin/mkdir -p $prefix"); run("/bin/mkdir -p $prefix");
run("cd $blddir && make install"); run("cd $blddir && make install");
run("test -e $prefix/share/man/man1/verilator.1");
run("test -e $prefix/share/verilator/examples/test_c/Makefile");
run("test -e $prefix/share/verilator/include/verilated.h");
run("test -e $prefix/bin/verilator");
run("test -e $prefix/bin/verilator_bin");
run("test -e $prefix/bin/verilator_bin_dbg");
run("test -e $prefix/bin/verilator_profcfunc");
} }
# Run a test using just the path # Run a test using just the path
if (1) { if ($Opt_Stage <= 2) {
run("/bin/rm -rf $testdir"); my $dir = $testdirp;
run("/bin/mkdir -p $testdir"); run("/bin/rm -rf $dir");
run("/bin/mkdir -p $dir");
my $bin1 = $prefix."/bin"; my $bin1 = $prefix."/bin";
my $bin2 = $prefix."/share/bin"; my $bin2 = $prefix."/share/bin";
IO::File->new(">$testdir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); end endmodule'."\n"); write_verilog($dir);
run("cd $testdir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v"); run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp");
run("cd $testdir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk"); run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
#Need .c file, and --exe for this to work run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
#run("cd $testdir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
} }
# Run a test using exact path to binary
if ($Opt_Stage <= 3) {
my $dir = $testdirn;
run("/bin/rm -rf $dir");
run("/bin/mkdir -p $dir");
write_verilog($dir);
my $bin1 = $prefix."/bin";
my $bin2 = $prefix."/share/bin";
run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp");
run("cd $dir/obj_dir && make -f Vfoo.mk");
run("cd $dir/obj_dir && ./Vfoo");
}
}
sub write_verilog {
my $dir = shift;
IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n");
my $fh = IO::File->new(">$dir/foo.cpp");
$fh->print('#include "Vfoo.h"' ,"\n");
$fh->print('unsigned int main_time = 0;' ,"\n");
$fh->print('double sc_time_stamp () {' ,"\n");
$fh->print(' return main_time;' ,"\n");
$fh->print('}' ,"\n");
$fh->print('int main() {' ,"\n");
$fh->print(' Vfoo *top = new Vfoo;' ,"\n");
$fh->print(' while (!Verilated::gotFinish()) {',"\n");
$fh->print(' top->eval();' ,"\n");
$fh->print(' main_time++;' ,"\n");
$fh->print(' }' ,"\n");
$fh->print(' top->final();' ,"\n");
$fh->print('}' ,"\n");
} }
sub cleanenv { sub cleanenv {
+2 -2
View File
@@ -40,7 +40,7 @@ print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
@@ -256,7 +256,7 @@ sub gentree {
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; }, 'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; }, 'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
'UNARYMIN' => sub { p " -";p1; }, 'NEGATE' => sub { p " -";p1; },
'VAR' => sub { p_var(); }, 'VAR' => sub { p_var(); },
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; }, 'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
'VARREF' => sub { a1; }, 'VARREF' => sub { a1; },
+7
View File
@@ -91,6 +91,10 @@ headers.
=item =item
You will need the C<flex> and C<bison> packages installed.
=item
C<cd> to the Verilator directory containing this README. C<cd> to the Verilator directory containing this README.
=item =item
@@ -147,6 +151,9 @@ most GNU tools support:
unsetenv VERILATOR_ROOT # if your shell is csh unsetenv VERILATOR_ROOT # if your shell is csh
./configure --prefix /opt/verilator-VERSION ./configure --prefix /opt/verilator-VERSION
Then after installing you will need to add /opt/verilator-VERSION/bin to
PATH.
=back =back
=item =item
+13 -24
View File
@@ -24,6 +24,7 @@
srcdir = @srcdir@ srcdir = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
PERL = @PERL@ PERL = @PERL@
EXEEXT = @EXEEXT@
#### End of system configuration section. #### #### End of system configuration section. ####
@@ -32,25 +33,11 @@ default: dbg opt
debug: dbg debug: dbg
optimize: opt optimize: opt
ifeq ($(OBJCACHE_HOSTS),)
ifneq ($(SLCHOOSED_HOST),)
ifeq ($(VERILATOR_AUTHOR_SITE),1)
export OBJCACHE_HOSTS := $(shell rschedule --no-allow-reserved --similar hostnames)
endif
endif
endif
ifeq ($(OBJCACHE_JOBS),)
ifneq ($(OBJCACHE_HOSTS),)
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
endif
endif
ifneq ($(words $(CURDIR)),1) ifneq ($(words $(CURDIR)),1)
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)') $(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
endif endif
UNDER_GIT = $(wildcard ../.git/logs/HEAD) UNDER_GIT = $(wildcard ${srcdir}/../.git/logs/HEAD)
#********************************************************************* #*********************************************************************
@@ -65,26 +52,25 @@ opt: ../verilator_bin
ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build
../verilator_bin: ../verilator_bin_dbg ../verilator_bin: ../verilator_bin_dbg
-rm -rf $@ $@.exe -rm -rf $@ $@.exe
-cp -p $< $@ -cp -p $<$(EXEEXT) $@$(EXEEXT)
-cp -p $<.exe $@.exe
else else
../verilator_bin: obj_opt prefiles ../verilator_bin: obj_opt prefiles
cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial
cd obj_opt && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ -f ../Makefile_obj cd obj_opt && $(MAKE) TGT=../$@ -f ../Makefile_obj
endif endif
dbg: ../verilator_bin_dbg dbg: ../verilator_bin_dbg
../verilator_bin_dbg: obj_dbg prefiles ../verilator_bin_dbg: obj_dbg prefiles
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial
cd obj_dbg && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
prefiles:: prefiles::
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
prefiles:: config_rev.h prefiles:: config_rev.h
# This output goes into srcdir, as we need to distribute it as part of the kit. # This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
config_rev.h: config_rev.pl ../.git/logs/HEAD config_rev.h: ${srcdir}/config_rev.pl ${srcdir}/../.git/logs/HEAD
$(PERL) config_rev.pl . >$@ $(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
endif endif
maintainer-copy:: maintainer-copy::
@@ -96,3 +82,6 @@ clean mostlyclean distclean maintainer-clean::
distclean maintainer-clean:: distclean maintainer-clean::
-rm -f Makefile Makefile_obj config_build.h -rm -f Makefile Makefile_obj config_build.h
maintainer-clean::
-rm -f config_rev.h
+14 -14
View File
@@ -57,9 +57,11 @@ datarootdir = @datarootdir@
pkgdatadir = @pkgdatadir@ pkgdatadir = @pkgdatadir@
# Compile options # Compile options
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@ CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
CPPFLAGSNOWALL += @CPPFLAGS@ CPPFLAGS += @CPPFLAGS@
LDFLAGS += @LDFLAGS@ LDFLAGS += @LDFLAGS@
EXEEXT = @EXEEXT@
#### End of system configuration section. #### #### End of system configuration section. ####
@@ -85,17 +87,18 @@ endif
# -lfl not needed as Flex invoked with %nowrap option # -lfl not needed as Flex invoked with %nowrap option
LIBS = -lm LIBS = -lm
CPPFLAGSNOWALL += -MMD CPPFLAGS += -MMD
CPPFLAGSNOWALL += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir) CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages CPPFLAGS += -DYYDEBUG # Required to get nice error messages
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool #CPPFLAGS += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
CPPFLAGSNOWALL += $(COPT) CPPFLAGS += $(COPT)
CPPFLAGS = $(CPPFLAGSNOWALL) CPPFLAGS += -MP # Only works on recent GCC versions
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
CPPFLAGSNOWALL += -MP # Only works on recent GCC versions
CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
#CPPFLAGS += -pedantic-errors #CPPFLAGS += -pedantic-errors
endif endif
CPPFLAGSWALL = $(CPPFLAGS)
CPPFLAGSNOWALL = $(CPPFLAGS) -Wno-unused
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
@@ -209,7 +212,6 @@ RAW_OBJS = \
V3PreShell.o \ V3PreShell.o \
V3Premit.o \ V3Premit.o \
V3Scope.o \ V3Scope.o \
V3Signed.o \
V3Slice.o \ V3Slice.o \
V3Split.o \ V3Split.o \
V3SplitAs.o \ V3SplitAs.o \
@@ -251,8 +253,6 @@ $(TGT): V3Ast__gen_classes.h $(OBJS)
@echo " Linking $@..." @echo " Linking $@..."
-rm -rf $@ [email protected] -rm -rf $@ [email protected]
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS} ${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
@-(cp [email protected] $@ || true)
# ok if cp failes on linux, it's there to insure executable works on NT
V3Number_test: V3Number_test.o V3Number_test: V3Number_test.o
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS} ${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
@@ -263,9 +263,9 @@ V3Number_test: V3Number_test.o
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp $(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
%.o: %.cpp %.o: %.cpp
$(OBJCACHE) ${CXX} ${CPPFLAGS} -c $< $(OBJCACHE) ${CXX} ${CPPFLAGSWALL} -c $<
%.o: %.c %.o: %.c
$(OBJCACHE) ${CC} ${CPPFLAGS} -c $< $(OBJCACHE) ${CC} ${CPPFLAGSWALL} -c $<
V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $< $(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
+5 -1
View File
@@ -148,7 +148,11 @@ public:
} }
public: public:
// CONSTUCTORS // CONSTUCTORS
ActiveNamer() {} ActiveNamer() {
m_scopep = NULL;
m_iActivep = NULL;
m_cActivep = NULL;
}
virtual ~ActiveNamer() {} virtual ~ActiveNamer() {}
void main(AstScope* nodep) { void main(AstScope* nodep) {
nodep->accept(*this); nodep->accept(*this);
+5 -5
View File
@@ -184,7 +184,7 @@ private:
} }
if (nodep->fullPragma() || nodep->priorityPragma()) { if (nodep->fullPragma() || nodep->priorityPragma()) {
// Simply need to add a default if there isn't one already // Simply need to add a default if there isn't one already
m_statAsFull++; ++m_statAsFull;
if (!has_default) { if (!has_default) {
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/, nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/,
newFireAssert(nodep, "synthesis full_case, but non-match found"))); newFireAssert(nodep, "synthesis full_case, but non-match found")));
@@ -193,7 +193,7 @@ private:
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) { if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
// Need to check that one, and only one of the case items match at any moment // Need to check that one, and only one of the case items match at any moment
// If there's a default, we allow none to match, else exactly one must match // If there's a default, we allow none to match, else exactly one must match
m_statAsFull++; ++m_statAsFull;
if (!has_default && !nodep->itemsp()) { if (!has_default && !nodep->itemsp()) {
// Not parallel, but harmlessly so. // Not parallel, but harmlessly so.
} else { } else {
@@ -241,18 +241,18 @@ private:
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name()); if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
nodep->stmtsp(), nodep->name()); nodep=NULL; nodep->stmtsp(), nodep->name()); nodep=NULL;
m_statAsCover++; ++m_statAsCover;
} }
virtual void visit(AstPslAssert* nodep, AstNUser*) { virtual void visit(AstPslAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(), newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
NULL, nodep->name()); nodep=NULL; NULL, nodep->name()); nodep=NULL;
m_statAsPsl++; ++m_statAsPsl;
} }
virtual void visit(AstVAssert* nodep, AstNUser*) { virtual void visit(AstVAssert* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
newVAssertion(nodep, nodep->propp()); nodep=NULL; newVAssertion(nodep, nodep->propp()); nodep=NULL;
m_statAsSV++; ++m_statAsSV;
} }
virtual void visit(AstNodeModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep, AstNUser*) {
+6 -4
View File
@@ -74,7 +74,9 @@ void AstNode::init() {
m_clonep = NULL; m_clonep = NULL;
m_cloneCnt = 0; m_cloneCnt = 0;
// Attributes // Attributes
m_signed = false; m_numeric = (int)AstNumeric::UNSIGNED;
m_didWidth = false;
m_doingWidth = false;
m_width = 0; m_width = 0;
m_widthMin = 0; m_widthMin = 0;
m_user1p = NULL; m_user1p = NULL;
@@ -428,7 +430,7 @@ void AstNode::replaceWith(AstNode* newp) {
repHandle.relink(newp); repHandle.relink(newp);
} }
void AstNRelinker::dump(ostream& str) { void AstNRelinker::dump(ostream& str) const {
str<<" BK="<<(uint32_t*)m_backp; str<<" BK="<<(uint32_t*)m_backp;
str<<" ITER="<<(uint32_t*)m_iterpp; str<<" ITER="<<(uint32_t*)m_iterpp;
str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":""); str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":"");
@@ -873,7 +875,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
if (this==NULL || node2p==NULL) return false; if (this==NULL || node2p==NULL) return false;
if (this->type() != node2p->type() if (this->type() != node2p->type()
|| this->width() != node2p->width() || this->width() != node2p->width()
|| this->isSigned() != node2p->isSigned() || this->numeric() != node2p->numeric()
|| !this->same(node2p)) { || !this->same(node2p)) {
return false; return false;
} }
@@ -945,7 +947,7 @@ void AstNode::checkTree() {
} }
} }
void AstNode::dumpPtrs(ostream& os) { void AstNode::dumpPtrs(ostream& os) const {
os<<"This="<<typeName()<<" "<<(void*)this; os<<"This="<<typeName()<<" "<<(void*)this;
os<<" back="<<(void*)backp(); os<<" back="<<(void*)backp();
if (nextp()) os<<" next="<<(void*)nextp(); if (nextp()) os<<" next="<<(void*)nextp();
+85 -27
View File
@@ -27,6 +27,7 @@
#include "V3Error.h" #include "V3Error.h"
#include "V3Number.h" #include "V3Number.h"
#include <vector> #include <vector>
#include <cmath>
#include "V3Ast__gen_classes.h" // From ./astgen #include "V3Ast__gen_classes.h" // From ./astgen
// Things like: // Things like:
@@ -56,9 +57,40 @@ public:
//###################################################################### //######################################################################
class AstNumeric {
public:
enum en {
UNSIGNED,
SIGNED,
DOUBLE
// Limited to 2 bits, unless change V3Ast's packing function
};
enum en m_e;
const char* ascii() const {
static const char* names[] = {
"UNSIGNED","SIGNED","DOUBLE"
};
return names[m_e];
};
inline AstNumeric () : m_e(UNSIGNED) {}
inline AstNumeric (en _e) : m_e(_e) {}
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; }
inline bool isDouble() const { return m_e==DOUBLE; }
inline bool isSigned() const { return m_e==SIGNED; }
inline bool isUnsigned() const { return m_e==UNSIGNED; }
};
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
//######################################################################
class AstPragmaType { class AstPragmaType {
public: public:
enum en { enum en {
ILLEGAL,
COVERAGE_BLOCK_OFF, COVERAGE_BLOCK_OFF,
INLINE_MODULE, INLINE_MODULE,
NO_INLINE_MODULE, NO_INLINE_MODULE,
@@ -67,7 +99,7 @@ public:
PUBLIC_TASK PUBLIC_TASK
}; };
enum en m_e; enum en m_e;
inline AstPragmaType () {} inline AstPragmaType () : m_e(ILLEGAL) {}
inline AstPragmaType (en _e) : m_e(_e) {} inline AstPragmaType (en _e) : m_e(_e) {}
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -90,7 +122,7 @@ public:
TRACE_CHANGE_SUB TRACE_CHANGE_SUB
}; };
enum en m_e; enum en m_e;
inline AstCFuncType () {} inline AstCFuncType () : m_e(FT_NORMAL) {}
inline AstCFuncType (en _e) : m_e(_e) {} inline AstCFuncType (en _e) : m_e(_e) {}
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -158,7 +190,7 @@ public:
}; };
return names[m_e]; return names[m_e];
}; };
inline AstEdgeType () {} inline AstEdgeType () : m_e(ET_ILLEGAL) {}
inline AstEdgeType (en _e) : m_e(_e) {} inline AstEdgeType (en _e) : m_e(_e) {}
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -172,6 +204,7 @@ public:
class AstAttrType { class AstAttrType {
public: public:
enum en { enum en {
ILLEGAL,
EXPR_BITS, // V3Const converts to constant EXPR_BITS, // V3Const converts to constant
// //
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
@@ -182,19 +215,20 @@ public:
VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat
}; };
enum en m_e; enum en m_e;
const char* ascii() const { const char* ascii() const {
static const char* names[] = { static const char* names[] = {
"EXPR_BITS", "VAR_BASE", "%E-AT", "EXPR_BITS", "VAR_BASE",
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW", "VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SFORMAT" "VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
}; };
return names[m_e]; return names[m_e];
}; };
inline AstAttrType () {} inline AstAttrType () : m_e(ILLEGAL) {}
inline AstAttrType (en _e) : m_e(_e) {} inline AstAttrType (en _e) : m_e(_e) {}
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -208,8 +242,9 @@ public:
class AstBasicDTypeKwd { class AstBasicDTypeKwd {
public: public:
enum en { enum en {
UNKNOWN,
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT, BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
REAL, REALTIME, SHORTINT, SHORTREAL, TIME, DOUBLE, SHORTINT, FLOAT, TIME,
// Closer to a class type, but limited usage // Closer to a class type, but limited usage
STRING, STRING,
// Internal types for mid-steps // Internal types for mid-steps
@@ -220,8 +255,9 @@ public:
enum en m_e; enum en m_e;
const char* ascii() const { const char* ascii() const {
static const char* names[] = { static const char* names[] = {
"%E-unk",
"bit", "byte", "chandle", "int", "integer", "logic", "longint", "bit", "byte", "chandle", "int", "integer", "logic", "longint",
"real", "realtime", "shortint", "shortreal", "time", "real", "shortint", "shortreal", "time",
"string", "string",
"VerilatedScope*", "char*", "VerilatedScope*", "char*",
"LOGIC_IMPLICIT" "LOGIC_IMPLICIT"
@@ -230,15 +266,16 @@ public:
}; };
const char* dpiType() const { const char* dpiType() const {
static const char* names[] = { static const char* names[] = {
"%E-unk",
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long", "unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
"double", "double", "short int", "float", "long long", "double", "short int", "float", "long long",
"const char*", "const char*",
"dpiScope", "const char*", "dpiScope", "const char*",
"" ""
}; };
return names[m_e]; return names[m_e];
}; };
inline AstBasicDTypeKwd () {} inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
inline AstBasicDTypeKwd (en _e) : m_e(_e) {} inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -251,6 +288,8 @@ public:
case INTEGER: return 32; case INTEGER: return 32;
case LOGIC: return 1; case LOGIC: return 1;
case LONGINT: return 64; case LONGINT: return 64;
case DOUBLE: return 64;
case FLOAT: return 32;
case SHORTINT: return 16; case SHORTINT: return 16;
case TIME: return 64; case TIME: return 64;
case STRING: return 64; // Just the pointer, for today case STRING: return 64; // Just the pointer, for today
@@ -265,7 +304,7 @@ public:
} }
bool isZeroInit() const { // Otherwise initializes to X bool isZeroInit() const { // Otherwise initializes to X
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|| m_e==STRING); || m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
} }
bool isSloppy() const { // Don't be as anal about width warnings bool isSloppy() const { // Don't be as anal about width warnings
return !(m_e==LOGIC || m_e==BIT); return !(m_e==LOGIC || m_e==BIT);
@@ -274,10 +313,13 @@ public:
return (m_e==LOGIC || m_e==BIT); return (m_e==LOGIC || m_e==BIT);
} }
bool isDpiUnsupported() const { bool isDpiUnsupported() const {
return (m_e==LOGIC || m_e==TIME || m_e==REALTIME); return (m_e==LOGIC || m_e==TIME);
} }
bool isOpaque() const { // IE not a simple number we can bit optimize bool isOpaque() const { // IE not a simple number we can bit optimize
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR); return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
}
bool isDouble() const {
return (m_e==DOUBLE);
} }
}; };
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); } inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
@@ -316,7 +358,7 @@ public:
XTEMP XTEMP
}; };
enum en m_e; enum en m_e;
inline AstVarType () {} inline AstVarType () : m_e(UNKNOWN) {}
inline AstVarType (en _e) : m_e(_e) {} inline AstVarType (en _e) : m_e(_e) {}
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -374,7 +416,7 @@ public:
CT_CASEZ CT_CASEZ
}; };
enum en m_e; enum en m_e;
inline AstCaseType () {} inline AstCaseType () : m_e(CT_CASE) {}
inline AstCaseType (en _e) : m_e(_e) {} inline AstCaseType (en _e) : m_e(_e) {}
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -396,7 +438,7 @@ public:
DT_FATAL DT_FATAL
}; };
enum en m_e; enum en m_e;
inline AstDisplayType () {} inline AstDisplayType () : m_e(DT_DISPLAY) {}
inline AstDisplayType (en _e) : m_e(_e) {} inline AstDisplayType (en _e) : m_e(_e) {}
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
@@ -606,7 +648,7 @@ public:
AstNRelinker() { m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;} AstNRelinker() { m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
void relink(AstNode* newp); void relink(AstNode* newp);
AstNode* oldp() const { return m_oldp; } AstNode* oldp() const { return m_oldp; }
void dump(ostream& str=cout); void dump(ostream& str=cout) const;
}; };
inline ostream& operator<<(ostream& os, AstNRelinker& rhs) { rhs.dump(os); return os;} inline ostream& operator<<(ostream& os, AstNRelinker& rhs) { rhs.dump(os); return os;}
@@ -684,7 +726,9 @@ class AstNode {
static int s_cloneCntGbl; // Count of which userp is set static int s_cloneCntGbl; // Count of which userp is set
// Attributes // Attributes
bool m_signed:1; // Node is signed uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
bool m_didWidth:1; // Did V3Width computation
bool m_doingWidth:1; // Inside V3Width
// // Space for more bools here // // Space for more bools here
int m_width; // Bit width of operation int m_width; // Bit width of operation
@@ -717,6 +761,7 @@ class AstNode {
void deleteTreeIter(); void deleteTreeIter();
void deleteNode(); void deleteNode();
static void relinkOneLink(AstNode*& pointpr, AstNode* newp); static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
// cppcheck-suppress functionConst
void debugTreeChange(const char* prefix, int lineno, bool next); void debugTreeChange(const char* prefix, int lineno, bool next);
protected: protected:
@@ -780,6 +825,9 @@ public:
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do triganomics
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
@@ -807,10 +855,18 @@ public:
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; } bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
void width(int width, int sized) { m_width=width; m_widthMin=sized; } void width(int width, int sized) { m_width=width; m_widthMin=sized; }
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }} void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); signedFrom(fromp); } void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
void signedFrom(AstNode* fromp) { if (fromp) { m_signed=fromp->m_signed; }} void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
void isSigned(bool flag) { m_signed=flag; } void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
bool isSigned() const { return m_signed; } AstNumeric numeric() const { return AstNumeric(m_numeric); }
bool isDouble() const { return numeric().isDouble(); }
bool isSigned() const { return numeric().isSigned(); }
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
bool isUnsigned() const { return numeric().isUnsigned(); }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
void doingWidth(bool flag) { m_doingWidth=flag; }
bool doingWidth() const { return m_doingWidth; }
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); } bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
bool isWide() const { return (width()>VL_QUADSIZE); } bool isWide() const { return (width()>VL_QUADSIZE); }
@@ -898,7 +954,7 @@ public:
bool sameTree(AstNode* node2p); // Does tree of this == node2p? bool sameTree(AstNode* node2p); // Does tree of this == node2p?
void deleteTree(); // Always deletes the next link void deleteTree(); // Always deletes the next link
void checkTree(); // User Interface version void checkTree(); // User Interface version
void dumpPtrs(ostream& str=cout); void dumpPtrs(ostream& str=cout) const;
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0); void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0); void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0);
void dumpTreeFile(const string& filename, bool append=false); void dumpTreeFile(const string& filename, bool append=false);
@@ -965,6 +1021,7 @@ struct AstNodeTermop : public AstNodeMath {
ASTNODE_BASE_FUNCS(NodeTermop) ASTNODE_BASE_FUNCS(NodeTermop)
// Know no children, and hot function, so skip iterator for speed // Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children // See checkTreeIter also that asserts no children
// cppcheck-suppress functionConst
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
}; };
@@ -981,6 +1038,8 @@ struct AstNodeUniop : public AstNodeMath {
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
virtual bool cleanLhs() = 0; virtual bool cleanLhs() = 0;
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
virtual int instrCount() const { return widthInstrs(); } virtual int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
@@ -1003,6 +1062,7 @@ struct AstNodeBiop : public AstNodeMath {
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors? virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
virtual int instrCount() const { return widthInstrs(); } virtual int instrCount() const { return widthInstrs(); }
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode*) const { return true; } virtual bool same(AstNode*) const { return true; }
@@ -1224,6 +1284,7 @@ public:
void packagep(AstPackage* nodep) { m_packagep=nodep; } void packagep(AstPackage* nodep) { m_packagep=nodep; }
// Know no children, and hot function, so skip iterator for speed // Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children // See checkTreeIter also that asserts no children
// cppcheck-suppress functionConst
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { } void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
}; };
@@ -1275,7 +1336,6 @@ private:
string m_name; // Name of task string m_name; // Name of task
string m_cname; // Name of task if DPI import string m_cname; // Name of task if DPI import
bool m_taskPublic:1; // Public task bool m_taskPublic:1; // Public task
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_attrIsolateAssign:1;// User isolate_assignments attribute bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_prototype:1; // Just a prototype bool m_prototype:1; // Just a prototype
bool m_dpiExport:1; // DPI exported bool m_dpiExport:1; // DPI exported
@@ -1286,7 +1346,7 @@ private:
public: public:
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp) AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
: AstNode(fileline) : AstNode(fileline)
, m_name(name), m_taskPublic(false), m_didSigning(false) , m_name(name), m_taskPublic(false)
, m_attrIsolateAssign(false), m_prototype(false) , m_attrIsolateAssign(false), m_prototype(false)
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false) , m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
, m_dpiTask(false), m_pure(false) { , m_dpiTask(false), m_pure(false) {
@@ -1313,8 +1373,6 @@ public:
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); } void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
void taskPublic(bool flag) { m_taskPublic=flag; } void taskPublic(bool flag) { m_taskPublic=flag; }
bool taskPublic() const { return m_taskPublic; } bool taskPublic() const { return m_taskPublic; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
bool attrIsolateAssign() const { return m_attrIsolateAssign; } bool attrIsolateAssign() const { return m_attrIsolateAssign; }
void prototype(bool flag) { m_prototype = flag; } void prototype(bool flag) { m_prototype = flag; }
+11 -5
View File
@@ -70,7 +70,7 @@ bool AstVar::isScQuad() const {
} }
bool AstVar::isScBv() const { bool AstVar::isScBv() const {
return (isSc() && width() >= v3Global.opt.pinsBv()); return ((isSc() && width() >= v3Global.opt.pinsBv()) || m_attrScBv);
} }
void AstVar::combineType(AstVarType type) { void AstVar::combineType(AstVarType type) {
@@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
arg += "const char*"; arg += "const char*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) { } else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
arg += "const VerilatedScope*"; arg += "const VerilatedScope*";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
arg += "double";
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
arg += "float";
} else if (strtype) { } else if (strtype) {
if (isInOnly()) arg += "const "; if (isInOnly()) arg += "const ";
arg += "string"; arg += "string";
@@ -185,7 +189,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
} else if (isWide()) { } else if (isWide()) {
arg += "uint32_t"; // []'s added later arg += "uint32_t"; // []'s added later
} else { } else {
arg += "uint64_t"; arg += "vluint64_t";
} }
if (isWide()) { if (isWide()) {
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead"); if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
@@ -237,7 +241,7 @@ string AstVar::scType() const {
return "uint32_t"; return "uint32_t";
} }
} else { } else {
return "uint64_t"; return "vluint64_t";
} }
} }
@@ -497,8 +501,9 @@ void AstNode::dump(ostream& os) {
//<<" "<<(void*)this->m_backp //<<" "<<(void*)this->m_backp
<<" <e"<<dec<<editCount() <<" <e"<<dec<<editCount()
<<((editCount()>=editCountLast())?"#>":">") <<((editCount()>=editCountLast())?"#>":">")
<<" {"<<dec<<fileline()->lineno()<<"}" <<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
<<" "<<(isSigned()?"s":"") <<" "<<(isSigned()?"s":"")
<<(isDouble()?"d":"")
<<"w"<<(widthSized()?"":"u")<<width(); <<"w"<<(widthSized()?"":"u")<<width();
if (!widthSized()) os<<"/"<<widthMin(); if (!widthSized()) os<<"/"<<widthMin();
if (name()!="") os<<" "<<AstNode::quoteName(name()); if (name()!="") os<<" "<<AstNode::quoteName(name());
@@ -608,7 +613,8 @@ void AstVar::dump(ostream& str) {
else if (isInput()) str<<" [I]"; else if (isInput()) str<<" [I]";
else if (isOutput()) str<<" [O]"; else if (isOutput()) str<<" [O]";
} }
if (isUsedClock()) str<<" [C]"; if (isConst()) str<<" [CONST]";
if (isUsedClock()) str<<" [CLK]";
if (isSigPublic()) str<<" [P]"; if (isSigPublic()) str<<" [P]";
if (isUsedLoopIdx()) str<<" [LOOP]"; if (isUsedLoopIdx()) str<<" [LOOP]";
if (attrClockEn()) str<<" [aCLKEN]"; if (attrClockEn()) str<<" [aCLKEN]";
+435 -49
View File
@@ -46,19 +46,25 @@ struct AstConst : public AstNodeMath {
private: private:
V3Number m_num; // Constant value V3Number m_num; // Constant value
public: public:
class Unsized32 {}; // for creator type-overload selection
AstConst(FileLine* fl, const V3Number& num) AstConst(FileLine* fl, const V3Number& num)
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(num) { ,m_num(num) {
width(m_num.width(), m_num.sized()?0:m_num.minWidth()); width(m_num.width(), m_num.sized()?0:m_num.minWidth());
isSigned(m_num.isSigned()); numeric(m_num.isDouble() ? AstNumeric::DOUBLE
: m_num.isSigned() ? AstNumeric::SIGNED
: AstNumeric::UNSIGNED);
} }
AstConst(FileLine* fl, uint32_t num) AstConst(FileLine* fl, uint32_t num)
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.minWidth()); } ,m_num(V3Number(fl,32,num)) { width(m_num.width(), m_num.sized()?0:m_num.minWidth()); }
class Unsized32 {}; // for creator type-overload selection
AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value AstConst(FileLine* fl, Unsized32, uint32_t num) // Unsized 32-bit integer of specified value
:AstNodeMath(fl) :AstNodeMath(fl)
,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.minWidth()); } ,m_num(V3Number(fl,32,num)) { m_num.width(32,false); width(32,m_num.minWidth()); }
class RealDouble {}; // for creator type-overload selection
AstConst(FileLine* fl, RealDouble, double num)
:AstNodeMath(fl)
,m_num(V3Number(fl,64)) { m_num.setDouble(num); numeric(AstNumeric::DOUBLE); }
class LogicFalse {}; class LogicFalse {};
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1 AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
:AstNodeMath(fl) :AstNodeMath(fl)
@@ -258,7 +264,8 @@ private:
m_keyword = AstBasicDTypeKwd::LOGIC; m_keyword = AstBasicDTypeKwd::LOGIC;
} }
if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED; if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED;
setSignedState(signst); if (keyword().isDouble()) numeric(AstNumeric::DOUBLE);
else setSignedState(signst);
if (!rangep) { // Set based on keyword properties if (!rangep) { // Set based on keyword properties
// V3Width will pull from this width // V3Width will pull from this width
if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0); if (keyword().width() > 1 && !isOpaque()) rangep = new AstRange(fileline(), keyword().width()-1, 0);
@@ -278,7 +285,8 @@ public:
AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable AstRange* rangep() const { return op1p()->castRange(); } // op1 = Range of variable
void rangep(AstRange* nodep) { setNOp1p(nodep); } void rangep(AstRange* nodep) { setNOp1p(nodep); }
void setSignedState(AstSignedState signst) { void setSignedState(AstSignedState signst) {
if (signst!=signedst_NOP) isSigned(signst==signedst_SIGNED); if (signst==signedst_UNSIGNED) numeric(AstNumeric::UNSIGNED);
else if (signst==signedst_SIGNED) numeric(AstNumeric::SIGNED);
} }
// METHODS // METHODS
virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } // (Slow) recurse down to find basic data type
@@ -300,6 +308,25 @@ public:
void implicit(bool flag) { m_implicit = flag; } void implicit(bool flag) { m_implicit = flag; }
}; };
struct AstConstDType : public AstNodeDType {
// const data type, ie "const some_dtype var_name [2:0]"
// ConstDType are removed in V3LinkLValue and become AstVar::isConst.
// When more generic types are supported AstConstDType will be propagated further.
AstConstDType(FileLine* fl, AstNodeDType* dtypep)
: AstNodeDType(fl) {
setOp1p(dtypep);
widthSignedFrom(dtypep);
}
ASTNODE_NODE_FUNCS(ConstDType, CONSTDTYPE)
AstNodeDType* dtypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
void dtypep(AstNodeDType* nodep) { setOp1p(nodep); }
// METHODS
virtual AstBasicDType* basicp() const { return dtypep()->basicp(); } // (Slow) recurse down to find basic data type
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
};
struct AstRefDType : public AstNodeDType { struct AstRefDType : public AstNodeDType {
private: private:
AstTypedef* m_defp; AstTypedef* m_defp;
@@ -434,10 +461,10 @@ public:
virtual V3Hash sameHash() const { return V3Hash(); } virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; } virtual bool same(AstNode* samep) const { return true; }
virtual int instrCount() const { return widthInstrs(); } virtual int instrCount() const { return widthInstrs(); }
unsigned length() { return m_length; } unsigned length() const { return m_length; }
void length(unsigned length) { m_length = length; } void length(unsigned length) { m_length = length; }
void start(unsigned start) { m_start = start; } void start(unsigned start) { m_start = start; }
unsigned start() { return m_start; } unsigned start() const { return m_start; }
// Special operators // Special operators
static int dimension(AstNode* nodep); ///< How many dimensions is this reference from the base variable? static int dimension(AstNode* nodep); ///< How many dimensions is this reference from the base variable?
static AstNode* baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences? static AstNode* baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences?
@@ -560,10 +587,9 @@ private:
bool m_funcLocal:1; // Local variable for a function bool m_funcLocal:1; // Local variable for a function
bool m_funcReturn:1; // Return variable for a function bool m_funcReturn:1; // Return variable for a function
bool m_attrClockEn:1;// User clock enable attribute bool m_attrClockEn:1;// User clock enable attribute
bool m_attrScBv:1; // User force bit vector attribute
bool m_attrIsolateAssign:1;// User isolate_assignments attribute bool m_attrIsolateAssign:1;// User isolate_assignments attribute
bool m_attrSFormat:1;// User sformat attribute bool m_attrSFormat:1;// User sformat attribute
bool m_didSigning:1; // V3Signed completed; can skip iteration
bool m_didWidth:1; // V3Width completed; can skip iteration
bool m_fileDescr:1; // File descriptor bool m_fileDescr:1; // File descriptor
bool m_isConst:1; // Table contains constant data bool m_isConst:1; // Table contains constant data
bool m_isStatic:1; // Static variable bool m_isStatic:1; // Static variable
@@ -576,8 +602,7 @@ private:
m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false; m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false;
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false; m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
m_funcLocal=false; m_funcReturn=false; m_funcLocal=false; m_funcReturn=false;
m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false; m_attrClockEn=false; m_attrScBv=false; m_attrIsolateAssign=false; m_attrSFormat=false;
m_didSigning=false; m_didWidth=false;
m_fileDescr=false; m_isConst=false; m_isStatic=false; m_fileDescr=false; m_isConst=false; m_isStatic=false;
m_trace=false; m_trace=false;
} }
@@ -588,6 +613,7 @@ public:
init(); init();
combineType(type); setOp1p(dtypep); combineType(type); setOp1p(dtypep);
if (dtypep && dtypep->basicp()) { if (dtypep && dtypep->basicp()) {
numericFrom(dtypep);
width(dtypep->basicp()->width(), 0); width(dtypep->basicp()->width(), 0);
} else width(1, 0); } else width(1, 0);
} }
@@ -607,6 +633,7 @@ public:
if (examplep->dtypep()) { if (examplep->dtypep()) {
setOp1p(examplep->dtypep()->cloneTree(true)); setOp1p(examplep->dtypep()->cloneTree(true));
} }
numericFrom(examplep);
width(examplep->width(), examplep->widthMin()); width(examplep->width(), examplep->widthMin());
} }
ASTNODE_NODE_FUNCS(Var, VAR) ASTNODE_NODE_FUNCS(Var, VAR)
@@ -638,12 +665,9 @@ public:
void attrClockEn(bool flag) { m_attrClockEn = flag; } void attrClockEn(bool flag) { m_attrClockEn = flag; }
void attrFileDescr(bool flag) { m_fileDescr = flag; } void attrFileDescr(bool flag) { m_fileDescr = flag; }
void attrScClocked(bool flag) { m_scClocked = flag; } void attrScClocked(bool flag) { m_scClocked = flag; }
void attrScBv(bool flag) { m_attrScBv = flag; }
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
void attrSFormat(bool flag) { m_attrSFormat = flag; } void attrSFormat(bool flag) { m_attrSFormat = flag; }
void didSigning(bool flag) { m_didSigning=flag; }
bool didSigning() const { return m_didSigning; }
void didWidth(bool flag) { m_didWidth=flag; }
bool didWidth() const { return m_didWidth; }
void usedClock(bool flag) { m_usedClock = flag; } void usedClock(bool flag) { m_usedClock = flag; }
void usedParam(bool flag) { m_usedParam = flag; } void usedParam(bool flag) { m_usedParam = flag; }
void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; } void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
@@ -677,7 +701,7 @@ public:
bool isToggleCoverable() const { return ((isIO() || isSignal()) bool isToggleCoverable() const { return ((isIO() || isSignal())
&& (isIO() || isBitLogic()) && (isIO() || isBitLogic())
// Wrapper would otherwise duplicate wrapped module's coverage // Wrapper would otherwise duplicate wrapped module's coverage
&& !isSc() && !isPrimaryIO()); } && !isSc() && !isPrimaryIO() && !isConst()); }
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); } bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); } bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); }
bool isPure() const { return (varType()==AstVarType::XTEMP); } bool isPure() const { return (varType()==AstVarType::XTEMP); }
@@ -702,6 +726,7 @@ public:
bool isFuncLocal() const { return m_funcLocal; } bool isFuncLocal() const { return m_funcLocal; }
bool isFuncReturn() const { return m_funcReturn; } bool isFuncReturn() const { return m_funcReturn; }
bool attrClockEn() const { return m_attrClockEn; } bool attrClockEn() const { return m_attrClockEn; }
bool attrScBv() const { return m_attrScBv; }
bool attrFileDescr() const { return m_fileDescr; } bool attrFileDescr() const { return m_fileDescr; }
bool attrScClocked() const { return m_scClocked; } bool attrScClocked() const { return m_scClocked; }
bool attrSFormat() const { return m_attrSFormat; } bool attrSFormat() const { return m_attrSFormat; }
@@ -948,6 +973,14 @@ struct AstModule : public AstNodeModule {
virtual string verilogKwd() const { return "module"; } virtual string verilogKwd() const { return "module"; }
}; };
struct AstNotFoundModule : public AstNodeModule {
// A missing module declaration
AstNotFoundModule(FileLine* fl, const string& name)
: AstNodeModule (fl,name) {}
ASTNODE_NODE_FUNCS(NotFoundModule, NOTFOUNDMODULE)
virtual string verilogKwd() const { return "/*not-found-*/ module"; }
};
struct AstPackage : public AstNodeModule { struct AstPackage : public AstNodeModule {
// A package declaration // A package declaration
AstPackage(FileLine* fl, const string& name) AstPackage(FileLine* fl, const string& name)
@@ -1605,7 +1638,7 @@ public:
void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; } void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; }
}; };
class AstSFormatF : public AstNode { struct AstSFormatF : public AstNode {
// Convert format to string, generally under a AstDisplay or AstSFormat // Convert format to string, generally under a AstDisplay or AstSFormat
// Also used as "real" function for /*verilator sformat*/ functions // Also used as "real" function for /*verilator sformat*/ functions
string m_text; string m_text;
@@ -1862,6 +1895,45 @@ public:
AstNode* msbp() const { return op4p()->castNode(); } AstNode* msbp() const { return op4p()->castNode(); }
}; };
struct AstSystemT : public AstNodeStmt {
// $system used as task
AstSystemT(FileLine* fileline, AstNode* lhsp)
: AstNodeStmt (fileline) {
setOp1p(lhsp);
}
ASTNODE_NODE_FUNCS(SystemT, SYSTEMT)
virtual string verilogKwd() const { return "$system"; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isSplittable() const { return false; }
virtual bool isOutputter() const { return true; }
virtual bool isUnlikely() const { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
AstNode* lhsp() const { return op1p(); }
};
struct AstSystemF : public AstNodeMath {
// $system used as function
AstSystemF(FileLine* fileline, AstNode* lhsp)
: AstNodeMath (fileline) {
setOp1p(lhsp);
}
ASTNODE_NODE_FUNCS(SystemF, SYSTEMF)
virtual string verilogKwd() const { return "$system"; }
virtual string emitVerilog() { return verilogKwd(); }
virtual string emitC() { return "VL_SYSTEM_%nq(%lw, %P)"; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual bool isSplittable() const { return false; }
virtual bool isOutputter() const { return true; }
virtual bool isUnlikely() const { return true; }
virtual bool cleanOut() { return true; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
AstNode* lhsp() const { return op1p(); }
};
struct AstValuePlusArgs : public AstNodeMath { struct AstValuePlusArgs : public AstNodeMath {
// Parents: expr // Parents: expr
// Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs // Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs
@@ -1973,6 +2045,18 @@ struct AstContinue : public AstNodeStmt {
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
}; };
struct AstDisable : public AstNodeStmt {
private:
string m_name; // Name of block
public:
AstDisable(FileLine* fileline, const string& name)
: AstNodeStmt(fileline), m_name(name) {}
ASTNODE_NODE_FUNCS(Disable, DISABLE)
virtual string name() const { return m_name; } // * = Block name
void name(const string& flag) { m_name=flag; }
virtual bool isSplittable() const { return false; } // SPECIAL: We don't process code after breaks
};
struct AstReturn : public AstNodeStmt { struct AstReturn : public AstNodeStmt {
AstReturn(FileLine* fileline, AstNode* lhsp=NULL) AstReturn(FileLine* fileline, AstNode* lhsp=NULL)
: AstNodeStmt (fileline) { : AstNodeStmt (fileline) {
@@ -2416,6 +2500,20 @@ struct AstTime : public AstNodeTermop {
virtual bool same(AstNode* samep) const { return true; } virtual bool same(AstNode* samep) const { return true; }
}; };
struct AstTimeD : public AstNodeTermop {
AstTimeD(FileLine* fl) : AstNodeTermop(fl) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(TimeD, TIMED)
virtual string emitVerilog() { return "%f$realtime"; }
virtual string emitC() { return "VL_TIME_D()"; }
virtual bool cleanOut() { return true; }
virtual bool isGateOptimizable() const { return false; }
virtual bool isPredictOptimizable() const { return false; }
virtual int instrCount() const { return instrCountTime(); }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool same(AstNode* samep) const { return true; }
};
struct AstUCFunc : public AstNodeMath { struct AstUCFunc : public AstNodeMath {
// User's $c function // User's $c function
// Perhaps this should be a AstNodeListop; but there's only one list math right now // Perhaps this should be a AstNodeListop; but there's only one list math right now
@@ -2441,19 +2539,32 @@ struct AstUCFunc : public AstNodeMath {
//====================================================================== //======================================================================
// Unary ops // Unary ops
struct AstUnaryMin : public AstNodeUniop { struct AstNegate : public AstNodeUniop {
AstUnaryMin(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstNegate(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
ASTNODE_NODE_FUNCS(UnaryMin, UNARYMIN) ASTNODE_NODE_FUNCS(Negate, NEGATE)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opUnaryMin(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegate(lhs); }
virtual string emitVerilog() { return "%f(- %l)"; } virtual string emitVerilog() { return "%f(- %l)"; }
virtual string emitC() { return "VL_UNARYMIN_%lq(%lW, %P, %li)"; } virtual string emitC() { return "VL_NEGATE_%lq(%lW, %P, %li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersLhs() {return true;}
}; };
struct AstNegateD : public AstNodeUniop {
AstNegateD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(NegateD, NEGATED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegateD(lhs); }
virtual string emitVerilog() { return "%f(- %l)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "-"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstRedAnd : public AstNodeUniop { struct AstRedAnd : public AstNodeUniop {
AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedAnd, REDAND) ASTNODE_NODE_FUNCS(RedAnd, REDAND)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
virtual string emitVerilog() { return "%f(& %l)"; } virtual string emitVerilog() { return "%f(& %l)"; }
@@ -2463,7 +2574,7 @@ struct AstRedAnd : public AstNodeUniop {
}; };
struct AstRedOr : public AstNodeUniop { struct AstRedOr : public AstNodeUniop {
AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedOr, REDOR) ASTNODE_NODE_FUNCS(RedOr, REDOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
virtual string emitVerilog() { return "%f(| %l)"; } virtual string emitVerilog() { return "%f(| %l)"; }
@@ -2473,7 +2584,7 @@ struct AstRedOr : public AstNodeUniop {
}; };
struct AstRedXor : public AstNodeUniop { struct AstRedXor : public AstNodeUniop {
AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedXor, REDXOR) ASTNODE_NODE_FUNCS(RedXor, REDXOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
virtual string emitVerilog() { return "%f(^ %l)"; } virtual string emitVerilog() { return "%f(^ %l)"; }
@@ -2487,7 +2598,7 @@ struct AstRedXor : public AstNodeUniop {
struct AstRedXnor : public AstNodeUniop { struct AstRedXnor : public AstNodeUniop {
// AstRedXnors are replaced with AstRedXors in V3Const. // AstRedXnors are replaced with AstRedXors in V3Const.
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(1,1); } width(1,1); numeric(AstNumeric::UNSIGNED); }
ASTNODE_NODE_FUNCS(RedXnor, REDXNOR) ASTNODE_NODE_FUNCS(RedXnor, REDXNOR)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
virtual string emitVerilog() { return "%f(~^ %l)"; } virtual string emitVerilog() { return "%f(~^ %l)"; }
@@ -2545,7 +2656,7 @@ struct AstExtendS : public AstNodeUniop {
struct AstSigned : public AstNodeUniop { struct AstSigned : public AstNodeUniop {
// $signed(lhs) // $signed(lhs)
AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
isSigned(true); numeric(AstNumeric::SIGNED);
} }
ASTNODE_NODE_FUNCS(Signed, SIGNED) ASTNODE_NODE_FUNCS(Signed, SIGNED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
@@ -2558,7 +2669,7 @@ struct AstSigned : public AstNodeUniop {
struct AstUnsigned : public AstNodeUniop { struct AstUnsigned : public AstNodeUniop {
// $unsigned(lhs) // $unsigned(lhs)
AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) { AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
isSigned(false); numeric(AstNumeric::UNSIGNED);
} }
ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED) ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); } virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
@@ -2568,6 +2679,63 @@ struct AstUnsigned : public AstNodeUniop {
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
virtual int instrCount() const { return 0; } virtual int instrCount() const { return 0; }
}; };
struct AstRToIS : public AstNodeUniop {
// $rtoi(lhs)
AstRToIS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(32,32); }
ASTNODE_NODE_FUNCS(RToIS, RTOIS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIS(lhs); }
virtual string emitVerilog() { return "%f$rtoi(%l)"; }
virtual string emitC() { return "VL_RTOI_I_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstRToIRoundS : public AstNodeUniop {
AstRToIRoundS(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(32,32); }
ASTNODE_NODE_FUNCS(RToIRoundS, RTOIROUNDS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIRoundS(lhs); }
virtual string emitVerilog() { return "%f$rtoi_rounded(%l)"; }
virtual string emitC() { return "VL_RTOIROUND_I_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstIToRD : public AstNodeUniop {
AstIToRD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(IToRD, ITORD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); }
virtual string emitVerilog() { return "%f$itor(%l)"; }
virtual string emitC() { return "VL_ITOR_D_I(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstRealToBits : public AstNodeUniop {
AstRealToBits(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
width(64,64); }
ASTNODE_NODE_FUNCS(RealToBits, REALTOBITS)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRealToBits(lhs); }
virtual string emitVerilog() { return "%f$realtobits(%l)"; }
virtual string emitC() { return "VL_CVT_Q_D(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstBitsToRealD : public AstNodeUniop {
AstBitsToRealD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(BitsToRealD, BITSTOREALD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opBitsToRealD(lhs); }
virtual string emitVerilog() { return "%f$bitstoreal(%l)"; }
virtual string emitC() { return "VL_CVT_D_Q(%li)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return false;} // Eliminated before matters
virtual bool sizeMattersLhs() {return false;} // Eliminated before matters
virtual int instrCount() const { return instrCountDouble(); }
};
struct AstCLog2 : public AstNodeUniop { struct AstCLog2 : public AstNodeUniop {
AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {} AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
ASTNODE_NODE_FUNCS(CLog2, CLOG2) ASTNODE_NODE_FUNCS(CLog2, CLOG2)
@@ -2685,7 +2853,7 @@ struct AstFEof : public AstNodeUniop {
ASTNODE_NODE_FUNCS(FEof, FEOF) ASTNODE_NODE_FUNCS(FEof, FEOF)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%f$feof(%l)"; } virtual string emitVerilog() { return "%f$feof(%l)"; }
virtual string emitC() { return "(%li ? feof(VL_CVT_Q_FP(%li)) : true)"; } virtual string emitC() { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*16; } virtual int instrCount() const { return widthInstrs()*16; }
@@ -2698,13 +2866,97 @@ struct AstFGetC : public AstNodeUniop {
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
virtual string emitVerilog() { return "%f$fgetc(%l)"; } virtual string emitVerilog() { return "%f$fgetc(%l)"; }
// Non-existent filehandle returns EOF // Non-existent filehandle returns EOF
virtual string emitC() { return "(%li ? fgetc(VL_CVT_Q_FP(%li)) : -1)"; } virtual string emitC() { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; }
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;} virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return widthInstrs()*64; } virtual int instrCount() const { return widthInstrs()*64; }
AstNode* filep() const { return lhsp(); } AstNode* filep() const { return lhsp(); }
}; };
struct AstCeilD : public AstNodeUniop {
AstCeilD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(CeilD, CEILD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(ceil(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$ceil(%l)"; }
virtual string emitC() { return "ceil(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstExpD : public AstNodeUniop {
AstExpD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(ExpD, EXPD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(exp(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$exp(%l)"; }
virtual string emitC() { return "exp(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstFloorD : public AstNodeUniop {
AstFloorD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(FloorD, FLOORD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(floor(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$floor(%l)"; }
virtual string emitC() { return "floor(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLogD : public AstNodeUniop {
AstLogD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(LogD, LOGD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(log(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$ln(%l)"; }
virtual string emitC() { return "log(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLog10D : public AstNodeUniop {
AstLog10D(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(Log10D, LOG10D)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(log10(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$log10(%l)"; }
virtual string emitC() { return "log10(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstSqrtD : public AstNodeUniop {
AstSqrtD(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(SqrtD, SQRTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
out.setDouble(sqrt(lhs.toDouble())); }
virtual string emitVerilog() { return "%f$sqrt(%l)"; }
virtual string emitC() { return "sqrt(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return false;}
virtual bool sizeMattersLhs() {return false;}
virtual int instrCount() const { return instrCountDoubleTrig(); }
virtual bool doubleFlavor() const { return true; }
};
//====================================================================== //======================================================================
// Binary ops // Binary ops
@@ -2820,6 +3072,20 @@ struct AstEq : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstEqD : public AstNodeBiCom {
AstEqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(EqD, EQD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEqD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "=="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstNeq : public AstNodeBiCom { struct AstNeq : public AstNodeBiCom {
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) { AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2832,6 +3098,20 @@ struct AstNeq : public AstNodeBiCom {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstNeqD : public AstNodeBiCom {
AstNeqD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(NeqD, NEQD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeqD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "!="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLt : public AstNodeBiop { struct AstLt : public AstNodeBiop {
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2844,6 +3124,20 @@ struct AstLt : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstLtD : public AstNodeBiop {
AstLtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(LtD, LTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLtD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f< %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "<"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLtS : public AstNodeBiop { struct AstLtS : public AstNodeBiop {
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2869,6 +3163,20 @@ struct AstGt : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstGtD : public AstNodeBiop {
AstGtD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(GtD, GTD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGtD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f> %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return ">"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstGtS : public AstNodeBiop { struct AstGtS : public AstNodeBiop {
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2894,6 +3202,20 @@ struct AstGte : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstGteD : public AstNodeBiop {
AstGteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(GteD, GTED)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opGteD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f>= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return ">="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstGteS : public AstNodeBiop { struct AstGteS : public AstNodeBiop {
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2919,6 +3241,20 @@ struct AstLte : public AstNodeBiop {
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;} virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
}; };
struct AstLteD : public AstNodeBiop {
AstLteD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); }
ASTNODE_NODE_FUNCS(LteD, LTED)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opLteD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f<= %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "<="; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstLteS : public AstNodeBiop { struct AstLteS : public AstNodeBiop {
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
width(1,1); } width(1,1); }
@@ -2987,6 +3323,20 @@ struct AstAdd : public AstNodeBiComAsv {
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
}; };
struct AstAddD : public AstNodeBiComAsv {
AstAddD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(AddD, ADDD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opAddD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f+ %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "+"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstSub : public AstNodeBiop { struct AstSub : public AstNodeBiop {
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -2999,6 +3349,20 @@ struct AstSub : public AstNodeBiop {
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
}; };
struct AstSubD : public AstNodeBiop {
AstSubD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(SubD, SUBD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opSubD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f- %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "-"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstMul : public AstNodeBiComAsv { struct AstMul : public AstNodeBiComAsv {
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) { AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -3012,6 +3376,20 @@ struct AstMul : public AstNodeBiComAsv {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return widthInstrs()*instrCountMul(); } virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
}; };
struct AstMulD : public AstNodeBiComAsv {
AstMulD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(MulD, MULD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opMulD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f* %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "*"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return instrCountDouble(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstMulS : public AstNodeBiComAsv { struct AstMulS : public AstNodeBiComAsv {
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) { AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -3038,6 +3416,20 @@ struct AstDiv : public AstNodeBiop {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
virtual int instrCount() const { return widthInstrs()*instrCountDiv(); } virtual int instrCount() const { return widthInstrs()*instrCountDiv(); }
}; };
struct AstDivD : public AstNodeBiop {
AstDivD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(DivD, DIVD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opDivD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f/ %r)"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual string emitSimpleOperator() { return "/"; }
virtual bool cleanOut() {return true;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDoubleDiv(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstDivS : public AstNodeBiop { struct AstDivS : public AstNodeBiop {
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -3088,6 +3480,19 @@ struct AstPow : public AstNodeBiop {
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return widthInstrs()*instrCountMul(); } virtual int instrCount() const { return widthInstrs()*instrCountMul(); }
}; };
struct AstPowD : public AstNodeBiop {
AstPowD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
numeric(AstNumeric::DOUBLE); }
ASTNODE_NODE_FUNCS(PowD, POWD)
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opPowD(lhs,rhs); }
virtual string emitVerilog() { return "%k(%l %f** %r)"; }
virtual string emitC() { return "pow(%li,%ri)"; }
virtual bool cleanOut() {return false;}
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
virtual int instrCount() const { return instrCountDoubleDiv(); }
virtual bool doubleFlavor() const { return true; }
};
struct AstPowS : public AstNodeBiop { struct AstPowS : public AstNodeBiop {
AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) { AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
if (lhsp) widthSignedFrom(lhsp); } if (lhsp) widthSignedFrom(lhsp); }
@@ -3185,7 +3590,7 @@ struct AstBufIf1 : public AstNodeBiop {
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); } virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
virtual string emitVerilog() { return "bufif(%r,%l)"; } virtual string emitVerilog() { return "bufif(%r,%l)"; }
virtual string emitC() { V3ERROR_NA; return "";} // Lclean || Rclean virtual string emitC() { V3ERROR_NA; return "";} // Lclean || Rclean
virtual string emitSimpleOperator() { V3ERROR_NA; return false;} // Lclean || Rclean virtual string emitSimpleOperator() { V3ERROR_NA; return "";} // Lclean || Rclean
virtual bool cleanOut() {V3ERROR_NA; return "";} // Lclean || Rclean virtual bool cleanOut() {V3ERROR_NA; return "";} // Lclean || Rclean
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;} virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;} virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
@@ -3624,25 +4029,6 @@ struct AstCReturn : public AstNodeStmt {
AstNode* lhsp() const { return op1p(); } AstNode* lhsp() const { return op1p(); }
}; };
struct AstCInclude : public AstNode {
// C++ use of another class
// Parents: MODULE
// Children: None
private:
AstNodeModule* m_modp;
public:
AstCInclude(FileLine* fl, AstNodeModule* modp)
: AstNode(fl) {
m_modp = modp;
}
ASTNODE_NODE_FUNCS(CInclude, CINCLUDE)
virtual bool broken() const { return (m_modp && !m_modp->brokeExists()); }
virtual void cloneRelink() { if (m_modp && m_modp->clonep()) {
m_modp = m_modp->clonep()->castNodeModule();
}}
AstNodeModule* modp() const { return m_modp; }
};
struct AstCMath : public AstNodeMath { struct AstCMath : public AstNodeMath {
private: private:
bool m_cleanOut; bool m_cleanOut;
+8 -4
View File
@@ -148,17 +148,19 @@ private:
bool isCaseTreeFast(AstCase* nodep) { bool isCaseTreeFast(AstCase* nodep) {
int width = 0; int width = 0;
bool opaque = false;
m_caseItems = 0; m_caseItems = 0;
m_caseNoOverlapsAllCovered = true; m_caseNoOverlapsAllCovered = true;
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) { for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) { for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
if (icondp->width() > width) width = icondp->width(); if (icondp->width() > width) width = icondp->width();
if (icondp->isDouble()) opaque = true;
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
m_caseItems++; m_caseItems++;
} }
} }
m_caseWidth = width; m_caseWidth = width;
if (width==0 || width > CASE_OVERLAP_WIDTH) { if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
m_caseNoOverlapsAllCovered = false; m_caseNoOverlapsAllCovered = false;
return false; // Too wide for analysis return false; // Too wide for analysis
} }
@@ -348,7 +350,9 @@ private:
and1p = cexprp->cloneTree(false); and1p = cexprp->cloneTree(false);
and2p = icondp; and2p = icondp;
} }
AstEq* condp = new AstEq(itemp->fileline(), and1p, and2p); AstNodeBiop* condp = (and1p->isDouble()
? (new AstEqD(itemp->fileline(), and1p, and2p))->castNodeBiop()
: (new AstEq(itemp->fileline(), and1p, and2p))->castNodeBiop());
if (!ifexprp) { if (!ifexprp) {
ifexprp = condp; ifexprp = condp;
} else { } else {
@@ -448,10 +452,10 @@ private:
if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) { if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) {
// It's a simple priority encoder or complete statement // It's a simple priority encoder or complete statement
// we can make a tree of statements to avoid extra comparisons // we can make a tree of statements to avoid extra comparisons
m_statCaseFast++; ++m_statCaseFast;
replaceCaseFast(nodep); nodep=NULL; replaceCaseFast(nodep); nodep=NULL;
} else { } else {
m_statCaseSlow++; ++m_statCaseSlow;
replaceCaseComplicated(nodep); nodep=NULL; replaceCaseComplicated(nodep); nodep=NULL;
} }
} }
+1 -1
View File
@@ -135,7 +135,7 @@ private:
insureLower32Cast(nodep); insureLower32Cast(nodep);
nodep->user1(1); nodep->user1(1);
} }
virtual void visit(AstUnaryMin* nodep, AstNUser*) { virtual void visit(AstNegate* nodep, AstNUser*) {
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
nodep->user1(nodep->lhsp()->user1()); nodep->user1(nodep->lhsp()->user1());
if (nodep->lhsp()->widthMin()==1) { if (nodep->lhsp()->widthMin()==1) {
+11 -1
View File
@@ -476,6 +476,12 @@ private:
void edgeReport() { void edgeReport() {
// Make report of all signal names and what clock edges they have // Make report of all signal names and what clock edges they have
//
// Due to flattening, many interesting direct-connect signals are
// lost, so we can't make a report showing I/Os for a low level
// module. Disabling flattening though makes us consider each
// signal in it's own unique clock domain.
UINFO(3,__FUNCTION__<<": "<<endl); UINFO(3,__FUNCTION__<<": "<<endl);
// Trace all sources and sinks // Trace all sources and sinks
@@ -505,6 +511,10 @@ private:
ostringstream os; ostringstream os;
os.setf(ios::left); os.setf(ios::left);
// Module name - doesn't work due to flattening having lost the original
// so we assume the modulename matches the filebasename
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
os<<" "<<setw(20)<<fname;
os<<" "<<setw(8)<<whatp; os<<" "<<setw(8)<<whatp;
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName(); os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
os<<" SRC="; os<<" SRC=";
@@ -739,7 +749,7 @@ public:
nodep->accept(*this); nodep->accept(*this);
analyze(); analyze();
//edgeReport(); // Not useful at the moment if (debug()>=1) edgeReport(); // Not useful to users at the moment
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; } if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
} }
+2 -1
View File
@@ -315,6 +315,7 @@ public:
m_exprp = exprp; m_exprp = exprp;
m_original = original; m_original = original;
m_state = STATE_UNKNOWN; m_state = STATE_UNKNOWN;
m_cloning = false;
if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: "); if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: ");
nodep->bodysp()->iterateAndNext(*this); nodep->bodysp()->iterateAndNext(*this);
if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: "); if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: ");
@@ -696,7 +697,7 @@ class GaterVisitor : public GaterBaseVisitor {
// Blow old statements from new body // Blow old statements from new body
GaterBodyVisitor(alwp,exprp,false); GaterBodyVisitor(alwp,exprp,false);
m_statGaters++; ++m_statGaters;
if (debug()>=9) alwp->dumpTree(cout," new: "); if (debug()>=9) alwp->dumpTree(cout," new: ");
} }
+6 -4
View File
@@ -70,8 +70,8 @@ protected:
virtual ~CombBaseVisitor() {} virtual ~CombBaseVisitor() {}
//***** optimization levels //***** optimization levels
bool emptyFunctionDeletion() { return true; } static bool emptyFunctionDeletion() { return true; }
bool duplicateFunctionCombine() { return true; } static bool duplicateFunctionCombine() { return true; }
// Note this is disabled, it still needed work // Note this is disabled, it still needed work
// Also repair it for DPI functions; when make __common need to insure proper // Also repair it for DPI functions; when make __common need to insure proper
// flags get inherited from the old to new AstCFunc, and that AstText doesn't // flags get inherited from the old to new AstCFunc, and that AstText doesn't
@@ -146,7 +146,9 @@ private:
} }
public: public:
// CONSTRUCTORS // CONSTRUCTORS
CombCallVisitor() {} CombCallVisitor() {
m_find = false;
}
virtual ~CombCallVisitor() {} virtual ~CombCallVisitor() {}
void main(AstNetlist* nodep) { void main(AstNetlist* nodep) {
nodep->accept(*this); nodep->accept(*this);
@@ -257,7 +259,7 @@ private:
UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl); UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl);
UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl); UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl);
// Mark user3p on entire old tree, so we don't process it more // Mark user3p on entire old tree, so we don't process it more
m_statCombs++; ++m_statCombs;
CombMarkVisitor visitor(oldfuncp); CombMarkVisitor visitor(oldfuncp);
m_call.replaceFunc(oldfuncp, newfuncp); m_call.replaceFunc(oldfuncp, newfuncp);
oldfuncp->unlinkFrBack(); oldfuncp->unlinkFrBack();
+16 -5
View File
@@ -37,7 +37,6 @@
#include "V3Const.h" #include "V3Const.h"
#include "V3Ast.h" #include "V3Ast.h"
#include "V3Width.h" #include "V3Width.h"
#include "V3Signed.h"
#include "V3Simulate.h" #include "V3Simulate.h"
//###################################################################### //######################################################################
@@ -822,7 +821,9 @@ private:
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign(); AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1); asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1); asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1ap); newp = newp->addNext(asn1ap);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn2ap); newp = newp->addNext(asn2ap);
} else { } else {
if (!m_modp) nodep->v3fatalSrc("Not under module"); if (!m_modp) nodep->v3fatalSrc("Not under module");
@@ -853,12 +854,16 @@ private:
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1); asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1); asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
// This order matters // This order matters
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1ap); newp = newp->addNext(asn1ap);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn2ap); newp = newp->addNext(asn2ap);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn1bp); newp = newp->addNext(asn1bp);
// cppcheck-suppress nullPointer // addNext deals with it
newp = newp->addNext(asn2bp); newp = newp->addNext(asn2bp);
} }
if (debug()>=9) newp->dumpTreeAndNext(cout," _new: "); if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: ");
nodep->addNextHere(newp); nodep->addNextHere(newp);
// Cleanup // Cleanup
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
@@ -1519,7 +1524,7 @@ private:
if (!inPct && ch=='%') { if (!inPct && ch=='%') {
inPct = true; inPct = true;
fmt = ch; fmt = ch;
} else if (inPct && isdigit(ch)) { } else if (inPct && (isdigit(ch) || ch=='.')) {
fmt += ch; fmt += ch;
} else if (inPct) { } else if (inPct) {
inPct = false; inPct = false;
@@ -1535,7 +1540,7 @@ private:
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl); UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
{ // fmt = out w/ replace % with %% as it must be literal. { // fmt = out w/ replace % with %% as it must be literal.
fmt = ""; fmt = "";
for (string::iterator pos = out.begin(); pos != out.end(); pos++) { for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
if (*pos == '%') fmt += '%'; if (*pos == '%') fmt += '%';
fmt += *pos; fmt += *pos;
} }
@@ -1664,7 +1669,7 @@ private:
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)"); TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)"); TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}"); TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}"); TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)"); TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)"); TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
@@ -1783,17 +1788,23 @@ private:
TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)"); TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X. TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)"); TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)"); TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
+1 -1
View File
@@ -97,7 +97,7 @@ private:
removep->unlinkFrBack(); pushDeletep(removep); removep=NULL; removep->unlinkFrBack(); pushDeletep(removep); removep=NULL;
// Remove node from comparison so don't hit it again // Remove node from comparison so don't hit it again
hashed.erase(dupit); hashed.erase(dupit);
m_statToggleJoins++; ++m_statToggleJoins;
} }
} }
} }
+1 -3
View File
@@ -224,7 +224,6 @@ private:
} }
// //
//=== Setting/not setting boolean: __Vdlyvset__ //=== Setting/not setting boolean: __Vdlyvset__
bool sharedVset = false;
AstVarScope* setvscp; AstVarScope* setvscp;
if (nodep->user3p()) { if (nodep->user3p()) {
@@ -232,9 +231,8 @@ private:
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one. // then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
// This is good for code like: // This is good for code like:
// for (i=0; i<5; i++) vector[i] <= something; // for (i=0; i<5; i++) vector[i] <= something;
sharedVset = true;
setvscp = nodep->user3p()->castNode()->castVarScope(); setvscp = nodep->user3p()->castNode()->castVarScope();
m_statSharedSet++; ++m_statSharedSet;
} else { // Create new one } else { // Create new one
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum)); string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1); setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
+45 -10
View File
@@ -55,9 +55,9 @@ public:
} }
// ACCESSORS // ACCESSORS
int splitFilenum() { return m_splitFilenum; } int splitFilenum() const { return m_splitFilenum; }
int splitFilenumInc() { m_splitSize = 0; return ++m_splitFilenum; } int splitFilenumInc() { m_splitSize = 0; return ++m_splitFilenum; }
int splitSize() { return m_splitSize; } int splitSize() const { return m_splitSize; }
void splitSizeInc(AstNode* nodep) { m_splitSize += EmitCBaseCounterVisitor(nodep).count(); } void splitSizeInc(AstNode* nodep) { m_splitSize += EmitCBaseCounterVisitor(nodep).count(); }
bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit() > 1 bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit() > 1
&& v3Global.opt.outputSplit() < splitSize()); } && v3Global.opt.outputSplit() < splitSize()); }
@@ -344,13 +344,11 @@ public:
puts(");\n"); puts(");\n");
} }
virtual void visit(AstFClose* nodep, AstNUser*) { virtual void visit(AstFClose* nodep, AstNUser*) {
puts("if ("); puts("VL_FCLOSE_I(");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(") { fclose (VL_CVT_Q_FP("); puts("); ");
nodep->filep()->iterateAndNext(*this);
puts(")); ");
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it. nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
puts("=0; }\n"); puts("=0;\n");
} }
virtual void visit(AstFFlush* nodep, AstNUser*) { virtual void visit(AstFFlush* nodep, AstNUser*) {
if (!nodep->filep()) { if (!nodep->filep()) {
@@ -358,11 +356,35 @@ public:
} else { } else {
puts("if ("); puts("if (");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(") { fflush (VL_CVT_Q_FP("); puts(") { fflush (VL_CVT_I_FP(");
nodep->filep()->iterateAndNext(*this); nodep->filep()->iterateAndNext(*this);
puts(")); }\n"); puts(")); }\n");
} }
} }
virtual void visit(AstSystemT* nodep, AstNUser*) {
puts("(void)VL_SYSTEM_I");
emitIQW(nodep->lhsp());
puts("(");
if (nodep->lhsp()->isWide()) {
puts(cvtToStr(nodep->lhsp()->widthWords()));
putbs(", ");
}
checkMaxWords(nodep->lhsp());
nodep->lhsp()->iterateAndNext(*this);
puts(");\n");
}
virtual void visit(AstSystemF* nodep, AstNUser*) {
puts("VL_SYSTEM_I");
emitIQW(nodep->lhsp());
puts("(");
if (nodep->lhsp()->isWide()) {
puts(cvtToStr(nodep->lhsp()->widthWords()));
putbs(", ");
}
checkMaxWords(nodep->lhsp());
nodep->lhsp()->iterateAndNext(*this);
puts(")");
}
virtual void visit(AstJumpGo* nodep, AstNUser*) { virtual void visit(AstJumpGo* nodep, AstNUser*) {
puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n"); puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n");
} }
@@ -547,6 +569,8 @@ public:
ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word))); ofp()->printf(",0x%08" VL_PRI64 "x", (vluint64_t)(nodep->num().dataWord(word)));
} }
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0))); ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
} else if (nodep->isDouble()) {
ofp()->printf("%.17g", nodep->num().toDouble());
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
vluint64_t num = nodep->toUQuad(); vluint64_t num = nodep->toUQuad();
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num); if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
@@ -830,6 +854,8 @@ class EmitCImp : EmitCStmts {
public: public:
EmitCImp() { EmitCImp() {
m_modp = NULL; m_modp = NULL;
m_slow = false;
m_fast = false;
} }
virtual ~EmitCImp() {} virtual ~EmitCImp() {}
void main(AstNodeModule* modp, bool slow, bool fast); void main(AstNodeModule* modp, bool slow, bool fast);
@@ -1212,6 +1238,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
switch (tolower(pos[0])) { switch (tolower(pos[0])) {
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
case '.':
// Digits, like %5d, etc. // Digits, like %5d, etc.
vfmt += pos[0]; vfmt += pos[0];
inPct = true; // Get more digits inPct = true; // Get more digits
@@ -1230,6 +1257,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
case 'h': case 'h':
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break; case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break; case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
case 'e': displayArg(nodep,&elistp,isScan, vfmt,'e'); break;
case 'f': displayArg(nodep,&elistp,isScan, vfmt,'f'); break;
case 'g': displayArg(nodep,&elistp,isScan, vfmt,'g'); break;
case 'm': { case 'm': {
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName"); if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
string suffix = scopenamep->scopePrettyName(); string suffix = scopenamep->scopePrettyName();
@@ -1420,6 +1450,7 @@ void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
// Need implementation here. Be careful of alignment code; needs to be uniquified // Need implementation here. Be careful of alignment code; needs to be uniquified
// with module name to avoid multiple symbols. // with module name to avoid multiple symbols.
//emitVarList(modp->stmtsp(), EVL_ALL, modp->name()); //emitVarList(modp->stmtsp(), EVL_ALL, modp->name());
puts(""); // NOP for cppcheck, otherwise const function
} }
void EmitCImp::emitTextSection(AstType type) { void EmitCImp::emitTextSection(AstType type) {
@@ -2011,7 +2042,9 @@ class EmitCTrace : EmitCStmts {
return varp->isSc() && varp->isScBv(); return varp->isSc() && varp->isScBv();
} }
void emitTraceInitOne(AstTraceDecl* nodep) { void emitTraceInitOne(AstTraceDecl* nodep) {
if (nodep->isWide()) { if (nodep->isDouble()) {
puts("vcdp->declDouble");
} else if (nodep->isWide()) {
puts("vcdp->declArray"); puts("vcdp->declArray");
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
puts("vcdp->declQuad "); puts("vcdp->declQuad ");
@@ -2040,7 +2073,9 @@ class EmitCTrace : EmitCStmts {
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB) || m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
? "full":"chg"); ? "full":"chg");
if (nodep->isWide() || emitTraceIsScBv(nodep)) { if (nodep->isDouble()) {
puts("vcdp->"+full+"Double");
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
puts("vcdp->"+full+"Array"); puts("vcdp->"+full+"Array");
} else if (nodep->isQuad()) { } else if (nodep->isQuad()) {
puts("vcdp->"+full+"Quad "); puts("vcdp->"+full+"Quad ");
+2 -2
View File
@@ -526,8 +526,8 @@ void EmitCSyms::emitDpiHdr() {
puts("#endif\n"); puts("#endif\n");
puts("\n"); puts("\n");
bool firstExp = false; int firstExp = 0;
bool firstImp = false; int firstImp = 0;
for (vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) { for (vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) {
AstCFunc* nodep = *it; AstCFunc* nodep = *it;
if (nodep->dpiExportWrapper()) { if (nodep->dpiExportWrapper()) {
+9 -4
View File
@@ -84,10 +84,15 @@ public:
if (v3Global.opt.systemPerl()) { if (v3Global.opt.systemPerl()) {
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
} }
else if (v3Global.opt.trace()) { else {
putMakeClassEntry(of, "verilated_vcd_c.cpp"); if (v3Global.opt.coverage()) {
if (v3Global.opt.systemC()) { putMakeClassEntry(of, "SpCoverage.cpp");
putMakeClassEntry(of, "verilated_vcd_sc.cpp"); }
if (v3Global.opt.trace()) {
putMakeClassEntry(of, "verilated_vcd_c.cpp");
if (v3Global.opt.systemC()) {
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
}
} }
} }
} }
+7
View File
@@ -217,6 +217,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
} }
puts(");\n"); puts(");\n");
} }
virtual void visit(AstDisable* nodep, AstNUser*) {
putbs("disable "+nodep->name()+";\n");
}
virtual void visit(AstDisplay* nodep, AstNUser*) { virtual void visit(AstDisplay* nodep, AstNUser*) {
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
} }
@@ -480,6 +483,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
putfs(nodep,nodep->prettyName()); putfs(nodep,nodep->prettyName());
if (nodep->rangep()) { puts(" "); nodep->rangep()->iterateAndNext(*this); puts(" "); } if (nodep->rangep()) { puts(" "); nodep->rangep()->iterateAndNext(*this); puts(" "); }
} }
virtual void visit(AstConstDType* nodep, AstNUser*) {
putfs(nodep,"const ");
nodep->dtypep()->iterateAndNext(*this);
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) { virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); } if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); }
else { putfs(nodep,nodep->prettyName()); } else { putfs(nodep,nodep->prettyName()); }
+40 -7
View File
@@ -34,8 +34,6 @@
//====================================================================== //======================================================================
// Statics // Statics
FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret());
int V3Error::s_errCount = 0; int V3Error::s_errCount = 0;
int V3Error::s_warnCount = 0; int V3Error::s_warnCount = 0;
int V3Error::s_debugDefault = 0; int V3Error::s_debugDefault = 0;
@@ -66,12 +64,28 @@ V3ErrorCode::V3ErrorCode(const char* msgp) {
m_e = V3ErrorCode::EC_ERROR; m_e = V3ErrorCode::EC_ERROR;
} }
//######################################################################
// FileLineSingleton class functions
int FileLineSingleton::nameToNumber(const string& filename) {
// Convert filenames to a filenameno
// This lets us assign a nice small identifier for debug messages, but more
// importantly lets us use a 4 byte int instead of 8 byte pointer in every FileLine.
map<string,int>::const_iterator iter = m_namemap.find(filename);
if (VL_LIKELY(iter != m_namemap.end())) return iter->second;
int num = m_names.size();
m_names.push_back(filename);
m_namemap.insert(make_pair(filename,num));
return num;
}
//###################################################################### //######################################################################
// FileLine class functions // FileLine class functions
FileLine::FileLine(FileLine::EmptySecret) { FileLine::FileLine(FileLine::EmptySecret) {
// Sort of a singleton
m_lineno=0; m_lineno=0;
m_filename="COMMAND_LINE"; m_filenameno=singleton().nameToNumber("AstRoot");
m_warnOn=0; m_warnOn=0;
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) { for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
@@ -80,6 +94,19 @@ FileLine::FileLine(FileLine::EmptySecret) {
} }
} }
const string FileLine::filenameLetters() const {
const int size = 1 + (64 / 4); // Each letter retires more than 4 bits of a > 64 bit number
char out[size];
char* op = out+size-1;
*--op = '\0'; // We build backwards
int num = m_filenameno;
do {
*--op = 'a'+num%26;
num /= 26;
} while (num);
return op;
}
string FileLine::lineDirectiveStrg(int enterExit) const { string FileLine::lineDirectiveStrg(int enterExit) const {
char numbuf[20]; sprintf(numbuf, "%d", lineno()); char numbuf[20]; sprintf(numbuf, "%d", lineno());
char levelbuf[20]; sprintf(levelbuf, "%d", enterExit); char levelbuf[20]; sprintf(levelbuf, "%d", enterExit);
@@ -262,6 +289,7 @@ void FileLine::deleteAllRemaining() {
// Eventually the list will be empty and terminate the loop. // Eventually the list will be empty and terminate the loop.
} }
fileLineLeakChecks.clear(); fileLineLeakChecks.clear();
FileLineSingleton::clear();
#endif #endif
} }
@@ -304,13 +332,18 @@ void V3Error::incErrors() {
void V3Error::abortIfErrors() { void V3Error::abortIfErrors() {
if (errorCount()) { if (errorCount()) {
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n"); abortIfWarnings();
} }
} }
void V3Error::abortIfWarnings() { void V3Error::abortIfWarnings() {
if (v3Global.opt.warnFatal() ? errorOrWarnCount() : errorCount()) { bool exwarn = v3Global.opt.warnFatal() && warnCount();
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n"); if (errorCount() && exwarn) {
v3fatal ("Exiting due to "<<dec<<errorCount()<<" error(s), "<<warnCount()<<" warning(s)\n");
} else if (errorCount()) {
v3fatal ("Exiting due to "<<dec<<errorCount()<<" error(s)\n");
} else if (exwarn) {
v3fatal ("Exiting due to "<<dec<<warnCount()<<" warning(s)\n");
} }
} }
@@ -370,7 +403,7 @@ void V3Error::suppressThisWarning() {
} }
void V3Error::v3errorEnd (ostringstream& sstr) { void V3Error::v3errorEnd (ostringstream& sstr) {
#ifdef __COVERITY__ #if defined(__COVERITY__) || defined(__cppcheck__)
if (s_errorCode==V3ErrorCode::EC_FATAL) __coverity_panic__(x); if (s_errorCode==V3ErrorCode::EC_FATAL) __coverity_panic__(x);
#endif #endif
if (!s_errorSuppressed if (!s_errorSuppressed
+62 -19
View File
@@ -28,6 +28,8 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <bitset> #include <bitset>
#include <map>
#include <deque>
//###################################################################### //######################################################################
@@ -46,13 +48,15 @@ public:
I_LINT, // All lint messages I_LINT, // All lint messages
I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE) I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE)
// Error codes: // Error codes:
E_BLKLOOPINIT, // Error: Delayed assignment to array inside for loops
E_MULTITOP, // Error: Multiple top level modules E_MULTITOP, // Error: Multiple top level modules
E_TASKNSVAR, // Error: Task I/O not simple E_TASKNSVAR, // Error: Task I/O not simple
E_BLKLOOPINIT, // Error: Delayed assignment to array inside for loops
// //
// Warning codes: // Warning codes:
EC_FIRST_WARN, // Just a code so the program knows where to start warnings EC_FIRST_WARN, // Just a code so the program knows where to start warnings
// //
ASSIGNDLY, // Assignment delays
ASSIGNIN, // Assigning to input
BLKANDNBLK, // Blocked and non-blocking assignments to same variable BLKANDNBLK, // Blocked and non-blocking assignments to same variable
BLKSEQ, // Blocking assignments in sequential block BLKSEQ, // Blocking assignments in sequential block
CASEINCOMPLETE, // Case statement has missing values CASEINCOMPLETE, // Case statement has missing values
@@ -73,6 +77,7 @@ public:
LITENDIAN, // Little bit endian vector LITENDIAN, // Little bit endian vector
MODDUP, // Duplicate module MODDUP, // Duplicate module
MULTIDRIVEN, // Driven from multiple blocks MULTIDRIVEN, // Driven from multiple blocks
REALCVT, // Real conversion
REDEFMACRO, // Redefining existing define macro REDEFMACRO, // Redefining existing define macro
STMTDLY, // Delayed statement STMTDLY, // Delayed statement
SYMRSVDWORD, // Symbol is Reserved Word SYMRSVDWORD, // Symbol is Reserved Word
@@ -89,7 +94,7 @@ public:
// ***Add new elements below also*** // ***Add new elements below also***
}; };
enum en m_e; enum en m_e;
inline V3ErrorCode () {} inline V3ErrorCode () : m_e(EC_MIN) {}
inline V3ErrorCode (en _e) : m_e(_e) {} inline V3ErrorCode (en _e) : m_e(_e) {}
V3ErrorCode (const char* msgp); // Matching code or ERROR V3ErrorCode (const char* msgp); // Matching code or ERROR
explicit inline V3ErrorCode (int _e) : m_e(static_cast<en>(_e)) {} explicit inline V3ErrorCode (int _e) : m_e(static_cast<en>(_e)) {}
@@ -101,9 +106,10 @@ public:
// Boolean // Boolean
" I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE", " I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE",
// Errors // Errors
"MULTITOP", "TASKNSVAR", "BLKLOOPINIT", "BLKLOOPINIT", "MULTITOP", "TASKNSVAR",
// Warnings // Warnings
" EC_FIRST_WARN", " EC_FIRST_WARN",
"ASSIGNDLY", "ASSIGNIN",
"BLKANDNBLK", "BLKSEQ", "BLKANDNBLK", "BLKSEQ",
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST", "CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST",
"COMBDLY", "DEFPARAM", "DECLFILENAME", "COMBDLY", "DEFPARAM", "DECLFILENAME",
@@ -111,7 +117,7 @@ public:
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH", "IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
"LITENDIAN", "MODDUP", "LITENDIAN", "MODDUP",
"MULTIDRIVEN", "MULTIDRIVEN",
"REDEFMACRO", "REALCVT", "REDEFMACRO",
"STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT", "VARHIDDEN", "WIDTH", "WIDTHCONCAT",
@@ -125,7 +131,8 @@ public:
bool dangerous() const { return ( m_e==COMBDLY ); } bool dangerous() const { return ( m_e==COMBDLY ); }
// Warnings we'll present to the user as errors // Warnings we'll present to the user as errors
// Later -Werror- options may make more of these. // Later -Werror- options may make more of these.
bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE || m_e==MODDUP || m_e==SYMRSVDWORD); } bool pretendError() const { return ( m_e==ASSIGNIN || m_e==BLKANDNBLK
|| m_e==IMPURE || m_e==MODDUP || m_e==SYMRSVDWORD); }
// Warnings to mention manual // Warnings to mention manual
bool mentionManual() const { return ( m_e==EC_FATALSRC || pretendError() ); } bool mentionManual() const { return ( m_e==EC_FATALSRC || pretendError() ); }
@@ -135,10 +142,12 @@ public:
|| m_e==CMPCONST || m_e==CMPCONST
|| m_e==IMPLICIT || m_e==IMPLICIT
|| m_e==LITENDIAN || m_e==LITENDIAN
|| m_e==REALCVT
|| m_e==UNSIGNED || m_e==UNSIGNED
|| m_e==WIDTH); } || m_e==WIDTH); }
// Warnings that are style only // Warnings that are style only
bool styleError() const { return ( m_e==BLKSEQ bool styleError() const { return ( m_e==ASSIGNDLY // More than style, but for backward compatibility
|| m_e==BLKSEQ
|| m_e==DEFPARAM || m_e==DEFPARAM
|| m_e==DECLFILENAME || m_e==DECLFILENAME
|| m_e==INCABSPATH || m_e==INCABSPATH
@@ -242,29 +251,58 @@ inline uint32_t cvtToHash(void* vp) {
//###################################################################### //######################################################################
class FileLine;
class FileLineSingleton {
map<string,int> m_namemap; // filenameno for each filename
deque<string> m_names; // filename text for each filenameno
// COSNTRUCTORS
FileLineSingleton() { }
~FileLineSingleton() { }
protected:
friend class FileLine;
// METHODS
int nameToNumber(const string& filename);
string numberToName(int filenameno) { return m_names[filenameno]; }
void clear() { m_namemap.clear(); m_names.clear(); }
};
class FileLine { class FileLine {
// File and line number of an object, mostly for error reporting // File and line number of an object, mostly for error reporting
int m_lineno; int m_lineno;
string m_filename; int m_filenameno;
bitset<V3ErrorCode::_ENUM_MAX> m_warnOn; bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
// Consider moving opt.language() into here, so can know language per-node // Consider moving opt.language() into here, so can know language per-node
static FileLine s_defaultFileLine;
private:
struct EmptySecret {}; struct EmptySecret {};
inline static FileLineSingleton& singleton() {
static FileLineSingleton s;
return s;
}
inline static FileLine& defaultFileLine() {
static FileLine* defFilelinep = new FileLine(FileLine::EmptySecret());
return *defFilelinep;
}
protected: protected:
// User routines should never need to change line numbers // User routines should never need to change line numbers
// We are storing pointers, so we CAN'T change them after initial reading. // We are storing pointers, so we CAN'T change them after initial reading.
friend class FileLineSingleton;
friend class V3ParseImp; friend class V3ParseImp;
friend class V3PreLex; friend class V3PreLex;
friend class V3PreProcImp; friend class V3PreProcImp;
void lineno(int num) { m_lineno = num; } void lineno(int num) { m_lineno = num; }
void filename(const string& name) { m_filename = name; } void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); }
void lineDirective(const char* textp, int& enterExitRef); void lineDirective(const char* textp, int& enterExitRef);
void linenoInc() { m_lineno++; } void linenoInc() { m_lineno++; }
void linenoIncInPlace() { m_lineno++; } void linenoIncInPlace() { m_lineno++; }
FileLine* copyOrSameFileLine(); FileLine* copyOrSameFileLine();
public: public:
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOn=s_defaultFileLine.m_warnOn; } FileLine (const string& filename, int lineno) {
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOn=fromp->m_warnOn; } m_lineno=lineno; m_filenameno = singleton().nameToNumber(filename);
m_warnOn=defaultFileLine().m_warnOn; }
FileLine (FileLine* fromp) {
m_lineno=fromp->m_lineno; m_filenameno = fromp->m_filenameno; m_warnOn=fromp->m_warnOn; }
FileLine (EmptySecret); FileLine (EmptySecret);
~FileLine() { } ~FileLine() { }
FileLine* create(const string& filename, int lineno) { return new FileLine(filename,lineno); } FileLine* create(const string& filename, int lineno) { return new FileLine(filename,lineno); }
@@ -277,7 +315,8 @@ public:
int lineno () const { return m_lineno; } int lineno () const { return m_lineno; }
string ascii() const; string ascii() const;
const string filename () const { return m_filename; } const string filename () const { return singleton().numberToName(m_filenameno); }
const string filenameLetters() const;
const string filebasename () const; const string filebasename () const;
const string filebasenameNoExt () const; const string filebasenameNoExt () const;
const string profileFuncname() const; const string profileFuncname() const;
@@ -289,7 +328,7 @@ public:
void warnLintOff(bool flag); void warnLintOff(bool flag);
void warnStyleOff(bool flag); void warnStyleOff(bool flag);
void warnStateFrom(const FileLine& from) { m_warnOn=from.m_warnOn; } void warnStateFrom(const FileLine& from) { m_warnOn=from.m_warnOn; }
void warnResetDefault() { warnStateFrom(s_defaultFileLine); } void warnResetDefault() { warnStateFrom(defaultFileLine()); }
// Specific flag ACCESSORS/METHODS // Specific flag ACCESSORS/METHODS
bool coverageOn() const { return m_warnOn.test(V3ErrorCode::I_COVERAGE); } bool coverageOn() const { return m_warnOn.test(V3ErrorCode::I_COVERAGE); }
@@ -298,10 +337,14 @@ public:
void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING,flag); } void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING,flag); }
// METHODS - Global // METHODS - Global
static void globalWarnLintOff(bool flag) { s_defaultFileLine.warnLintOff(flag); } static void globalWarnLintOff(bool flag) {
static void globalWarnStyleOff(bool flag) { s_defaultFileLine.warnStyleOff(flag); } defaultFileLine().warnLintOff(flag); }
static void globalWarnOff(V3ErrorCode code, bool flag) { s_defaultFileLine.warnOff(code, flag); } static void globalWarnStyleOff(bool flag) {
static bool globalWarnOff(const string& code, bool flag) { return s_defaultFileLine.warnOff(code, flag); } defaultFileLine().warnStyleOff(flag); }
static void globalWarnOff(V3ErrorCode code, bool flag) {
defaultFileLine().warnOff(code, flag); }
static bool globalWarnOff(const string& code, bool flag) {
return defaultFileLine().warnOff(code, flag); }
// METHODS - Called from netlist // METHODS - Called from netlist
// Merge warning disables from another fileline // Merge warning disables from another fileline
@@ -313,8 +356,8 @@ public:
// OPERATORS // OPERATORS
void v3errorEnd(ostringstream& str); void v3errorEnd(ostringstream& str);
inline bool operator==(FileLine rhs) { inline bool operator==(FileLine rhs) const {
return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename && m_warnOn==rhs.m_warnOn); return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno && m_warnOn==rhs.m_warnOn);
} }
}; };
ostream& operator<<(ostream& os, FileLine* fileline); ostream& operator<<(ostream& os, FileLine* fileline);
+2 -3
View File
@@ -696,8 +696,7 @@ private:
int lhswidth = lhsp->widthMin(); int lhswidth = lhsp->widthMin();
if (lhswidth==1) { if (lhswidth==1) {
UINFO(8," REPLICATE(w1) "<<nodep<<endl); UINFO(8," REPLICATE(w1) "<<nodep<<endl);
newp = new AstUnaryMin (nodep->fileline(), newp = new AstNegate (nodep->fileline(), lhsp);
lhsp);
} else { } else {
UINFO(8," REPLICATE "<<nodep<<endl); UINFO(8," REPLICATE "<<nodep<<endl);
AstConst* constp = nodep->rhsp()->castConst(); AstConst* constp = nodep->rhsp()->castConst();
@@ -731,7 +730,7 @@ private:
for (int w=0; w<rhsp->widthWords(); w++) { for (int w=0; w<rhsp->widthWords(); w++) {
AstNode* newp; AstNode* newp;
if (lhswidth==1) { if (lhswidth==1) {
newp = new AstUnaryMin (nodep->fileline(), lhsp->cloneTree(true)); newp = new AstNegate (nodep->fileline(), lhsp->cloneTree(true));
newp->width(VL_WORDSIZE,VL_WORDSIZE); newp->width(VL_WORDSIZE,VL_WORDSIZE);
} else { } else {
newp = newAstWordSelClone (lhsp, w); newp = newAstWordSelClone (lhsp, w);
+3
View File
@@ -327,6 +327,7 @@ private:
#endif #endif
} }
// cppcheck-suppress functionConst
void checkFilter(bool hang) { void checkFilter(bool hang) {
#ifdef INFILTER_PIPE #ifdef INFILTER_PIPE
if (!m_pidExited && waitpid(m_pid, &m_pidStatus, hang?0:WNOHANG)) { if (!m_pidExited && waitpid(m_pid, &m_pidStatus, hang?0:WNOHANG)) {
@@ -355,6 +356,7 @@ private:
|| errno == EWOULDBLOCK || errno == EWOULDBLOCK
#endif #endif
) { ) {
// cppcheck-suppress obsoleteFunctionsusleep
checkFilter(false); usleep(1000); continue; checkFilter(false); usleep(1000); continue;
} else { m_readEof = true; break; } } else { m_readEof = true; break; }
} }
@@ -390,6 +392,7 @@ private:
|| errno == EWOULDBLOCK || errno == EWOULDBLOCK
#endif #endif
) { ) {
// cppcheck-suppress obsoleteFunctionsusleep
checkFilter(false); usleep(1000); continue; checkFilter(false); usleep(1000); continue;
} }
else break; else break;
+2 -2
View File
@@ -535,7 +535,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
AstNode* substp = okVisitor.substTree(); AstNode* substp = okVisitor.substTree();
if (debug()>=5) logicp->dumpTree(cout,"\telimVar: "); if (debug()>=5) logicp->dumpTree(cout,"\telimVar: ");
if (debug()>=5) substp->dumpTree(cout,"\t subst: "); if (debug()>=5) substp->dumpTree(cout,"\t subst: ");
m_statSigs++; ++m_statSigs;
while (V3GraphEdge* edgep = vvertexp->outBeginp()) { while (V3GraphEdge* edgep = vvertexp->outBeginp()) {
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top()); GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
AstNode* consumerp = consumeVertexp->nodep(); AstNode* consumerp = consumeVertexp->nodep();
@@ -557,7 +557,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
} }
// Remove the edge // Remove the edge
edgep->unlinkDelete(); edgep=NULL; edgep->unlinkDelete(); edgep=NULL;
m_statRefs++; ++m_statRefs;
} }
// Remove input links // Remove input links
while (V3GraphEdge* edgep = vvertexp->inBeginp()) { while (V3GraphEdge* edgep = vvertexp->inBeginp()) {
+4 -4
View File
@@ -70,7 +70,7 @@ private:
// MEMBERS // MEMBERS
uint32_t m_step; // Processing step, so we can avoid clearUser all the time uint32_t m_step; // Processing step, so we can avoid clearUser all the time
HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes HashMap m_hashMap; // Dfa Vertex for each set of NFA vertexes
int debug() { return 0; } static int debug() { return 0; }
// METHODS // METHODS
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); } DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
@@ -94,7 +94,7 @@ private:
} }
// Hashing // Hashing
uint32_t hashVertex(V3GraphVertex* vertexp) { static uint32_t hashVertex(V3GraphVertex* vertexp) {
union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u; union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
u.l.upper=0; u.l.lower=0; u.up=vertexp; u.l.upper=0; u.l.lower=0; u.up=vertexp;
return u.l.upper ^ u.l.lower; return u.l.upper ^ u.l.lower;
@@ -362,7 +362,7 @@ void DfaGraph::nfaToDfa() {
class DfaGraphReduce : GraphAlg { class DfaGraphReduce : GraphAlg {
private: private:
// METHODS // METHODS
int debug() { return 0; } static int debug() { return 0; }
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); } DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
bool isDead(DfaVertex* vertexp) { bool isDead(DfaVertex* vertexp) {
@@ -507,7 +507,7 @@ private:
DfaVertex* m_tempNewerReject; DfaVertex* m_tempNewerReject;
// METHODS // METHODS
int debug() { return 9; } static int debug() { return 9; }
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); } DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
void add_complement_edges() { void add_complement_edges() {
+1
View File
@@ -326,6 +326,7 @@ public:
class V3GraphTestImport : public V3GraphTest { class V3GraphTestImport : public V3GraphTest {
// cppcheck-suppress functionConst
void dotImport(); void dotImport();
public: public:
+1 -1
View File
@@ -106,7 +106,7 @@ private:
if (m_cellp) nodep->v3error("Cloning should have already been done bottom-up"); if (m_cellp) nodep->v3error("Cloning should have already been done bottom-up");
UINFO(5," Inline CELL "<<nodep<<endl); UINFO(5," Inline CELL "<<nodep<<endl);
UINFO(5," To MOD "<<m_modp<<endl); UINFO(5," To MOD "<<m_modp<<endl);
m_statCells++; ++m_statCells;
// Before cloning simplify pin assignments // Before cloning simplify pin assignments
// Better off before, as if module has multiple instantiations // Better off before, as if module has multiple instantiations
+3
View File
@@ -293,6 +293,7 @@ private:
// LIFE MAP // LIFE MAP
// For each basic block, we'll make a new map of what variables that if/else is changing // For each basic block, we'll make a new map of what variables that if/else is changing
typedef std::map<AstVarScope*, LifeVarEntry> LifeMap; typedef std::map<AstVarScope*, LifeVarEntry> LifeMap;
// cppcheck-suppress memleak // cppcheck bug - it is deleted
LifeBlock* m_lifep; // Current active lifetime map for current scope LifeBlock* m_lifep; // Current active lifetime map for current scope
// METHODS // METHODS
@@ -455,6 +456,8 @@ public:
m_sideEffect = false; m_sideEffect = false;
m_noopt = false; m_noopt = false;
{ {
// Cpp check bug, it is deleted
// cppcheck-suppress leak
m_lifep = new LifeBlock (NULL, m_statep); m_lifep = new LifeBlock (NULL, m_statep);
nodep->accept(*this); nodep->accept(*this);
delete m_lifep; m_lifep=NULL; delete m_lifep; m_lifep=NULL;
+1 -1
View File
@@ -157,7 +157,7 @@ private:
// Mark so LifePostElimVisitor will get it // Mark so LifePostElimVisitor will get it
rhsp->varScopep()->user4p(lhsp->varScopep()); rhsp->varScopep()->user4p(lhsp->varScopep());
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
m_statAssnDel++; ++m_statAssnDel;
} }
} }
} }
+7 -2
View File
@@ -428,7 +428,7 @@ private:
if (dtypep) dtypep->unlinkFrBack(); if (dtypep) dtypep->unlinkFrBack();
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC); else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep); AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep);
newvarp->isSigned(nodep->isSigned()); if (nodep->isSigned()) newvarp->numeric(AstNumeric::SIGNED);
newvarp->funcReturn(true); newvarp->funcReturn(true);
newvarp->trace(false); // Not user visible newvarp->trace(false); // Not user visible
newvarp->attrIsolateAssign(nodep->attrIsolateAssign()); newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
@@ -563,8 +563,13 @@ private:
nodep->v3fatalSrc("Cell has unlinked module"); // V3LinkCell should have errored out nodep->v3fatalSrc("Cell has unlinked module"); // V3LinkCell should have errored out
} }
else { else {
if (nodep->modp()->castNotFoundModule()) {
// Prevent warnings about missing pin connects
if (nodep->pinsp()) nodep->pinsp()->unlinkFrBackWithNext()->deleteTree();
if (nodep->paramsp()) nodep->paramsp()->unlinkFrBackWithNext()->deleteTree();
}
// Need to pass the module info to this cell, so we can link up the pin names // Need to pass the module info to this cell, so we can link up the pin names
if (m_idState==ID_RESOLVE) { else if (m_idState==ID_RESOLVE) {
m_cellVarsp = nodep->modp()->user4p()->castSymTable(); m_cellVarsp = nodep->modp()->user4p()->castSymTable();
UINFO(4,"(Backto) Link Cell: "<<nodep<<endl); UINFO(4,"(Backto) Link Cell: "<<nodep<<endl);
//if (debug()) { nodep->dumpTree(cout,"linkcell:"); } //if (debug()) { nodep->dumpTree(cout,"linkcell:"); }
+12 -2
View File
@@ -135,7 +135,15 @@ private:
AstNodeModule* modp = vvertexp->modp(); AstNodeModule* modp = vvertexp->modp();
modp->level(vvertexp->rank()+1); modp->level(vvertexp->rank()+1);
if (vvertexp == m_topVertexp && modp->level() != 2) { if (vvertexp == m_topVertexp && modp->level() != 2) {
v3error("Specified --top-module '"<<v3Global.opt.topModule()<<"' isn't at the top level, it's under another cell."); AstNodeModule* abovep = NULL;
if (V3GraphEdge* edgep = vvertexp->inBeginp()) {
if (LinkCellsVertex* eFromVertexp = dynamic_cast<LinkCellsVertex*>(edgep->fromp())) {
abovep = eFromVertexp->modp();
}
}
v3error("Specified --top-module '"<<v3Global.opt.topModule()
<<"' isn't at the top level, it's under another cell '"
<<(abovep ? abovep->prettyName() : "UNKNOWN")<<"'");
} }
} }
} }
@@ -176,8 +184,10 @@ private:
AstNodeModule* modp = m_mods.findIdUpward(nodep->modName())->castNodeModule(); AstNodeModule* modp = m_mods.findIdUpward(nodep->modName())->castNodeModule();
if (!modp) { if (!modp) {
// Read-subfile // Read-subfile
// If file not found, make AstNotFoundModule, rather than error out.
// We'll throw the error when we know the module will really be needed.
V3Parse parser (v3Global.rootp(), m_filterp); V3Parse parser (v3Global.rootp(), m_filterp);
parser.parseFile(nodep->fileline(), nodep->modName(), false); parser.parseFile(nodep->fileline(), nodep->modName(), false, "");
V3Error::abortIfErrors(); V3Error::abortIfErrors();
// We've read new modules, grab new pointers to their names // We've read new modules, grab new pointers to their names
readModNames(); readModNames();
+31 -5
View File
@@ -47,7 +47,7 @@ private:
typedef vector<AstBegin*> BeginStack; typedef vector<AstBegin*> BeginStack;
// STATE // STATE
AstModule* m_modp; // Current module AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current function/task AstNodeFTask* m_ftaskp; // Current function/task
AstWhile* m_loopp; // Current loop AstWhile* m_loopp; // Current loop
bool m_loopInc; // In loop increment bool m_loopInc; // In loop increment
@@ -82,6 +82,11 @@ private:
nodep->v3fatalSrc("Unknown jump point for break/disable/continue"); nodep->v3fatalSrc("Unknown jump point for break/disable/continue");
return NULL; return NULL;
} }
// Skip over variables as we'll just move them in a momement
// Also this would otherwise prevent us from using a label twice
// see t_func_return test.
while (underp && underp->castVar()) underp = underp->nextp();
if (underp) UINFO(5," Underpoint is "<<underp<<endl);
if (!underp) { if (!underp) {
nodep->v3fatalSrc("Break/disable/continue not under expected statement"); nodep->v3fatalSrc("Break/disable/continue not under expected statement");
@@ -109,7 +114,7 @@ private:
} }
// VISITORS // VISITORS
virtual void visit(AstModule* nodep, AstNUser*) { virtual void visit(AstNodeModule* nodep, AstNUser*) {
m_modp = nodep; m_modp = nodep;
m_repeatNum = 0; m_repeatNum = 0;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@@ -135,8 +140,8 @@ private:
// Spec says value is integral, if negative is ignored // Spec says value is integral, if negative is ignored
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name, AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
AstLogicPacked(), 32); AstLogicPacked(), 32);
varp->isSigned(true); varp->numeric(AstNumeric::SIGNED);
varp->dtypep()->isSigned(true); varp->dtypep()->numeric(AstNumeric::SIGNED);
varp->usedLoopIdx(true); varp->usedLoopIdx(true);
m_modp->addStmtp(varp); m_modp->addStmtp(varp);
AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), AstNode* initsp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
@@ -144,7 +149,7 @@ private:
AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true), AstNode* decp = new AstAssign(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, true),
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
new AstConst(nodep->fileline(), 1))); new AstConst(nodep->fileline(), 1)));
AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->isSigned(true); AstNode* zerosp = new AstConst(nodep->fileline(), 0); zerosp->numeric(AstNumeric::SIGNED);
AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false), AstNode* condp = new AstGtS(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
zerosp); zerosp);
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext(); AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
@@ -211,6 +216,27 @@ private:
} }
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL; nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
} }
virtual void visit(AstDisable* nodep, AstNUser*) {
UINFO(8," DISABLE "<<nodep<<endl);
nodep->iterateChildren(*this);
AstBegin* beginp = NULL;
for (BeginStack::reverse_iterator it = m_beginStack.rbegin(); it != m_beginStack.rend(); ++it) {
UINFO(9," UNDERBLK "<<*it<<endl);
if ((*it)->name() == nodep->name()) {
beginp = *it;
break;
}
}
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labeli: "); }
if (!beginp) { nodep->v3error("disable isn't underneath a begin with name: "<<nodep->name()); }
else {
// Jump to the end of the named begin
AstJumpLabel* labelp = findAddLabel(beginp, false);
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
}
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout," labelo: "); }
}
virtual void visit(AstVarRef* nodep, AstNUser*) { virtual void visit(AstVarRef* nodep, AstNUser*) {
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true); if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
} }
+12 -1
View File
@@ -45,6 +45,7 @@ private:
// STATE // STATE
bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments
AstInitial* m_initialp; // In an initial block
AstNodeFTask* m_ftaskp; // Function or task we're inside AstNodeFTask* m_ftaskp; // Function or task we're inside
// METHODS // METHODS
@@ -64,9 +65,13 @@ private:
if (nodep->varp()) { if (nodep->varp()) {
if (nodep->lvalue() && nodep->varp()->isInOnly()) { if (nodep->lvalue() && nodep->varp()->isInOnly()) {
if (!m_ftaskp) { if (!m_ftaskp) {
nodep->v3error("Assigning to input variable: "<<nodep->prettyName()); nodep->v3warn(ASSIGNIN,"Assigning to input variable: "<<nodep->prettyName());
} }
} }
if (nodep->lvalue() && nodep->varp()->isConst()
&& !m_initialp) { // Too loose, but need to allow our generated first assignment
nodep->v3error("Assigning to const variable: "<<nodep->prettyName());
}
} }
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
} }
@@ -222,6 +227,11 @@ private:
} }
m_setRefLvalue = last_setRefLvalue; m_setRefLvalue = last_setRefLvalue;
} }
virtual void visit(AstInitial* nodep, AstNUser*) {
m_initialp = nodep;
nodep->iterateChildren(*this);
m_initialp = NULL;
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) { virtual void visit(AstNodeFTask* nodep, AstNUser*) {
m_ftaskp = nodep; m_ftaskp = nodep;
nodep->iterateChildren(*this); nodep->iterateChildren(*this);
@@ -259,6 +269,7 @@ public:
LinkLValueVisitor(AstNode* nodep, bool start) { LinkLValueVisitor(AstNode* nodep, bool start) {
m_setRefLvalue = start; m_setRefLvalue = start;
m_ftaskp = NULL; m_ftaskp = NULL;
m_initialp = NULL;
nodep->accept(*this); nodep->accept(*this);
} }
virtual ~LinkLValueVisitor() {} virtual ~LinkLValueVisitor() {}
+5
View File
@@ -326,6 +326,11 @@ private:
m_varp->attrSFormat(true); m_varp->attrSFormat(true);
nodep->unlinkFrBack()->deleteTree(); nodep=NULL; nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
} }
else if (nodep->attrType() == AstAttrType::VAR_SC_BV) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrScBv(true);
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
}
} }
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) { virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
+4
View File
@@ -95,6 +95,9 @@ private:
nodep->dtypeSkipRefp()->castArrayDType())) { nodep->dtypeSkipRefp()->castArrayDType())) {
nodep->v3error("Unsupported: Inputs and outputs must be simple data types"); nodep->v3error("Unsupported: Inputs and outputs must be simple data types");
} }
if (nodep->dtypeSkipRefp()->castConstDType()) {
nodep->isConst(true);
}
if (m_ftaskp) nodep->funcLocal(true); if (m_ftaskp) nodep->funcLocal(true);
if (nodep->isSigModPublic()) { if (nodep->isSigModPublic()) {
nodep->sigModPublic(false); // We're done with this attribute nodep->sigModPublic(false); // We're done with this attribute
@@ -254,6 +257,7 @@ private:
switch (tolower(ch)) { switch (tolower(ch)) {
case '0': case '1': case '2': case '3': case '4': case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
case '.':
inPct = true; inPct = true;
break; break;
case '%': break; // %% - just output a % case '%': break; // %% - just output a %
+7 -4
View File
@@ -60,7 +60,7 @@ private:
T m_nextp; // Pointer to next element, NULL=end T m_nextp; // Pointer to next element, NULL=end
T m_prevp; // Pointer to previous element, NULL=beginning T m_prevp; // Pointer to previous element, NULL=beginning
friend class V3List<T>; friend class V3List<T>;
static V3ListEnt* baseToListEnt(void* newbasep, uint32_t offset) { static V3ListEnt* baseToListEnt(void* newbasep, size_t offset) {
// "this" must be a element inside of *basep // "this" must be a element inside of *basep
// Use that to determine a structure offset, then apply to the new base // Use that to determine a structure offset, then apply to the new base
// to get our new pointer information // to get our new pointer information
@@ -80,7 +80,8 @@ public:
// METHODS // METHODS
void pushBack (V3List<T>& listr, T newp) { void pushBack (V3List<T>& listr, T newp) {
// "this" must be a element inside of *newp // "this" must be a element inside of *newp
uint32_t offset = (vluint8_t*)(this) - (vluint8_t*)(newp); // cppcheck-suppress thisSubtraction
size_t offset = (vluint8_t*)(this) - (vluint8_t*)(newp);
m_nextp = NULL; m_nextp = NULL;
if (!listr.m_headp) listr.m_headp = newp; if (!listr.m_headp) listr.m_headp = newp;
m_prevp = listr.m_tailp; m_prevp = listr.m_tailp;
@@ -89,7 +90,8 @@ public:
} }
void pushFront (V3List<T>& listr, T newp) { void pushFront (V3List<T>& listr, T newp) {
// "this" must be a element inside of *newp // "this" must be a element inside of *newp
uint32_t offset = (vluint8_t*)(this) - (vluint8_t*)(newp); // cppcheck-suppress thisSubtraction
size_t offset = (vluint8_t*)(this) - (vluint8_t*)(newp);
m_nextp = listr.m_headp; m_nextp = listr.m_headp;
if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = newp; if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = newp;
listr.m_headp = newp; listr.m_headp = newp;
@@ -99,7 +101,8 @@ public:
// Unlink from side // Unlink from side
void unlink (V3List<T>& listr, T oldp) { void unlink (V3List<T>& listr, T oldp) {
// "this" must be a element inside of *oldp // "this" must be a element inside of *oldp
uint32_t offset = (vluint8_t*)(this) - (vluint8_t*)(oldp); // cppcheck-suppress thisSubtraction
size_t offset = (vluint8_t*)(this) - (vluint8_t*)(oldp);
if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = m_prevp; if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = m_prevp;
else listr.m_tailp = m_prevp; else listr.m_tailp = m_prevp;
if (m_prevp) baseToListEnt(m_prevp,offset)->m_nextp = m_nextp; if (m_prevp) baseToListEnt(m_prevp,offset)->m_nextp = m_nextp;
+1 -1
View File
@@ -141,7 +141,7 @@ private:
&& nodep->user1p()) { // Single cfunc && nodep->user1p()) { // Single cfunc
// We don't need to test for tracing; it would be in the tracefunc if it was needed // We don't need to test for tracing; it would be in the tracefunc if it was needed
UINFO(4," ModVar->BlkVar "<<nodep<<endl); UINFO(4," ModVar->BlkVar "<<nodep<<endl);
m_statLocVars++; ++m_statLocVars;
AstCFunc* newfuncp = nodep->user1p()->castNode()->castCFunc(); AstCFunc* newfuncp = nodep->user1p()->castNode()->castCFunc();
nodep->unlinkFrBack(); nodep->unlinkFrBack();
newfuncp->addInitsp(nodep); newfuncp->addInitsp(nodep);
+145 -39
View File
@@ -25,33 +25,19 @@
#include <cstdio> #include <cstdio>
#include <cstdarg> #include <cstdarg>
#include <algorithm> #include <algorithm>
#include <iomanip>
#include "V3Number.h" #include "V3Number.h"
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
//###################################################################### //######################################################################
// Read class functions // Read class functions
// CREATION // CREATION
void V3Number::width(int width, bool sized) {
// Set width. Only set m_width here, as we need to tweak vector size
if (width) { m_sized = sized; m_width=width; }
else { m_sized = false; m_width=1; }
if (m_value.size() < (unsigned)(words()+1)) {
m_value.resize(words()+1);
m_valueX.resize(words()+1);
}
}
void V3Number::init (FileLine* fileline, int swidth) {
m_fileline = fileline;
m_signed = false;
m_autoExtend = false;
m_fromString = false;
width(swidth);
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
}
V3Number::V3Number(VerilogString, FileLine* fileline, const string& str) { V3Number::V3Number(VerilogString, FileLine* fileline, const string& str) {
// Create a number using a verilog string as the value, thus 8 bits per character. // Create a number using a verilog string as the value, thus 8 bits per character.
// cppcheck bug - doesn't see init() resets these
// cppcheck: Member variable 'm_sized/m_width' is not initialized in the constructor
init(fileline, str.length()*8); init(fileline, str.length()*8);
m_fromString = true; m_fromString = true;
for (unsigned pos=0; pos<str.length(); ++pos) { for (unsigned pos=0; pos<str.length(); ++pos) {
@@ -298,6 +284,24 @@ V3Number& V3Number::setLong(uint32_t value) {
m_value[0] = value; m_value[0] = value;
return *this; return *this;
} }
V3Number& V3Number::setLongS(vlsint32_t value) {
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
union { uint32_t u; vlsint32_t s; } u;
u.s = value;
m_value[0] = u.u;
return *this;
}
V3Number& V3Number::setDouble(double value) {
if (VL_UNLIKELY(width()!=64)) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
m_double = true;
union { double d; uint32_t u[2]; } u;
u.d = value;
for (int i=2; i<words(); i++) m_value[i]=m_valueX[i] = 0;
m_value[0] = u.u[0]; m_value[1] = u.u[1];
return *this;
}
V3Number& V3Number::setSingleBits(char value) { V3Number& V3Number::setSingleBits(char value) {
for (int i=1/*upper*/; i<words(); i++) m_value[i]=m_valueX[i] = 0; for (int i=1/*upper*/; i<words(); i++) m_value[i]=m_valueX[i] = 0;
m_value[0] = (value=='1'||value=='x'||value==1||value==3); m_value[0] = (value=='1'||value=='x'||value==1||value==3);
@@ -306,12 +310,12 @@ V3Number& V3Number::setSingleBits(char value) {
} }
V3Number& V3Number::setAllBits0() { V3Number& V3Number::setAllBits0() {
for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; } for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; }
return *this; return *this;
} }
V3Number& V3Number::setAllBits1() { V3Number& V3Number::setAllBits1() {
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; } for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
return *this; return *this;
} }
V3Number& V3Number::setAllBitsX() { V3Number& V3Number::setAllBitsX() {
for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; } for (int i=0; i<words(); i++) { m_value[i]=m_valueX[i] = ~0; }
@@ -333,6 +337,11 @@ V3Number& V3Number::setMask(int nbits) {
string V3Number::ascii(bool prefixed, bool cleanVerilog) const { string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
ostringstream out; ostringstream out;
if (isDouble()) {
out.precision(17);
out<<toDouble();
return out.str();
}
if (prefixed) { if (prefixed) {
if (sized()) { if (sized()) {
out<<width()<<"'"; out<<width()<<"'";
@@ -375,6 +384,9 @@ bool V3Number::displayedFmtLegal(char format) {
case 'b': return true; case 'b': return true;
case 'c': return true; case 'c': return true;
case 'd': return true; // Unsigned decimal case 'd': return true; // Unsigned decimal
case 'e': return true;
case 'f': return true;
case 'g': return true;
case 'h': return true; case 'h': return true;
case 'o': return true; case 'o': return true;
case 's': return true; case 's': return true;
@@ -388,9 +400,9 @@ bool V3Number::displayedFmtLegal(char format) {
string V3Number::displayed(const string& vformat) const { string V3Number::displayed(const string& vformat) const {
string::const_iterator pos = vformat.begin(); string::const_iterator pos = vformat.begin();
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this); UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
pos++; ++pos;
string fmtsize; string fmtsize;
for (; pos != vformat.end() && isdigit(pos[0]); pos++) { for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); ++pos) {
fmtsize += pos[0]; fmtsize += pos[0];
} }
string str; string str;
@@ -472,9 +484,20 @@ string V3Number::displayed(const string& vformat) const {
str = cvtToStr(toUQuad()); str = cvtToStr(toUQuad());
} }
int intfmtsize = atoi(fmtsize.c_str()); int intfmtsize = atoi(fmtsize.c_str());
while ((int)(str.length()) < intfmtsize) str = " "+str; bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0';
while ((int)(str.length()) < intfmtsize) {
if (zeropad) str = "0"+str;
else str = " "+str;
}
return str; return str;
} }
case 'e':
case 'f':
case 'g': {
char tmp[MAX_SPRINTF_DOUBLE_SIZE];
sprintf(tmp, vformat.c_str(), toDouble());
return tmp;
}
default: default:
m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]); m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]);
return "ERR"; return "ERR";
@@ -490,6 +513,18 @@ uint32_t V3Number::toUInt() const {
return m_value[0]; return m_value[0];
} }
double V3Number::toDouble() const {
if (VL_UNLIKELY(!isDouble())) {
m_fileline->v3fatalSrc("Real conversion on non real number");
}
if (VL_UNLIKELY(width()!=64)) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
union { double d; uint32_t u[2]; } u;
u.u[0] = m_value[0]; u.u[1] = m_value[1];
return u.d;
}
vlsint32_t V3Number::toSInt() const { vlsint32_t V3Number::toSInt() const {
if (isSigned()) { if (isSigned()) {
uint32_t v = toUInt(); uint32_t v = toUInt();
@@ -1049,7 +1084,7 @@ V3Number& V3Number::opShiftR (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opShiftRS (const V3Number& lhs, const V3Number& rhs) {
// L(lhs) bit return // L(lhs) bit return
// The spec says a unsigned >>> still acts as a normal >>. // The spec says a unsigned >>> still acts as a normal >>.
// We presume it is signed; as that's V3Signed's job to convert to opShiftR // We presume it is signed; as that's V3Width's job to convert to opShiftR
if (rhs.isFourState()) return setAllBitsX(); if (rhs.isFourState()) return setAllBitsX();
setZero(); setZero();
uint32_t rhsval = rhs.toUInt(); uint32_t rhsval = rhs.toUInt();
@@ -1079,12 +1114,12 @@ V3Number& V3Number::opAbsS (const V3Number& lhs) {
// op i, L(lhs) bit return // op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX(); if (lhs.isFourState()) return setAllBitsX();
if (lhs.isNegative()) { if (lhs.isNegative()) {
return opUnaryMin(lhs); return opNegate(lhs);
} else { } else {
return opAssign(lhs); return opAssign(lhs);
} }
} }
V3Number& V3Number::opUnaryMin (const V3Number& lhs) { V3Number& V3Number::opNegate (const V3Number& lhs) {
// op i, L(lhs) bit return // op i, L(lhs) bit return
if (lhs.isFourState()) return setAllBitsX(); if (lhs.isFourState()) return setAllBitsX();
V3Number notlhs (lhs.m_fileline, width()); V3Number notlhs (lhs.m_fileline, width());
@@ -1112,7 +1147,7 @@ V3Number& V3Number::opSub (const V3Number& lhs, const V3Number& rhs) {
// i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return // i op j, max(L(lhs),L(rhs)) bit return, if any 4-state, 4-state return
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
V3Number negrhs (rhs.m_fileline, rhs.width()); V3Number negrhs (rhs.m_fileline, rhs.width());
negrhs.opUnaryMin(rhs); negrhs.opNegate(rhs);
return opAdd(lhs, negrhs); return opAdd(lhs, negrhs);
} }
V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
@@ -1140,12 +1175,12 @@ V3Number& V3Number::opMul (const V3Number& lhs, const V3Number& rhs) {
V3Number& V3Number::opMulS (const V3Number& lhs, const V3Number& rhs) { V3Number& V3Number::opMulS (const V3Number& lhs, const V3Number& rhs) {
// Signed multiply // Signed multiply
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs); V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs); V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opMul(lhsNoSign,rhsNoSign); V3Number qNoSign = opMul(lhsNoSign,rhsNoSign);
if ((lhs.isNegative() && !rhs.isNegative()) if ((lhs.isNegative() && !rhs.isNegative())
|| (!lhs.isNegative() && rhs.isNegative())) { || (!lhs.isNegative() && rhs.isNegative())) {
opUnaryMin(qNoSign); opNegate(qNoSign);
} else { } else {
opAssign(qNoSign); opAssign(qNoSign);
} }
@@ -1169,13 +1204,13 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
//UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl); //UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl);
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX(); if (rhs.isEqZero()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs); V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs); V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign); V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign);
//UINFO(9, " >divs-mid "<<lhs<<" "<<rhs<<" "<<qNoSign<<endl); //UINFO(9, " >divs-mid "<<lhs<<" "<<rhs<<" "<<qNoSign<<endl);
if ((lhs.isNegative() && !rhs.isNegative()) if ((lhs.isNegative() && !rhs.isNegative())
|| (!lhs.isNegative() && rhs.isNegative())) { || (!lhs.isNegative() && rhs.isNegative())) {
opUnaryMin(qNoSign); opNegate(qNoSign);
} else { } else {
opAssign(qNoSign); opAssign(qNoSign);
} }
@@ -1198,11 +1233,11 @@ V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
// Signed moddiv // Signed moddiv
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX(); if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
if (rhs.isEqZero()) return setAllBitsX(); if (rhs.isEqZero()) return setAllBitsX();
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs); V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs); V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign); V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign);
if (lhs.isNegative()) { // Just lhs' sign (*DIFFERENT FROM PERL, which uses rhs sign*) if (lhs.isNegative()) { // Just lhs' sign (*DIFFERENT FROM PERL, which uses rhs sign*)
opUnaryMin(qNoSign); opNegate(qNoSign);
} else { } else {
opAssign(qNoSign); opAssign(qNoSign);
} }
@@ -1434,3 +1469,74 @@ V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3
} }
return *this; return *this;
} }
//======================================================================
// Ops - Floating point
V3Number& V3Number::opIToRD (const V3Number& lhs) {
return setDouble(lhs.toSInt());
}
V3Number& V3Number::opRToIS (const V3Number& lhs) {
double v = VL_TRUNC(lhs.toDouble());
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
return setLongS(i);
}
V3Number& V3Number::opRToIRoundS (const V3Number& lhs) {
double v = VL_ROUND(lhs.toDouble());
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
return setLongS(i);
}
V3Number& V3Number::opRealToBits (const V3Number& lhs) {
// Conveniently our internal format is identical so we can copy bits...
if (lhs.width()!=64 || this->width()!=64) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
return opAssign(lhs);
}
V3Number& V3Number::opBitsToRealD (const V3Number& lhs) {
// Conveniently our internal format is identical so we can copy bits...
if (lhs.width()!=64 || this->width()!=64) {
m_fileline->v3fatalSrc("Real operation on wrong sized number");
}
return opAssign(lhs);
}
V3Number& V3Number::opNegateD (const V3Number& lhs) {
return setDouble(- lhs.toDouble());
}
V3Number& V3Number::opAddD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() + rhs.toDouble());
}
V3Number& V3Number::opSubD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() - rhs.toDouble());
}
V3Number& V3Number::opMulD (const V3Number& lhs, const V3Number& rhs) {
return setDouble(lhs.toDouble() * rhs.toDouble());
}
V3Number& V3Number::opDivD (const V3Number& lhs, const V3Number& rhs) {
// On exceptions, we just generate 'inf' through floating point
// IEEE says it's implementation defined what happens
return setDouble(lhs.toDouble() / rhs.toDouble());
}
V3Number& V3Number::opPowD (const V3Number& lhs, const V3Number& rhs) {
// On exceptions, we just generate 'inf' through floating point
// IEEE says it's implementation defined what happens
return setDouble(pow(lhs.toDouble(), rhs.toDouble()));
}
V3Number& V3Number::opEqD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() == rhs.toDouble());
}
V3Number& V3Number::opNeqD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() != rhs.toDouble());
}
V3Number& V3Number::opGtD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() > rhs.toDouble());
}
V3Number& V3Number::opGteD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() >= rhs.toDouble());
}
V3Number& V3Number::opLtD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() < rhs.toDouble());
}
V3Number& V3Number::opLteD (const V3Number& lhs, const V3Number& rhs) {
return setSingleBits(lhs.toDouble() <= rhs.toDouble());
}
+46 -3
View File
@@ -35,13 +35,13 @@ class V3Number {
int m_width; // Width as specified/calculated. int m_width; // Width as specified/calculated.
bool m_sized:1; // True if the user specified the width, else we track it. bool m_sized:1; // True if the user specified the width, else we track it.
bool m_signed:1; // True if signed value bool m_signed:1; // True if signed value
bool m_double:1; // True if double real value
bool m_fromString:1; // True if from string bool m_fromString:1; // True if from string
bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width
FileLine* m_fileline; FileLine* m_fileline;
vector<uint32_t> m_value; // The Value, with bit 0 being in bit 0 of this vector (unless X/Z) vector<uint32_t> m_value; // The Value, with bit 0 being in bit 0 of this vector (unless X/Z)
vector<uint32_t> m_valueX; // Each bit is true if it's X or Z, 10=z, 11=x vector<uint32_t> m_valueX; // Each bit is true if it's X or Z, 10=z, 11=x
// METHODS // METHODS
void init(FileLine* fileline, int width);
V3Number& setSingleBits(char value); V3Number& setSingleBits(char value);
void opCleanThis(); void opCleanThis();
public: public:
@@ -50,6 +50,8 @@ public:
V3Number& setZero(); V3Number& setZero();
V3Number& setQuad(vluint64_t value); V3Number& setQuad(vluint64_t value);
V3Number& setLong(uint32_t value); V3Number& setLong(uint32_t value);
V3Number& setLongS(vlsint32_t value);
V3Number& setDouble(double value);
void setBit (int bit, char value) { // Note must be pre-zeroed! void setBit (int bit, char value) { // Note must be pre-zeroed!
if (bit>=m_width) return; if (bit>=m_width) return;
if (value=='0'||value==0) m_value [bit/32] &= ~(1UL<<(bit&31)); if (value=='0'||value==0) m_value [bit/32] &= ~(1UL<<(bit&31));
@@ -115,6 +117,27 @@ public:
V3Number(FileLine* fileline, const char* source); // Create from a verilog 32'hxxxx number. V3Number(FileLine* fileline, const char* source); // Create from a verilog 32'hxxxx number.
V3Number(VerilogString, FileLine* fileline, const string& vvalue); V3Number(VerilogString, FileLine* fileline, const string& vvalue);
private:
void init(FileLine* fileline, int swidth) {
m_fileline = fileline;
m_signed = false;
m_double = false;
m_autoExtend = false;
m_fromString = false;
width(swidth);
for (int i=0; i<words(); i++) m_value[i]=m_valueX[i] = 0;
}
public:
void width(int width, bool sized=true) {
// Set width. Only set m_width here, as we need to tweak vector size
if (width) { m_sized = sized; m_width=width; }
else { m_sized = false; m_width=1; }
if (VL_UNLIKELY(m_value.size() < (unsigned)(words()+1))) {
m_value.resize(words()+1);
m_valueX.resize(words()+1);
}
}
// SETTERS // SETTERS
V3Number& setAllBitsX(); V3Number& setAllBitsX();
V3Number& setAllBitsZ(); V3Number& setAllBitsZ();
@@ -132,6 +155,7 @@ public:
bool autoExtend() const { return m_autoExtend; } bool autoExtend() const { return m_autoExtend; }
bool isFromString() const { return m_fromString; } bool isFromString() const { return m_fromString; }
bool isSigned() const { return m_signed; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned()) bool isSigned() const { return m_signed; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
bool isDouble() const { return m_double; } // Only correct for parsing of numbers from strings, otherwise not used (use AstConst::isSigned())
bool isNegative() const { return bitIs1(width()-1); } bool isNegative() const { return bitIs1(width()-1); }
bool isFourState() const { for (int i=0;i<words();i++) {if (m_valueX[i]) return true;} return false; } bool isFourState() const { for (int i=0;i<words();i++) {if (m_valueX[i]) return true;} return false; }
bool hasZ() const { for(int i=0;i<words();i++) {if((~m_value[i]) & m_valueX[i]) return true;} return false;} bool hasZ() const { for(int i=0;i<words();i++) {if((~m_value[i]) & m_valueX[i]) return true;} return false;}
@@ -143,7 +167,6 @@ public:
bool isEqAllOnes(int optwidth=0) const; bool isEqAllOnes(int optwidth=0) const;
bool isCaseEq(const V3Number& rhsp) const; // operator== bool isCaseEq(const V3Number& rhsp) const; // operator==
bool isLt(const V3Number& rhsp) const; // operator< bool isLt(const V3Number& rhsp) const; // operator<
void width(int width, bool sized=true);
void isSigned(bool ssigned) { m_signed=ssigned; } void isSigned(bool ssigned) { m_signed=ssigned; }
bool isUnknown() const; bool isUnknown() const;
uint32_t toUInt() const; uint32_t toUInt() const;
@@ -151,6 +174,7 @@ public:
vluint64_t toUQuad() const; vluint64_t toUQuad() const;
vlsint64_t toSQuad() const; vlsint64_t toSQuad() const;
string toString() const; string toString() const;
double toDouble() const;
uint32_t toHash() const; uint32_t toHash() const;
uint32_t dataWord(int word) const; uint32_t dataWord(int word) const;
uint32_t countOnes() const; uint32_t countOnes() const;
@@ -203,7 +227,7 @@ public:
V3Number& opLogAnd (const V3Number& lhs, const V3Number& rhs); V3Number& opLogAnd (const V3Number& lhs, const V3Number& rhs);
V3Number& opLogOr (const V3Number& lhs, const V3Number& rhs); V3Number& opLogOr (const V3Number& lhs, const V3Number& rhs);
V3Number& opAbsS (const V3Number& lhs); V3Number& opAbsS (const V3Number& lhs);
V3Number& opUnaryMin(const V3Number& lhs); V3Number& opNegate (const V3Number& lhs);
V3Number& opAdd (const V3Number& lhs, const V3Number& rhs); V3Number& opAdd (const V3Number& lhs, const V3Number& rhs);
V3Number& opSub (const V3Number& lhs, const V3Number& rhs); V3Number& opSub (const V3Number& lhs, const V3Number& rhs);
V3Number& opMul (const V3Number& lhs, const V3Number& rhs); V3Number& opMul (const V3Number& lhs, const V3Number& rhs);
@@ -236,6 +260,25 @@ public:
V3Number& opLte (const V3Number& lhs, const V3Number& rhs); V3Number& opLte (const V3Number& lhs, const V3Number& rhs);
V3Number& opLteS (const V3Number& lhs, const V3Number& rhs); // Signed V3Number& opLteS (const V3Number& lhs, const V3Number& rhs); // Signed
// "D" - double (aka real) math
V3Number& opIToRD (const V3Number& lhs);
V3Number& opRToIS (const V3Number& lhs);
V3Number& opRToIRoundS (const V3Number& lhs);
V3Number& opRealToBits (const V3Number& lhs);
V3Number& opBitsToRealD(const V3Number& lhs);
V3Number& opNegateD (const V3Number& lhs);
V3Number& opAddD (const V3Number& lhs, const V3Number& rhs);
V3Number& opSubD (const V3Number& lhs, const V3Number& rhs);
V3Number& opMulD (const V3Number& lhs, const V3Number& rhs);
V3Number& opDivD (const V3Number& lhs, const V3Number& rhs);
V3Number& opPowD (const V3Number& lhs, const V3Number& rhs);
// Comparisons
V3Number& opEqD (const V3Number& lhs, const V3Number& rhs);
V3Number& opNeqD (const V3Number& lhs, const V3Number& rhs);
V3Number& opGtD (const V3Number& lhs, const V3Number& rhs);
V3Number& opGteD (const V3Number& lhs, const V3Number& rhs);
V3Number& opLtD (const V3Number& lhs, const V3Number& rhs);
V3Number& opLteD (const V3Number& lhs, const V3Number& rhs);
}; };
inline ostream& operator<<(ostream& os, V3Number rhs) { return os<<rhs.ascii(); } inline ostream& operator<<(ostream& os, V3Number rhs) { return os<<rhs.ascii(); }
+3 -3
View File
@@ -51,7 +51,7 @@ void test(string lhss, string op, string rhss, string exps) {
else if (op=="repl") gotnum.opRepl (lhnum,rhnum); else if (op=="repl") gotnum.opRepl (lhnum,rhnum);
else if (op=="~") gotnum.opNot (lhnum); else if (op=="~") gotnum.opNot (lhnum);
else if (op=="!") gotnum.opLogNot (lhnum); else if (op=="!") gotnum.opLogNot (lhnum);
else if (op=="unaryMin") gotnum.opUnaryMin (lhnum); else if (op=="negate") gotnum.opNegate (lhnum);
else if (op=="+") gotnum.opAdd (lhnum,rhnum); else if (op=="+") gotnum.opAdd (lhnum,rhnum);
else if (op=="-") gotnum.opSub (lhnum,rhnum); else if (op=="-") gotnum.opSub (lhnum,rhnum);
else if (op=="*") gotnum.opMul (lhnum,rhnum); else if (op=="*") gotnum.opMul (lhnum,rhnum);
@@ -96,8 +96,8 @@ int main() {
test("32'b0x","|","32'b10","32'b1x"); test("32'b0x","|","32'b10","32'b1x");
test("32'b10","&","32'b11","32'b10"); test("32'b10","&","32'b11","32'b10");
test("32'b10","+","32'b10","32'b100"); test("32'b10","+","32'b10","32'b100");
test("3'b000","unaryMin","","3'b000"); test("3'b000","negate","","3'b000");
test("3'b001","unaryMin","","3'b111"); test("3'b001","negate","","3'b111");
test("32'b11","-","32'b001","32'b10"); test("32'b11","-","32'b001","32'b10");
test("3'b000","-","3'b111","3'b001"); test("3'b000","-","3'b111","3'b001");
test("3'b000","-","3'b000","3'b000"); test("3'b000","-","3'b000","3'b000");
+93 -46
View File
@@ -51,17 +51,29 @@ struct V3OptionsImp {
// STATE // STATE
list<string> m_allArgs; // List of every argument encountered list<string> m_allArgs; // List of every argument encountered
list<string> m_incDirs; // Include directories (ordered) list<string> m_incDirUsers; // Include directories (ordered)
set<string> m_incDirSet; // Include directories (for removing duplicates) set<string> m_incDirUserSet; // Include directories (for removing duplicates)
list<string> m_incDirFallbacks; // Include directories (ordered)
set<string> m_incDirFallbackSet; // Include directories (for removing duplicates)
list<string> m_libExts; // Library extensions (ordered) list<string> m_libExts; // Library extensions (ordered)
set<string> m_libExtSet; // Library extensions (for removing duplicates) set<string> m_libExtSet; // Library extensions (for removing duplicates)
DirMap m_dirMap; // Directory listing DirMap m_dirMap; // Directory listing
// ACCESSOR METHODS // ACCESSOR METHODS
void addIncDir(const string& incdir) { void addIncDirUser(const string& incdir) {
if (m_incDirSet.find(incdir) == m_incDirSet.end()) { if (m_incDirUserSet.find(incdir) == m_incDirUserSet.end()) {
m_incDirSet.insert(incdir); m_incDirUserSet.insert(incdir);
m_incDirs.push_back(incdir); m_incDirUsers.push_back(incdir);
m_incDirFallbacks.remove(incdir); // User has priority over Fallback
m_incDirFallbackSet.erase(incdir); // User has priority over Fallback
}
}
void addIncDirFallback(const string& incdir) {
if (m_incDirUserSet.find(incdir) == m_incDirUserSet.end()) { // User has priority over Fallback
if (m_incDirFallbackSet.find(incdir) == m_incDirFallbackSet.end()) {
m_incDirFallbackSet.insert(incdir);
m_incDirFallbacks.push_back(incdir);
}
} }
} }
void addLibExt(const string& libext) { void addLibExt(const string& libext) {
@@ -73,8 +85,11 @@ struct V3OptionsImp {
V3OptionsImp() {} V3OptionsImp() {}
}; };
void V3Options::addIncDir(const string& incdir) { void V3Options::addIncDirUser(const string& incdir) {
m_impp->addIncDir(incdir); m_impp->addIncDirUser(incdir);
}
void V3Options::addIncDirFallback(const string& incdir) {
m_impp->addIncDirFallback(incdir);
} }
void V3Options::addLibExt(const string& libext) { void V3Options::addLibExt(const string& libext) {
m_impp->addLibExt(libext); m_impp->addLibExt(libext);
@@ -288,42 +303,68 @@ string V3Options::fileExists (const string& filename) {
return filenameOut; return filenameOut;
} }
string V3Options::filePath (FileLine* fl, const string& modname, const string& errmsg) { string V3Options::filePathCheckOneDir(const string& modname, const string& dirname) {
// Find a filename to read the specified module name, for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
// using the incdir and libext's. string fn = filenameFromDirBase(dirname, modname+*extIter);
// Return "" if not found. string exists = fileExists(fn);
for (list<string>::iterator dirIter=m_impp->m_incDirs.begin(); dirIter!=m_impp->m_incDirs.end(); ++dirIter) { if (exists!="") {
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) { // Strip ./, it just looks ugly
string fn = filenameFromDirBase(*dirIter,modname+*extIter); if (exists.substr(0,2)=="./") exists.erase(0,2);
string exists = fileExists(fn); return exists;
if (exists!="") {
// Strip ./, it just looks ugly
if (exists.substr(0,2)=="./") exists.erase(0,2);
return exists;
}
}
}
// Warn and return not found
fl->v3error(errmsg+modname);
static bool shown_notfound_msg = false;
if (!shown_notfound_msg) {
shown_notfound_msg = true;
if (m_impp->m_incDirs.empty()) {
fl->v3error("This may be because there's no search path specified with -I<dir>."<<endl);
} else {
fl->v3error("Looked in:"<<endl);
for (list<string>::iterator dirIter=m_impp->m_incDirs.begin(); dirIter!=m_impp->m_incDirs.end(); ++dirIter) {
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
fl->v3error(" "<<fn<<endl);
}
}
} }
} }
return ""; return "";
} }
string V3Options::filePath (FileLine* fl, const string& modname,
const string& errmsg) { // Error prefix or "" to suppress error
// Find a filename to read the specified module name,
// using the incdir and libext's.
// Return "" if not found.
for (list<string>::iterator dirIter=m_impp->m_incDirUsers.begin();
dirIter!=m_impp->m_incDirUsers.end(); ++dirIter) {
string exists = filePathCheckOneDir(modname, *dirIter);
if (exists!="") return exists;
}
for (list<string>::iterator dirIter=m_impp->m_incDirFallbacks.begin();
dirIter!=m_impp->m_incDirFallbacks.end(); ++dirIter) {
string exists = filePathCheckOneDir(modname, *dirIter);
if (exists!="") return exists;
}
// Warn and return not found
if (errmsg != "") {
fl->v3error(errmsg+modname);
filePathLookedMsg(fl, modname);
}
return "";
}
void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
static bool shown_notfound_msg = false;
if (!shown_notfound_msg) {
shown_notfound_msg = true;
if (m_impp->m_incDirUsers.empty()) {
fl->v3error("This may be because there's no search path specified with -I<dir>."<<endl);
}
fl->v3error("Looked in:"<<endl);
for (list<string>::iterator dirIter=m_impp->m_incDirUsers.begin();
dirIter!=m_impp->m_incDirUsers.end(); ++dirIter) {
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
fl->v3error(" "<<fn<<endl);
}
}
for (list<string>::iterator dirIter=m_impp->m_incDirFallbacks.begin();
dirIter!=m_impp->m_incDirFallbacks.end(); ++dirIter) {
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
string fn = filenameFromDirBase(*dirIter,modname+*extIter);
fl->v3error(" "<<fn<<endl);
}
}
}
}
void V3Options::unlinkRegexp(const string& dir, const string& regexp) { void V3Options::unlinkRegexp(const string& dir, const string& regexp) {
if (DIR* dirp = opendir(dir.c_str())) { if (DIR* dirp = opendir(dir.c_str())) {
while (struct dirent* direntp = readdir(dirp)) { while (struct dirent* direntp = readdir(dirp)) {
@@ -528,6 +569,11 @@ string V3Options::version() {
return ver; return ver;
} }
void V3Options::throwSigsegv() {
// cppcheck-suppress nullPointer
char* zp=NULL; *zp=0;
}
//###################################################################### //######################################################################
// V3 Options utilities // V3 Options utilities
@@ -561,7 +607,7 @@ void V3Options::parseOpts (FileLine* fl, int argc, char** argv) {
if (modPrefix()=="") m_modPrefix = prefix(); if (modPrefix()=="") m_modPrefix = prefix();
// Find files in makedir // Find files in makedir
addIncDir(makeDir()); addIncDirFallback(makeDir());
} }
//====================================================================== //======================================================================
@@ -599,7 +645,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
addDefine (string (sw+strlen("+define+"))); addDefine (string (sw+strlen("+define+")));
} }
else if ( !strncmp (sw, "+incdir+", 8)) { else if ( !strncmp (sw, "+incdir+", 8)) {
addIncDir (parseFileArg(optdir, string (sw+strlen("+incdir+")))); addIncDirUser (parseFileArg(optdir, string (sw+strlen("+incdir+"))));
} }
else if ( !strncmp (sw, "+libext+", 8)) { else if ( !strncmp (sw, "+libext+", 8)) {
string exts = string(sw+strlen("+libext+")); string exts = string(sw+strlen("+libext+"));
@@ -643,7 +689,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if ( onoff (sw, "-covsp", flag/*ref*/) ) { } // TBD else if ( onoff (sw, "-covsp", flag/*ref*/) ) { } // TBD
else if ( !strcmp (sw, "-debug-abort") ) { abort(); } // Undocumented, see also --debug-sigsegv else if ( !strcmp (sw, "-debug-abort") ) { abort(); } // Undocumented, see also --debug-sigsegv
else if ( onoff (sw, "-debug-check", flag/*ref*/) ){ m_debugCheck = flag; } else if ( onoff (sw, "-debug-check", flag/*ref*/) ){ m_debugCheck = flag; }
else if ( !strcmp (sw, "-debug-sigsegv") ) { char* zp=NULL; *zp=0; } // Undocumented, see also --debug-abort else if ( !strcmp (sw, "-debug-sigsegv") ) { throwSigsegv(); } // Undocumented, see also --debug-abort
else if ( !strcmp (sw, "-debug-fatalsrc") ) { v3fatalSrc("--debug-fatal-src"); } // Undocumented, see also --debug-abort else if ( !strcmp (sw, "-debug-fatalsrc") ) { v3fatalSrc("--debug-fatal-src"); } // Undocumented, see also --debug-abort
else if ( onoff (sw, "-dump-tree", flag/*ref*/) ) { m_dumpTree = flag; } else if ( onoff (sw, "-dump-tree", flag/*ref*/) ) { m_dumpTree = flag; }
else if ( onoff (sw, "-exe", flag/*ref*/) ) { m_exe = flag; } else if ( onoff (sw, "-exe", flag/*ref*/) ) { m_exe = flag; }
@@ -722,7 +768,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
m_errorLimit = atoi(argv[i]); m_errorLimit = atoi(argv[i]);
} }
else if ( !strncmp (sw, "-I", 2)) { else if ( !strncmp (sw, "-I", 2)) {
addIncDir (parseFileArg(optdir, string (sw+strlen("-I")))); addIncDirUser (parseFileArg(optdir, string (sw+strlen("-I"))));
} }
else if ( !strcmp (sw, "-if-depth") && (i+1)<argc ) { else if ( !strcmp (sw, "-if-depth") && (i+1)<argc ) {
shift; shift;
@@ -747,7 +793,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
} }
else if ( !strcmp (sw, "-Mdir") && (i+1)<argc ) { else if ( !strcmp (sw, "-Mdir") && (i+1)<argc ) {
shift; m_makeDir = argv[i]; shift; m_makeDir = argv[i];
addIncDir (string (m_makeDir)); // Need to find generated files there too addIncDirFallback (string (m_makeDir)); // Need to find generated files there too
} }
else if ( !strcmp (sw, "-o") && (i+1)<argc ) { else if ( !strcmp (sw, "-o") && (i+1)<argc ) {
shift; m_exeName = argv[i]; shift; m_exeName = argv[i];
@@ -913,7 +959,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
} }
} }
else if ( !strcmp (sw, "-y") && (i+1)<argc ) { else if ( !strcmp (sw, "-y") && (i+1)<argc ) {
shift; addIncDir (parseFileArg(optdir,string (argv[i]))); shift; addIncDirUser (parseFileArg(optdir,string (argv[i])));
} }
else { else {
fl->v3fatal ("Invalid Option: "<<argv[i]); fl->v3fatal ("Invalid Option: "<<argv[i]);
@@ -973,6 +1019,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) {
break; // Ignore to EOL break; // Ignore to EOL
} else if (*pos=='/' && *(pos+1)=='*') { } else if (*pos=='/' && *(pos+1)=='*') {
inCmt = true; inCmt = true;
// cppcheck-suppress StlMissingComparison
++pos; ++pos;
} else { } else {
oline += *pos; oline += *pos;
@@ -1127,7 +1174,7 @@ V3Options::V3Options() {
addLibExt(".v"); addLibExt(".v");
addLibExt(".sv"); addLibExt(".sv");
// Default -I // Default -I
addIncDir("."); // Looks better than {long_cwd_path}/... addIncDirFallback("."); // Looks better than {long_cwd_path}/...
} }
V3Options::~V3Options() { V3Options::~V3Options() {
+8 -2
View File
@@ -178,10 +178,11 @@ class V3Options {
private: private:
// METHODS // METHODS
void addArg(const string& incdir); void addArg(const string& flag);
void addDefine(const string& defline); void addDefine(const string& defline);
void addFuture(const string& flag); void addFuture(const string& flag);
void addIncDir(const string& incdir); void addIncDirUser(const string& incdir); // User requested
void addIncDirFallback(const string& incdir); // Low priority if not found otherwise
void addLibExt(const string& libext); void addLibExt(const string& libext);
void optimize(int level); void optimize(int level);
void showVersion(bool verbose); void showVersion(bool verbose);
@@ -189,6 +190,7 @@ class V3Options {
bool onoff(const char* sw, const char* arg, bool& flag); bool onoff(const char* sw, const char* arg, bool& flag);
bool suffixed(const char* sw, const char* arg); bool suffixed(const char* sw, const char* arg);
string parseFileArg(const string& optdir, const string& relfilename); string parseFileArg(const string& optdir, const string& relfilename);
string filePathCheckOneDir(const string& modname, const string& dirname);
static bool wildmatchi(const char* s, const char* p); static bool wildmatchi(const char* s, const char* p);
static string getenvStr(const string& envvar, const string& defaultValue); static string getenvStr(const string& envvar, const string& defaultValue);
@@ -345,8 +347,12 @@ class V3Options {
// METHODS (file utilities using these options) // METHODS (file utilities using these options)
string fileExists (const string& filename); string fileExists (const string& filename);
string filePath (FileLine* fl, const string& modname, const string& errmsg); string filePath (FileLine* fl, const string& modname, const string& errmsg);
void filePathLookedMsg(FileLine* fl, const string& modname);
static bool fileStatDir (const string& filename); static bool fileStatDir (const string& filename);
static bool fileStatNormal (const string& filename); static bool fileStatNormal (const string& filename);
// METHODS (other OS)
static void throwSigsegv();
}; };
//###################################################################### //######################################################################
+6 -3
View File
@@ -148,7 +148,7 @@ private:
public: public:
OrderMoveDomScope(OrderLoopId inLoop, AstSenTree* domainp, AstScope* scopep) OrderMoveDomScope(OrderLoopId inLoop, AstSenTree* domainp, AstScope* scopep)
: m_onReadyList(false), m_domainp(domainp), m_inLoop(inLoop) {} : m_onReadyList(false), m_domainp(domainp), m_scopep(scopep), m_inLoop(inLoop) {}
OrderMoveDomScope* readyDomScopeNextp() const { return m_readyDomScopeE.nextp(); } OrderMoveDomScope* readyDomScopeNextp() const { return m_readyDomScopeE.nextp(); }
OrderLoopId inLoop() const { return m_inLoop; } OrderLoopId inLoop() const { return m_inLoop; }
AstSenTree* domainp() const { return m_domainp; } AstSenTree* domainp() const { return m_domainp; }
@@ -391,8 +391,8 @@ private:
void nodeMarkCircular(OrderVarVertex* vertexp, OrderEdge* edgep) { void nodeMarkCircular(OrderVarVertex* vertexp, OrderEdge* edgep) {
AstVarScope* nodep = vertexp->varScp(); AstVarScope* nodep = vertexp->varScp();
nodep->circular(true); nodep->circular(true);
m_statCut[vertexp->type()]++; ++m_statCut[vertexp->type()];
if (edgep) m_statCut[edgep->type()]++; if (edgep) ++m_statCut[edgep->type()];
if (vertexp->isClock()) { if (vertexp->isClock()) {
// Seems obvious; no warning yet // Seems obvious; no warning yet
//nodep->v3warn(GENCLK,"Signal unoptimizable: Generated clock: "<<nodep->prettyName()); //nodep->v3warn(GENCLK,"Signal unoptimizable: Generated clock: "<<nodep->prettyName());
@@ -715,6 +715,9 @@ public:
m_settleDomainp = NULL; m_settleDomainp = NULL;
m_settleVxp = NULL; m_settleVxp = NULL;
m_inputsVxp = NULL; m_inputsVxp = NULL;
m_activeSenVxp = NULL;
m_logicVxp = NULL;
m_pomNewFuncp = NULL;
m_loopIdMax = LOOPID_FIRST; m_loopIdMax = LOOPID_FIRST;
m_pomNewStmts = 0; m_pomNewStmts = 0;
if (debug()) m_graph.debug(5); // 3 is default if global debug; we want acyc debugging if (debug()) m_graph.debug(5); // 3 is default if global debug; we want acyc debugging
+1 -1
View File
@@ -105,7 +105,7 @@ struct OrderVEdgeType {
return names[m_e]; return names[m_e];
} }
enum en m_e; enum en m_e;
inline OrderVEdgeType () {} inline OrderVEdgeType () : m_e(VERTEX_UNKNOWN) {}
inline OrderVEdgeType (en _e) : m_e(_e) {} inline OrderVEdgeType (en _e) : m_e(_e) {}
explicit inline OrderVEdgeType (int _e) : m_e(static_cast<en>(_e)) {} explicit inline OrderVEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
operator en () const { return m_e; } operator en () const { return m_e; }
-1
View File
@@ -43,7 +43,6 @@
#include "V3Case.h" #include "V3Case.h"
#include "V3Const.h" #include "V3Const.h"
#include "V3Width.h" #include "V3Width.h"
#include "V3Signed.h"
#include "V3Unroll.h" #include "V3Unroll.h"
//###################################################################### //######################################################################
+2 -1
View File
@@ -45,7 +45,8 @@ public:
// METHODS // METHODS
// Preprocess and read the Verilog file specified into the netlist database // Preprocess and read the Verilog file specified into the netlist database
void parseFile(FileLine* fileline, const string& modname, bool inLibrary); void parseFile(FileLine* fileline, const string& modname, bool inLibrary,
const string& errmsg);
// Push preprocessed text to the lexer // Push preprocessed text to the lexer
static void ppPushText(V3ParseImp* impp, const string& text); static void ppPushText(V3ParseImp* impp, const string& text);
+13 -4
View File
@@ -89,7 +89,8 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) {
return got; return got;
} }
void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary) { void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
const string& errmsg) { // "" for no error, make fake node
string modname = V3Options::filenameNonExt(modfilename); string modname = V3Options::filenameNonExt(modfilename);
UINFO(2,__FUNCTION__<<": "<<modname<<(inLibrary?" [LIB]":"")<<endl); UINFO(2,__FUNCTION__<<": "<<modname<<(inLibrary?" [LIB]":"")<<endl);
@@ -104,7 +105,14 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i
} }
// Preprocess into m_ppBuffer // Preprocess into m_ppBuffer
V3PreShell::preproc(fileline, modfilename, m_filterp, this); bool ok = V3PreShell::preproc(fileline, modfilename, m_filterp, this, errmsg);
if (!ok) {
if (errmsg != "") return; // Threw error already
// Create fake node for later error reporting
AstNodeModule* nodep = new AstNotFoundModule(fileline, modname);
v3Global.rootp()->addModulep(nodep);
return;
}
if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) { if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) {
// Create output file with all the preprocessor output we buffered up // Create output file with all the preprocessor output we buffered up
@@ -157,8 +165,9 @@ V3Parse::V3Parse(AstNetlist* rootp, V3InFilter* filterp) {
V3Parse::~V3Parse() { V3Parse::~V3Parse() {
delete m_impp; m_impp = NULL; delete m_impp; m_impp = NULL;
} }
void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary) { void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary,
m_impp->parseFile(fileline, modname, inLibrary); const string& errmsg) {
m_impp->parseFile(fileline, modname, inLibrary, errmsg);
} }
void V3Parse::ppPushText(V3ParseImp* impp, const string& text) { void V3Parse::ppPushText(V3ParseImp* impp, const string& text) {
impp->ppPushText(text); impp->ppPushText(text);
+12 -9
View File
@@ -254,9 +254,10 @@ public:
void verilatorCmtLintSave(); void verilatorCmtLintSave();
void verilatorCmtLintRestore(); void verilatorCmtLintRestore();
void verilatorCmtBad(const char* text); void verilatorCmtBad(const char* text);
double parseDouble(const char* text, size_t length);
void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; } void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; }
bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; } bool popBeginKeywords() { if (m_inBeginKwd) { m_inBeginKwd--; return true; } else return false; }
int lastVerilogState() { return m_lastVerilogState; } int lastVerilogState() const { return m_lastVerilogState; }
static const char* tokenName(int tok); static const char* tokenName(int tok);
void ppPushText(const string& text) { m_ppBuffers.push_back(text); } void ppPushText(const string& text) { m_ppBuffers.push_back(text); }
@@ -290,12 +291,12 @@ public:
} }
// Return next token, for bison, since bison isn't class based, use a global THIS // Return next token, for bison, since bison isn't class based, use a global THIS
FileLine* fileline() { return m_fileline; } FileLine* fileline() const { return m_fileline; }
AstNetlist* rootp() { return m_rootp; } AstNetlist* rootp() const { return m_rootp; }
FileLine* copyOrSameFileLine() { return fileline()->copyOrSameFileLine(); } FileLine* copyOrSameFileLine() { return fileline()->copyOrSameFileLine(); }
bool inCellDefine() { return m_inCellDefine; } bool inCellDefine() const { return m_inCellDefine; }
void inCellDefine(bool flag) { m_inCellDefine = flag; } void inCellDefine(bool flag) { m_inCellDefine = flag; }
bool inLibrary() { return m_inLibrary; } bool inLibrary() const { return m_inLibrary; }
// Interactions with parser // Interactions with parser
int bisonParse(); int bisonParse();
@@ -305,8 +306,8 @@ public:
void lexDestroy(); void lexDestroy();
void stateExitPsl(); // Parser -> lexer communication void stateExitPsl(); // Parser -> lexer communication
void statePushVlg(); // Parser -> lexer communication void statePushVlg(); // Parser -> lexer communication
void statePop(); // Parser -> lexer communication void statePop(); // Parser -> lexer communication
int stateVerilogRecent(); // Parser -> lexer communication static int stateVerilogRecent(); // Parser -> lexer communication
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); } size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); }
//==== Symbol tables //==== Symbol tables
@@ -315,7 +316,8 @@ public:
public: public:
// CREATORS // CREATORS
V3ParseImp(AstNetlist* rootp, V3InFilter* filterp) V3ParseImp(AstNetlist* rootp, V3InFilter* filterp)
: m_sym(rootp), m_filterp(filterp) { : m_filterp(filterp), m_sym(rootp) {
m_fileline = NULL;
m_rootp = rootp; m_lexerp = NULL; m_rootp = rootp; m_lexerp = NULL;
m_inCellDefine = false; m_inCellDefine = false;
m_inLibrary = false; m_inLibrary = false;
@@ -331,7 +333,8 @@ public:
// Preprocess and read the Verilog file specified into the netlist database // Preprocess and read the Verilog file specified into the netlist database
int lexToBison(); // Pass token to bison int lexToBison(); // Pass token to bison
void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary); void parseFile(FileLine* fileline, const string& modfilename, bool inLibrary,
const string& errmsg);
private: private:
void lexFile(const string& modname); void lexFile(const string& modname);
+1 -1
View File
@@ -62,7 +62,7 @@ public:
void V3ParseImp::stateExitPsl() { parsep()->m_lexerp->stateExitPsl(); } void V3ParseImp::stateExitPsl() { parsep()->m_lexerp->stateExitPsl(); }
void V3ParseImp::statePushVlg() { parsep()->m_lexerp->stateExitPsl(); } void V3ParseImp::statePushVlg() { parsep()->m_lexerp->stateExitPsl(); }
void V3ParseImp::statePop() { parsep()->m_lexerp->statePop(); } void V3ParseImp::statePop() { parsep()->m_lexerp->statePop(); }
int V3ParseImp::yylexThis() { parsep()->m_lexerp->yylex(); } int V3ParseImp::yylexThis() { return parsep()->m_lexerp->yylex(); }
//###################################################################### //######################################################################
// Read class functions // Read class functions
+1 -1
View File
@@ -203,7 +203,7 @@ class V3PreLex {
/// Called by V3PreProc.cpp to get data from lexer /// Called by V3PreProc.cpp to get data from lexer
YY_BUFFER_STATE currentBuffer(); YY_BUFFER_STATE currentBuffer();
int lex(); int lex();
int currentStartState(); int currentStartState() const;
void dumpSummary(); void dumpSummary();
void dumpStack(); void dumpStack();
void unused(); void unused();
+2 -1
View File
@@ -488,7 +488,7 @@ YY_BUFFER_STATE V3PreLex::currentBuffer() {
return YY_CURRENT_BUFFER; return YY_CURRENT_BUFFER;
} }
int V3PreLex::currentStartState() { int V3PreLex::currentStartState() const {
return YY_START; return YY_START;
} }
@@ -538,6 +538,7 @@ void V3PreLex::unused() {
if (0) { if (0) {
// Prevent unused warnings // Prevent unused warnings
yy_top_state(); yy_top_state();
yyerror((char*)"");
} }
} }
+8 -1
View File
@@ -127,7 +127,7 @@ struct V3PreProcImp : public V3PreProc {
ps_DEFNAME_IFDEF, ps_DEFNAME_IFNDEF, ps_DEFNAME_ELSIF, ps_DEFNAME_IFDEF, ps_DEFNAME_IFNDEF, ps_DEFNAME_ELSIF,
ps_DEFFORM, ps_DEFVALUE, ps_DEFPAREN, ps_DEFARG, ps_DEFFORM, ps_DEFVALUE, ps_DEFPAREN, ps_DEFARG,
ps_INCNAME, ps_ERRORNAME, ps_JOIN, ps_STRIFY }; ps_INCNAME, ps_ERRORNAME, ps_JOIN, ps_STRIFY };
const char* procStateName(ProcState s) { static const char* procStateName(ProcState s) {
static const char* states[] static const char* states[]
= {"ps_TOP", = {"ps_TOP",
"ps_DEFNAME_UNDEF", "ps_DEFNAME_DEFINE", "ps_DEFNAME_UNDEF", "ps_DEFNAME_DEFINE",
@@ -251,6 +251,10 @@ public:
m_finAtBol = true; m_finAtBol = true;
m_defDepth = 0; m_defDepth = 0;
m_defPutJoin = false; m_defPutJoin = false;
m_finToken = 0;
m_finFilelinep = NULL;
m_lexp = NULL;
m_preprocp = NULL;
} }
void configure(FileLine* filelinep) { void configure(FileLine* filelinep) {
// configure() separate from constructor to avoid calling abstract functions // configure() separate from constructor to avoid calling abstract functions
@@ -393,6 +397,9 @@ void V3PreProcImp::comment(const string& text) {
} else if (0==(strncmp(cp,"cadence",strlen("cadence")))) { } else if (0==(strncmp(cp,"cadence",strlen("cadence")))) {
cp+=strlen("cadence"); cp+=strlen("cadence");
synth = true; synth = true;
} else if (0==(strncmp(cp,"pragma",strlen("pragma")))) {
cp+=strlen("pragma");
synth = true;
} else if (0==(strncmp(cp,"ambit synthesis",strlen("ambit synthesis")))) { } else if (0==(strncmp(cp,"ambit synthesis",strlen("ambit synthesis")))) {
cp+=strlen("ambit synthesis"); cp+=strlen("ambit synthesis");
synth = true; synth = true;
+4 -4
View File
@@ -67,10 +67,10 @@ public:
// CONTROL METHODS // CONTROL METHODS
// These options control how the parsing proceeds // These options control how the parsing proceeds
int keepComments() { return 2; } // Return comments, 0=no, 1=yes, 2=callback static int keepComments() { return 2; } // Return comments, 0=no, 1=yes, 2=callback
bool keepWhitespace() { return false; } static bool keepWhitespace() { return false; }
bool lineDirectives() { return true; } // Insert `line directives static bool lineDirectives() { return true; } // Insert `line directives
bool pedantic() { return false; } // Obey standard; Don't substitute `error static bool pedantic() { return false; } // Obey standard; Don't substitute `error
static bool optPsl(); static bool optPsl();
// CALLBACK METHODS // CALLBACK METHODS
+14 -6
View File
@@ -74,7 +74,8 @@ protected:
} }
} }
void preproc (FileLine* fl, const string& modname, V3InFilter* filterp, V3ParseImp* parsep) { bool preproc (FileLine* fl, const string& modname, V3InFilter* filterp, V3ParseImp* parsep,
const string& errmsg) { // "" for no error
debug(true); // Recheck if debug on - first check was before command line passed debug(true); // Recheck if debug on - first check was before command line passed
// Preprocess the given module, putting output in vppFilename // Preprocess the given module, putting output in vppFilename
@@ -82,11 +83,14 @@ protected:
// Preprocess // Preprocess
s_filterp = filterp; s_filterp = filterp;
preprocOpen(fl, s_filterp, modname, "Cannot find file containing module: "); bool ok = preprocOpen(fl, s_filterp, modname, errmsg);
if (!ok) return false;
while (!s_preprocp->isEof()) { while (!s_preprocp->isEof()) {
string line = s_preprocp->getline(); string line = s_preprocp->getline();
V3Parse::ppPushText(parsep, line); V3Parse::ppPushText(parsep, line);
} }
return true;
} }
void preprocInclude (FileLine* fl, const string& modname) { void preprocInclude (FileLine* fl, const string& modname) {
@@ -96,17 +100,20 @@ protected:
preprocOpen(fl, s_filterp, modname, "Cannot find include file: "); preprocOpen(fl, s_filterp, modname, "Cannot find include file: ");
} }
void preprocOpen (FileLine* fl, V3InFilter* filterp, const string& modname, const string& errmsg) { bool preprocOpen (FileLine* fl, V3InFilter* filterp, const string& modname,
const string& errmsg) { // Error message or "" to suppress
// Returns true if successful
// Allow user to put `defined names on the command line instead of filenames, // Allow user to put `defined names on the command line instead of filenames,
// then convert them properly. // then convert them properly.
string ppmodname = s_preprocp->removeDefines (modname); string ppmodname = s_preprocp->removeDefines (modname);
// Open include or master file // Open include or master file
string filename = v3Global.opt.filePath (fl, ppmodname, errmsg); string filename = v3Global.opt.filePath (fl, ppmodname, errmsg);
if (filename=="") return; // Not found if (filename=="") return false; // Not found
UINFO(2," Reading "<<filename<<endl); UINFO(2," Reading "<<filename<<endl);
s_preprocp->openFile(fl, filterp, filename); s_preprocp->openFile(fl, filterp, filename);
return true;
} }
// CONSTRUCTORS // CONSTRUCTORS
@@ -124,8 +131,9 @@ V3InFilter* V3PreShellImp::s_filterp = NULL;
void V3PreShell::boot(char** env) { void V3PreShell::boot(char** env) {
V3PreShellImp::s_preImp.boot(env); V3PreShellImp::s_preImp.boot(env);
} }
void V3PreShell::preproc(FileLine* fl, const string& modname, V3InFilter* filterp, V3ParseImp* parsep) { bool V3PreShell::preproc(FileLine* fl, const string& modname, V3InFilter* filterp,
V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep); V3ParseImp* parsep, const string& errmsg) {
return V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep, errmsg);
} }
void V3PreShell::preprocInclude(FileLine* fl, const string& modname) { void V3PreShell::preprocInclude(FileLine* fl, const string& modname) {
V3PreShellImp::s_preImp.preprocInclude(fl, modname); V3PreShellImp::s_preImp.preprocInclude(fl, modname);
+2 -1
View File
@@ -36,7 +36,8 @@ class V3PreShell {
// Static class for calling preprocessor // Static class for calling preprocessor
public: public:
static void boot(char** env); static void boot(char** env);
static void preproc(FileLine* fileline, const string& module, V3InFilter* filterp, V3ParseImp* parsep); static bool preproc(FileLine* fileline, const string& module, V3InFilter* filterp,
V3ParseImp* parsep, const string& errmsg);
static void preprocInclude(FileLine* fileline, const string& module); static void preprocInclude(FileLine* fileline, const string& module);
static string dependFiles() { return ""; } // Perl only static string dependFiles() { return ""; } // Perl only
static void defineCmdLine(const string& name, const string& value); static void defineCmdLine(const string& name, const string& value);
+6 -6
View File
@@ -208,12 +208,12 @@ private:
// Then over shifting gives the sign bit, not all zeros // Then over shifting gives the sign bit, not all zeros
// Note *NOT* clean output -- just like normal shift! // Note *NOT* clean output -- just like normal shift!
// Create equivalent of VL_SIGNONES_(node_width) // Create equivalent of VL_SIGNONES_(node_width)
constzerop = new AstUnaryMin (nodep->fileline(), constzerop = new AstNegate (nodep->fileline(),
new AstShiftR(nodep->fileline(), new AstShiftR(nodep->fileline(),
nodep->lhsp()->cloneTree(false), nodep->lhsp()->cloneTree(false),
new AstConst(nodep->fileline(), new AstConst(nodep->fileline(),
nodep->widthMin()-1), nodep->widthMin()-1),
nodep->width())); nodep->width()));
} else { } else {
V3Number zeronum (nodep->fileline(), nodep->width(), 0); V3Number zeronum (nodep->fileline(), nodep->width(), 0);
constzerop = new AstConst(nodep->fileline(), zeronum); constzerop = new AstConst(nodep->fileline(), zeronum);
-450
View File
@@ -1,450 +0,0 @@
//*************************************************************************
// DESCRIPTION: Verilator: Signed/unsigned resolution
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
// Signedness depends on:
// Decimal numbers are signed
// Based numbers are unsigned unless 's' prefix
// Comparison results are unsigned
// Bit&Part selects are unsigned, even if whole
// Concatenates are unsigned
// Ignore signedness of self-determined:
// shift rhs, ** rhs, x?: lhs, concat and replicate members
// Else, if any operand unsigned, output unsigned
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include <cstdio>
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <iomanip>
#include "V3Global.h"
#include "V3Signed.h"
#include "V3Ast.h"
//######################################################################
// Signed class functions
class SignedVisitor : public AstNVisitor {
private:
// NODE STATE/TYPES
// STATE
int m_taskDepth; // Recursion check
bool m_paramsOnly; // Computing parameter value; limit operation
// METHODS - special type detection
bool backRequiresUnsigned(AstNode* nodep) {
// The spec doesn't state this, but if you have an array select where the selection
// index is NOT wide enough, you do not sign extend, but always zero extend.
return (nodep->castArraySel()
|| nodep->castSel());
}
// VISITORS
//========
// Signed: Output explicit by user, Lhs either
virtual void visit(AstSigned* nodep, AstNUser*) { signed_Os_Ix(nodep); }
virtual void visit(AstUnsigned* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//========
// Signed: Output unsigned, Operands either
virtual void visit(AstSel* nodep, AstNUser*) { signed_Ou_Ix(nodep); } //See backRequiresUnsigned
virtual void visit(AstAttrOf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstCountOnes* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstCLog2* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstPslBool* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTime* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstRedAnd* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRedOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRedXnor* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstRedXor* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstIsUnknown* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstOneHot0* nodep,AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFEof* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetC* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFGetS* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstFScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstSScanF* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstTestPlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstValuePlusArgs* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
//
virtual void visit(AstConcat* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstReplicate* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstRange* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... One presumes these are unsigned out, though the spec doesn't say
virtual void visit(AstLogNot* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogAnd* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogOr* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIf* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstLogIff* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstBufIf1* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These shouldn't matter, just make unsigned
virtual void visit(AstScopeName* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstText* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstUCFunc* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
// ... These comparisons don't care about inbound types
// ... (Though they should match. We don't check.)
virtual void visit(AstEq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqCase* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstEqWild* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeq* nodep, AstNUser*) { signed_Ou_Ix(nodep); }
virtual void visit(AstNeqCase* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
virtual void visit(AstNeqWild* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
// ... Opaque returns, so arbitrary
virtual void visit(AstCvtPackString* nodep, AstNUser*){ signed_Ou_Ix(nodep); }
//========
// Signed: Output signed
virtual void visit(AstRand* nodep, AstNUser*) { signed_Os_Ix(nodep); }
//=======
// Signed: Output signed iff LHS signed; unary operator
virtual void visit(AstNot* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstUnaryMin* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstShiftL* nodep, AstNUser*) { signed_Olhs(nodep); }
virtual void visit(AstShiftR* nodep, AstNUser*) { signed_Olhs(nodep); }
// Signed: Output signed iff LHS signed; binary operator
// Note by contrast, bit extract selects are unsigned
virtual void visit(AstArraySel* nodep, AstNUser*) { signed_Olhs(nodep); } //See backRequiresUnsigned
//=======
// Signed: Output signed iff LHS & RHS signed; binary operator
virtual void visit(AstAnd* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstOr* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstXnor* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstXor* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstSub* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
virtual void visit(AstAdd* nodep, AstNUser*) { signed_OlhsAndRhs(nodep); }
//=======
// Signed: Output signed iff RHS & THS signed
virtual void visit(AstNodeCond* nodep, AstNUser*) { signed_OrhsAndThs(nodep); }
//=======
// These have proper signedness set when they were created.
virtual void visit(AstReturn* nodep, AstNUser*) { nodep->iterateChildren(*this); }
virtual void visit(AstNodeDType* nodep, AstNUser*) { nodep->iterateChildren(*this); }
// Inherit from others
virtual void visit(AstVar* nodep, AstNUser*) {
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
if (nodep->didSigning()) return;
nodep->didSigning(true);
nodep->iterateChildren(*this);
nodep->signedFrom(nodep->dtypep());
}
virtual void visit(AstNodeVarRef* nodep, AstNUser*) {
nodep->varp()->iterate(*this);
nodep->signedFrom(nodep->varp());
}
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
nodep->itemp()->iterate(*this);
nodep->signedFrom(nodep->itemp());
}
virtual void visit(AstCast* nodep, AstNUser*) {
nodep->lhsp()->iterate(*this);
nodep->dtypep()->iterate(*this);
nodep->signedFrom(nodep->dtypep());
}
virtual void visit(AstConst* nodep, AstNUser*) {
// The node got setup with the signed state of the node.
// However a later operation may have changed the node->signed w/o changing
// the number's sign. So we don't: nodep->isSigned(nodep->num().isSigned());
}
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
// Avoid recursion; can't use user() as they're all full, and anyhow this is often called
if (nodep->didSigning()) return;
nodep->didSigning(true);
nodep->iterateChildren(*this);
if (nodep->fvarp()) {
nodep->signedFrom(nodep->fvarp()); // Which will get it from fvarp()->dtypep()
}
}
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->taskp()) nodep->taskp()->iterate(*this);
nodep->signedFrom(nodep->taskp());
}
virtual void visit(AstRefDType* nodep, AstNUser*) {
nodep->iterateChildren(*this);
if (nodep->defp()) nodep->defp()->iterate(*this);
nodep->signedFrom(nodep->skipRefp());
}
virtual void visit(AstNodeIf* nodep, AstNUser*) {
if (!nodep->castGenIf()) { // for m_paramsOnly
nodep->ifsp()->iterateAndNext(*this);
nodep->elsesp()->iterateAndNext(*this);
}
nodep->condp()->iterateAndNext(*this);
}
virtual void visit(AstPin* nodep, AstNUser*) {
// Same as above taskref argument.
nodep->iterateChildren(*this);
}
// VISITORS - Special
virtual void visit(AstSFormatF* nodep, AstNUser*) {
nodep->iterateChildren(*this);
//
UINFO(9," Display in "<<nodep->text()<<endl);
string dispout = "";
bool inPct = false;
AstNode* argp = nodep->exprsp();
for (const char* inp = nodep->text().c_str(); *inp; inp++) {
char ch = *inp; // Breaks with iterators...
if (!inPct && ch=='%') {
inPct = true;
} else if (inPct && isdigit(ch)) {
} else if (tolower(inPct)) {
inPct = false;
switch (tolower(ch)) {
case '%': break; // %% - just output a %
case 'm': break; // %m - auto insert "name"
case 'd': { // Convert decimal to either 'd' or 'u'
if (argp && argp->isSigned()) { // Convert it
ch = '~';
}
if (argp) argp=argp->nextp();
break;
}
default: // Most operators, just move to next argument
if (argp) argp=argp->nextp();
break;
} // switch
}
dispout += ch;
}
nodep->text(dispout);
UINFO(9," Display out "<<nodep->text()<<endl);
}
// VISITORS - These need to be changed to different op types
// Uniop
virtual void visit(AstExtend* nodep, AstNUser*) {
signed_Olhs(nodep);
if (nodep->isSigned() && !backRequiresUnsigned(nodep->backp())) {
replaceWithSignedVersion(nodep, new AstExtendS (nodep->fileline(), nodep->lhsp()->unlinkFrBack())); nodep=NULL;
}
}
virtual void visit(AstExtendS* nodep, AstNUser*) {
signed_Olhs(nodep);
if (!(nodep->isSigned() && !backRequiresUnsigned(nodep->backp()))) {
replaceWithSignedVersion(nodep, new AstExtend (nodep->fileline(), nodep->lhsp()->unlinkFrBack())); nodep=NULL;
}
}
// Biop
virtual void visit(AstPow* nodep, AstNUser*) {
// Pow is special, output sign only depends on LHS sign
signed_Olhs(nodep);
if (nodep->isSigned()) {
replaceWithSignedVersion(nodep, new AstPowS (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack())); nodep=NULL;
}
}
virtual void visit(AstPowS* nodep, AstNUser*) {
// Pow is special, output sign only depends on LHS sign
signed_Olhs(nodep);
if (!nodep->isSigned()) {
replaceWithSignedVersion(nodep, new AstPow (nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack())); nodep=NULL;
}
}
// These have different node types, as they operate differently
// Must add to case statement below,
virtual void visit(AstGt* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGtS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGte* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstGteS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLt* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLtS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLte* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
virtual void visit(AstLteS* nodep, AstNUser*) { checkReplace_Ou_FlavLhsAndRhs(nodep); }
// Need replacements; output matches input sign
virtual void visit(AstDiv* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstDivS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstModDiv* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstModDivS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstMul* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
virtual void visit(AstMulS* nodep, AstNUser*) { checkReplace_OlhsAndRhs(nodep); }
// ShiftRS converts to ShiftR, but not vice-versa
virtual void visit(AstShiftRS* nodep, AstNUser*) { checkReplace_Olhs(nodep); }
void checkReplace_Ou_FlavLhsAndRhs(AstNodeBiop* nodep) {
// For compares, the output of the comparison is unsigned.
// However, we need the appropriate type of compare selected by RHS & LHS
signed_Ou_Ix(nodep);
checkReplace(nodep, nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
}
void checkReplace_Olhs(AstNodeBiop* nodep) {
signed_Olhs(nodep);
checkReplace(nodep, nodep->isSigned());
}
void checkReplace_OlhsAndRhs(AstNodeBiop* nodep) {
signed_OlhsAndRhs(nodep);
checkReplace(nodep, nodep->isSigned());
}
void checkReplace(AstNodeBiop* nodep, bool signedFlavorNeeded) {
if (signedFlavorNeeded != nodep->signedFlavor()) {
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* rhsp = nodep->rhsp()->unlinkFrBack();
AstNode* newp = NULL;
// Given a signed/unsigned node type, create the opposite type
switch (nodep->type()) {
case AstType::atGT: newp = new AstGtS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTS: newp = new AstGt (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTE: newp = new AstGteS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atGTES: newp = new AstGte (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLT: newp = new AstLtS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTS: newp = new AstLt (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTE: newp = new AstLteS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atLTES: newp = new AstLte (nodep->fileline(), lhsp, rhsp); break;
case AstType::atDIV: newp = new AstDivS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atDIVS: newp = new AstDiv (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMODDIV: newp = new AstModDivS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMODDIVS: newp = new AstModDiv (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMUL: newp = new AstMulS (nodep->fileline(), lhsp, rhsp); break;
case AstType::atMULS: newp = new AstMul (nodep->fileline(), lhsp, rhsp); break;
case AstType::atSHIFTRS: newp = new AstShiftR (nodep->fileline(), lhsp, rhsp); break;
default:
nodep->v3fatalSrc("Node needs sign change, but bad case: "<<nodep<<endl);
break;
}
replaceWithSignedVersion(nodep,newp);
}
}
// VISITORS - defaults
virtual void visit(AstNodeMath* nodep, AstNUser*) {
nodep->v3fatalSrc("Visit function missing? Signedness unknown for this node: "<<nodep);
nodep->iterateChildren(*this);
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
// COMMON SCHEMES
// Signed: Output signed, Lhs/Rhs/etc either
void signed_Os_Ix(AstNode* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(true);
}
// Signed: Output unsigned, Lhs/Rhs/etx either
void signed_Ou_Ix(AstNode* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(false);
}
// Signed: Output signed iff LHS signed; unary operator
void signed_Olhs(AstNodeUniop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned());
}
// Signed: Output signed iff LHS signed; binary operator
void signed_Olhs(AstNodeBiop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned());
}
// Signed: Output signed iff LHS signed; select operator
void signed_Olhs(AstSel* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->fromp()->isSigned());
}
// Signed: Output signed iff LHS & RHS signed; binary operator
void signed_OlhsAndRhs(AstNodeBiop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned());
}
// Signed: Output signed iff RHS & THS signed
void signed_OrhsAndThs(AstNodeTriop* nodep) {
nodep->iterateChildren(*this);
nodep->isSigned(nodep->rhsp()->isSigned() && nodep->thsp()->isSigned());
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
SignedVisitor(bool paramsOnly) {
m_paramsOnly = paramsOnly;
m_taskDepth = 0;
}
virtual ~SignedVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
// Signed class functions
/// Remove all $signed, $unsigned, we're done with them.
class SignedRemoveVisitor : public AstNVisitor {
private:
// VISITORS
virtual void visit(AstSigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstUnsigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
SignedRemoveVisitor() {}
virtual ~SignedRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
// Top Signed class
void V3Signed::signedAll(AstNetlist* nodep) {
UINFO(2,__FUNCTION__<<": "<<endl);
(void)signedParamsEdit(nodep);
}
AstNode* V3Signed::signedParamsEdit(AstNode* nodep) {
// Only called from V3Width::widthParamsEdit
UINFO(4,__FUNCTION__<<": "<<endl);
SignedVisitor visitor (true);
nodep = visitor.mainAcceptEdit(nodep);
SignedRemoveVisitor rvisitor;
nodep = rvisitor.mainAcceptEdit(nodep);
return nodep;
}
-40
View File
@@ -1,40 +0,0 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Signed/unsigned resolution
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2005-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3SIGNED_H_
#define _V3SIGNED_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3Signed {
public:
static void signedAll(AstNetlist* nodep);
protected:
friend class V3Width; // Use widthParamsEdit instead of signedParamsEdit
static AstNode* signedParamsEdit(AstNode* nodep); // May replace nodep
};
#endif // Guard
+25 -9
View File
@@ -229,6 +229,7 @@ private:
// STATE // STATE
bool m_reorder; // Reorder statements vs. just splitting bool m_reorder; // Reorder statements vs. just splitting
string m_noReorderWhy; // Reason we can't reorder
VStack m_stmtStackps; // Current statements being tracked VStack m_stmtStackps; // Current statements being tracked
SplitPliVertex* m_pliVertexp; // Element specifying PLI ordering SplitPliVertex* m_pliVertexp; // Element specifying PLI ordering
V3Graph m_graph; // Scoreboard of var usages/dependencies V3Graph m_graph; // Scoreboard of var usages/dependencies
@@ -249,6 +250,7 @@ private:
m_graph.clear(); m_graph.clear();
m_stmtStackps.clear(); m_stmtStackps.clear();
m_pliVertexp = NULL; m_pliVertexp = NULL;
m_noReorderWhy = "";
AstNode::user1ClearTree(); AstNode::user1ClearTree();
AstNode::user2ClearTree(); AstNode::user2ClearTree();
AstNode::user3ClearTree(); AstNode::user3ClearTree();
@@ -336,6 +338,7 @@ private:
} }
// Weak coloring to determine what needs to remain in order // Weak coloring to determine what needs to remain in order
// This follows all step-relevant edges excluding PostEdges, which are done later
m_graph.weaklyConnected(&SplitEdge::followScoreboard); m_graph.weaklyConnected(&SplitEdge::followScoreboard);
// Add hard orderings between all nodes of same color, in the order they appeared // Add hard orderings between all nodes of same color, in the order they appeared
@@ -413,7 +416,7 @@ private:
newListp = newListp->addNext(nextp); newListp = newListp->addNext(nextp);
} }
if (splitAlwaysp) { if (splitAlwaysp) {
m_statSplits++; ++m_statSplits;
AstAlways* alwaysp = new AstAlways(newListp->fileline(), NULL, NULL); AstAlways* alwaysp = new AstAlways(newListp->fileline(), NULL, NULL);
addAfterp->addNextHere(alwaysp); addAfterp=alwaysp; addAfterp->addNextHere(alwaysp); addAfterp=alwaysp;
alwaysp->addStmtp(newListp); alwaysp->addStmtp(newListp);
@@ -445,14 +448,18 @@ private:
UINFO(9," processBlock "<<nodep<<endl); UINFO(9," processBlock "<<nodep<<endl);
// Process block and followers // Process block and followers
scanBlock(nodep); scanBlock(nodep);
// Reorder statements in this block if (m_noReorderWhy != "") { // Jump or something nasty
cleanupBlockGraph(nodep); UINFO(9," NoReorderBlock because "<<m_noReorderWhy<<endl);
reorderBlock(nodep); } else {
// Delete old vertexes and edges only applying to this block // Reorder statements in this block
while (firstp->backp()->nextp()==firstp) firstp = firstp->backp(); // Walk back to first in list cleanupBlockGraph(nodep);
for (AstNode* nextp=firstp; nextp; nextp=nextp->nextp()) { reorderBlock(nodep);
SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p(); // Delete old vertexes and edges only applying to this block
vvertexp->unlinkDelete(&m_graph); while (firstp->backp()->nextp()==firstp) firstp = firstp->backp(); // Walk back to first in list
for (AstNode* nextp=firstp; nextp; nextp=nextp->nextp()) {
SplitLogicVertex* vvertexp = (SplitLogicVertex*)nextp->user3p();
vvertexp->unlinkDelete(&m_graph);
}
} }
} }
// Again, nodep may no longer be first. // Again, nodep may no longer be first.
@@ -534,6 +541,15 @@ private:
} }
} }
} }
virtual void visit(AstJumpGo* nodep, AstNUser*) {
// Jumps will disable reordering at all levels
// This is overly pessimistic; we could treat jumps as barriers, and
// reorder everything between jumps/labels, however jumps are rare
// in always, so the performance gain probably isn't worth the work.
UINFO(9," NoReordering "<<nodep<<endl);
m_noReorderWhy = "JumpGo";
nodep->iterateChildren(*this);
}
//-------------------- //--------------------
// Default // Default
+1 -1
View File
@@ -185,7 +185,7 @@ private:
// Now isolate the always // Now isolate the always
if (m_splitVscp) { if (m_splitVscp) {
splitAlways(nodep); splitAlways(nodep);
m_statSplits++; ++m_statSplits;
} else { } else {
nodep->user1(true); nodep->user1(true);
} }
+1 -1
View File
@@ -309,7 +309,7 @@ private:
if (debug()>5) newp->dumpTree(cout," w_new: "); if (debug()>5) newp->dumpTree(cout," w_new: ");
nodep->replaceWith(newp); nodep->replaceWith(newp);
pushDeletep(nodep); nodep=NULL; pushDeletep(nodep); nodep=NULL;
m_statSubsts++; ++m_statSubsts;
} }
virtual void visit(AstWordSel* nodep, AstNUser*) { virtual void visit(AstWordSel* nodep, AstNUser*) {
nodep->rhsp()->accept(*this); nodep->rhsp()->accept(*this);
+2 -2
View File
@@ -176,8 +176,8 @@ public:
private: private:
void createTable(AstAlways* nodep) { void createTable(AstAlways* nodep) {
// We've determined this table of nodes is optimizable, do it. // We've determined this table of nodes is optimizable, do it.
m_modTables++; ++m_modTables;
m_statTablesCre++; ++m_statTablesCre;
// Index into our table // Index into our table
AstVar* indexVarp = new AstVar (nodep->fileline(), AstVarType::BLOCKTEMP, AstVar* indexVarp = new AstVar (nodep->fileline(), AstVarType::BLOCKTEMP,
+8
View File
@@ -408,6 +408,7 @@ private:
AstAssign* assp = new AstAssign (pinp->fileline(), AstAssign* assp = new AstAssign (pinp->fileline(),
pinp, pinp,
new AstVarRef(outvscp->fileline(), outvscp, false)); new AstVarRef(outvscp->fileline(), outvscp, false));
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
// Put assignment BEHIND of all other statements // Put assignment BEHIND of all other statements
beginp->addNext(assp); beginp->addNext(assp);
} }
@@ -418,6 +419,7 @@ private:
AstAssign* assp = new AstAssign (pinp->fileline(), AstAssign* assp = new AstAssign (pinp->fileline(),
new AstVarRef(inVscp->fileline(), inVscp, true), new AstVarRef(inVscp->fileline(), inVscp, true),
pinp); pinp);
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
// Put assignment in FRONT of all other statements // Put assignment in FRONT of all other statements
if (AstNode* afterp = beginp->nextp()) { if (AstNode* afterp = beginp->nextp()) {
afterp->unlinkFrBackWithNext(); afterp->unlinkFrBackWithNext();
@@ -507,6 +509,7 @@ private:
AstAssign* assp = new AstAssign (pinp->fileline(), AstAssign* assp = new AstAssign (pinp->fileline(),
pinp, pinp,
new AstVarRef(outvscp->fileline(), outvscp, false)); new AstVarRef(outvscp->fileline(), outvscp, false));
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
// Put assignment BEHIND of all other statements // Put assignment BEHIND of all other statements
beginp->addNext(assp); beginp->addNext(assp);
} }
@@ -618,6 +621,11 @@ private:
stmt += "VL_CVT_VP_Q("; stmt += "VL_CVT_VP_Q(";
ket += ")"; ket += ")";
} }
else if (portp->basicp() && portp->basicp()->isBitLogic() && portp->widthMin() != 1 && portp->isQuad()) {
// SV is vector, Verilator isn't
stmt += "VL_SET_QW(";
ket += ")";
}
if (!cvt if (!cvt
&& portp->basicp() && portp->basicp()->isBitLogic() && portp->widthMin() != 1 && !portp->isWide()) && portp->basicp() && portp->basicp()->isBitLogic() && portp->widthMin() != 1 && !portp->isWide())
stmt += "*"; // it's a svBitVecVal, which other code won't think is arrayed (as WData aren't), but really is stmt += "*"; // it's a svBitVecVal, which other code won't think is arrayed (as WData aren't), but really is
+8 -8
View File
@@ -71,19 +71,19 @@ class TraceActivityVertex : public V3GraphVertex {
bool m_activityCodeValid; bool m_activityCodeValid;
bool m_slow; // If always slow, we can use the same code bool m_slow; // If always slow, we can use the same code
public: public:
enum { ACTIVITY_NEVER =((1UL<<31) - 1) };
enum { ACTIVITY_ALWAYS=((1UL<<31) - 2) };
enum { ACTIVITY_SLOW=0 };
TraceActivityVertex(V3Graph* graphp, AstNode* nodep, bool slow) TraceActivityVertex(V3Graph* graphp, AstNode* nodep, bool slow)
: V3GraphVertex(graphp), m_insertp(nodep) { : V3GraphVertex(graphp), m_insertp(nodep) {
m_activityCode = 0; m_activityCode = 0;
m_activityCodeValid = false; m_activityCodeValid = false;
m_slow = slow; m_slow = slow;
} }
enum { ACTIVITY_NEVER =((1UL<<31) - 1) };
enum { ACTIVITY_ALWAYS=((1UL<<31) - 2) };
enum { ACTIVITY_SLOW=0 };
class ActivityAlways {};
TraceActivityVertex(V3Graph* graphp, vlsint32_t code) TraceActivityVertex(V3Graph* graphp, vlsint32_t code)
: V3GraphVertex(graphp) { : V3GraphVertex(graphp), m_insertp(NULL) {
activityCode(code); m_activityCode = code;
m_activityCodeValid = true;
m_slow = false; m_slow = false;
} }
virtual ~TraceActivityVertex() {} virtual ~TraceActivityVertex() {}
@@ -484,7 +484,7 @@ private:
nodep->code(m_code); nodep->code(m_code);
m_code += nodep->codeInc(); m_code += nodep->codeInc();
m_statUniqCodes += nodep->codeInc(); m_statUniqCodes += nodep->codeInc();
m_statUniqSigs++; ++m_statUniqSigs;
} }
return nodep->code(); return nodep->code();
} }
@@ -517,7 +517,7 @@ private:
if (!codePreassigned) { if (!codePreassigned) {
// Add to trace cfuncs // Add to trace cfuncs
if (needChg) { if (needChg) {
m_statChgSigs++; ++m_statChgSigs;
incAddp = nodep->cloneTree(true); incAddp = nodep->cloneTree(true);
} }
+3 -2
View File
@@ -103,6 +103,7 @@ private:
} else { } else {
basep->v3fatalSrc("Strange base function type"); basep->v3fatalSrc("Strange base function type");
} }
// cppcheck-suppress nullPointer // above fatal prevents it
AstCCall* callp = new AstCCall(funcp->fileline(), funcp); AstCCall* callp = new AstCCall(funcp->fileline(), funcp);
callp->argTypes("vlSymsp, vcdp, code"); callp->argTypes("vlSymsp, vcdp, code");
basep->addStmtsp(callp); basep->addStmtsp(callp);
@@ -137,12 +138,12 @@ private:
if (showname.substr(0,4) == "TOP ") showname.replace(0,4,""); if (showname.substr(0,4) == "TOP ") showname.replace(0,4,"");
if (!m_initSubFuncp) nodep->v3fatalSrc("NULL"); if (!m_initSubFuncp) nodep->v3fatalSrc("NULL");
if (varIgnoreTrace(varp)) { if (varIgnoreTrace(varp)) {
m_statIgnSigs++; ++m_statIgnSigs;
m_initSubFuncp->addStmtsp( m_initSubFuncp->addStmtsp(
new AstComment(nodep->fileline(), new AstComment(nodep->fileline(),
"Tracing: "+showname+" // Ignored: "+varIgnoreTrace(varp))); "Tracing: "+showname+" // Ignored: "+varIgnoreTrace(varp)));
} else { } else {
m_statSigs++; ++m_statSigs;
AstNode* valuep = NULL; AstNode* valuep = NULL;
if (nodep->valuep()) valuep=nodep->valuep()->cloneTree(true); if (nodep->valuep()) valuep=nodep->valuep()->cloneTree(true);
else valuep = new AstVarRef(nodep->fileline(), nodep, false); else valuep = new AstVarRef(nodep->fileline(), nodep, false);
+15 -4
View File
@@ -76,8 +76,8 @@ public:
private: private:
// METHODS // METHODS
inline bool bitNumOk(int bit) const { return (bit*FLAGS_PER_BIT < (int)m_flags.size()); } inline bool bitNumOk(int bit) const { return (bit*FLAGS_PER_BIT < (int)m_flags.size()); }
inline bool usedFlag(int bit) { return m_usedWhole || m_flags[bit*FLAGS_PER_BIT + FLAG_USED]; } inline bool usedFlag(int bit) const { return m_usedWhole || m_flags[bit*FLAGS_PER_BIT + FLAG_USED]; }
inline bool drivenFlag(int bit) { return m_drivenWhole || m_flags[bit*FLAGS_PER_BIT + FLAG_DRIVEN]; } inline bool drivenFlag(int bit) const { return m_drivenWhole || m_flags[bit*FLAGS_PER_BIT + FLAG_DRIVEN]; }
enum BitNamesWhich { BN_UNUSED, BN_UNDRIVEN, BN_BOTH }; enum BitNamesWhich { BN_UNUSED, BN_UNDRIVEN, BN_BOTH };
string bitNames(BitNamesWhich which) { string bitNames(BitNamesWhich which) {
string bits=""; string bits="";
@@ -217,6 +217,7 @@ private:
// STATE // STATE
vector<UndrivenVarEntry*> m_entryps; // Nodes to delete when we are finished vector<UndrivenVarEntry*> m_entryps; // Nodes to delete when we are finished
bool m_markBoth; // Mark as driven+used bool m_markBoth; // Mark as driven+used
AstNodeFTask* m_taskp; // Current task
// METHODS // METHODS
static int debug() { static int debug() {
@@ -241,12 +242,14 @@ private:
virtual void visit(AstVar* nodep, AstNUser*) { virtual void visit(AstVar* nodep, AstNUser*) {
UndrivenVarEntry* entryp = getEntryp (nodep); UndrivenVarEntry* entryp = getEntryp (nodep);
if (nodep->isInput() if (nodep->isInput()
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()) { || nodep->isSigPublic() || nodep->isSigUserRWPublic()
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
entryp->drivenWhole(); entryp->drivenWhole();
} }
if (nodep->isOutput() if (nodep->isOutput()
|| nodep->isSigPublic() || nodep->isSigUserRWPublic() || nodep->isSigPublic() || nodep->isSigUserRWPublic()
|| nodep->isSigUserRdPublic()) { || nodep->isSigUserRdPublic()
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
entryp->usedWhole(); entryp->usedWhole();
} }
// Discover variables used in bit definitions, etc // Discover variables used in bit definitions, etc
@@ -284,6 +287,13 @@ private:
m_markBoth = prevMark; m_markBoth = prevMark;
} }
virtual void visit(AstNodeFTask* nodep, AstNUser*) {
AstNodeFTask* prevTaskp = m_taskp;
m_taskp = nodep;
nodep->iterateChildren(*this);
m_taskp = prevTaskp;
}
// Until we support tables, primitives will have undriven and unused I/Os // Until we support tables, primitives will have undriven and unused I/Os
virtual void visit(AstPrimitive* nodep, AstNUser*) {} virtual void visit(AstPrimitive* nodep, AstNUser*) {}
@@ -303,6 +313,7 @@ public:
// CONSTUCTORS // CONSTUCTORS
UndrivenVisitor(AstNetlist* nodep) { UndrivenVisitor(AstNetlist* nodep) {
m_markBoth = false; m_markBoth = false;
m_taskp = NULL;
nodep->accept(*this); nodep->accept(*this);
} }
virtual ~UndrivenVisitor() { virtual ~UndrivenVisitor() {
+1 -1
View File
@@ -289,7 +289,7 @@ private:
AstVar* newvarp AstVar* newvarp
= new AstVar (nodep->fileline(), AstVarType::XTEMP, newvarname, = new AstVar (nodep->fileline(), AstVarType::XTEMP, newvarname,
AstLogicPacked(), nodep->width()); AstLogicPacked(), nodep->width());
m_statUnkVars++; ++m_statUnkVars;
AstNRelinker replaceHandle; AstNRelinker replaceHandle;
nodep->unlinkFrBack(&replaceHandle); nodep->unlinkFrBack(&replaceHandle);
AstNodeVarRef* newref1p = new AstVarRef(nodep->fileline(), newvarp, false); AstNodeVarRef* newref1p = new AstVarRef(nodep->fileline(), newvarp, false);
+5 -2
View File
@@ -241,14 +241,17 @@ private:
} }
if (precondsp) { if (precondsp) {
precondsp->unlinkFrBackWithNext(); precondsp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(precondsp); stmtsp = stmtsp->addNextNull(precondsp);
} }
if (bodysp) { if (bodysp) {
bodysp->unlinkFrBackWithNext(); bodysp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(bodysp); // Maybe null if no body stmtsp = stmtsp->addNextNull(bodysp); // Maybe null if no body
} }
if (incp && !nodep->castGenFor()) { // Generates don't need to increment loop index if (incp && !nodep->castGenFor()) { // Generates don't need to increment loop index
incp->unlinkFrBackWithNext(); incp->unlinkFrBackWithNext();
// cppcheck-suppress nullPointer // addNextNull deals with it
stmtsp = stmtsp->addNextNull(incp); // Maybe null if no body stmtsp = stmtsp->addNextNull(incp); // Maybe null if no body
} }
// Mark variable to disable some later warnings // Mark variable to disable some later warnings
@@ -259,7 +262,7 @@ private:
loopValue.opAssign(numInit); loopValue.opAssign(numInit);
AstNode* newbodysp = NULL; AstNode* newbodysp = NULL;
m_statLoops++; ++m_statLoops;
if (stmtsp) { if (stmtsp) {
int times = 0; int times = 0;
while (1) { while (1) {
@@ -287,7 +290,7 @@ private:
if (newbodysp) newbodysp->addNext(oneloopp); if (newbodysp) newbodysp->addNext(oneloopp);
else newbodysp = oneloopp; else newbodysp = oneloopp;
m_statIters++; ++m_statIters;
if (++times > unrollCount()*3) { if (++times > unrollCount()*3) {
nodep->v3error("Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "<<unrollCount()); nodep->v3error("Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "<<unrollCount());
break; break;
+1073 -528
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -34,7 +34,6 @@ public:
static void width(AstNetlist* nodep); static void width(AstNetlist* nodep);
// Smaller step... Only do a single node for parameter propagation // Smaller step... Only do a single node for parameter propagation
static AstNode* widthParamsEdit(AstNode* nodep); static AstNode* widthParamsEdit(AstNode* nodep);
static AstNode* widthParamsEditIfNeed(AstNode* nodep);
// Final step... Mark all widths as equal // Final step... Mark all widths as equal
static void widthCommit(AstNetlist* nodep); static void widthCommit(AstNetlist* nodep);
+103
View File
@@ -0,0 +1,103 @@
// -*- C++ -*-
//*************************************************************************
// DESCRIPTION: Verilator: Cleanup stage in V3Width
//
// Code available from: http://www.veripool.org/verilator
//
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
//
//*************************************************************************
//
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3WIDTHCOMMIT_H_
#define _V3WIDTHCOMMIT_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
#ifndef _V3WIDTH_CPP_
# error "V3WidthCommit for V3Width internal use only"
#endif
//######################################################################
/// Remove all $signed, $unsigned, we're done with them.
class WidthRemoveVisitor : public AstNVisitor {
private:
// VISITORS
virtual void visit(AstSigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstUnsigned* nodep, AstNUser*) {
replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()); nodep=NULL;
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->iterateChildren(*this);
}
void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) {
UINFO(6," Replace "<<nodep<<" w/ "<<newp<<endl);
nodep->replaceWith(newp);
newp->widthSignedFrom(nodep);
pushDeletep(nodep); nodep=NULL;
}
public:
// CONSTRUCTORS
WidthRemoveVisitor() {}
virtual ~WidthRemoveVisitor() {}
AstNode* mainAcceptEdit(AstNode* nodep) {
return nodep->acceptSubtreeReturnEdits(*this);
}
};
//######################################################################
class WidthCommitVisitor : public AstNVisitor {
// Now that all widthing is complete,
// Copy all width() to widthMin(). V3Const expects this
private:
// VISITORS
virtual void visit(AstConst* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
if ((nodep->width() != nodep->num().width()) || !nodep->num().sized()) {
V3Number num (nodep->fileline(), nodep->width());
num.opAssign(nodep->num());
num.isSigned(nodep->isSigned());
AstNode* newp = new AstConst(nodep->fileline(), num);
nodep->replaceWith(newp);
//if (debug()>4) nodep->dumpTree(cout," fixConstSize_old: ");
//if (debug()>4) newp->dumpTree(cout," _new: ");
pushDeletep(nodep); nodep=NULL;
}
}
virtual void visit(AstNode* nodep, AstNUser*) {
nodep->width(nodep->width(),nodep->width());
nodep->iterateChildren(*this);
}
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
// This check could go anywhere after V3Param
nodep->v3fatalSrc("Presels should have been removed before this point");
}
public:
// CONSTUCTORS
WidthCommitVisitor(AstNetlist* nodep) {
nodep->accept(*this);
}
virtual ~WidthCommitVisitor() {}
};
//######################################################################
#endif // Guard
+3 -3
View File
@@ -111,12 +111,12 @@ private:
// We must make sure sub gets sign of original value // We must make sure sub gets sign of original value
AstNode* newp = new AstSub(lhsp->fileline(), lhsp, AstNode* newp = new AstSub(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs)); new AstConst(lhsp->fileline(), AstConst::Unsized32(), rhs));
newp->signedFrom(lhsp); newp->numericFrom(lhsp);
return newp; return newp;
} else { // rhs < 0; } else { // rhs < 0;
AstNode* newp = new AstAdd(lhsp->fileline(), lhsp, AstNode* newp = new AstAdd(lhsp->fileline(), lhsp,
new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs)); new AstConst(lhsp->fileline(), AstConst::Unsized32(), -rhs));
newp->signedFrom(lhsp); newp->numericFrom(lhsp);
return newp; return newp;
} }
} }
@@ -126,7 +126,7 @@ private:
AstNode* newp = new AstSub(rhsp->fileline(), AstNode* newp = new AstSub(rhsp->fileline(),
new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs), new AstConst(rhsp->fileline(), AstConst::Unsized32(), lhs),
rhsp); rhsp);
newp->signedFrom(rhsp); // Important as AstSub default is lhs's sign newp->numericFrom(rhsp); // Important as AstSub default is lhs's sign
return newp; return newp;
} }
+4 -9
View File
@@ -74,7 +74,6 @@
#include "V3PreShell.h" #include "V3PreShell.h"
#include "V3Premit.h" #include "V3Premit.h"
#include "V3Scope.h" #include "V3Scope.h"
#include "V3Signed.h"
#include "V3Slice.h" #include "V3Slice.h"
#include "V3Split.h" #include "V3Split.h"
#include "V3SplitAs.h" #include "V3SplitAs.h"
@@ -107,7 +106,8 @@ void V3Global::readFiles() {
for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin(); for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin();
it != v3Global.opt.vFiles().end(); ++it) { it != v3Global.opt.vFiles().end(); ++it) {
string filename = *it; string filename = *it;
parser.parseFile(new FileLine("CommandLine",0), filename, false); parser.parseFile(new FileLine("COMMAND_LINE",0), filename, false,
"Cannot find file containing module: ");
} }
// Read libraries // Read libraries
@@ -116,7 +116,8 @@ void V3Global::readFiles() {
for (V3StringSet::const_iterator it = v3Global.opt.libraryFiles().begin(); for (V3StringSet::const_iterator it = v3Global.opt.libraryFiles().begin();
it != v3Global.opt.libraryFiles().end(); ++it) { it != v3Global.opt.libraryFiles().end(); ++it) {
string filename = *it; string filename = *it;
parser.parseFile(new FileLine("CommandLine",0), filename, true); parser.parseFile(new FileLine("COMMAND_LINE",0), filename, true,
"Cannot find file containing library module: ");
} }
//v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree")); //v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree"));
V3Error::abortIfErrors(); V3Error::abortIfErrors();
@@ -168,9 +169,6 @@ void process () {
V3Width::width(v3Global.rootp()); V3Width::width(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("width.tree")); v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("width.tree"));
// Compute signed/unsigned
V3Signed::signedAll(v3Global.rootp());
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("signed.tree"));
V3Error::abortIfErrors(); V3Error::abortIfErrors();
// Commit to the widths we've chosen; Make widthMin==width // Commit to the widths we've chosen; Make widthMin==width
@@ -571,9 +569,6 @@ int main(int argc, char** argv, char** env) {
v3Global.opt.bin(argv[0]); v3Global.opt.bin(argv[0]);
string argString = V3Options::argString(argc-1, argv+1); string argString = V3Options::argString(argc-1, argv+1);
v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1); v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1);
if (v3Global.opt.coverage() && !v3Global.opt.systemPerl() && !v3Global.opt.lintOnly()) {
v3fatal("Unsupported: Coverage analysis requires --sp output.");
}
if (!v3Global.opt.outFormatOk() if (!v3Global.opt.outFormatOk()
&& !v3Global.opt.preprocOnly() && !v3Global.opt.preprocOnly()
&& !v3Global.opt.lintOnly() && !v3Global.opt.lintOnly()
+118 -9
View File
@@ -7,28 +7,36 @@ use Getopt::Long;
use IO::File; use IO::File;
use Pod::Usage; use Pod::Usage;
use strict; use strict;
use vars qw ($Debug @Types %Classes); use vars qw ($Debug @Types %Classes %Children %ClassRefs %Stages);
#====================================================================== #======================================================================
# main # main
$Debug = 0; $Debug = 0;
my $opt_classes; my $opt_classes;
my $opt_report;
my @Opt_Cpt; my @Opt_Cpt;
my @Opt_I; my @Opt_I;
Getopt::Long::config ("pass_through", "no_auto_abbrev"); Getopt::Long::config ("pass_through", "no_auto_abbrev");
if (! GetOptions ( if (! GetOptions (
"help" => \&usage, "help" => \&report,
"debug" => \&debug, "debug" => \&debug,
"classes!" => \$opt_classes, "classes!" => \$opt_classes,
"<>" => \&parameter, "report!" => \$opt_report,
)) { "<>" => \&parameter,
)) {
usage(); usage();
} }
read_types("$Opt_I[0]/V3Ast.h"); read_types("$Opt_I[0]/V3Ast.h");
read_types("$Opt_I[0]/V3AstNodes.h"); read_types("$Opt_I[0]/V3AstNodes.h");
read_stages("$Opt_I[0]/Verilator.cpp");
read_refs(glob("$Opt_I[0]/*.y"), glob("$Opt_I[0]/*.h"), glob("$Opt_I[0]/*.cpp"));
if ($opt_report) {
write_report(undef);
}
if ($opt_classes) { if ($opt_classes) {
write_report("V3Ast__gen_report.txt");
write_classes("V3Ast__gen_classes.h"); write_classes("V3Ast__gen_classes.h");
write_visitor("V3Ast__gen_visitor.h"); write_visitor("V3Ast__gen_visitor.h");
write_intf("V3Ast__gen_interface.h"); write_intf("V3Ast__gen_interface.h");
@@ -42,7 +50,7 @@ foreach my $cpt (@Opt_Cpt) {
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub usage { sub usage {
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
@@ -80,11 +88,50 @@ sub read_types {
$class =~ s/^Ast//; $class =~ s/^Ast//;
$inh =~ s/^Ast//; $inh =~ s/^Ast//;
$Classes{$class} = $inh; $Classes{$class} = $inh;
$Children{$inh}{$class} = 1;
} }
} }
} }
} }
sub read_stages {
my $filename = shift;
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
my $n = 0;
while (defined (my $line = $fh->getline())) {
$line =~ s/\/\/.*$//;
next if $line =~ /^\s*$/;
if ($line =~ /^\s*([A-Za-z0-9]+)::/) {
my $stage = $1.".cpp";
if (!defined ($Stages{$stage})) {
$Stages{$stage} = $n++;
}
}
}
}
sub read_refs {
my @filenames = @_;
foreach my $filename (@filenames) {
(my $basename = $filename) =~ s!.*/!!;
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
while (defined (my $line = $fh->getline())) {
$line =~ s/\/\/.*$//;
while ($line =~ /\bnew\s*(Ast[A-Za-z0-9_]+)/g) {
$ClassRefs{$1}{newed}{$basename} = 1;
}
while ($line =~ /\b(Ast[A-Za-z0-9_]+)/g) {
$ClassRefs{$1}{used}{$basename} = 1;
}
}
}
#use Data::Dumper;print Dumper(\%ClassRefs);
}
#----------------------------------------------------------------------
sub open_file { sub open_file {
my $filename = shift; my $filename = shift;
my $fh = IO::File->new($filename,"w") or die "%Error: $! $filename,"; my $fh = IO::File->new($filename,"w") or die "%Error: $! $filename,";
@@ -106,8 +153,66 @@ sub subclasses_of {
return (reverse @cllist); return (reverse @cllist);
} }
sub children_of {
my $type = shift;
my @cllist;
my @todo;
push @todo, $type;
while (my $subclass = shift @todo) {
foreach my $child (sort keys %{$::Children{$subclass}}) {
push @todo, $child;
push @cllist, $child;
}
}
return (@cllist);
}
#---------------------------------------------------------------------- #----------------------------------------------------------------------
sub write_report {
my $filename = shift;
my $fh = defined($filename) ? open_file($filename) : \*STDOUT;
$fh->print("Processing stages (approximate, based on order in Verilator.cpp):\n");
foreach my $class (sort {$Stages{$a} <=> $Stages{$b}} keys %Stages) {
$fh->print("\t$class\n");
}
$fh->print("\nProcessing stages (approximate, based on order in Verilator.cpp):\n");
foreach my $type (sort (keys %Classes)) {
printf $fh " class %-20s\n", "Ast${type}";
$fh->print("\tparent:\t");
foreach my $subclass (subclasses_of($type)) {
next if $subclass eq 'Node';
printf $fh "Ast%-12s ",$subclass;
}
printf $fh "\n";
$fh->print("\tchilds:\t");
foreach my $subclass (children_of($type)) {
next if $subclass eq 'Node';
printf $fh "Ast%-12s ",$subclass;
}
printf $fh "\n";
if (my $refs = $ClassRefs{"Ast${type}"}) {
$fh->print("\tnewed:\t");
foreach my $stage (sort {($Stages{$a}||-1) <=> ($Stages{$b}||-1)}
keys %{$refs->{newed}}) {
$fh->print($stage." ");
}
$fh->print("\n");
$fh->print("\tused:\t");
foreach my $stage (sort {($Stages{$a}||-1) <=> ($Stages{$b}||-1)}
keys %{$refs->{used}}) {
$fh->print($stage." ");
}
$fh->print("\n");
}
$fh->print("\n");
}
}
sub write_classes { sub write_classes {
my $fh = open_file(@_); my $fh = open_file(@_);
foreach my $type (sort (keys %Classes)) { foreach my $type (sort (keys %Classes)) {
@@ -501,7 +606,11 @@ Displays this message and program version and exits.
=item --classes =item --classes
Makes class declaration files Makes class declaration files.
=item --report
Makes a report report.
=back =back
@@ -526,5 +635,5 @@ Wilson Snyder <[email protected]>
###################################################################### ######################################################################
### Local Variables: ### Local Variables:
### compile-command: "./astgen " ### compile-command: "./astgen -I. --report"
### End: ### End:
+96 -23
View File
@@ -9,7 +9,7 @@ use Pod::Usage;
use strict; use strict;
use vars qw ($Debug $VERSION); use vars qw ($Debug $VERSION);
$VERSION = '3.202'; $VERSION = '3.307';
our $Self; our $Self;
@@ -56,7 +56,7 @@ process();
sub usage { sub usage {
print "Version $VERSION\n"; print "Version $VERSION\n";
pod2usage(-verbose=>2, -exitval => 2); pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
exit (1); exit (1);
} }
@@ -74,9 +74,10 @@ sub parameter {
sub process { sub process {
remove_outputs(); remove_outputs();
clean_input($Opt_Input, tmp_prefix().".y"); $Self->{bison_version} = bison_version_check();
my $supports_report = ($Self->{bison_version} >= 2.3);
my $supports_report = (bison_version_check() >= 2.3); clean_input($Opt_Input, tmp_prefix().".y");
# Run bison # Run bison
my $command = ($Opt_Yacc my $command = ($Opt_Yacc
@@ -100,11 +101,11 @@ sub process {
die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n"; die "bisonpre: %Error: $Opt_Yacc version $v run failed due to errors\n";
} }
clean_output(tmp_prefix().".output",output_prefix().".output", 1); clean_output(tmp_prefix().".output",output_prefix().".output", 1,0);
warning_check(output_prefix().".output"); warning_check(output_prefix().".output");
clean_output(tmp_prefix().".c", output_prefix().".c", 0); clean_output(tmp_prefix().".c", output_prefix().".c", 0,1);
clean_output(tmp_prefix().".h", output_prefix().".h", 0); clean_output(tmp_prefix().".h", output_prefix().".h", 0,1);
remove_tmp(); remove_tmp();
} }
@@ -150,15 +151,17 @@ sub clean_output {
my $filename = shift; my $filename = shift;
my $outname = shift || $filename; my $outname = shift || $filename;
my $is_output = shift; my $is_output = shift;
my $is_c = shift;
print " edit $filename $outname\n"; print " edit $filename $outname\n";
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
my @lines = $fh->getlines; my @lines = $fh->getlines;
$fh->close; $fh->close;
(my $basename = tmp_prefix().".y") =~ s!.*/!!; (my $basename = tmp_prefix().".") =~ s!.*/!!;
$basename = quotemeta($basename); $basename = quotemeta($basename);
(my $newbase = $Opt_Input) =~ s!.*/!!; (my $newbase = $Opt_Input) =~ s!.*/!!;
$newbase =~ s/\.y/./;
if ($is_output) { if ($is_output) {
my %state_line; my $l=0; my %state_line; my $l=0;
@@ -178,6 +181,28 @@ sub clean_output {
} }
@lines = @out; @out = (); @lines = @out; @out = ();
} }
if ($is_c) {
my %token_values;
my $in_en=0;
foreach my $line (@lines) {
$in_en=1 if $line =~ /enum\s+yytokentype/;
$in_en=0 if $line =~ /;/;
$token_values{$2} = $1 if $in_en && $line =~ /\b(\S+) = (\d+)/;
}
my @out;
foreach my $line (@lines) {
if ($line =~ /BISONPRE_TOKEN_NAMES/) {
push @out, $line;
foreach my $tv (sort keys %token_values) {
push @out, sprintf("\tcase %d: return \"%s\";\n",
$tv, $token_values{$tv});
}
next;
}
push @out, $line;
}
@lines = @out; @out = ();
}
$fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n"; $fh = IO::File->new(">$outname") or die "%Error: $! writing $outname\n";
foreach my $line (@lines) { foreach my $line (@lines) {
@@ -211,6 +236,7 @@ sub clean_input {
my $outname = shift || $filename; # Can == filename if desired my $outname = shift || $filename; # Can == filename if desired
print " edit $filename $outname\n"; print " edit $filename $outname\n";
$Self->{filename} = $filename;
my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n";
my @lines = $fh->getlines; my @lines = $fh->getlines;
$fh->close; $fh->close;
@@ -232,7 +258,7 @@ sub clean_input {
$section++; $section++;
if ($section==2) { $last_rule = undef; } if ($section==2) { $last_rule = undef; }
} }
elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S+)>:/$1:/) { elsif ($line =~ s/^([a-zA-Z0-9_]+)<(\S*)>:/$1:/) {
!$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n"; !$rules{$1}{name} or die "%Error: $filename:$l: Redeclaring '$1': $line\n";
$types{$2}{$1} = 1; $types{$2}{$1} = 1;
$rules{$1}{name} = $1; $rules{$1}{name} = $1;
@@ -272,6 +298,25 @@ sub clean_input {
#use Data::Dumper; print Dumper(\%rules); #use Data::Dumper; print Dumper(\%rules);
# Replace BISONPRE_VERSION(ver,,...) with expanded list
{
my @linesin = @lines; @lines=(); my $l=0;
foreach my $line (@linesin) {
$l++;
if ($line =~ /BISONPRE_VERSION/) {
($line =~ /BISONPRE_VERSION\((\S+)\s*,\s*([^\),]+)\)\s*$/)
or die "%Error: $filename:$l: Bad form of BISONPRE_VERSION: $line\n";
my $ver=$1; my $cmd=$2;
if ($Self->{bison_version} >= $1) {
$line = $cmd."\n";
} else {
$line = "//NOP: $line";
}
}
push @lines, $line;
}
}
# Replace BISONPRE_NOT(type,...) with expanded list # Replace BISONPRE_NOT(type,...) with expanded list
{ {
my @linesin = @lines; @lines=(); my $l=0; my @linesin = @lines; @lines=(); my $l=0;
@@ -308,20 +353,7 @@ sub clean_input {
foreach my $line (@linesin) { foreach my $line (@linesin) {
$l++; $l++;
if ($line =~ /BISONPRE_COPY/) { if ($line =~ /BISONPRE_COPY/) {
($line =~ s/BISONPRE_COPY\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/) $line = _bisonpre_copy($line,$l,0);
or die "%Error: $filename:$l: Bad form of BISONPRE_NOT: $line\n";
my $rule = $1; my $code = $2;
$rules{$rule} or die "%Error: $filename:$l: Can't find definition for rule: $rule\n";
# Push it all onto one line to avoid error messages changing
my $insert = $rules{$rule}{rules_and_productions};
$insert =~ s/^\S+://g; # Strip rule name
#print "COPY code $code\n";
#print "COPY in $insert\n";
$_=$insert; eval("$code; \$_;"); $insert = $_;
#print "COPY out $insert\n";
while ($insert =~ s/[ \t\n]+\n/\n/go) {}
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
$line =~ s/{HERE}/$insert/;
} }
push @lines, $line; push @lines, $line;
} }
@@ -346,6 +378,7 @@ sub clean_input {
if ($line =~ m!//BISONPRE_TYPES!) { if ($line =~ m!//BISONPRE_TYPES!) {
push @lines, $line; push @lines, $line;
foreach my $type (sort keys %types) { foreach my $type (sort keys %types) {
next if !$type;
my $line = "%type<$type>\t"; my $line = "%type<$type>\t";
foreach my $rule (sort keys %{$types{$type}}) { foreach my $rule (sort keys %{$types{$type}}) {
$line.=" ".$rule; $line.=" ".$rule;
@@ -372,6 +405,37 @@ sub clean_input {
$fh->close; $fh->close;
} }
sub _bisonpre_copy {
my $text = shift;
my $l = shift;
my $depth = shift;
while ($text =~ /BISONPRE_COPY/) {
($text =~ s/BISONPRE_COPY(_ONCE)?\((\S+)\s*,\s*{([^}]*)}\s*\)/{HERE}/)
or die "%Error: $Self->{filename}:$l: Bad form of BISONPRE_NOT: $text\n";
my $once = $1; my $rule = $2; my $code = $3;
$Self->{rules}{$rule} or die "%Error: $Self->{filename}:$l: Can't find definition for rule: $rule\n";
if ($depth > 0 && $once) {
# _ONCE means don't inherit
$text =~ s/\|[ \t]+{HERE}//; # Don't OR in nothing
$text =~ s/{HERE}//;
} else {
# Push it all onto one line to avoid error messages changing
my $insert = $Self->{rules}{$rule}{rules_and_productions};
$insert =~ s/^\S+://g; # Strip rule name
# Recurse so BISONPRE under B
#print "COPY $l code $code\n";
#print "COPY $l in $insert\n";
$_=$insert; eval("$code; \$_;"); $insert = $_;
#print "COPY $l out $insert\n";
while ($insert =~ s/[ \t\n]+\n/\n/go) {}
while ($insert =~ s/\n/ /go) {} # Optional - preserve line numbering
$text =~ s/{HERE}/$insert/;
}
$depth++;
}
return $text;
}
####################################################################### #######################################################################
__END__ __END__
@@ -416,10 +480,19 @@ rule. The type will be inserted where /*BISONPRE_TYPES*/ is encountered.
Copy the rules and productions from the specified rule, filter through the Copy the rules and productions from the specified rule, filter through the
Perl code provided in the {} and insert here into the output file. Perl code provided in the {} and insert here into the output file.
=item BISONPRE_COPY_ONCE(rule, {code})
As with BISONPRE_COPY, but if called from underneath another BISONPRE_COPY
rule, ignore it.
=item BISONPRE_NOT(token[, token...]) =item BISONPRE_NOT(token[, token...])
Create a rule that matches every token except for those specified. Create a rule that matches every token except for those specified.
=item BISONPRE_VERSION(ver, cmd)
If the bison version is >= the specified version, include the given command.
=back =back
=head1 ARGUMENTS =head1 ARGUMENTS
+4 -28
View File
@@ -25,41 +25,17 @@
//********************************************************************** //**********************************************************************
//**** Version and host name //**** Version and host name
#define DTVERSION "Verilator 3.813 2011/06/28" // Autoconf substitutes this with the strings from AC_INIT.
#define PACKAGE_STRING ""
#define DTVERSION PACKAGE_STRING
//********************************************************************** //**********************************************************************
//**** Functions //**** Functions
// Set define if we have function: strdup (string)
#define HAVE_STRDUP 0
//********************************************************************** //**********************************************************************
//**** Headers //**** Headers
// Set define if we have header: <fcntl.h>
#define HAVE_FCNTL_H 0
// Set define if we have header: <math.h>
#define HAVE_MATH_H 1
// Set define if we have header: <unistd.h>
#define HAVE_UNISTD_H 0
// Set define if we have header: <sys/time.h>
#define HAVE_SYS_TIME_H 0
// Set define if we have header: <sys/un.h>
#define HAVE_SYS_UN_H 0
// Set define if we have header: <stdint.h>
#define HAVE_STDINT_H 0
// Set define if we have header: <mingw/stdint.h>
#define HAVE_MINGW_STDINT_H 0
// Set define if we have header: <inttypes.h>
#define HAVE_INTTYPES_H 0
//********************************************************************** //**********************************************************************
//**** Default environment //**** Default environment
+155 -25
View File
@@ -134,7 +134,7 @@ void yyerrorf(const char* format, ...) {
%s V95 V01 V05 S05 S09 %s V95 V01 V05 S05 S09
%s STRING ATTRMODE TABLE %s STRING ATTRMODE TABLE
%s PSL VLT %s VA5 SA9 PSL VLT
%s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR %s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR
%s IGNORE %s IGNORE
@@ -168,13 +168,16 @@ word [a-zA-Z0-9_]+
/************************************************************************/ /************************************************************************/
/* Verilog 1995 */ /* Verilog 1995 */
<V95,V01,V05,S05,S09,PSL>{ <V95,V01,V05,VA5,S05,S09,SA9,PSL>{
{ws} { } /* otherwise ignore white-space */ {ws} { } /* otherwise ignore white-space */
{crnl} { NEXTLINE(); } /* Count line numbers */ {crnl} { NEXTLINE(); } /* Count line numbers */
/* Extensions to Verilog set, some specified by PSL */ /* Extensions to Verilog set, some specified by PSL */
"$c"[0-9]* { FL; return yD_C; } /*Verilator only*/ "$c"[0-9]* { FL; return yD_C; } /*Verilator only*/
/* System Tasks */ /* System Tasks */
"$bitstoreal" { FL; return yD_BITSTOREAL; }
"$ceil" { FL; return yD_CEIL; }
"$display" { FL; return yD_DISPLAY; } "$display" { FL; return yD_DISPLAY; }
"$exp" { FL; return yD_EXP; }
"$fclose" { FL; return yD_FCLOSE; } "$fclose" { FL; return yD_FCLOSE; }
"$fdisplay" { FL; return yD_FDISPLAY; } "$fdisplay" { FL; return yD_FDISPLAY; }
"$feof" { FL; return yD_FEOF; } "$feof" { FL; return yD_FEOF; }
@@ -182,28 +185,37 @@ word [a-zA-Z0-9_]+
"$fgetc" { FL; return yD_FGETC; } "$fgetc" { FL; return yD_FGETC; }
"$fgets" { FL; return yD_FGETS; } "$fgets" { FL; return yD_FGETS; }
"$finish" { FL; return yD_FINISH; } "$finish" { FL; return yD_FINISH; }
"$floor" { FL; return yD_FLOOR; }
"$fopen" { FL; return yD_FOPEN; } "$fopen" { FL; return yD_FOPEN; }
"$fscanf" { FL; return yD_FSCANF; } "$fscanf" { FL; return yD_FSCANF; }
"$fullskew" { FL; return yaTIMINGSPEC; } "$fullskew" { FL; return yaTIMINGSPEC; }
"$fwrite" { FL; return yD_FWRITE; } "$fwrite" { FL; return yD_FWRITE; }
"$hold" { FL; return yaTIMINGSPEC; } "$hold" { FL; return yaTIMINGSPEC; }
"$itor" { FL; return yD_ITOR; }
"$ln" { FL; return yD_LN; }
"$log10" { FL; return yD_LOG10; }
"$nochange" { FL; return yaTIMINGSPEC; } "$nochange" { FL; return yaTIMINGSPEC; }
"$period" { FL; return yaTIMINGSPEC; } "$period" { FL; return yaTIMINGSPEC; }
"$pow" { FL; return yD_POW; }
"$random" { FL; return yD_RANDOM; } "$random" { FL; return yD_RANDOM; }
"$readmemb" { FL; return yD_READMEMB; } "$readmemb" { FL; return yD_READMEMB; }
"$readmemh" { FL; return yD_READMEMH; } "$readmemh" { FL; return yD_READMEMH; }
"$realtime" { FL; return yD_TIME; } "$realtime" { FL; return yD_REALTIME; }
"$realtobits" { FL; return yD_REALTOBITS; }
"$recovery" { FL; return yaTIMINGSPEC; } "$recovery" { FL; return yaTIMINGSPEC; }
"$recrem" { FL; return yaTIMINGSPEC; } "$recrem" { FL; return yaTIMINGSPEC; }
"$removal" { FL; return yaTIMINGSPEC; } "$removal" { FL; return yaTIMINGSPEC; }
"$rtoi" { FL; return yD_RTOI; }
"$setup" { FL; return yaTIMINGSPEC; } "$setup" { FL; return yaTIMINGSPEC; }
"$setuphold" { FL; return yaTIMINGSPEC; } "$setuphold" { FL; return yaTIMINGSPEC; }
"$sformat" { FL; return yD_SFORMAT; } "$sformat" { FL; return yD_SFORMAT; }
"$skew" { FL; return yaTIMINGSPEC; } "$skew" { FL; return yaTIMINGSPEC; }
"$sqrt" { FL; return yD_SQRT; }
"$sscanf" { FL; return yD_SSCANF; } "$sscanf" { FL; return yD_SSCANF; }
"$stime" { FL; return yD_STIME; } "$stime" { FL; return yD_STIME; }
"$stop" { FL; return yD_STOP; } "$stop" { FL; return yD_STOP; }
"$swrite" { FL; return yD_SWRITE; } "$swrite" { FL; return yD_SWRITE; }
"$system" { FL; return yD_SYSTEM; }
"$test$plusargs" { FL; return yD_TESTPLUSARGS; } "$test$plusargs" { FL; return yD_TESTPLUSARGS; }
"$time" { FL; return yD_TIME; } "$time" { FL; return yD_TIME; }
"$timeskew" { FL; return yaTIMINGSPEC; } "$timeskew" { FL; return yaTIMINGSPEC; }
@@ -261,6 +273,8 @@ word [a-zA-Z0-9_]+
"pulldown" { FL; return yPULLDOWN; } "pulldown" { FL; return yPULLDOWN; }
"pullup" { FL; return yPULLUP; } "pullup" { FL; return yPULLUP; }
"rcmos" { FL; return yRCMOS; } "rcmos" { FL; return yRCMOS; }
"real" { FL; return yREAL; }
"realtime" { FL; return yREALTIME; }
"reg" { FL; return yREG; } "reg" { FL; return yREG; }
"repeat" { FL; return yREPEAT; } "repeat" { FL; return yREPEAT; }
"rnmos" { FL; return yRNMOS; } "rnmos" { FL; return yRNMOS; }
@@ -310,8 +324,6 @@ word [a-zA-Z0-9_]+
"medium" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "medium" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"pull0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "pull0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"pull1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "pull1" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"real" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"realtime" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"release" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "release" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"small" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "small" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
"strong0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); } "strong0" { yyerrorf("Unsupported: Verilog 1995 reserved word not implemented: %s",yytext); }
@@ -329,7 +341,7 @@ word [a-zA-Z0-9_]+
} }
/* Verilog 2001 */ /* Verilog 2001 */
<V01,V05,S05,S09,PSL>{ <V01,V05,VA5,S05,S09,SA9,PSL>{
/* System Tasks */ /* System Tasks */
"$signed" { FL; return yD_SIGNED; } "$signed" { FL; return yD_SIGNED; }
"$unsigned" { FL; return yD_UNSIGNED; } "$unsigned" { FL; return yD_UNSIGNED; }
@@ -360,7 +372,7 @@ word [a-zA-Z0-9_]+
} }
/* Verilog 2005 */ /* Verilog 2005 */
<V05,S05,S09,PSL>{ <V05,S05,S09,SA9,PSL>{
/* Keywords */ /* Keywords */
"uwire" { FL; return yWIRE; } "uwire" { FL; return yWIRE; }
} }
@@ -478,12 +490,12 @@ word [a-zA-Z0-9_]+
<S05,S09>{ <S05,S09>{
/* Keywords */ /* Keywords */
"assert" { FL; return yASSERT; } "assert" { FL; return yASSERT; }
"const" { FL; return yCONST__LEX; }
"cover" { FL; return yCOVER; } "cover" { FL; return yCOVER; }
"property" { FL; return yPROPERTY; } "property" { FL; return yPROPERTY; }
/* Generic unsupported warnings */ /* Generic unsupported warnings */
"assume" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "assume" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"before" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "before" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"const" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"sequence" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "sequence" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"union" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "union" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
"within" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); } "within" { yyerrorf("Unsupported: SystemVerilog 2005 reserved word not implemented in non-PSL context: %s",yytext); }
@@ -519,7 +531,7 @@ word [a-zA-Z0-9_]+
} }
/* Default PLI rule */ /* Default PLI rule */
<V95,V01,V05,S05,S09,PSL>{ <V95,V01,V05,VA5,S05,S09,SA9,PSL>{
"$"[a-zA-Z_$][a-zA-Z0-9_$]* { string str (yytext,yyleng); "$"[a-zA-Z_$][a-zA-Z0-9_$]* { string str (yytext,yyleng);
yylval.strp = PARSEP->newString(AstNode::encodeName(str)); yylval.strp = PARSEP->newString(AstNode::encodeName(str));
// Lookup unencoded name including the $, to avoid hitting normal signals // Lookup unencoded name including the $, to avoid hitting normal signals
@@ -529,11 +541,104 @@ word [a-zA-Z0-9_]+
} }
} }
/************************************************************************/
/* AMS */
<VA5,SA9>{
/* Generic unsupported warnings */
"above" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"abs" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"absdelay" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"abstol" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ac_stim" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"access" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"acos" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"acosh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"aliasparam" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"analog" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"analysis" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"asin" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"asinh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"assert" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"atan" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"atan2" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"atanh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"branch" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ceil" { FL; return yD_CEIL; }
"connect" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"connectmodule" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"connectrules" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"continuous" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"cos" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"cosh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"cross" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ddt" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ddt_nature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ddx" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"discipline" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"discrete" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"domain" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"driver_update" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"endconnectrules" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"enddiscipline" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"endnature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"endparamset" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"exclude" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"exp" { FL; return yD_EXP; }
"final_step" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"flicker_noise" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"floor" { FL; return yD_FLOOR; }
"flow" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"from" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ground" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"hypot" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"idt" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"idt_nature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"idtmod" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"inf" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"initial_step" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"laplace_nd" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"laplace_np" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"laplace_zd" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"laplace_zp" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"last_crossing" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"limexp" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"ln" { FL; return yD_LN; }
"log" { FL; return yD_LOG10; }
"max" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"merged" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"min" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"nature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"net_resolution" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"noise_table" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"paramset" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"potential" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"pow" { FL; return yD_POW; }
"resolveto" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"sin" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"sinh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"slew" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"split" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"sqrt" { FL; return yD_SQRT; }
"string" { FL; return ySTRING; }
"tan" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"tanh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"timer" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"transition" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"units" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"white_noise" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"wreal" { FL; return yWREAL; }
"zi_nd" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"zi_np" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"zi_zd" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
"zi_zp" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
}
/************************************************************************/ /************************************************************************/
/* PSL */ /* PSL */
/*Entry into PSL; mode change */ /*Entry into PSL; mode change */
<V95,V01,V05,S05,S09>{ <V95,V01,V05,VA5,S05,S09,SA9>{
"psl" { yy_push_state(PSL); FL; return yPSL; } "psl" { yy_push_state(PSL); FL; return yPSL; }
} }
@@ -622,7 +727,7 @@ word [a-zA-Z0-9_]+
/* Meta comments */ /* Meta comments */
/* Converted from //{cmt}verilator ...{cmt} by preprocessor */ /* Converted from //{cmt}verilator ...{cmt} by preprocessor */
<V95,V01,V05,S05,S09,PSL>{ <V95,V01,V05,VA5,S05,S09,SA9,PSL>{
"/*verilator"{ws}*"*/" {} /* Ignore empty comments, may be `endif // verilator */ "/*verilator"{ws}*"*/" {} /* Ignore empty comments, may be `endif // verilator */
"/*verilator clock_enable*/" { FL; return yVL_CLOCK_ENABLE; } "/*verilator clock_enable*/" { FL; return yVL_CLOCK_ENABLE; }
"/*verilator coverage_block_off*/" { FL; return yVL_COVERAGE_BLOCK_OFF; } "/*verilator coverage_block_off*/" { FL; return yVL_COVERAGE_BLOCK_OFF; }
@@ -638,6 +743,7 @@ word [a-zA-Z0-9_]+
"/*verilator public_flat_rw*/" { FL; return yVL_PUBLIC_FLAT_RW; } // The @(edge) is converted by the preproc "/*verilator public_flat_rw*/" { FL; return yVL_PUBLIC_FLAT_RW; } // The @(edge) is converted by the preproc
"/*verilator public_module*/" { FL; return yVL_PUBLIC_MODULE; } "/*verilator public_module*/" { FL; return yVL_PUBLIC_MODULE; }
"/*verilator sc_clock*/" { FL; return yVL_CLOCK; } "/*verilator sc_clock*/" { FL; return yVL_CLOCK; }
"/*verilator sc_bv*/" { FL; return yVL_SC_BV; }
"/*verilator sformat*/" { FL; return yVL_SFORMAT; } "/*verilator sformat*/" { FL; return yVL_SFORMAT; }
"/*verilator systemc_clock*/" { FL; return yVL_CLOCK; } "/*verilator systemc_clock*/" { FL; return yVL_CLOCK; }
"/*verilator tracing_off*/" {PARSEP->fileline()->tracingOn(false); } "/*verilator tracing_off*/" {PARSEP->fileline()->tracingOn(false); }
@@ -656,11 +762,11 @@ word [a-zA-Z0-9_]+
/************************************************************************/ /************************************************************************/
/* Single character operator thingies */ /* Single character operator thingies */
<V95,V01,V05,S05,S09>{ <V95,V01,V05,VA5,S05,S09,SA9>{
"{" { FL; return yytext[0]; } "{" { FL; return yytext[0]; }
"}" { FL; return yytext[0]; } "}" { FL; return yytext[0]; }
} }
<V95,V01,V05,S05,S09,PSL>{ <V95,V01,V05,VA5,S05,S09,SA9,PSL>{
"!" { FL; return yytext[0]; } "!" { FL; return yytext[0]; }
"#" { FL; return yytext[0]; } "#" { FL; return yytext[0]; }
"$" { FL; return yytext[0]; } "$" { FL; return yytext[0]; }
@@ -692,7 +798,7 @@ word [a-zA-Z0-9_]+
/* Operators and multi-character symbols */ /* Operators and multi-character symbols */
/* Verilog 1995 Operators */ /* Verilog 1995 Operators */
<V95,V01,V05,S05,S09,PSL>{ <V95,V01,V05,VA5,S05,S09,SA9,PSL>{
"&&" { FL; return yP_ANDAND; } "&&" { FL; return yP_ANDAND; }
"||" { FL; return yP_OROR; } "||" { FL; return yP_OROR; }
"<=" { FL; return yP_LTE; } "<=" { FL; return yP_LTE; }
@@ -714,7 +820,7 @@ word [a-zA-Z0-9_]+
} }
/* Verilog 2001 Operators */ /* Verilog 2001 Operators */
<V01,V05,S05,S09,PSL>{ <V01,V05,VA5,S05,S09,SA9,PSL>{
"<<<" { FL; return yP_SLEFT; } "<<<" { FL; return yP_SLEFT; }
">>>" { FL; return yP_SSRIGHT; } ">>>" { FL; return yP_SSRIGHT; }
"**" { FL; return yP_POW; } "**" { FL; return yP_POW; }
@@ -773,7 +879,7 @@ word [a-zA-Z0-9_]+
} }
/* Identifiers and numbers */ /* Identifiers and numbers */
<V95,V01,V05,S05,S09,PSL,VLT>{ <V95,V01,V05,VA5,S05,S09,SA9,PSL,VLT>{
{escid} { FL; yylval.strp = PARSEP->newString {escid} { FL; yylval.strp = PARSEP->newString
(AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash (AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash
return yaID__LEX; return yaID__LEX;
@@ -812,11 +918,11 @@ word [a-zA-Z0-9_]+
return yaINTNUM; return yaINTNUM;
} }
[0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? { [0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? {
FL; yylval.cdouble = 0; /* Only for delays, not used yet */ FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
return yaFLOATNUM; return yaFLOATNUM;
} }
[0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) { [0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) {
FL; yylval.cdouble = 0; /* Only for delays, not used yet */ FL; yylval.cdouble = PARSEP->parseDouble(yytext, yyleng);
return yaFLOATNUM; return yaFLOATNUM;
} }
[0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) { [0-9][_0-9]*(\.[_0-9]+)?(fs|ps|ns|us|ms|s|step) {
@@ -848,8 +954,9 @@ word [a-zA-Z0-9_]+
/************************************************************************/ /************************************************************************/
/* Attributes */ /* Attributes */
<V95,V01,V05,S05,S09>{ /* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
"(*"/{ws}*[^)] { yymore(); yy_push_state(ATTRMODE); } // Doesn't match (*) <V95,V01,V05,VA5,S05,S09,SA9>{
"(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } // Doesn't match (*), but (* attr_spec
} }
/************************************************************************/ /************************************************************************/
@@ -865,7 +972,7 @@ word [a-zA-Z0-9_]+
/* Preprocessor */ /* Preprocessor */
/* Common for all SYSC header states */ /* Common for all SYSC header states */
/* OPTIMIZE: we return one per line, make it one for the entire block */ /* OPTIMIZE: we return one per line, make it one for the entire block */
<V95,V01,V05,S05,S09,PSL,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{ <V95,V01,V05,VA5,S05,S09,SA9,PSL,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
"`accelerate" { } // Verilog-XL compatibility "`accelerate" { } // Verilog-XL compatibility
"`autoexpand_vectornets" { } // Verilog-XL compatibility "`autoexpand_vectornets" { } // Verilog-XL compatibility
"`celldefine" { PARSEP->inCellDefine(true); } "`celldefine" { PARSEP->inCellDefine(true); }
@@ -906,9 +1013,11 @@ word [a-zA-Z0-9_]+
"`begin_keywords"[ \t]*\"1364-2001\" { yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); } "`begin_keywords"[ \t]*\"1364-2001\" { yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1364-2001-noconfig\" { yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); } "`begin_keywords"[ \t]*\"1364-2001-noconfig\" { yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1364-2005\" { yy_push_state(V05); PARSEP->pushBeginKeywords(YY_START); } "`begin_keywords"[ \t]*\"1364-2005\" { yy_push_state(V05); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"VAMS[-0-9.]*\" { yy_push_state(VA5); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); } "`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); }
"`begin_keywords"[ \t]*\"1800-2009\" { yy_push_state(S09); PARSEP->pushBeginKeywords(YY_START); } "`begin_keywords"[ \t]*\"1800-2009\" { yy_push_state(S09); PARSEP->pushBeginKeywords(YY_START); }
"`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); } "`begin_keywords"[ \t]*\"1800+VAMS\" { yy_push_state(SA9); PARSEP->pushBeginKeywords(YY_START); }
"`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
/* Verilator */ /* Verilator */
"`systemc_ctor" { BEGIN SYSCCTOR; } "`systemc_ctor" { BEGIN SYSCCTOR; }
@@ -938,7 +1047,7 @@ word [a-zA-Z0-9_]+
/************************************************************************/ /************************************************************************/
/* Default rules - leave last */ /* Default rules - leave last */
<V95,V01,V05,S05,S09,PSL,VLT>{ <V95,V01,V05,VA5,S05,S09,SA9,PSL,VLT>{
"`"[a-zA-Z_0-9]+ { FL; yyerrorf("Define or directive not defined: %s",yytext); } "`"[a-zA-Z_0-9]+ { FL; yyerrorf("Define or directive not defined: %s",yytext); }
"//"[^\n]* { } /* throw away single line comments */ "//"[^\n]* { } /* throw away single line comments */
. { FL; return yytext[0]; } /* return single char ops. */ . { FL; return yytext[0]; } /* return single char ops. */
@@ -949,6 +1058,22 @@ word [a-zA-Z0-9_]+
%% %%
int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; } int V3ParseImp::stateVerilogRecent() { return STATE_VERILOG_RECENT; }
double V3ParseImp::parseDouble(const char* textp, size_t length) {
char* strgp = new char[length+1];
char* dp=strgp;
for (const char* sp=textp; sp<(textp+length);) {
if (*sp != '_') *dp++ = *sp++;
else sp++;
}
*dp++ = '\0';
char* endp = strgp;
double d = strtod(strgp, &endp);
size_t parsed_len = endp-strgp;
if (parsed_len != length) { yyerrorf("Syntax error parsing real: %s",strgp); }
delete strgp;
return d;
}
int V3ParseImp::lexToken() { int V3ParseImp::lexToken() {
// called from lexToBison, has a "this" // called from lexToBison, has a "this"
// Fetch next token from prefetch or real lexer // Fetch next token from prefetch or real lexer
@@ -964,7 +1089,8 @@ int V3ParseImp::lexToken() {
//yylval // Set by yylexThis() //yylval // Set by yylexThis()
} }
// If a paren, read another // If a paren, read another
if (token == yGLOBAL__LEX if (token == yCONST__LEX
|| token == yGLOBAL__LEX
// Never put yID_* here; below symbol table resolution would break // Never put yID_* here; below symbol table resolution would break
) { ) {
if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; } if (debugFlex()) { cout<<" lexToken: reading ahead to find possible strength"<<endl; }
@@ -975,7 +1101,11 @@ int V3ParseImp::lexToken() {
m_aheadVal = yylval; m_aheadVal = yylval;
yylval = curValue; yylval = curValue;
// Now potentially munge the current token // Now potentially munge the current token
if (token == yGLOBAL__LEX) { if (token == yCONST__LEX) {
//UNSUP if (nexttok == yREF) token = yCONST__REF;
token = yCONST__ETC;
}
else if (token == yGLOBAL__LEX) {
if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING; if (nexttok == yCLOCKING) token = yGLOBAL__CLOCKING;
else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } // Avoid 2009 "global" conflicting with old code when we can else { token = yaID__LEX; yylval.strp = PARSEP->newString("global"); } // Avoid 2009 "global" conflicting with old code when we can
} }
+69 -24
View File
@@ -71,7 +71,7 @@ public:
m_varIO = AstVarType::UNKNOWN; m_varIO = AstVarType::UNKNOWN;
m_varDTypep = NULL; m_varDTypep = NULL;
m_pinNum = -1; m_pinNum = -1;
m_instModule; m_instModule = "";
m_instParamp = NULL; m_instParamp = NULL;
m_modp = NULL; m_modp = NULL;
m_modTypeImpNum = 0; m_modTypeImpNum = 0;
@@ -274,6 +274,8 @@ class AstSenTree;
%token<fl> yCASEZ "casez" %token<fl> yCASEZ "casez"
%token<fl> yCHANDLE "chandle" %token<fl> yCHANDLE "chandle"
%token<fl> yCLOCKING "clocking" %token<fl> yCLOCKING "clocking"
%token<fl> yCONST__ETC "const"
%token<fl> yCONST__LEX "const-in-lex"
%token<fl> yCMOS "cmos" %token<fl> yCMOS "cmos"
%token<fl> yCONTEXT "context" %token<fl> yCONTEXT "context"
%token<fl> yCONTINUE "continue" %token<fl> yCONTINUE "continue"
@@ -340,6 +342,8 @@ class AstSenTree;
%token<fl> yPULLUP "pullup" %token<fl> yPULLUP "pullup"
%token<fl> yPURE "pure" %token<fl> yPURE "pure"
%token<fl> yRCMOS "rcmos" %token<fl> yRCMOS "rcmos"
%token<fl> yREAL "real"
%token<fl> yREALTIME "realtime"
%token<fl> yREG "reg" %token<fl> yREG "reg"
%token<fl> yREPEAT "repeat" %token<fl> yREPEAT "repeat"
%token<fl> yRETURN "return" %token<fl> yRETURN "return"
@@ -376,15 +380,19 @@ class AstSenTree;
%token<fl> yVOID "void" %token<fl> yVOID "void"
%token<fl> yWHILE "while" %token<fl> yWHILE "while"
%token<fl> yWIRE "wire" %token<fl> yWIRE "wire"
%token<fl> yWREAL "wreal"
%token<fl> yXNOR "xnor" %token<fl> yXNOR "xnor"
%token<fl> yXOR "xor" %token<fl> yXOR "xor"
%token<fl> yD_BITS "$bits" %token<fl> yD_BITS "$bits"
%token<fl> yD_BITSTOREAL "$bitstoreal"
%token<fl> yD_C "$c" %token<fl> yD_C "$c"
%token<fl> yD_CEIL "$ceil"
%token<fl> yD_CLOG2 "$clog2" %token<fl> yD_CLOG2 "$clog2"
%token<fl> yD_COUNTONES "$countones" %token<fl> yD_COUNTONES "$countones"
%token<fl> yD_DISPLAY "$display" %token<fl> yD_DISPLAY "$display"
%token<fl> yD_ERROR "$error" %token<fl> yD_ERROR "$error"
%token<fl> yD_EXP "$exp"
%token<fl> yD_FATAL "$fatal" %token<fl> yD_FATAL "$fatal"
%token<fl> yD_FCLOSE "$fclose" %token<fl> yD_FCLOSE "$fclose"
%token<fl> yD_FDISPLAY "$fdisplay" %token<fl> yD_FDISPLAY "$fdisplay"
@@ -393,22 +401,32 @@ class AstSenTree;
%token<fl> yD_FGETC "$fgetc" %token<fl> yD_FGETC "$fgetc"
%token<fl> yD_FGETS "$fgets" %token<fl> yD_FGETS "$fgets"
%token<fl> yD_FINISH "$finish" %token<fl> yD_FINISH "$finish"
%token<fl> yD_FLOOR "$floor"
%token<fl> yD_FOPEN "$fopen" %token<fl> yD_FOPEN "$fopen"
%token<fl> yD_FSCANF "$fscanf" %token<fl> yD_FSCANF "$fscanf"
%token<fl> yD_FWRITE "$fwrite" %token<fl> yD_FWRITE "$fwrite"
%token<fl> yD_INFO "$info" %token<fl> yD_INFO "$info"
%token<fl> yD_ISUNKNOWN "$isunknown" %token<fl> yD_ISUNKNOWN "$isunknown"
%token<fl> yD_ITOR "$itor"
%token<fl> yD_LN "$ln"
%token<fl> yD_LOG10 "$log10"
%token<fl> yD_ONEHOT "$onehot" %token<fl> yD_ONEHOT "$onehot"
%token<fl> yD_ONEHOT0 "$onehot0" %token<fl> yD_ONEHOT0 "$onehot0"
%token<fl> yD_POW "$pow"
%token<fl> yD_RANDOM "$random" %token<fl> yD_RANDOM "$random"
%token<fl> yD_READMEMB "$readmemb" %token<fl> yD_READMEMB "$readmemb"
%token<fl> yD_READMEMH "$readmemh" %token<fl> yD_READMEMH "$readmemh"
%token<fl> yD_REALTIME "$realtime"
%token<fl> yD_REALTOBITS "$realtobits"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SFORMAT "$sformat" %token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SIGNED "$signed" %token<fl> yD_SIGNED "$signed"
%token<fl> yD_SQRT "$sqrt"
%token<fl> yD_SSCANF "$sscanf" %token<fl> yD_SSCANF "$sscanf"
%token<fl> yD_STIME "$stime" %token<fl> yD_STIME "$stime"
%token<fl> yD_STOP "$stop" %token<fl> yD_STOP "$stop"
%token<fl> yD_SWRITE "$swrite" %token<fl> yD_SWRITE "$swrite"
%token<fl> yD_SYSTEM "$system"
%token<fl> yD_TESTPLUSARGS "$test$plusargs" %token<fl> yD_TESTPLUSARGS "$test$plusargs"
%token<fl> yD_TIME "$time" %token<fl> yD_TIME "$time"
%token<fl> yD_UNIT "$unit" %token<fl> yD_UNIT "$unit"
@@ -431,6 +449,7 @@ class AstSenTree;
%token<fl> yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/" %token<fl> yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/"
%token<fl> yVL_NO_INLINE_MODULE "/*verilator no_inline_module*/" %token<fl> yVL_NO_INLINE_MODULE "/*verilator no_inline_module*/"
%token<fl> yVL_NO_INLINE_TASK "/*verilator no_inline_task*/" %token<fl> yVL_NO_INLINE_TASK "/*verilator no_inline_task*/"
%token<fl> yVL_SC_BV "/*verilator sc_bv*/"
%token<fl> yVL_SFORMAT "/*verilator sformat*/" %token<fl> yVL_SFORMAT "/*verilator sformat*/"
%token<fl> yVL_PARALLEL_CASE "/*verilator parallel_case*/" %token<fl> yVL_PARALLEL_CASE "/*verilator parallel_case*/"
%token<fl> yVL_PUBLIC "/*verilator public*/" %token<fl> yVL_PUBLIC "/*verilator public*/"
@@ -1065,6 +1084,14 @@ integer_vector_type<bdtypep>: // ==IEEE: integer_atom_type
| yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg | yREG { $$ = new AstBasicDType($1,AstBasicDTypeKwd::LOGIC); } // logic==reg
; ;
non_integer_type<bdtypep>: // ==IEEE: non_integer_type
yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
| yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
//UNSUP ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::FLOAT); }
// // VAMS - somewhat hackish
| yWREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); VARDECL(WIRE); }
;
signingE<signstate>: // IEEE: signing - plus empty signingE<signstate>: // IEEE: signing - plus empty
/*empty*/ { $$ = signedst_NOP; } /*empty*/ { $$ = signedst_NOP; }
| signing { $$ = $1; } | signing { $$ = $1; }
@@ -1095,7 +1122,7 @@ simple_type<dtypep>: // ==IEEE: simple_type
// // IEEE: integer_type // // IEEE: integer_type
integer_atom_type { $$ = $1; } integer_atom_type { $$ = $1; }
| integer_vector_type { $$ = $1; } | integer_vector_type { $$ = $1; }
//UNSUP non_integer_type { $$ = $1; } | non_integer_type { $$ = $1; }
// // IEEE: ps_type_identifier // // IEEE: ps_type_identifier
// // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE) // // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE)
| ps_type { $$ = $1; } | ps_type { $$ = $1; }
@@ -1118,7 +1145,7 @@ data_type<dtypep>: // ==IEEE: data_type
data_typeBasic<dtypep>: // IEEE: part of data_type data_typeBasic<dtypep>: // IEEE: part of data_type
integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); } integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3,true); }
| integer_atom_type signingE { $1->setSignedState($2); $$ = $1; } | integer_atom_type signingE { $1->setSignedState($2); $$ = $1; }
//UNSUP non_integer_type { UNSUP } | non_integer_type { $$ = $1; }
; ;
data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references data_typeNoRef<dtypep>: // ==IEEE: data_type, excluding class_type etc references
@@ -1269,23 +1296,24 @@ data_declarationVar<nodep>: // IEEE: part of data_declaration
; ;
data_declarationVarFront: // IEEE: part of data_declaration data_declarationVarFront: // IEEE: part of data_declaration
// // Expanded: "constE yVAR lifetimeE data_type"
// // implicit_type expanded into /*empty*/ or "signingE rangeList" // // implicit_type expanded into /*empty*/ or "signingE rangeList"
constE yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($4); } /**/ yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($3); }
| constE yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstBasicDType($<fl>2, LOGIC_IMPLICIT)); } | /**/ yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstBasicDType($<fl>1, LOGIC_IMPLICIT)); }
| constE yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4),$5,false)); } | /**/ yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(GRAMMARP->addRange(new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $3), $4,false)); }
//
// // implicit_type expanded into /*empty*/ or "signingE rangeList"
| yCONST__ETC yVAR lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, $4)); }
| yCONST__ETC yVAR lifetimeE { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, new AstBasicDType($<fl>2, LOGIC_IMPLICIT))); }
| yCONST__ETC yVAR lifetimeE signingE rangeList { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, GRAMMARP->addRange(new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $4), $5,false))); }
// //
// // Expanded: "constE lifetimeE data_type" // // Expanded: "constE lifetimeE data_type"
| /**/ data_type { /*VARRESET-in-ddVar*/ VARDTYPE($1); } | /**/ data_type { /*VARRESET-in-ddVar*/ VARDTYPE($1); }
| /**/ lifetime data_type { /*VARRESET-in-ddVar*/ VARDTYPE($2); } | /**/ lifetime data_type { /*VARRESET-in-ddVar*/ VARDTYPE($2); }
//UNSUP yCONST__ETC lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE($3); } | yCONST__ETC lifetimeE data_type { /*VARRESET-in-ddVar*/ VARDTYPE(new AstConstDType($<fl>1, $3)); }
// // = class_new is in variable_decl_assignment // // = class_new is in variable_decl_assignment
; ;
constE: // IEEE: part of data_declaration
/* empty */ { }
//UNSUP yCONST__ETC { UNSUP }
;
implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit implicit_typeE<dtypep>: // IEEE: part of *data_type_or_implicit
// // Also expanded in data_declaration // // Also expanded in data_declaration
/* empty */ { $$ = NULL; } /* empty */ { $$ = NULL; }
@@ -1504,7 +1532,7 @@ assignOne<nodep>:
delayE: delayE:
/* empty */ { } /* empty */ { }
| delay_control { } /* ignored */ | delay_control { $1->v3warn(ASSIGNDLY,"Unsupported: Ignoring delay on this assignment/primitive."); } /* ignored */
; ;
delay_control<fl>: //== IEEE: delay_control delay_control<fl>: //== IEEE: delay_control
@@ -1524,8 +1552,7 @@ delay_value: // ==IEEE:delay_value
delayExpr: delayExpr:
expr { } expr { }
// // Verilator doesn't support yaFLOATNUM/yaTIMENUM, so not in expr // // Verilator doesn't support yaTIMENUM, so not in expr
| yaFLOATNUM { }
| yaTIMENUM { } | yaTIMENUM { }
; ;
@@ -1574,6 +1601,7 @@ sigAttr<nodep>:
| yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); | yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW);
$$ = $$->addNext(new AstAlwaysPublic($1,$2,NULL)); } $$ = $$->addNext(new AstAlwaysPublic($1,$2,NULL)); }
| yVL_ISOLATE_ASSIGNMENTS { $$ = new AstAttrOf($1,AstAttrType::VAR_ISOLATE_ASSIGNMENTS); } | yVL_ISOLATE_ASSIGNMENTS { $$ = new AstAttrOf($1,AstAttrType::VAR_ISOLATE_ASSIGNMENTS); }
| yVL_SC_BV { $$ = new AstAttrOf($1,AstAttrType::VAR_SC_BV); }
| yVL_SFORMAT { $$ = new AstAttrOf($1,AstAttrType::VAR_SFORMAT); } | yVL_SFORMAT { $$ = new AstAttrOf($1,AstAttrType::VAR_SFORMAT); }
; ;
@@ -1710,8 +1738,6 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + named_parameter_assignment
| expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); } | expr { $$ = new AstPin($1->fileline(),PINNUMINC(),"",$1); }
//UNSUP expr ':' expr { } //UNSUP expr ':' expr { }
//UNSUP expr ':' expr ':' expr { } //UNSUP expr ':' expr ':' expr { }
// // Floatnum should only occur with UDPs, but since ports aren't floats, it's legal to round always
| yaFLOATNUM { $$ = new AstPin($<fl>1,PINNUMINC(),"",new AstConst($<fl>1,AstConst::Unsized32(),(int)(($1<0)?($1-0.5):($1+0.5)))); }
; ;
//************************************************ //************************************************
@@ -1746,8 +1772,8 @@ event_control<sentreep>: // ==IEEE: event_control
event_expression<senitemp>: // IEEE: event_expression - split over several event_expression<senitemp>: // IEEE: event_expression - split over several
senitem { $$ = $1; } senitem { $$ = $1; }
| event_expression yOR senitem { $$ = $1;$1->addNext($3); } | event_expression yOR senitem { $$ = $1;$1->addNextNull($3); }
| event_expression ',' senitem { $$ = $1;$1->addNext($3); } /* Verilog 2001 */ | event_expression ',' senitem { $$ = $1;$1->addNextNull($3); } /* Verilog 2001 */
; ;
senitem<senitemp>: // IEEE: part of event_expression, non-'OR' ',' terms senitem<senitemp>: // IEEE: part of event_expression, non-'OR' ',' terms
@@ -1756,6 +1782,11 @@ senitem<senitemp>: // IEEE: part of event_expression, non-'OR' ',' terms
| '(' senitemVar ')' { $$ = $2; } | '(' senitemVar ')' { $$ = $2; }
//UNSUP expr { UNSUP } //UNSUP expr { UNSUP }
//UNSUP expr yIFF expr { UNSUP } //UNSUP expr yIFF expr { UNSUP }
// Since expr is unsupported we allow and ignore constants (removed in V3Const)
| yaINTNUM { $$ = NULL; }
| yaFLOATNUM { $$ = NULL; }
| '(' yaINTNUM ')' { $$ = NULL; }
| '(' yaFLOATNUM ')' { $$ = NULL; }
; ;
senitemVar<senitemp>: senitemVar<senitemp>:
@@ -1886,7 +1917,7 @@ statement_item<nodep>: // IEEE: statement_item
| statementVerilatorPragmas { $$ = $1; } | statementVerilatorPragmas { $$ = $1; }
// //
// // IEEE: disable_statement // // IEEE: disable_statement
//UNSUP yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { UNSUP } | yDISABLE idAny/*hierarchical_identifier-task_or_block*/ ';' { $$ = new AstDisable($1,*$2); }
//UNSUP yDISABLE yFORK ';' { UNSUP } //UNSUP yDISABLE yFORK ';' { UNSUP }
// // IEEE: event_trigger // // IEEE: event_trigger
//UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP } //UNSUP yP_MINUSGT hierarchical_identifier/*event*/ ';' { UNSUP }
@@ -1909,7 +1940,7 @@ statement_item<nodep>: // IEEE: statement_item
// //
//UNSUP par_block { $$ = $1; } //UNSUP par_block { $$ = $1; }
// // IEEE: procedural_timing_control_statement + procedural_timing_control // // IEEE: procedural_timing_control_statement + procedural_timing_control
| delay_control stmtBlock { $$ = $2; $1->v3warn(STMTDLY,"Ignoring delay on this delayed statement."); } | delay_control stmtBlock { $$ = $2; $1->v3warn(STMTDLY,"Unsupported: Ignoring delay on this delayed statement."); }
//UNSUP event_control stmtBlock { UNSUP } //UNSUP event_control stmtBlock { UNSUP }
//UNSUP cycle_delay stmtBlock { UNSUP } //UNSUP cycle_delay stmtBlock { UNSUP }
// //
@@ -2098,7 +2129,7 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); } | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
| yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); } | yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
| yD_FFLUSH parenE { $1->v3error("Unsupported: $fflush of all handles does not map to C++."); } | yD_FFLUSH parenE { $1->v3error("Unsupported: $fflush of all handles does not map to C++."); }
| yD_FFLUSH '(' idClassSel ')' { $$ = new AstFClose($1, $3); } | yD_FFLUSH '(' idClassSel ')' { $$ = new AstFFlush($1, $3); }
| yD_FINISH parenE { $$ = new AstFinish($1); } | yD_FINISH parenE { $$ = new AstFinish($1); }
| yD_FINISH '(' expr ')' { $$ = new AstFinish($1); } | yD_FINISH '(' expr ')' { $$ = new AstFinish($1); }
| yD_STOP parenE { $$ = new AstStop($1); } | yD_STOP parenE { $$ = new AstStop($1); }
@@ -2106,6 +2137,7 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
// //
| yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); } | yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
| yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); } | yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1,$3); }
// //
| yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,"", NULL,NULL); } | yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,"", NULL,NULL); }
| yD_DISPLAY '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,*$3,NULL,$4); } | yD_DISPLAY '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,*$3,NULL,$4); }
@@ -2139,8 +2171,16 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); } | yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); } | yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
// //
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
| yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); }
| yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); }
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); } | yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); } | yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); } | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); }
| yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); } | yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); }
| yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); } | yD_COUNTONES '(' expr ')' { $$ = new AstCountOnes($1,$3); }
@@ -2149,11 +2189,16 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); } | yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); } | yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); } | yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); } | yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); } | yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); } | yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); }
| yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); } | yD_RANDOM '(' expr ')' { $1->v3error("Unsupported: Seeding $random doesn't map to C++, use $c(\"srand\")"); }
| yD_RANDOM parenE { $$ = new AstRand($1); } | yD_RANDOM parenE { $$ = new AstRand($1); }
| yD_REALTIME parenE { $$ = new AstTimeD($1); }
| yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); }
| yD_RTOI '(' expr ')' { $$ = new AstRToIS($1,$3); }
//| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug //| yD_SFORMATF '(' str commaEListE ')' { $$ = new AstSFormatF($1,*$3,false,$4); } // Have AST, just need testing and debug
| yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); } | yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); }
| yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); } | yD_STIME parenE { $$ = new AstSel($1,new AstTime($1),0,32); }
@@ -2374,7 +2419,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// //
// // IEEE: unary_operator primary // // IEEE: unary_operator primary
'+' ~r~expr %prec prUNARYARITH { $$ = $2; } '+' ~r~expr %prec prUNARYARITH { $$ = $2; }
| '-' ~r~expr %prec prUNARYARITH { $$ = new AstUnaryMin ($1,$2); } | '-' ~r~expr %prec prUNARYARITH { $$ = new AstNegate ($1,$2); }
| '!' ~r~expr %prec prNEGATION { $$ = new AstLogNot ($1,$2); } | '!' ~r~expr %prec prNEGATION { $$ = new AstLogNot ($1,$2); }
| '&' ~r~expr %prec prREDUCTION { $$ = new AstRedAnd ($1,$2); } | '&' ~r~expr %prec prREDUCTION { $$ = new AstRedAnd ($1,$2); }
| '~' ~r~expr %prec prNEGATION { $$ = new AstNot ($1,$2); } | '~' ~r~expr %prec prNEGATION { $$ = new AstNot ($1,$2); }
@@ -2452,7 +2497,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
// //
// // IEEE: primary_literal (minus string, which is handled specially) // // IEEE: primary_literal (minus string, which is handled specially)
| yaINTNUM { $$ = new AstConst($<fl>1,*$1); } | yaINTNUM { $$ = new AstConst($<fl>1,*$1); }
//UNSUP yaFLOATNUM { UNSUP } | yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
//UNSUP yaTIMENUM { UNSUP } //UNSUP yaTIMENUM { UNSUP }
| strAsInt~noStr__IGNORE~ { $$ = $1; } | strAsInt~noStr__IGNORE~ { $$ = $1; }
// //

Some files were not shown because too many files have changed in this diff Show More