mirror of
https://github.com/verilator/verilator.git
synced 2026-10-02 16:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4100f20a69 | ||
|
|
bedf946fb2 | ||
|
|
b9e67157c6 | ||
|
|
b30b2a183b | ||
|
|
9ab3bcdde3 | ||
|
|
5df3bbe188 | ||
|
|
8cf12416c0 | ||
|
|
b7c2c83c88 | ||
|
|
3b6da93331 | ||
|
|
b4642d3fd4 | ||
|
|
88a2b0b911 | ||
|
|
954e127f1d | ||
|
|
7654add5e5 | ||
|
|
85a37ea53f | ||
|
|
b337acebcc | ||
|
|
fb9ca54c95 | ||
|
|
1a15d41523 | ||
|
|
e378cc5791 | ||
|
|
748c189c79 | ||
|
|
b89be6c4b9 | ||
|
|
df207807b6 | ||
|
|
1f2b40cff1 | ||
|
|
734400fd37 | ||
|
|
f19979d928 | ||
|
|
19be7a53da | ||
|
|
e56af34fb0 | ||
|
|
7737aa20e8 | ||
|
|
ead046201c | ||
|
|
0aa7c3f659 | ||
|
|
4aa7222022 | ||
|
|
86e3c78776 | ||
|
|
40076287ea | ||
|
|
ca81db8edf | ||
|
|
ae68a80e98 | ||
|
|
beb7c58375 | ||
|
|
e080b9d565 | ||
|
|
ca2db37039 | ||
|
|
194825f78e | ||
|
|
55bd765ea0 | ||
|
|
b03d61e2cf | ||
|
|
6fc0e5167b | ||
|
|
0065be011f | ||
|
|
3f7cbce58c | ||
|
|
246b62e322 | ||
|
|
7c2fdd1ee9 | ||
|
|
f77aa2623c | ||
|
|
20847a3ff5 | ||
|
|
eb6d42acf9 | ||
|
|
094d676a8b | ||
|
|
71306ceb1d | ||
|
|
8bbfc7fc22 | ||
|
|
19baba12b1 | ||
|
|
15b8819136 | ||
|
|
3fae8ade05 | ||
|
|
f9bbf31d65 | ||
|
|
df1da3dda9 | ||
|
|
c83f2a4abd | ||
|
|
ad53833040 | ||
|
|
bc8c85668a | ||
|
|
d12a3dde45 | ||
|
|
301c878c0f | ||
|
|
bd55bfa071 | ||
|
|
6d2f09b579 | ||
|
|
4bfea7f54d | ||
|
|
55906486d8 | ||
|
|
d5478e6e08 | ||
|
|
d88d85c172 | ||
|
|
59c3c536c7 | ||
|
|
a007458cb8 | ||
|
|
d051912f21 | ||
|
|
a547158a50 | ||
|
|
95f2351aa0 | ||
|
|
698aaffb0b | ||
|
|
73eccecbf8 | ||
|
|
ae4a261463 | ||
|
|
c9f0d0cec2 | ||
|
|
4fa1e45d45 | ||
|
|
1b3d252bfe | ||
|
|
a9ba4a9fcd | ||
|
|
7f49619875 | ||
|
|
696660639a | ||
|
|
da4323062d | ||
|
|
a901e171b2 | ||
|
|
6e41d532fe | ||
|
|
4fc78ffb58 | ||
|
|
8137f41fc3 | ||
|
|
2e9471797d | ||
|
|
344248cea0 | ||
|
|
2789e3dba5 | ||
|
|
cca759a41e | ||
|
|
4f7b3d8882 | ||
|
|
2b330b78b7 | ||
|
|
d47ca1912b | ||
|
|
3fd2108b10 | ||
|
|
96e2a407f4 | ||
|
|
cdf18c96f4 | ||
|
|
53acaa05b8 | ||
|
|
fb85679068 | ||
|
|
9558e14479 | ||
|
|
4af0af93bf | ||
|
|
df4bc950fe | ||
|
|
250394f72b | ||
|
|
ca83fd6dc1 | ||
|
|
d5e9e7cd2b | ||
|
|
9a96f621ef | ||
|
|
5d7ce096c6 | ||
|
|
c9f8109c06 |
@@ -24,6 +24,8 @@ src/Makefile_obj$
|
||||
include/verilated.mk$
|
||||
config.cache$
|
||||
config.status$
|
||||
verilator.log
|
||||
verilator.tex
|
||||
verilator_bin.*
|
||||
.vcsmx_rebuild$
|
||||
autom4te\.cache/
|
||||
|
||||
+36
-20
@@ -88,7 +88,10 @@ pkgdatadir = @pkgdatadir@
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
# Compile options
|
||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
######################################################################
|
||||
@@ -101,8 +104,6 @@ INFOS = README internals.txt verilator.txt verilator.html verilator.1 verilator.
|
||||
|
||||
# Files that can be generated, but should be up to date for a distribution.
|
||||
DISTDEP = info Makefile
|
||||
# Files to distribute.
|
||||
DISTBIN = $(wildcard bin/verilator-*)
|
||||
|
||||
DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
*.in *.ac \
|
||||
@@ -129,7 +130,6 @@ DISTFILES_INC = $(INFOS) .gitignore Artistic COPYING COPYING.LESSER \
|
||||
test_regress/t/*.pl \
|
||||
test_regress/t/*.pf \
|
||||
test_regress/t/*.v* \
|
||||
verilator.* \
|
||||
|
||||
INST_PROJ_FILES = \
|
||||
bin/verilator \
|
||||
@@ -171,7 +171,7 @@ msg_test:
|
||||
@echo
|
||||
|
||||
.PHONY:test
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
ifeq ($(CFG_WITH_LONGTESTS),yes) # Local... Else don't burden users
|
||||
test: test_vcs test_c test_sc test_sp test_verilated test_regress
|
||||
else
|
||||
test: test_c test_sc test_sp
|
||||
@@ -203,17 +203,18 @@ test_regress: all_nomsg
|
||||
info: $(INFOS)
|
||||
|
||||
# Use --no-split to avoid creating filenames > 14 chars.
|
||||
verilator.1: bin/verilator
|
||||
verilator.1: ${srcdir}/bin/verilator
|
||||
pod2man $< $@
|
||||
|
||||
verilator.txt: bin/verilator
|
||||
verilator.txt: ${srcdir}/bin/verilator
|
||||
$(POD2TEXT) $< $@
|
||||
|
||||
verilator.html: bin/verilator
|
||||
verilator.html: ${srcdir}/bin/verilator
|
||||
pod2html $< >$@
|
||||
|
||||
verilator.pdf: bin/verilator $(DISTCONFIG)
|
||||
pod2latex --full --out verilator.tex bin/verilator
|
||||
# PDF needs DIST variables; but having configure.ac as dependency isn't detected
|
||||
verilator.pdf: ${srcdir}/bin/verilator Makefile
|
||||
pod2latex --full --out verilator.tex ${srcdir}/bin/verilator
|
||||
cat < verilator.tex \
|
||||
| sed 's/\\begin{document}/\\usepackage[left=1.7in,right=1.7in,top=1.3in,bottom=1.3in]{geometry}\n\\begin{document}/' \
|
||||
| sed 's/\\begin{document}/\\usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref}\n\\begin{document}/' \
|
||||
@@ -257,7 +258,7 @@ VL_INST_DATA_SRCDIR_FILES = \
|
||||
test_v/*.[chv]* \
|
||||
test_c/*.[chv]* test_c/Makefile test_c/Makefile_obj \
|
||||
test_sc/*.[chv]* test_sc/Makefile test_sc/Makefile_obj \
|
||||
test_sp/*.[chv]* test_sp/Makefile test_sp/Makefile_obj \
|
||||
test_sp/Makefile test_sp/Makefile_obj \
|
||||
|
||||
installbin:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(bindir)
|
||||
@@ -268,9 +269,11 @@ installbin:
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgdatadir)/bin
|
||||
( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer )
|
||||
|
||||
# Man files can either be part of the original kit, or built in current directory
|
||||
# So important we use $< so VPATH is searched
|
||||
installman: $(VL_INST_MAN_FILES)
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||
for p in $(VL_INST_MAN_FILES) ; do \
|
||||
for p in $< ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||
done
|
||||
|
||||
@@ -315,6 +318,8 @@ install: all_nomsg installbin installman installdata install-msg
|
||||
install-here: installman ftp
|
||||
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
DISTNAMEREV = $(shell sed -e '/DTVERSION/!d' -e 's/.*verilator_\([^"]*\).*/\1/' -e q ${srcdir}/src/config_rev.h)
|
||||
|
||||
DIRPROJECT := $(shell project_dir --project)
|
||||
VERILATOR_CAD_DIR = $(CAD_DIR)/verilator/$(DISTNAMEREV)/$(DIRPROJECT_ARCH)
|
||||
INST_PROJ_CVS = cp_if_cvs_diff
|
||||
@@ -323,7 +328,7 @@ install-project: dist
|
||||
@echo "Install-project to $(DIRPROJECT)"
|
||||
strip verilator_bin*
|
||||
$(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; \
|
||||
done
|
||||
$(INST_PROJ_CVS) $(DISTNAME).tgz $(DIRPROJECT)/hw/utils/verilator/verilator.tgz
|
||||
@@ -347,7 +352,7 @@ install-cadtools: dist
|
||||
strip verilator_bin*
|
||||
$(MAKE) install-cadtools-quick
|
||||
$(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; \
|
||||
done
|
||||
$(INST_PROJ_CVS) $(DISTNAME).tgz $(VERILATOR_CAD_DIR)/verilator.tgz
|
||||
@@ -371,6 +376,15 @@ endif
|
||||
# VERILATOR_AUTHOR_SITE
|
||||
endif
|
||||
|
||||
CPPCHECK = cppcheck
|
||||
CPPCHECK_FLAGS = --enable=all --inline-suppr --suppress=unusedScopedObject
|
||||
CPPCHECK_CPP = $(wildcard $(srcdir)/include/*.cpp $(srcdir)/src/*.cpp)
|
||||
CPPCHECK_DEP = $(subst .cpp,.cppcheck,$(CPPCHECK_CPP))
|
||||
|
||||
cppcheck: $(CPPCHECK_DEP)
|
||||
%.cppcheck: %.cpp
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -I$(srcdir)/include -I$(srcdir)/src $<
|
||||
|
||||
ftp: info
|
||||
|
||||
install-msg:
|
||||
@@ -391,8 +405,13 @@ Makefile: Makefile.in config.status $(IN_WILD)
|
||||
src/Makefile: src/Makefile.in Makefile
|
||||
config.status: configure
|
||||
./config.status --recheck
|
||||
|
||||
configure: configure.ac
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
autoconf --warnings=all
|
||||
else
|
||||
autoconf
|
||||
endif
|
||||
|
||||
maintainer-clean::
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@@ -433,15 +452,12 @@ dist-file-list:
|
||||
######################################################################
|
||||
# Distributions
|
||||
|
||||
DISTCONFIG = ${srcdir}/src/config_build.h.in
|
||||
|
||||
DISTTITLE := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e 's/v/V/' -e q $(DISTCONFIG))
|
||||
DISTNAME := $(shell sed -e '/DTVERSION/!d' -e 's/[^0-9]*\([0-9.a-z]*\).*/verilator-\1/' -e q $(DISTCONFIG))
|
||||
DISTDATEPRE := $(shell sed -e '/DTVERSION/!d' -e 's/.*\([1-2][0-9][0-9][0-9].[0-9]*[0-9].[0-9]*[0-9]\).*/\1/' -e q $(DISTCONFIG))
|
||||
DISTNAMEREV := $(shell sed -e '/DTVERSION/!d' -e 's/.*verilator_\([^"]*\).*/\1/' -e q src/config_rev.h)
|
||||
DISTTITLE := Verilator $(word 1,$(PACKAGE_VERSION))
|
||||
DISTNAME := verilator-$(word 1,$(PACKAGE_VERSION))
|
||||
DISTDATEPRE := $(word 2,$(PACKAGE_VERSION))
|
||||
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
||||
|
||||
DISTTAGNAME := $(subst .,_,$(subst -,_,$(DISTNAME)))
|
||||
DISTDATE := $(subst /,-,$(DISTDATEPRE))
|
||||
|
||||
tag:
|
||||
svnorcvs tag $(DISTTAGNAME)
|
||||
|
||||
+142
-76
@@ -70,7 +70,7 @@ if (! GetOptions (
|
||||
# "version!" => \&version, # Also passthru'ed
|
||||
# Switches
|
||||
"gdb=s" => \$opt_gdb, # Undocumented debugging
|
||||
"gdbbt!" => \$opt_gdbbt, # Undocumented debugging
|
||||
"gdbbt!" => \$opt_gdbbt,
|
||||
# Additional parameters
|
||||
"<>" => sub {}, # Ignored
|
||||
)) {
|
||||
@@ -99,7 +99,7 @@ if ($opt_gdbbt && !$opt_gdb && $Debug) {
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-exitstatus=>2, -verbose=>2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
}
|
||||
|
||||
sub debug {
|
||||
@@ -125,7 +125,14 @@ sub verilator_bin {
|
||||
$bin = "$dir/$basename"; # From pointing to kit directory
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
@@ -196,8 +203,9 @@ Verilator - Convert Verilog code to C++/SystemC
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Verilator converts synthesizable (not behavioral) Verilog code, plus some
|
||||
Synthesis, SystemVerilog and Sugar/PSL assertions, into C++, SystemC or
|
||||
SystemPerl code. It is not a complete simulator, just a compiler.
|
||||
Synthesis, SystemVerilog and a small subset of Verilog AMS and Sugar/PSL
|
||||
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
|
||||
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
|
||||
--Mdir <directory> Name of output object directory
|
||||
--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
|
||||
+notimingchecks Ignored
|
||||
-O0 Disable optimizations
|
||||
@@ -292,8 +300,8 @@ descriptions in the next sections for more information.
|
||||
--top-module <topname> Name of top level input module
|
||||
--trace Enable waveform creation
|
||||
--trace-depth <levels> Depth of tracing
|
||||
--trace-max-array <bits> Maximum bit width for tracing
|
||||
--trace-max-width <depth> Maximum array depth for tracing
|
||||
--trace-max-array <depth> Maximum bit width for tracing
|
||||
--trace-max-width <width> Maximum array depth for tracing
|
||||
--trace-underscore Enable tracing of _signals
|
||||
-U<var> Undefine preprocessor define
|
||||
--unroll-count <loops> Tune maximum loop iterations
|
||||
@@ -562,10 +570,7 @@ Displays this message and program version and exits.
|
||||
|
||||
=item -II<dir>
|
||||
|
||||
Add the directory to the list of directories that should be searched for
|
||||
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.
|
||||
See -y.
|
||||
|
||||
=item --if-depth I<value>
|
||||
|
||||
@@ -574,10 +579,7 @@ defaults to 0 which disables this warning.
|
||||
|
||||
=item +incdir+I<dir>
|
||||
|
||||
Add the directory to the list of directories that should be searched for
|
||||
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.
|
||||
See -y.
|
||||
|
||||
=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.
|
||||
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
|
||||
the preferable option is to edit the code to repair new keywords, or add
|
||||
appropriate `begin_keywords.
|
||||
"1364-2005", "1800-2005", "VAMS-2.3". Verilator also allows the
|
||||
non-standard "1800+VAMS" to allow both the full SystemVerilog and
|
||||
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>...
|
||||
|
||||
@@ -713,9 +719,10 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
||||
=item --pins-bv I<width>
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
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
|
||||
traced. Defaults to 32, as tracing large arrays may greatly slow traced
|
||||
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
|
||||
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
|
||||
enabled), but do not affect style messages. This is equivalent to
|
||||
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
|
||||
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNSIGNED
|
||||
-Wwarn-WIDTH".
|
||||
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-REALCVT
|
||||
-Wwarn-UNSIGNED -Wwarn-WIDTH".
|
||||
|
||||
=item -Wwarn-style
|
||||
|
||||
Enable all code style related warning messages. This is equivalent to
|
||||
"-Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH -Wwarn-SYNCASYNCNET
|
||||
-Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
|
||||
"-Wwarn ASSIGNDLY -Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH
|
||||
-Wwarn-SYNCASYNCNET -Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
|
||||
|
||||
=item -x-assign 0
|
||||
|
||||
@@ -965,9 +972,14 @@ enable rerunning with that same seed so you can reproduce bugs.
|
||||
=item -y I<dir>
|
||||
|
||||
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
|
||||
are fairly standard across Verilog tools while -I is an alias for GCC
|
||||
compatibility.
|
||||
include files or libraries. The three flags -y, +incdir and -I have
|
||||
similar effect; +incdir and +y are fairly standard across Verilog tools while -I
|
||||
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
|
||||
|
||||
@@ -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
|
||||
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
|
||||
|
||||
Required for SystemC output mode. If set, specifies the directory
|
||||
@@ -1306,10 +1313,13 @@ example:
|
||||
|
||||
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
|
||||
return main_time;
|
||||
return main_time; // converts to double, to match
|
||||
// what SystemC does
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
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.)
|
||||
|
||||
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,
|
||||
$bits, $countones, $error, $fatal, $info, $isunknown, $onehot, $onehot0,
|
||||
$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
|
||||
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;
|
||||
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
|
||||
|
||||
Most future work is being directed towards improving SystemVerilog
|
||||
@@ -1711,8 +1733,8 @@ assertion clocks.
|
||||
=head2 Synthesis Directive Assertion Support
|
||||
|
||||
With the --assert switch, Verilator reads any "//synopsys full_case" or "//
|
||||
synopsys parallel_case" directives. The same applies to any "//cadence" or
|
||||
"// ambit synthesis" directives of the same form.
|
||||
synopsys parallel_case" directives. The same applies to any "// ambit
|
||||
synthesis", "//cadence" or "//pragma" directives of the same form.
|
||||
|
||||
When these synthesis directives are discovered, Verilator will either
|
||||
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
|
||||
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*/
|
||||
|
||||
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
|
||||
|
||||
Floating Point numbers are not synthesizable, and so not supported.
|
||||
Floating Point (real) numbers are supported.
|
||||
|
||||
=head2 Latches
|
||||
|
||||
@@ -2258,6 +2289,13 @@ not arrays nor structs.
|
||||
Treated as a "longint"; does not yet warn about operations that are
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
arrays.
|
||||
|
||||
=item $realtime
|
||||
|
||||
Treated as $time.
|
||||
|
||||
=item $test$plusargs, $value$plusargs
|
||||
|
||||
Supported, but the instantiating C++/SystemC testbench must call
|
||||
@@ -2377,6 +2406,29 @@ List of all warnings:
|
||||
|
||||
=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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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?
|
||||
|
||||
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?
|
||||
|
||||
Verilator supports both block (line) coverage and user inserted functional
|
||||
coverage. Both currently require SystemPerl output mode and the SystemPerl
|
||||
package.
|
||||
coverage. Both require the SystemPerl package to be installed but do not
|
||||
require use of the SystemPerl output mode.
|
||||
|
||||
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
|
||||
@@ -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
|
||||
to compile on parallel machines and avoid compilations altogether. See the
|
||||
--output-split option, and the web for the ccache, distcc and icecream
|
||||
packages, and the Make::Cache package available from
|
||||
L<http://www.veripool.org/>. Make::Cache will skip GCC runs between
|
||||
identical source builds, even across different users. You can use the
|
||||
OBJCACHE environment variable to use these CC wrappers.
|
||||
packages. ccache will skip GCC runs between identical source builds, even
|
||||
across different users. You can use the OBJCACHE environment variable to
|
||||
use these CC wrappers.
|
||||
|
||||
=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
|
||||
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.
|
||||
|
||||
Signals wider than 64 bits are stored as an array of 32-bit uint32_t's.
|
||||
@@ -3296,25 +3357,30 @@ Brooks, Duane Galbi, Paul Wasson, and Wilson Snyder. Major testers include
|
||||
Jeff Dutton, Ralf Karge, David Hewson, Wim Michiels, and Gene Weber.
|
||||
|
||||
Some of the people who have provided ideas and feedback for Verilator
|
||||
include David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
|
||||
include: David Addison, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, J
|
||||
Baxter, Jeremy Bennett, David Black, Gregg Bouchard, Christopher Boumenot,
|
||||
Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee, Lawrence Butcher,
|
||||
Chris Candler, Lauren Carlson, Donal Casey, Robert A. Clark, Allan
|
||||
Cochrane, Gunter Dannoritzer, Bernard Deadman, John Deroo, John Dickol,
|
||||
Danny Ding, Alex Duller, Jeff Dutton, Robert Farrell, Eugen Fekete, Andrea
|
||||
Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone, Chitlesh Goorah, Thomas
|
||||
Hawkins, David Hewson, Jae Hossell, Ben Jackson, Mike Kagen, Guy-Armand
|
||||
Kamendje, Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman,
|
||||
Jonathan Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang,
|
||||
Stephane Laurent, Charlie Lind, Dan Lussier, Fred Ma, Duraid Madina, Mark
|
||||
Marshall, Wim Michiels, Dennis Muhlestein, John Murphy, Richard Myers,
|
||||
Dimitris Nalbantis, Paul Nitza, Pete Nixon, Lisa Noack, Mark Nodine,
|
||||
Andreas Olofsson, Niranjan Prabhu, Oleg Rodionov, John Sanguinetti, Mike
|
||||
Shinkarovsky, Rafael Shirakawa, Rodney Sinclair, Brian Small, Art Stamness,
|
||||
John Stroebel, Emerson Suguimoto, Renga Sundararajan, Stefan Thiede, Gary
|
||||
Thomas, Steve Tong, Holger Waechtler, Shawn Wang, Greg Waters, Eugene
|
||||
Weber, Leon Wildman, Gerald Williams, Jeff Winston, Johan Wouters, and Ding
|
||||
Xiaoliang.
|
||||
Nick Bowler, Byron Bradley, Bryan Brady, Lane Brooks, John Brownlee,
|
||||
Lawrence Butcher, Chris Candler, Lauren Carlson, Donal Casey, Terry Chen,
|
||||
Robert A. Clark, Allan Cochrane, Gunter Dannoritzer, Ashutosh Das, Bernard
|
||||
Deadman, John Deroo, John Dickol, Danny Ding, Ivan Djordjevic, Alex Duller,
|
||||
Jeff Dutton, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Robert Farrell,
|
||||
Eugen Fekete, Andrea Foletto, Bob Fredieu, Shankar Giri, Sam Gladstone,
|
||||
Amir Gonnen, Chitlesh Goorah, Neil Hamilton, Thomas Hawkins, David Hewson,
|
||||
Jae Hossell, Ben Jackson, Iztok Jeras, Mike Kagen, Guy-Armand Kamendje,
|
||||
Vasu Kandadi, Patricio Kaplan, Ralf Karge, Dan Katz, Sol Katzman, Jonathan
|
||||
Kimmitt, Gernot Koch, Soon Koh, Steve Kolecki, Steve Lang, Stephane
|
||||
Laurent, Christian Leber, Charlie Lind, Paul Liu, Dan Lussier, Fred Ma,
|
||||
Duraid Madina, Mark Marshall, Jason McMullan, Wim Michiels, Dennis
|
||||
Muhlestein, John Murphy, Richard Myers, Dimitris Nalbantis, Paul Nitza,
|
||||
Pete Nixon, Lisa Noack, Mark Nodine, Andreas Olofsson, Brad Parker, Dominic
|
||||
Plunkett, Niranjan Prabhu, Usha Priyadharshini, Oleg Rodionov, John
|
||||
Sanguinetti, Salman Sheikh, Mike Shinkarovsky, Rafael Shirakawa, Jeffrey
|
||||
Short, Rodney Sinclair, Brian Small, Alex Solomatnikov, Art Stamness, John
|
||||
Stroebel, Emerson Suguimoto, Gene Sullivan, Renga Sundararajan, Stefan
|
||||
Thiede, Gary Thomas, Steve Tong, Holger Waechtler, Stefan Wallentowitz,
|
||||
Shawn Wang, Greg Waters, Eugene Weber, David Welch, Leon Wildman, Gerald
|
||||
Williams, Trevor Williams, Jeff Winston, Joshua Wise, Johan Wouters, and
|
||||
Ding Xiaoliang.
|
||||
|
||||
Thanks all.
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ sub filter {
|
||||
next if $line =~ / This=/;
|
||||
$line =~ s/0x[a-f0-9]+/0x/g;
|
||||
$line =~ s/<e[0-9]+\#?>/<e>/g;
|
||||
$line =~ s/{\d+}/{}/g if !$Opt_Lineno;
|
||||
$line =~ s/{[a-z]*\d+}/{}/g if !$Opt_Lineno;
|
||||
print $f2 $line;
|
||||
}
|
||||
$f1->close;
|
||||
@@ -109,7 +109,7 @@ sub filter {
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ profcfunc($Opt_File);
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
+100
-31
@@ -1,35 +1,83 @@
|
||||
dnl 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
|
||||
dnl redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
dnl General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
# DESCRIPTION: Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
# Copyright 2003-2011 by Wilson Snyder. Verilator is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU Lesser
|
||||
# General Public License Version 3 or the Perl Artistic License Version 2.0.
|
||||
|
||||
AC_INIT(src/Verilator.cpp)
|
||||
AC_INIT([Verilator],[3.830])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||
|
||||
dnl Special Substitutions
|
||||
AC_ARG_ENABLE(defenv,
|
||||
[AS_HELP_STRING([--disable-defenv], [disable hardcoded default environment variables])],
|
||||
CFG_WITH_DEFENV=$enableval,
|
||||
CFG_WITH_DEFENV=yes)
|
||||
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||
|
||||
# Special Substitutions - CFG_WITH_DEFENV
|
||||
AC_MSG_CHECKING(whether to disable hardcoded paths)
|
||||
AC_ARG_ENABLE([defenv],
|
||||
[AS_HELP_STRING([--disable-defenv],
|
||||
[disable using some hardcoded data paths extracted from some default environment variables (the default is to use hardcoded paths)])],
|
||||
[case "${enableval}" in
|
||||
yes) CFG_WITH_DEFENV=yes ;;
|
||||
no) CFG_WITH_DEFENV=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --disable-defenv]) ;;
|
||||
esac],
|
||||
CFG_WITH_DEFENV=yes)
|
||||
AC_SUBST(CFG_WITH_DEFENV)
|
||||
AC_MSG_RESULT($CFG_WITH_DEFENV)
|
||||
|
||||
dnl Compiler flags
|
||||
# Special Substitutions - CFG_WITH_CCWARN
|
||||
AC_MSG_CHECKING(whether to show and stop on compilation warnings)
|
||||
AC_ARG_ENABLE([ccwarn],
|
||||
[AS_HELP_STRING([--enable-ccwarn],
|
||||
[enable showing and stopping on compilation warnings])],
|
||||
[case "${enableval}" in
|
||||
yes) CFG_WITH_CCWARN=yes ;;
|
||||
no) CFG_WITH_CCWARN=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-ccwarn]) ;;
|
||||
esac],
|
||||
[case "x${VERILATOR_AUTHOR_SITE}" in
|
||||
x) CFG_WITH_CCWARN=no ;;
|
||||
*) CFG_WITH_CCWARN=yes ;;
|
||||
esac]
|
||||
)
|
||||
AC_SUBST(CFG_WITH_CCWARN)
|
||||
AC_MSG_RESULT($CFG_WITH_CCWARN)
|
||||
|
||||
# Special Substitutions - CFG_WITH_LONGTESTS
|
||||
AC_MSG_CHECKING(whether to run long tests)
|
||||
AC_ARG_ENABLE([longtests],
|
||||
[AS_HELP_STRING([--enable-longtests],
|
||||
[enable running long developer tests])],
|
||||
[case "${enableval}" in
|
||||
yes) CFG_WITH_LONGTESTS=yes ;;
|
||||
no) CFG_WITH_LONGTESTS=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-longtests]) ;;
|
||||
esac],
|
||||
[case "x${VERILATOR_AUTHOR_SITE}" in
|
||||
x) CFG_WITH_LONGTESTS=no ;;
|
||||
*) CFG_WITH_LONGTESTS=yes ;;
|
||||
esac]
|
||||
)
|
||||
AC_SUBST(CFG_WITH_LONGTESTS)
|
||||
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
||||
|
||||
# Compiler flags
|
||||
CFLAGS=-I${includedir}
|
||||
CPPFLAGS=-I${includedir}
|
||||
CXXFLAGS=-I${includedir}
|
||||
LDFLAGS=-L${libdir}
|
||||
|
||||
dnl Checks for programs.
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_INSTALL
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
AC_MSG_CHECKING([that C++ compiler can compile simple program])
|
||||
AC_TRY_RUN([int main() { return 0; }],
|
||||
AC_RUN_IFELSE(
|
||||
[AC_LANG_SOURCE([int main() { return 0; }])],
|
||||
AC_MSG_RESULT(yes),
|
||||
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]))
|
||||
AC_MSG_RESULT(no);AC_MSG_ERROR([a working C++ compiler is required]),
|
||||
AC_MSG_RESULT(yes))
|
||||
|
||||
AC_PATH_PROG(PERL,perl)
|
||||
if test "x$PERL" = "x" ; then
|
||||
@@ -44,33 +92,54 @@ if test "x$YACC" = "x" ; then
|
||||
AC_MSG_ERROR([Cannot find "bison" in your PATH, please install it])
|
||||
fi
|
||||
|
||||
dnl Checks for libraries.
|
||||
# Checks for libraries.
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(fcntl.h unistd.h inttypes.h sys/file.h sys/time.h sys/un.h math.h stdint.h mingw/stdint.h)
|
||||
|
||||
dnl Checks for typedefs, structures
|
||||
# Checks for typedefs, structures
|
||||
AC_CHECK_TYPE(size_t,unsigned int)
|
||||
AC_CHECK_TYPE(uint_t,unsigned int)
|
||||
AC_CHECK_TYPE(ulong_t,unsigned long)
|
||||
AC_TYPE_SIZE_T
|
||||
AC_STRUCT_TM
|
||||
|
||||
dnl Checks for compiler characteristics.
|
||||
# Checks for compiler characteristics.
|
||||
AC_C_INLINE
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_DEFUN([_MY_CXX_CHECK_OPT],
|
||||
[# _MY_CXX_CHECK_OPT(flag) -- Check if compiler supports specific options
|
||||
ACO_SAVE_CXXFLAGS="$CXXFLAGS"
|
||||
# -Werror needed otherwise unknown -Wno-div-by-zero won't report problems
|
||||
CXXFLAGS="$CXXFLAGS $1 -Werror"
|
||||
AC_MSG_CHECKING([whether $CXX accepts $1])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([],[])],
|
||||
[_my_result=yes],
|
||||
[_my_result=no])
|
||||
AC_MSG_RESULT($_my_result)
|
||||
if test "$_my_result" = "yes" ; then
|
||||
CFG_CXXFLAGS_NO_UNUSED="$CFG_CXXFLAGS_NO_UNUSED $1"
|
||||
fi
|
||||
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
|
||||
])# _MY_CXX_CHECK_OPT
|
||||
|
||||
dnl Checks for system services
|
||||
# For example, -Wno-div-by-zero isn't in 4.1.2
|
||||
_MY_CXX_CHECK_OPT(-Wno-char-subscripts)
|
||||
# Random code often does / 0. Unfortunately VL_DIV_I(0,0) will warn
|
||||
# without this flag, even though there's a conditional to prevent the divide.
|
||||
# We still don't add no-div-by-zero as it throws message to stdout, though doesn't die.
|
||||
#_MY_CXX_CHECK_OPT(-Wno-div-by-zero)
|
||||
_MY_CXX_CHECK_OPT(-Wno-sign-compare)
|
||||
_MY_CXX_CHECK_OPT(-Wno-uninitialized)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-parameter)
|
||||
_MY_CXX_CHECK_OPT(-Wno-unused-variable)
|
||||
AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
|
||||
dnl Other install directories
|
||||
# Checks for library functions.
|
||||
|
||||
# Checks for system services
|
||||
|
||||
# Other install directories
|
||||
pkgdatadir=${datadir}/verilator
|
||||
AC_SUBST(pkgdatadir)
|
||||
|
||||
AC_OUTPUT(Makefile src/Makefile src/Makefile_obj include/verilated.mk)
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([Now type 'gmake'])
|
||||
AC_MSG_RESULT([Now type 'make' (or sometimes 'gmake') to build Verilator.])
|
||||
AC_MSG_RESULT([])
|
||||
|
||||
+78
-12
@@ -26,7 +26,6 @@
|
||||
#define _VERILATED_CPP_
|
||||
#include "verilated_imp.h"
|
||||
#include <cctype>
|
||||
#include <vector>
|
||||
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 1024 ///< Max static char array for VL_VALUE_STRING
|
||||
|
||||
@@ -285,12 +284,15 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
// Note also assumes variables < 64 are not wide, this assumption is
|
||||
// sometimes not true in low-level routines written here in verilated.cpp
|
||||
static VL_THREAD char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
static VL_THREAD char tmpf[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const char* pctp = NULL; // Most recent %##.##g format
|
||||
bool inPct = false;
|
||||
bool widthSet = false;
|
||||
int width = 0;
|
||||
const char* pos = formatp;
|
||||
for (; *pos; ++pos) {
|
||||
if (!inPct && pos[0]=='%') {
|
||||
pctp = pos;
|
||||
inPct = true;
|
||||
widthSet = false;
|
||||
width = 0;
|
||||
@@ -312,6 +314,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
widthSet = true;
|
||||
width = width*10 + (fmt - '0');
|
||||
break;
|
||||
case '.':
|
||||
inPct = true; // Get more digits
|
||||
break;
|
||||
case '%':
|
||||
output += '%';
|
||||
break;
|
||||
@@ -325,6 +330,18 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
output += cstrp;
|
||||
break;
|
||||
}
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g': {
|
||||
const int lbits = va_arg(ap, int);
|
||||
double d = va_arg(ap, double);
|
||||
if (lbits) {} // UNUSED - always 64
|
||||
strncpy(tmpf, pctp, pos-pctp+1);
|
||||
tmpf[pos-pctp+1] = '\0';
|
||||
sprintf(tmp, tmpf, d);
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Deal with all read-and-print somethings
|
||||
const int lbits = va_arg(ap, int);
|
||||
@@ -358,14 +375,26 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
case 'd': { // Signed decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "d",(vlsint64_t)(VL_EXTENDS_QQ(lbits,lbits,ld)));
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
output.append(needmore,'0'); // Pre-pad zero
|
||||
} else {
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
case 'u': { // Unsigned decimal
|
||||
int digits=sprintf(tmp,"%" VL_PRI64 "u",ld);
|
||||
int needmore = width-digits;
|
||||
if (needmore>0) output.append(needmore,' '); // Pre-pad spaces
|
||||
if (needmore>0) {
|
||||
if (pctp && pctp[0] && pctp[1]=='0') { //%0
|
||||
output.append(needmore,'0'); // Pre-pad zero
|
||||
} else {
|
||||
output.append(needmore,' '); // Pre-pad spaces
|
||||
}
|
||||
}
|
||||
output += tmp;
|
||||
break;
|
||||
}
|
||||
@@ -569,6 +598,17 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
VL_SET_WQ(owp,ld);
|
||||
break;
|
||||
}
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'g': { // Real number
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
_vl_vsss_read(fp,floc,fromp, tmp, "+-.0123456789eE");
|
||||
if (!tmp[0]) goto done;
|
||||
union { double r; vlsint64_t ld; } u;
|
||||
u.r = strtod(tmp, NULL);
|
||||
VL_SET_WQ(owp,u.ld);
|
||||
break;
|
||||
}
|
||||
case 't': // FALLTHRU // Time
|
||||
case 'u': { // Unsigned decimal
|
||||
_vl_vsss_skipspace(fp,floc,fromp);
|
||||
@@ -628,6 +668,10 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
||||
//===========================================================================
|
||||
// File I/O
|
||||
|
||||
FILE* VL_CVT_I_FP(IData lhs) {
|
||||
return VerilatedImp::fdToFp(lhs);
|
||||
}
|
||||
|
||||
void _VL_VINT_TO_STRING(int obits, char* destoutp, WDataInP sourcep) {
|
||||
// See also VL_DATA_TO_STRING_NW
|
||||
int lsb=obits-1;
|
||||
@@ -655,8 +699,8 @@ void _VL_STRING_TO_VINT(int obits, void* destp, int srclen, const char* srcp) {
|
||||
for (; i<bytes; i++) { *op++ = 0; }
|
||||
}
|
||||
|
||||
IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
IData VL_FGETS_IXI(int obits, void* destp, IData fpi) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
// The string needs to be padded with 0's in unused spaces in front of
|
||||
@@ -683,16 +727,26 @@ IData VL_FGETS_IXQ(int obits, void* destp, QData fpq) {
|
||||
return got;
|
||||
}
|
||||
|
||||
QData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData VL_FOPEN_QI(QData filename, IData mode) {
|
||||
IData fnw[2]; VL_SET_WQ(fnw, filename);
|
||||
return VL_FOPEN_WI(2, fnw, mode);
|
||||
}
|
||||
QData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
IData VL_FOPEN_WI(int fnwords, WDataInP filenamep, IData mode) {
|
||||
char filenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, filenamez, filenamep);
|
||||
char modez[5];
|
||||
_VL_VINT_TO_STRING(VL_WORDSIZE, modez, &mode);
|
||||
return VL_CVT_FP_Q(fopen(filenamez,modez));
|
||||
return VL_FOPEN_S(filenamez,modez);
|
||||
}
|
||||
IData VL_FOPEN_S(const char* filenamep, const char* modep) {
|
||||
return VerilatedImp::fdNew(fopen(filenamep,modep));
|
||||
}
|
||||
|
||||
void VL_FCLOSE_I(IData fdi) {
|
||||
FILE* fp = VL_CVT_I_FP(fdi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
fclose(fp);
|
||||
VerilatedImp::fdDelete(fdi);
|
||||
}
|
||||
|
||||
void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...) {
|
||||
@@ -726,8 +780,8 @@ void VL_WRITEF(const char* formatp, ...) {
|
||||
VL_PRINTF("%s", output.c_str());
|
||||
}
|
||||
|
||||
void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
void VL_FWRITEF(IData fpi, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return;
|
||||
|
||||
va_list ap;
|
||||
@@ -739,8 +793,8 @@ void VL_FWRITEF(QData fpq, const char* formatp, ...) {
|
||||
fputs(output.c_str(), fp);
|
||||
}
|
||||
|
||||
IData VL_FSCANF_IX(QData fpq, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_Q_FP(fpq);
|
||||
IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) {
|
||||
FILE* fp = VL_CVT_I_FP(fpi);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
|
||||
va_list ap;
|
||||
@@ -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) {
|
||||
string match = VerilatedImp::argPlusMatch(formatp);
|
||||
if (match == "") return 0;
|
||||
@@ -1038,6 +1103,7 @@ VerilatedScope::VerilatedScope() {
|
||||
m_callbacksp = NULL;
|
||||
m_namep = NULL;
|
||||
m_funcnumMax = 0;
|
||||
m_symsp = NULL;
|
||||
m_varsp = NULL;
|
||||
}
|
||||
|
||||
|
||||
+43
-24
@@ -35,6 +35,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
// <iostream> avoided to reduce compile time
|
||||
// <string> avoided and instead in verilated_heavy.h to reduce compile time
|
||||
using namespace std;
|
||||
@@ -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);
|
||||
|
||||
/// File I/O
|
||||
extern IData VL_FGETS_IXQ(int obits, void* destp, QData fpq);
|
||||
extern IData VL_FGETS_IXI(int obits, void* destp, IData fpi);
|
||||
|
||||
extern QData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern QData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline QData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||
extern IData VL_FOPEN_S(const char* filenamep, const char* mode);
|
||||
extern IData VL_FOPEN_WI(int fnwords, WDataInP ofilename, IData mode);
|
||||
extern IData VL_FOPEN_QI(QData ofilename, IData mode);
|
||||
inline IData VL_FOPEN_II(IData ofilename, IData mode) { return VL_FOPEN_QI(ofilename,mode); }
|
||||
|
||||
extern void VL_FCLOSE_I(IData fdi);
|
||||
|
||||
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilename, void* memp, IData start, IData end);
|
||||
@@ -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); }
|
||||
|
||||
extern void VL_WRITEF(const char* formatp, ...);
|
||||
extern void VL_FWRITEF(QData fpq, const char* formatp, ...);
|
||||
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
|
||||
|
||||
extern IData VL_FSCANF_IX(QData fpq, const char* formatp, ...);
|
||||
extern IData VL_FSCANF_IX(IData fpi, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...);
|
||||
extern IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...);
|
||||
|
||||
extern void VL_SFORMAT_X(int obits, void* destp, const char* formatp, ...);
|
||||
|
||||
extern IData VL_SYSTEM_IW(int lhsnwords, WDataInP lhs);
|
||||
extern IData VL_SYSTEM_IQ(QData lhs);
|
||||
inline IData VL_SYSTEM_II(IData lhs) { return VL_SYSTEM_IQ(lhs); }
|
||||
|
||||
extern IData VL_TESTPLUSARGS_I(const char* formatp);
|
||||
extern IData VL_VALUEPLUSARGS_IW(int rbits, const char* prefixp, char fmt, WDataOutP rwp);
|
||||
extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish
|
||||
@@ -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_QII(ld,rd) ( ((QData)(ld)<<VL_ULL(32)) | (QData)(rd) )
|
||||
|
||||
/// Return FILE* from IData
|
||||
extern FILE* VL_CVT_I_FP(IData lhs);
|
||||
|
||||
// Use a union to avoid cast-to-different-size warnings
|
||||
/// Return FILE* from QData
|
||||
static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return void* from QData
|
||||
static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; }
|
||||
/// Return QData from FILE*
|
||||
static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return QData from void*
|
||||
static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; }
|
||||
/// Return double from QData (bits, not numerically)
|
||||
static inline double VL_CVT_D_Q(QData lhs) { union { double d; QData q; } u; u.q=lhs; return u.d; }
|
||||
/// Return QData from double (bits, not numerically)
|
||||
static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.d=lhs; return u.q; }
|
||||
/// Return double from QData (numeric)
|
||||
static inline double VL_ITOR_D_I(IData lhs) { return ((double)((vlsint32_t)(lhs))); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOI_I_D(double lhs) { return ((vlsint32_t)(VL_TRUNC(lhs))); }
|
||||
/// Return QData from double (numeric)
|
||||
static inline IData VL_RTOIROUND_I_D(double lhs) { return ((vlsint32_t)(VL_ROUND(lhs))); }
|
||||
|
||||
// Sign extend such that if MSB set, we get ffff_ffff, else 0s
|
||||
// (Requires clean input)
|
||||
@@ -402,9 +419,11 @@ void _VL_DEBUG_PRINT_W(int lbits, WDataInP iwp);
|
||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION>20011000)
|
||||
# define VL_TIME_I() ((IData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() ((QData)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() ((double)(sc_time_stamp().to_default_time_units()*VL_TIME_MULTIPLIER))
|
||||
#else
|
||||
# define VL_TIME_I() ((IData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_Q() ((QData)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
# define VL_TIME_D() ((double)(sc_time_stamp()*VL_TIME_MULTIPLIER))
|
||||
extern double sc_time_stamp();
|
||||
#endif
|
||||
|
||||
@@ -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,
|
||||
// we can't just
|
||||
//# define VL_UNARYMIN_I(data) (-(data))
|
||||
static inline IData VL_UNARYMIN_I(IData data) { return -data; }
|
||||
static inline QData VL_UNARYMIN_Q(QData data) { return -data; }
|
||||
//# define VL_NEGATE_I(data) (-(data))
|
||||
static inline IData VL_NEGATE_I(IData data) { return -data; }
|
||||
static inline QData VL_NEGATE_Q(QData data) { return -data; }
|
||||
|
||||
static inline WDataOutP VL_UNARYMIN_W(int words, WDataOutP owp,WDataInP lwp){
|
||||
static inline WDataOutP VL_NEGATE_W(int words, WDataOutP owp,WDataInP lwp){
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; i++) {
|
||||
carry = carry + (QData)(IData)(~lwp[i]);
|
||||
@@ -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]);
|
||||
if (lneg) { // Negate lhs
|
||||
lwusp = lwstore;
|
||||
VL_UNARYMIN_W(words, lwstore, lwp);
|
||||
VL_NEGATE_W(words, lwstore, lwp);
|
||||
lwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||
}
|
||||
IData rneg = VL_SIGN_I(lbits,rwp[words-1]);
|
||||
if (rneg) { // Negate rhs
|
||||
rwusp = rwstore;
|
||||
VL_UNARYMIN_W(words, rwstore, rwp);
|
||||
VL_NEGATE_W(words, rwstore, rwp);
|
||||
rwstore[words-1] &= VL_MASK_I(lbits); // Clean it
|
||||
}
|
||||
VL_MUL_W(words,owp,lwusp,rwusp);
|
||||
owp[words-1] &= VL_MASK_I(lbits); // Clean. Note it's ok for the multiply to overflow into the sign bit
|
||||
if ((lneg ^ rneg) & 1) { // Negate output (not using UNARYMIN, as owp==lwp)
|
||||
if ((lneg ^ rneg) & 1) { // Negate output (not using NEGATE, as owp==lwp)
|
||||
QData carry = 0;
|
||||
for (int i=0; i<words; i++) {
|
||||
carry = carry + (QData)(IData)(~owp[i]);
|
||||
@@ -1056,12 +1075,12 @@ static inline WDataOutP VL_DIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDataI
|
||||
IData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP ltup = lwp;
|
||||
WDataInP rtup = rwp;
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if ((lsign && !rsign) || (!lsign && rsign)) {
|
||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||
VL_DIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
return owp;
|
||||
} else {
|
||||
return VL_DIV_WWW(lbits,owp,ltup,rtup);
|
||||
@@ -1075,12 +1094,12 @@ static inline WDataOutP VL_MODDIVS_WWW(int lbits, WDataOutP owp,WDataInP lwp,WDa
|
||||
IData rwstore[VL_MULS_MAX_WORDS];
|
||||
WDataInP ltup = lwp;
|
||||
WDataInP rtup = rwp;
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { ltup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), lwstore, lwp)); }
|
||||
if (rsign) { rtup = _VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), rwstore, rwp)); }
|
||||
if (lsign) { // Only dividend sign matters for modulus
|
||||
IData qNoSign[VL_MULS_MAX_WORDS];
|
||||
VL_MODDIV_WWW(lbits,qNoSign,ltup,rtup);
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_UNARYMIN_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
_VL_CLEAN_INPLACE_W(lbits, VL_NEGATE_W(VL_WORDS_I(lbits), owp, qNoSign));
|
||||
return owp;
|
||||
} else {
|
||||
return VL_MODDIV_WWW(lbits,owp,ltup,rtup);
|
||||
@@ -1633,6 +1652,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o,
|
||||
|
||||
#undef _END
|
||||
|
||||
// Debugging
|
||||
//======================================================================
|
||||
|
||||
#endif /*_VERILATED_H_*/
|
||||
|
||||
+12
-6
@@ -13,6 +13,12 @@ LINK = @CXX@
|
||||
AR = ar
|
||||
RANLIB = ranlib
|
||||
|
||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||
|
||||
# Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero
|
||||
CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
|
||||
|
||||
######################################################################
|
||||
# Programs
|
||||
|
||||
@@ -38,13 +44,9 @@ VK_CPPFLAGS_ALWAYS += \
|
||||
-DVM_TRACE=$(VM_TRACE) \
|
||||
-DVM_COVERAGE=$(VM_COVERAGE) \
|
||||
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
VK_CPPFLAGS_WALL += -Wall \
|
||||
-Wno-char-subscripts \
|
||||
-Wno-sign-compare \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-unused-variable \
|
||||
-Wno-uninitialized \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
-Werror
|
||||
endif
|
||||
|
||||
@@ -116,6 +118,10 @@ ifeq ($(VM_SP),1)
|
||||
$(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \
|
||||
--preproc $(VK_CLASSES_SP)
|
||||
else
|
||||
ifeq ($(VM_COVERAGE),1)
|
||||
CPPFLAGS += -I$(SYSTEMPERL_INCLUDE)
|
||||
VPATH += $(SYSTEMPERL_INCLUDE)
|
||||
endif
|
||||
preproc:
|
||||
endif
|
||||
|
||||
|
||||
+2
-6
@@ -27,11 +27,7 @@
|
||||
`define coverage_block_off
|
||||
`endif
|
||||
|
||||
// Hide file descriptor difference
|
||||
`ifdef verilator
|
||||
`define verilator_file_descriptor reg [63:0]
|
||||
`else
|
||||
`define verilator_file_descriptor integer
|
||||
`endif
|
||||
// Hide file descriptor difference - deprecated - for older versions
|
||||
`define verilator_file_descriptor integer
|
||||
|
||||
`endif // guard
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#define _VERILATED_DPI_CPP_
|
||||
#include "verilatedos.h"
|
||||
#include "verilated_dpi.h"
|
||||
#include "verilated_imp.h"
|
||||
|
||||
// On MSVC++ we need svdpi.h to declare exports, not imports
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// -*- C++ -*-
|
||||
//*************************************************************************
|
||||
//
|
||||
// Copyright 2003-2011 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License.
|
||||
// Version 2.0.
|
||||
//
|
||||
// Verilator is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//*************************************************************************
|
||||
///
|
||||
/// \file
|
||||
/// \brief Verilator: Common include for all Verilated C files that use DPI
|
||||
///
|
||||
/// This file is included automatically by Verilator at the top of
|
||||
/// all C++ files it generates where DPI is used. It contains
|
||||
/// DPI interface functions required by the Verilated code.
|
||||
///
|
||||
/// Code available from: http://www.veripool.org/verilator
|
||||
///
|
||||
//*************************************************************************
|
||||
|
||||
|
||||
#ifndef _VERILATED_DPI_H_
|
||||
#define _VERILATED_DPI_H_ 1 ///< Header Guard
|
||||
|
||||
#include "verilated.h" // Presumed done by caller
|
||||
#include "svdpi.h"
|
||||
|
||||
//===================================================================
|
||||
// SETTING OPERATORS
|
||||
|
||||
/// Return svBitVecVal from WData
|
||||
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) {
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i];
|
||||
owp[words-1] = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, svLogicVecVal* lwp) {
|
||||
// Note we ignore X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words-1; i++) owp[i]=lwp[i].aval;
|
||||
owp[words-1] = lwp[words-1].aval & VL_MASK_I(obits);
|
||||
}
|
||||
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) {
|
||||
// Note we don't create X/Z in svLogicVecVal
|
||||
int words = VL_WORDS_I(obits);
|
||||
for (int i=0; i<words; i++) owp[i].bval=0;
|
||||
for (int i=0; i<words-1; i++) owp[i].aval=lwp[i];
|
||||
owp[words-1].aval = lwp[words-1] & VL_MASK_I(obits);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
||||
#endif // _VERILATED_DPI_H_
|
||||
+39
-1
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
class VerilatedScope;
|
||||
@@ -62,9 +63,18 @@ class VerilatedImp {
|
||||
ExportNameMap m_exportMap; ///< Map of <export_func_proto, func number>
|
||||
int m_exportNext; ///< Next export funcnum
|
||||
|
||||
// File I/O
|
||||
vector<FILE*> m_fdps; ///< File descriptors
|
||||
deque<IData> m_fdFree; ///< List of free descriptors (SLOW - FOPEN/CLOSE only)
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {}
|
||||
VerilatedImp() : m_argVecLoaded(false), m_exportNext(0) {
|
||||
m_fdps.resize(3);
|
||||
m_fdps[0] = stdin;
|
||||
m_fdps[1] = stdout;
|
||||
m_fdps[2] = stderr;
|
||||
}
|
||||
~VerilatedImp() {}
|
||||
|
||||
// METHODS - arguments
|
||||
@@ -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
|
||||
// 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
|
||||
|
||||
@@ -86,8 +86,8 @@ private:
|
||||
NameMap* m_namemapp; ///< List of names for the header
|
||||
static vector<VerilatedVcd*> s_vcdVecp; ///< List of all created traces
|
||||
|
||||
inline size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline size_t bufferInsertSize() { return 16*1024; }
|
||||
inline static size_t bufferSize() { return 256*1024; } // See below for slack calculation
|
||||
inline static size_t bufferInsertSize() { return 16*1024; }
|
||||
void bufferFlush();
|
||||
void bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
@@ -110,6 +110,7 @@ private:
|
||||
void dumpHeader();
|
||||
void dumpPrep (vluint64_t timeui);
|
||||
void dumpFull (vluint64_t timeui);
|
||||
// cppcheck-suppress functionConst
|
||||
void dumpDone ();
|
||||
inline void printCode (vluint32_t code) {
|
||||
if (code>=(94*94*94)) *m_writep++ = ((char)((code/94/94/94)%94+33));
|
||||
@@ -117,7 +118,7 @@ private:
|
||||
if (code>=(94)) *m_writep++ = ((char)((code/94)%94+33));
|
||||
*m_writep++ = ((char)((code)%94+33));
|
||||
}
|
||||
string stringCode (vluint32_t code) {
|
||||
static string stringCode (vluint32_t code) {
|
||||
string out;
|
||||
if (code>=(94*94*94)) out += ((char)((code/94/94/94)%94+33));
|
||||
if (code>=(94*94)) out += ((char)((code/94/94)%94+33));
|
||||
@@ -141,6 +142,8 @@ public:
|
||||
m_evcd = false;
|
||||
m_scopeEscape = '.'; // Backward compatibility
|
||||
m_wroteBytes = 0;
|
||||
m_fd = 0;
|
||||
m_fullDump = true;
|
||||
}
|
||||
~VerilatedVcd();
|
||||
|
||||
|
||||
+42
-20
@@ -95,9 +95,14 @@ typedef PLI_INT32 (*VerilatedPliCb)(struct t_cb_data *);
|
||||
|
||||
class VerilatedVpioCb : public VerilatedVpio {
|
||||
t_cb_data m_cbData;
|
||||
s_vpi_value m_value;
|
||||
QData m_time;
|
||||
public:
|
||||
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() {}
|
||||
static inline VerilatedVpioCb* castp(vpiHandle h) { return dynamic_cast<VerilatedVpioCb*>((VerilatedVpio*)h); }
|
||||
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",
|
||||
vop,varop->fullname(), *((CData*)newDatap)););
|
||||
memcpy(prevDatap, newDatap, varop->entSize());
|
||||
vpi_get_value(vop->cb_datap()->obj, vop->cb_datap()->value);
|
||||
(vop->cb_rtnp()) (vop->cb_datap());
|
||||
}
|
||||
}
|
||||
@@ -735,19 +741,26 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p,
|
||||
|
||||
// I/O routines
|
||||
|
||||
//-PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *fileName) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 cd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *format, ...) {
|
||||
PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) {
|
||||
return VL_FOPEN_S(filenamep,"wb");
|
||||
}
|
||||
|
||||
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
|
||||
VL_FCLOSE_I(mcd); return 0;
|
||||
}
|
||||
|
||||
//-PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
|
||||
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
|
||||
va_end(ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) {
|
||||
va_list ap;
|
||||
va_start(ap,formatp);
|
||||
@@ -760,15 +773,24 @@ PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
|
||||
return VL_VPRINTF(formatp, ap);
|
||||
}
|
||||
|
||||
//-PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_flush(void) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
//-PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
|
||||
//- _VL_VPI_UNIMP(); return 0;
|
||||
//-}
|
||||
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) {
|
||||
FILE* fp = VL_CVT_I_FP(mcd);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
int chars = vfprintf(fp, format, ap);
|
||||
return chars;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_flush(void) {
|
||||
Verilated::flushCall();
|
||||
return 0;
|
||||
}
|
||||
|
||||
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
|
||||
FILE* fp = VL_CVT_I_FP(mcd);
|
||||
if (VL_UNLIKELY(!fp)) return 1;
|
||||
fflush(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// utility routines
|
||||
|
||||
|
||||
@@ -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_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*/
|
||||
|
||||
+6
-5
@@ -207,10 +207,10 @@ viewers let us know; ZGRViewer isn't great for large graphs.
|
||||
Tree files are dumps of the AST Tree and are produced between every major
|
||||
algorithmic stage. An example:
|
||||
|
||||
NETLIST 0x90fb00 <e1> {0} w0
|
||||
1: MODULE 0x912b20 <e8822> {8} w0 top L2 [P]
|
||||
*1:2: VAR 0x91a780 <e74#> {22} w70 out_wide [O] WIRE
|
||||
1:2:1: BASICDTYPE 0x91a3c0 <e73> {22} w70 [logic]
|
||||
NETLIST 0x90fb00 <e1> {a0} w0
|
||||
1: MODULE 0x912b20 <e8822> {a8} w0 top L2 [P]
|
||||
*1:2: VAR 0x91a780 <e74#> {a22} w70 out_wide [O] WIRE
|
||||
1:2:1: BASICDTYPE 0x91a3c0 <e73> {a22} w70 [logic]
|
||||
|
||||
=over 4
|
||||
|
||||
@@ -224,7 +224,8 @@ algorithmic stage. An example:
|
||||
this node. A trailing # indicates this node changed since the last tree
|
||||
dump was made. You can gdb break on this edit; see below.
|
||||
|
||||
"{22}" indicates this node is related to line 22 in the source.
|
||||
"{a22}" indicates this node is related to line 22 in the source filename
|
||||
"a", where "a" is the first file read, "z" the 36th, and "aa" the 37th.
|
||||
|
||||
"w70" indicates the width is 70 bits. sw70 would be signed 70 bits.
|
||||
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ cwrite ("graph_export.cpp");
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ dotwrite();
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
+55
-11
@@ -12,12 +12,15 @@ use vars qw ($Debug);
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
our $Opt_Stage = 0;
|
||||
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config ("no_auto_abbrev");
|
||||
if (! GetOptions (
|
||||
"debug" => sub { $Debug = 1; },
|
||||
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
||||
"stage=i" => \$Opt_Stage,
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'install_test --help'\n";
|
||||
}
|
||||
@@ -37,8 +40,10 @@ sub test {
|
||||
my $srcdir = getcwd();
|
||||
my $blddir = $srcdir."/test_regress/obj_dir/install_test_bld";
|
||||
my $prefix = $srcdir."/test_regress/obj_dir/install_test_prefix";
|
||||
my $testdir = $srcdir."/test_regress/obj_dir/install_test_test";
|
||||
if (1) {
|
||||
my $testdirp= $srcdir."/test_regress/obj_dir/install_test_testp";
|
||||
my $testdirn= $srcdir."/test_regress/obj_dir/install_test_testn";
|
||||
|
||||
if ($Opt_Stage <= 0) {
|
||||
run("/bin/rm -rf $blddir");
|
||||
run("/bin/mkdir -p $blddir");
|
||||
run("cd $blddir && $srcdir/configure --prefix $prefix");
|
||||
@@ -46,24 +51,63 @@ sub test {
|
||||
}
|
||||
|
||||
# Install it under the prefix
|
||||
if (1) {
|
||||
if ($Opt_Stage <= 1) {
|
||||
run("/bin/rm -rf $prefix");
|
||||
run("/bin/mkdir -p $prefix");
|
||||
run("cd $blddir && make install");
|
||||
run("test -e $prefix/share/man/man1/verilator.1");
|
||||
run("test -e $prefix/share/verilator/examples/test_c/Makefile");
|
||||
run("test -e $prefix/share/verilator/include/verilated.h");
|
||||
run("test -e $prefix/bin/verilator");
|
||||
run("test -e $prefix/bin/verilator_bin");
|
||||
run("test -e $prefix/bin/verilator_bin_dbg");
|
||||
run("test -e $prefix/bin/verilator_profcfunc");
|
||||
}
|
||||
|
||||
# Run a test using just the path
|
||||
if (1) {
|
||||
run("/bin/rm -rf $testdir");
|
||||
run("/bin/mkdir -p $testdir");
|
||||
if ($Opt_Stage <= 2) {
|
||||
my $dir = $testdirp;
|
||||
run("/bin/rm -rf $dir");
|
||||
run("/bin/mkdir -p $dir");
|
||||
my $bin1 = $prefix."/bin";
|
||||
my $bin2 = $prefix."/share/bin";
|
||||
IO::File->new(">$testdir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); end endmodule'."\n");
|
||||
run("cd $testdir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v");
|
||||
run("cd $testdir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
|
||||
#Need .c file, and --exe for this to work
|
||||
#run("cd $testdir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
|
||||
write_verilog($dir);
|
||||
run("cd $dir && PATH=$bin1:$bin2:\$PATH verilator --cc foo.v --exe foo.cpp");
|
||||
run("cd $dir/obj_dir && PATH=$bin1:$bin2:\$PATH make -f Vfoo.mk");
|
||||
run("cd $dir && PATH=$bin1:$bin2:\$PATH obj_dir/Vfoo");
|
||||
}
|
||||
|
||||
# Run a test using exact path to binary
|
||||
if ($Opt_Stage <= 3) {
|
||||
my $dir = $testdirn;
|
||||
run("/bin/rm -rf $dir");
|
||||
run("/bin/mkdir -p $dir");
|
||||
write_verilog($dir);
|
||||
my $bin1 = $prefix."/bin";
|
||||
my $bin2 = $prefix."/share/bin";
|
||||
run("cd $dir && $bin1/verilator --cc foo.v --exe foo.cpp");
|
||||
run("cd $dir/obj_dir && make -f Vfoo.mk");
|
||||
run("cd $dir/obj_dir && ./Vfoo");
|
||||
}
|
||||
}
|
||||
|
||||
sub write_verilog {
|
||||
my $dir = shift;
|
||||
IO::File->new(">$dir/foo.v")->print('module t; initial begin $display("HELLO WORLD"); $finish; end endmodule'."\n");
|
||||
my $fh = IO::File->new(">$dir/foo.cpp");
|
||||
$fh->print('#include "Vfoo.h"' ,"\n");
|
||||
$fh->print('unsigned int main_time = 0;' ,"\n");
|
||||
$fh->print('double sc_time_stamp () {' ,"\n");
|
||||
$fh->print(' return main_time;' ,"\n");
|
||||
$fh->print('}' ,"\n");
|
||||
$fh->print('int main() {' ,"\n");
|
||||
$fh->print(' Vfoo *top = new Vfoo;' ,"\n");
|
||||
$fh->print(' while (!Verilated::gotFinish()) {',"\n");
|
||||
$fh->print(' top->eval();' ,"\n");
|
||||
$fh->print(' main_time++;' ,"\n");
|
||||
$fh->print(' }' ,"\n");
|
||||
$fh->print(' top->final();' ,"\n");
|
||||
$fh->print('}' ,"\n");
|
||||
}
|
||||
|
||||
sub cleanenv {
|
||||
|
||||
+1
-13
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','axiom-athdl');
|
||||
eval `modulecmd perl add axiom-athdl`;
|
||||
exec('atsim',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
|
||||
+1
-13
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence-ius');
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('iccr',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
|
||||
+1
-13
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','cadence-ius');
|
||||
eval `modulecmd perl add cds-ius`;
|
||||
exec('ncverilog',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
|
||||
+1
-13
@@ -8,21 +8,9 @@ use strict;
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
delete $ENV{MODULE_VERSION};
|
||||
_setup_modules();
|
||||
module('add','synopsys-vcs');
|
||||
eval `modulecmd perl add synopsys-vcs`;
|
||||
exec('vcs',@ARGV);
|
||||
|
||||
#######################################################################
|
||||
# Modules package
|
||||
|
||||
sub _setup_modules {
|
||||
# Load the 'module' command into the environment
|
||||
my $init = "$ENV{MODULESHOME}/init/perl";
|
||||
(-f $init) or die "%Error: Script not found: $init,";
|
||||
require $init;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ sub gentree {
|
||||
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
|
||||
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
|
||||
'UNARYMIN' => sub { p " -";p1; },
|
||||
'NEGATE' => sub { p " -";p1; },
|
||||
'VAR' => sub { p_var(); },
|
||||
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
||||
'VARREF' => sub { a1; },
|
||||
|
||||
@@ -91,6 +91,10 @@ headers.
|
||||
|
||||
=item
|
||||
|
||||
You will need the C<flex> and C<bison> packages installed.
|
||||
|
||||
=item
|
||||
|
||||
C<cd> to the Verilator directory containing this README.
|
||||
|
||||
=item
|
||||
@@ -147,6 +151,9 @@ most GNU tools support:
|
||||
unsetenv VERILATOR_ROOT # if your shell is csh
|
||||
./configure --prefix /opt/verilator-VERSION
|
||||
|
||||
Then after installing you will need to add /opt/verilator-VERSION/bin to
|
||||
PATH.
|
||||
|
||||
=back
|
||||
|
||||
=item
|
||||
|
||||
+13
-24
@@ -24,6 +24,7 @@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
PERL = @PERL@
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
@@ -32,25 +33,11 @@ default: dbg opt
|
||||
debug: dbg
|
||||
optimize: opt
|
||||
|
||||
ifeq ($(OBJCACHE_HOSTS),)
|
||||
ifneq ($(SLCHOOSED_HOST),)
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1)
|
||||
export OBJCACHE_HOSTS := $(shell rschedule --no-allow-reserved --similar hostnames)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OBJCACHE_JOBS),)
|
||||
ifneq ($(OBJCACHE_HOSTS),)
|
||||
export OBJCACHE_JOBS := -j $(shell objcache --jobs "$(OBJCACHE_HOSTS)")
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(words $(CURDIR)),1)
|
||||
$(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
|
||||
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
|
||||
../verilator_bin: ../verilator_bin_dbg
|
||||
-rm -rf $@ $@.exe
|
||||
-cp -p $< $@
|
||||
-cp -p $<.exe $@.exe
|
||||
-cp -p $<$(EXEEXT) $@$(EXEEXT)
|
||||
else
|
||||
../verilator_bin: obj_opt prefiles
|
||||
cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial
|
||||
cd obj_opt && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ -f ../Makefile_obj
|
||||
cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial
|
||||
cd obj_opt && $(MAKE) TGT=../$@ -f ../Makefile_obj
|
||||
endif
|
||||
|
||||
dbg: ../verilator_bin_dbg
|
||||
../verilator_bin_dbg: obj_dbg prefiles
|
||||
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial
|
||||
cd obj_dbg && $(MAKE) $(OBJCACHE_JOBS) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
|
||||
cd obj_dbg && $(MAKE) -j 1 TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj serial
|
||||
cd obj_dbg && $(MAKE) TGT=../$@ VL_DEBUG=1 -f ../Makefile_obj
|
||||
|
||||
prefiles::
|
||||
|
||||
ifneq ($(UNDER_GIT),) # If local git tree... Else don't burden users
|
||||
prefiles:: config_rev.h
|
||||
# This output goes into srcdir, as we need to distribute it as part of the kit.
|
||||
config_rev.h: config_rev.pl ../.git/logs/HEAD
|
||||
$(PERL) config_rev.pl . >$@
|
||||
# This output goes into srcdir if locally configured, as we need to distribute it as part of the kit.
|
||||
config_rev.h: ${srcdir}/config_rev.pl ${srcdir}/../.git/logs/HEAD
|
||||
$(PERL) ${srcdir}/config_rev.pl ${srcdir} >$@
|
||||
endif
|
||||
|
||||
maintainer-copy::
|
||||
@@ -96,3 +82,6 @@ clean mostlyclean distclean maintainer-clean::
|
||||
|
||||
distclean maintainer-clean::
|
||||
-rm -f Makefile Makefile_obj config_build.h
|
||||
|
||||
maintainer-clean::
|
||||
-rm -f config_rev.h
|
||||
|
||||
+14
-14
@@ -57,9 +57,11 @@ datarootdir = @datarootdir@
|
||||
pkgdatadir = @pkgdatadir@
|
||||
|
||||
# Compile options
|
||||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||
CPPFLAGSNOWALL += @CPPFLAGS@
|
||||
CPPFLAGS += @CPPFLAGS@
|
||||
LDFLAGS += @LDFLAGS@
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
@@ -85,17 +87,18 @@ endif
|
||||
# -lfl not needed as Flex invoked with %nowrap option
|
||||
LIBS = -lm
|
||||
|
||||
CPPFLAGSNOWALL += -MMD
|
||||
CPPFLAGSNOWALL += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
|
||||
CPPFLAGSNOWALL += -DYYDEBUG # Required to get nice error messages
|
||||
#CPPFLAGSNOWALL += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
||||
CPPFLAGSNOWALL += $(COPT)
|
||||
CPPFLAGS = $(CPPFLAGSNOWALL)
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
CPPFLAGSNOWALL += -MP # Only works on recent GCC versions
|
||||
CPPFLAGS += -MMD
|
||||
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir)
|
||||
CPPFLAGS += -DYYDEBUG # Required to get nice error messages
|
||||
#CPPFLAGS += -DVL_LEAK_CHECKS # If running valgrind or other hunting tool
|
||||
CPPFLAGS += $(COPT)
|
||||
CPPFLAGS += -MP # Only works on recent GCC versions
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
CPPFLAGS += -W -Wall -Wno-unused-parameter -Wno-char-subscripts -Werror
|
||||
#CPPFLAGS += -pedantic-errors
|
||||
endif
|
||||
CPPFLAGSWALL = $(CPPFLAGS)
|
||||
CPPFLAGSNOWALL = $(CPPFLAGS) -Wno-unused
|
||||
|
||||
ifneq ($(SYSTEMPERL),) # Intuit SYSTEMPERL_INCLUDE as it's new
|
||||
SYSTEMPERL_INCLUDE ?= $(SYSTEMPERL)/src
|
||||
@@ -209,7 +212,6 @@ RAW_OBJS = \
|
||||
V3PreShell.o \
|
||||
V3Premit.o \
|
||||
V3Scope.o \
|
||||
V3Signed.o \
|
||||
V3Slice.o \
|
||||
V3Split.o \
|
||||
V3SplitAs.o \
|
||||
@@ -251,8 +253,6 @@ $(TGT): V3Ast__gen_classes.h $(OBJS)
|
||||
@echo " Linking $@..."
|
||||
-rm -rf $@ [email protected]
|
||||
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
|
||||
@-(cp [email protected] $@ || true)
|
||||
# ok if cp failes on linux, it's there to insure executable works on NT
|
||||
|
||||
V3Number_test: V3Number_test.o
|
||||
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
|
||||
@@ -263,9 +263,9 @@ V3Number_test: V3Number_test.o
|
||||
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
|
||||
|
||||
%.o: %.cpp
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGS} -c $<
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGSWALL} -c $<
|
||||
%.o: %.c
|
||||
$(OBJCACHE) ${CC} ${CPPFLAGS} -c $<
|
||||
$(OBJCACHE) ${CC} ${CPPFLAGSWALL} -c $<
|
||||
|
||||
V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
||||
|
||||
+5
-1
@@ -148,7 +148,11 @@ public:
|
||||
}
|
||||
public:
|
||||
// CONSTUCTORS
|
||||
ActiveNamer() {}
|
||||
ActiveNamer() {
|
||||
m_scopep = NULL;
|
||||
m_iActivep = NULL;
|
||||
m_cActivep = NULL;
|
||||
}
|
||||
virtual ~ActiveNamer() {}
|
||||
void main(AstScope* nodep) {
|
||||
nodep->accept(*this);
|
||||
|
||||
+5
-5
@@ -184,7 +184,7 @@ private:
|
||||
}
|
||||
if (nodep->fullPragma() || nodep->priorityPragma()) {
|
||||
// Simply need to add a default if there isn't one already
|
||||
m_statAsFull++;
|
||||
++m_statAsFull;
|
||||
if (!has_default) {
|
||||
nodep->addItemsp(new AstCaseItem(nodep->fileline(), NULL/*DEFAULT*/,
|
||||
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
||||
@@ -193,7 +193,7 @@ private:
|
||||
if (nodep->parallelPragma() || nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||
// Need to check that one, and only one of the case items match at any moment
|
||||
// If there's a default, we allow none to match, else exactly one must match
|
||||
m_statAsFull++;
|
||||
++m_statAsFull;
|
||||
if (!has_default && !nodep->itemsp()) {
|
||||
// Not parallel, but harmlessly so.
|
||||
} else {
|
||||
@@ -241,18 +241,18 @@ private:
|
||||
if (m_beginp && nodep->name() == "") nodep->name(m_beginp->name());
|
||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||
nodep->stmtsp(), nodep->name()); nodep=NULL;
|
||||
m_statAsCover++;
|
||||
++m_statAsCover;
|
||||
}
|
||||
virtual void visit(AstPslAssert* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
newPslAssertion(nodep, nodep->propp(), nodep->sentreep(),
|
||||
NULL, nodep->name()); nodep=NULL;
|
||||
m_statAsPsl++;
|
||||
++m_statAsPsl;
|
||||
}
|
||||
virtual void visit(AstVAssert* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
newVAssertion(nodep, nodep->propp()); nodep=NULL;
|
||||
m_statAsSV++;
|
||||
++m_statAsSV;
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
|
||||
+6
-4
@@ -74,7 +74,9 @@ void AstNode::init() {
|
||||
m_clonep = NULL;
|
||||
m_cloneCnt = 0;
|
||||
// Attributes
|
||||
m_signed = false;
|
||||
m_numeric = (int)AstNumeric::UNSIGNED;
|
||||
m_didWidth = false;
|
||||
m_doingWidth = false;
|
||||
m_width = 0;
|
||||
m_widthMin = 0;
|
||||
m_user1p = NULL;
|
||||
@@ -428,7 +430,7 @@ void AstNode::replaceWith(AstNode* newp) {
|
||||
repHandle.relink(newp);
|
||||
}
|
||||
|
||||
void AstNRelinker::dump(ostream& str) {
|
||||
void AstNRelinker::dump(ostream& str) const {
|
||||
str<<" BK="<<(uint32_t*)m_backp;
|
||||
str<<" ITER="<<(uint32_t*)m_iterpp;
|
||||
str<<" CHG="<<(m_chg==RELINK_NEXT?"[NEXT] ":"");
|
||||
@@ -873,7 +875,7 @@ bool AstNode::sameTreeIter(AstNode* node2p, bool ignNext) {
|
||||
if (this==NULL || node2p==NULL) return false;
|
||||
if (this->type() != node2p->type()
|
||||
|| this->width() != node2p->width()
|
||||
|| this->isSigned() != node2p->isSigned()
|
||||
|| this->numeric() != node2p->numeric()
|
||||
|| !this->same(node2p)) {
|
||||
return false;
|
||||
}
|
||||
@@ -945,7 +947,7 @@ void AstNode::checkTree() {
|
||||
}
|
||||
}
|
||||
|
||||
void AstNode::dumpPtrs(ostream& os) {
|
||||
void AstNode::dumpPtrs(ostream& os) const {
|
||||
os<<"This="<<typeName()<<" "<<(void*)this;
|
||||
os<<" back="<<(void*)backp();
|
||||
if (nextp()) os<<" next="<<(void*)nextp();
|
||||
|
||||
+85
-27
@@ -27,6 +27,7 @@
|
||||
#include "V3Error.h"
|
||||
#include "V3Number.h"
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "V3Ast__gen_classes.h" // From ./astgen
|
||||
// Things like:
|
||||
@@ -56,9 +57,40 @@ public:
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstNumeric {
|
||||
public:
|
||||
enum en {
|
||||
UNSIGNED,
|
||||
SIGNED,
|
||||
DOUBLE
|
||||
// Limited to 2 bits, unless change V3Ast's packing function
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"UNSIGNED","SIGNED","DOUBLE"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstNumeric () : m_e(UNSIGNED) {}
|
||||
inline AstNumeric (en _e) : m_e(_e) {}
|
||||
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
inline bool isDouble() const { return m_e==DOUBLE; }
|
||||
inline bool isSigned() const { return m_e==SIGNED; }
|
||||
inline bool isUnsigned() const { return m_e==UNSIGNED; }
|
||||
};
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
|
||||
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
|
||||
|
||||
//######################################################################
|
||||
|
||||
class AstPragmaType {
|
||||
public:
|
||||
enum en {
|
||||
ILLEGAL,
|
||||
COVERAGE_BLOCK_OFF,
|
||||
INLINE_MODULE,
|
||||
NO_INLINE_MODULE,
|
||||
@@ -67,7 +99,7 @@ public:
|
||||
PUBLIC_TASK
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstPragmaType () {}
|
||||
inline AstPragmaType () : m_e(ILLEGAL) {}
|
||||
inline AstPragmaType (en _e) : m_e(_e) {}
|
||||
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -90,7 +122,7 @@ public:
|
||||
TRACE_CHANGE_SUB
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstCFuncType () {}
|
||||
inline AstCFuncType () : m_e(FT_NORMAL) {}
|
||||
inline AstCFuncType (en _e) : m_e(_e) {}
|
||||
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -158,7 +190,7 @@ public:
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstEdgeType () {}
|
||||
inline AstEdgeType () : m_e(ET_ILLEGAL) {}
|
||||
inline AstEdgeType (en _e) : m_e(_e) {}
|
||||
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -172,6 +204,7 @@ public:
|
||||
class AstAttrType {
|
||||
public:
|
||||
enum en {
|
||||
ILLEGAL,
|
||||
EXPR_BITS, // V3Const converts to constant
|
||||
//
|
||||
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
@@ -182,19 +215,20 @@ public:
|
||||
VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
|
||||
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
|
||||
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
|
||||
VAR_SFORMAT // V3LinkParse moves to AstVar::attrSFormat
|
||||
};
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"EXPR_BITS", "VAR_BASE",
|
||||
"%E-AT", "EXPR_BITS", "VAR_BASE",
|
||||
"VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
||||
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SFORMAT"
|
||||
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstAttrType () {}
|
||||
inline AstAttrType () : m_e(ILLEGAL) {}
|
||||
inline AstAttrType (en _e) : m_e(_e) {}
|
||||
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -208,8 +242,9 @@ public:
|
||||
class AstBasicDTypeKwd {
|
||||
public:
|
||||
enum en {
|
||||
UNKNOWN,
|
||||
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
|
||||
REAL, REALTIME, SHORTINT, SHORTREAL, TIME,
|
||||
DOUBLE, SHORTINT, FLOAT, TIME,
|
||||
// Closer to a class type, but limited usage
|
||||
STRING,
|
||||
// Internal types for mid-steps
|
||||
@@ -220,8 +255,9 @@ public:
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"%E-unk",
|
||||
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
||||
"real", "realtime", "shortint", "shortreal", "time",
|
||||
"real", "shortint", "shortreal", "time",
|
||||
"string",
|
||||
"VerilatedScope*", "char*",
|
||||
"LOGIC_IMPLICIT"
|
||||
@@ -230,15 +266,16 @@ public:
|
||||
};
|
||||
const char* dpiType() const {
|
||||
static const char* names[] = {
|
||||
"%E-unk",
|
||||
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
||||
"double", "double", "short int", "float", "long long",
|
||||
"double", "short int", "float", "long long",
|
||||
"const char*",
|
||||
"dpiScope", "const char*",
|
||||
""
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstBasicDTypeKwd () {}
|
||||
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
|
||||
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
|
||||
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -251,6 +288,8 @@ public:
|
||||
case INTEGER: return 32;
|
||||
case LOGIC: return 1;
|
||||
case LONGINT: return 64;
|
||||
case DOUBLE: return 64;
|
||||
case FLOAT: return 32;
|
||||
case SHORTINT: return 16;
|
||||
case TIME: return 64;
|
||||
case STRING: return 64; // Just the pointer, for today
|
||||
@@ -265,7 +304,7 @@ public:
|
||||
}
|
||||
bool isZeroInit() const { // Otherwise initializes to X
|
||||
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|
||||
|| m_e==STRING);
|
||||
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isSloppy() const { // Don't be as anal about width warnings
|
||||
return !(m_e==LOGIC || m_e==BIT);
|
||||
@@ -274,10 +313,13 @@ public:
|
||||
return (m_e==LOGIC || m_e==BIT);
|
||||
}
|
||||
bool isDpiUnsupported() const {
|
||||
return (m_e==LOGIC || m_e==TIME || m_e==REALTIME);
|
||||
return (m_e==LOGIC || m_e==TIME);
|
||||
}
|
||||
bool isOpaque() const { // IE not a simple number we can bit optimize
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR);
|
||||
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
|
||||
}
|
||||
bool isDouble() const {
|
||||
return (m_e==DOUBLE);
|
||||
}
|
||||
};
|
||||
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
@@ -316,7 +358,7 @@ public:
|
||||
XTEMP
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstVarType () {}
|
||||
inline AstVarType () : m_e(UNKNOWN) {}
|
||||
inline AstVarType (en _e) : m_e(_e) {}
|
||||
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -374,7 +416,7 @@ public:
|
||||
CT_CASEZ
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstCaseType () {}
|
||||
inline AstCaseType () : m_e(CT_CASE) {}
|
||||
inline AstCaseType (en _e) : m_e(_e) {}
|
||||
explicit inline AstCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -396,7 +438,7 @@ public:
|
||||
DT_FATAL
|
||||
};
|
||||
enum en m_e;
|
||||
inline AstDisplayType () {}
|
||||
inline AstDisplayType () : m_e(DT_DISPLAY) {}
|
||||
inline AstDisplayType (en _e) : m_e(_e) {}
|
||||
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
@@ -606,7 +648,7 @@ public:
|
||||
AstNRelinker() { m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
|
||||
void relink(AstNode* newp);
|
||||
AstNode* oldp() const { return m_oldp; }
|
||||
void dump(ostream& str=cout);
|
||||
void dump(ostream& str=cout) const;
|
||||
};
|
||||
inline ostream& operator<<(ostream& os, AstNRelinker& rhs) { rhs.dump(os); return os;}
|
||||
|
||||
@@ -684,7 +726,9 @@ class AstNode {
|
||||
static int s_cloneCntGbl; // Count of which userp is set
|
||||
|
||||
// Attributes
|
||||
bool m_signed:1; // Node is signed
|
||||
uint32_t m_numeric:2; // Node is real/signed - important that bitfields remain unsigned
|
||||
bool m_didWidth:1; // Did V3Width computation
|
||||
bool m_doingWidth:1; // Inside V3Width
|
||||
// // Space for more bools here
|
||||
|
||||
int m_width; // Bit width of operation
|
||||
@@ -717,6 +761,7 @@ class AstNode {
|
||||
void deleteTreeIter();
|
||||
void deleteNode();
|
||||
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
|
||||
// cppcheck-suppress functionConst
|
||||
void debugTreeChange(const char* prefix, int lineno, bool next);
|
||||
|
||||
protected:
|
||||
@@ -780,6 +825,9 @@ public:
|
||||
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
|
||||
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
|
||||
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
|
||||
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
|
||||
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
|
||||
static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do triganomics
|
||||
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
|
||||
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
|
||||
|
||||
@@ -807,10 +855,18 @@ public:
|
||||
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
||||
void width(int width, int sized) { m_width=width; m_widthMin=sized; }
|
||||
void widthFrom(AstNode* fromp) { if (fromp) { m_width=fromp->m_width; m_widthMin=fromp->m_widthMin; }}
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); signedFrom(fromp); }
|
||||
void signedFrom(AstNode* fromp) { if (fromp) { m_signed=fromp->m_signed; }}
|
||||
void isSigned(bool flag) { m_signed=flag; }
|
||||
bool isSigned() const { return m_signed; }
|
||||
void widthSignedFrom(AstNode* fromp) { widthFrom(fromp); numericFrom(fromp); }
|
||||
void numericFrom(AstNode* fromp) { numeric(fromp->numeric()); }
|
||||
void numeric(AstNumeric flag) { m_numeric = (int)flag; if (flag.isDouble()) width(64,64); }
|
||||
AstNumeric numeric() const { return AstNumeric(m_numeric); }
|
||||
bool isDouble() const { return numeric().isDouble(); }
|
||||
bool isSigned() const { return numeric().isSigned(); }
|
||||
void isSigned(bool flag) { numeric(flag ? AstNumeric::SIGNED : AstNumeric::UNSIGNED); }
|
||||
bool isUnsigned() const { return numeric().isUnsigned(); }
|
||||
void didWidth(bool flag) { m_didWidth=flag; }
|
||||
bool didWidth() const { return m_didWidth; }
|
||||
void doingWidth(bool flag) { m_doingWidth=flag; }
|
||||
bool doingWidth() const { return m_doingWidth; }
|
||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||
|
||||
@@ -898,7 +954,7 @@ public:
|
||||
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
|
||||
void deleteTree(); // Always deletes the next link
|
||||
void checkTree(); // User Interface version
|
||||
void dumpPtrs(ostream& str=cout);
|
||||
void dumpPtrs(ostream& str=cout) const;
|
||||
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
||||
void dumpTreeFile(const string& filename, bool append=false);
|
||||
@@ -965,6 +1021,7 @@ struct AstNodeTermop : public AstNodeMath {
|
||||
ASTNODE_BASE_FUNCS(NodeTermop)
|
||||
// Know no children, and hot function, so skip iterator for speed
|
||||
// See checkTreeIter also that asserts no children
|
||||
// cppcheck-suppress functionConst
|
||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
||||
};
|
||||
|
||||
@@ -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 bool cleanLhs() = 0;
|
||||
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
||||
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
||||
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
@@ -1003,6 +1062,7 @@ struct AstNodeBiop : public AstNodeMath {
|
||||
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
||||
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
|
||||
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
||||
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode*) const { return true; }
|
||||
@@ -1224,6 +1284,7 @@ public:
|
||||
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
||||
// Know no children, and hot function, so skip iterator for speed
|
||||
// See checkTreeIter also that asserts no children
|
||||
// cppcheck-suppress functionConst
|
||||
void iterateChildren(AstNVisitor& v, AstNUser* vup=NULL) { }
|
||||
};
|
||||
|
||||
@@ -1275,7 +1336,6 @@ private:
|
||||
string m_name; // Name of task
|
||||
string m_cname; // Name of task if DPI import
|
||||
bool m_taskPublic:1; // Public task
|
||||
bool m_didSigning:1; // V3Signed completed; can skip iteration
|
||||
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
|
||||
bool m_prototype:1; // Just a prototype
|
||||
bool m_dpiExport:1; // DPI exported
|
||||
@@ -1286,7 +1346,7 @@ private:
|
||||
public:
|
||||
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
||||
: AstNode(fileline)
|
||||
, m_name(name), m_taskPublic(false), m_didSigning(false)
|
||||
, m_name(name), m_taskPublic(false)
|
||||
, m_attrIsolateAssign(false), m_prototype(false)
|
||||
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
|
||||
, m_dpiTask(false), m_pure(false) {
|
||||
@@ -1313,8 +1373,6 @@ public:
|
||||
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
||||
void taskPublic(bool flag) { m_taskPublic=flag; }
|
||||
bool taskPublic() const { return m_taskPublic; }
|
||||
void didSigning(bool flag) { m_didSigning=flag; }
|
||||
bool didSigning() const { return m_didSigning; }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
||||
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
||||
void prototype(bool flag) { m_prototype = flag; }
|
||||
|
||||
+11
-6
@@ -70,7 +70,7 @@ bool AstVar::isScQuad() const {
|
||||
}
|
||||
|
||||
bool AstVar::isScBv() const {
|
||||
return (isSc() && width() >= v3Global.opt.pinsBv());
|
||||
return ((isSc() && width() >= v3Global.opt.pinsBv()) || m_attrScBv);
|
||||
}
|
||||
|
||||
void AstVar::combineType(AstVarType type) {
|
||||
@@ -113,6 +113,10 @@ string AstVar::vlArgType(bool named, bool forReturn) const {
|
||||
arg += "const char*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::SCOPEPTR) {
|
||||
arg += "const VerilatedScope*";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::DOUBLE) {
|
||||
arg += "double";
|
||||
} else if (bdtypep && bdtypep->keyword()==AstBasicDTypeKwd::FLOAT) {
|
||||
arg += "float";
|
||||
} else if (strtype) {
|
||||
if (isInOnly()) arg += "const ";
|
||||
arg += "string";
|
||||
@@ -185,7 +189,7 @@ string AstVar::cPubArgType(bool named, bool forReturn) const {
|
||||
} else if (isWide()) {
|
||||
arg += "uint32_t"; // []'s added later
|
||||
} else {
|
||||
arg += "uint64_t";
|
||||
arg += "vluint64_t";
|
||||
}
|
||||
if (isWide()) {
|
||||
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
|
||||
@@ -202,7 +206,6 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
||||
if (forReturn) named=false;
|
||||
string arg;
|
||||
if (!basicp()) arg = "UNKNOWN";
|
||||
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
|
||||
if (basicp()->isBitLogic()) {
|
||||
if (widthMin() == 1) {
|
||||
arg = "unsigned char";
|
||||
@@ -238,7 +241,7 @@ string AstVar::scType() const {
|
||||
return "uint32_t";
|
||||
}
|
||||
} else {
|
||||
return "uint64_t";
|
||||
return "vluint64_t";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,8 +501,9 @@ void AstNode::dump(ostream& os) {
|
||||
//<<" "<<(void*)this->m_backp
|
||||
<<" <e"<<dec<<editCount()
|
||||
<<((editCount()>=editCountLast())?"#>":">")
|
||||
<<" {"<<dec<<fileline()->lineno()<<"}"
|
||||
<<" {"<<fileline()->filenameLetters()<<dec<<fileline()->lineno()<<"}"
|
||||
<<" "<<(isSigned()?"s":"")
|
||||
<<(isDouble()?"d":"")
|
||||
<<"w"<<(widthSized()?"":"u")<<width();
|
||||
if (!widthSized()) os<<"/"<<widthMin();
|
||||
if (name()!="") os<<" "<<AstNode::quoteName(name());
|
||||
@@ -609,7 +613,8 @@ void AstVar::dump(ostream& str) {
|
||||
else if (isInput()) str<<" [I]";
|
||||
else if (isOutput()) str<<" [O]";
|
||||
}
|
||||
if (isUsedClock()) str<<" [C]";
|
||||
if (isConst()) str<<" [CONST]";
|
||||
if (isUsedClock()) str<<" [CLK]";
|
||||
if (isSigPublic()) str<<" [P]";
|
||||
if (isUsedLoopIdx()) str<<" [LOOP]";
|
||||
if (attrClockEn()) str<<" [aCLKEN]";
|
||||
|
||||
+442
-53
@@ -46,19 +46,25 @@ struct AstConst : public AstNodeMath {
|
||||
private:
|
||||
V3Number m_num; // Constant value
|
||||
public:
|
||||
class Unsized32 {}; // for creator type-overload selection
|
||||
AstConst(FileLine* fl, const V3Number& num)
|
||||
:AstNodeMath(fl)
|
||||
,m_num(num) {
|
||||
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)
|
||||
:AstNodeMath(fl)
|
||||
,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
|
||||
:AstNodeMath(fl)
|
||||
,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 {};
|
||||
AstConst(FileLine* fl, LogicFalse) // Shorthand const 0, know the dtype should be a logic of size 1
|
||||
:AstNodeMath(fl)
|
||||
@@ -258,7 +264,8 @@ private:
|
||||
m_keyword = AstBasicDTypeKwd::LOGIC;
|
||||
}
|
||||
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
|
||||
// V3Width will pull from this width
|
||||
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
|
||||
void rangep(AstRange* nodep) { setNOp1p(nodep); }
|
||||
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
|
||||
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; }
|
||||
};
|
||||
|
||||
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 {
|
||||
private:
|
||||
AstTypedef* m_defp;
|
||||
@@ -364,9 +391,10 @@ public:
|
||||
struct AstEnumItemRef : public AstNodeMath {
|
||||
private:
|
||||
AstEnumItem* m_itemp; // [AfterLink] Pointer to item
|
||||
AstPackage* m_packagep; // Package hierarchy
|
||||
public:
|
||||
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp)
|
||||
: AstNodeMath(fl), m_itemp(itemp) {
|
||||
AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstPackage* packagep)
|
||||
: AstNodeMath(fl), m_itemp(itemp), m_packagep(packagep) {
|
||||
if (m_itemp) widthSignedFrom(m_itemp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(EnumItemRef, ENUMITEMREF)
|
||||
@@ -381,6 +409,8 @@ public:
|
||||
virtual string emitVerilog() { V3ERROR_NA; return ""; } // Implemented specially
|
||||
virtual string emitC() { V3ERROR_NA; return ""; }
|
||||
virtual bool cleanOut() { return true; }
|
||||
AstPackage* packagep() const { return m_packagep; }
|
||||
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
||||
};
|
||||
|
||||
struct AstEnumDType : public AstNodeDType {
|
||||
@@ -431,10 +461,10 @@ public:
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(AstNode* samep) const { return true; }
|
||||
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 start(unsigned start) { m_start = start; }
|
||||
unsigned start() { return m_start; }
|
||||
unsigned start() const { return m_start; }
|
||||
// Special operators
|
||||
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?
|
||||
@@ -557,10 +587,9 @@ private:
|
||||
bool m_funcLocal:1; // Local variable for a function
|
||||
bool m_funcReturn:1; // Return variable for a function
|
||||
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_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_isConst:1; // Table contains constant data
|
||||
bool m_isStatic:1; // Static variable
|
||||
@@ -573,8 +602,7 @@ private:
|
||||
m_usedClock=false; m_usedParam=false; m_usedLoopIdx=false;
|
||||
m_sigPublic=false; m_sigModPublic=false; m_sigUserRdPublic=false; m_sigUserRWPublic=false;
|
||||
m_funcLocal=false; m_funcReturn=false;
|
||||
m_attrClockEn=false; m_attrIsolateAssign=false; m_attrSFormat=false;
|
||||
m_didSigning=false; m_didWidth=false;
|
||||
m_attrClockEn=false; m_attrScBv=false; m_attrIsolateAssign=false; m_attrSFormat=false;
|
||||
m_fileDescr=false; m_isConst=false; m_isStatic=false;
|
||||
m_trace=false;
|
||||
}
|
||||
@@ -585,6 +613,7 @@ public:
|
||||
init();
|
||||
combineType(type); setOp1p(dtypep);
|
||||
if (dtypep && dtypep->basicp()) {
|
||||
numericFrom(dtypep);
|
||||
width(dtypep->basicp()->width(), 0);
|
||||
} else width(1, 0);
|
||||
}
|
||||
@@ -604,6 +633,7 @@ public:
|
||||
if (examplep->dtypep()) {
|
||||
setOp1p(examplep->dtypep()->cloneTree(true));
|
||||
}
|
||||
numericFrom(examplep);
|
||||
width(examplep->width(), examplep->widthMin());
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Var, VAR)
|
||||
@@ -635,12 +665,9 @@ public:
|
||||
void attrClockEn(bool flag) { m_attrClockEn = flag; }
|
||||
void attrFileDescr(bool flag) { m_fileDescr = flag; }
|
||||
void attrScClocked(bool flag) { m_scClocked = flag; }
|
||||
void attrScBv(bool flag) { m_attrScBv = flag; }
|
||||
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = 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 usedParam(bool flag) { m_usedParam = flag; }
|
||||
void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
|
||||
@@ -674,7 +701,7 @@ public:
|
||||
bool isToggleCoverable() const { return ((isIO() || isSignal())
|
||||
&& (isIO() || isBitLogic())
|
||||
// Wrapper would otherwise duplicate wrapped module's coverage
|
||||
&& !isSc() && !isPrimaryIO()); }
|
||||
&& !isSc() && !isPrimaryIO() && !isConst()); }
|
||||
bool isStatementTemp() const { return (varType()==AstVarType::STMTTEMP); }
|
||||
bool isMovableToBlock() const { return (varType()==AstVarType::BLOCKTEMP || isFuncLocal()); }
|
||||
bool isPure() const { return (varType()==AstVarType::XTEMP); }
|
||||
@@ -699,6 +726,7 @@ public:
|
||||
bool isFuncLocal() const { return m_funcLocal; }
|
||||
bool isFuncReturn() const { return m_funcReturn; }
|
||||
bool attrClockEn() const { return m_attrClockEn; }
|
||||
bool attrScBv() const { return m_attrScBv; }
|
||||
bool attrFileDescr() const { return m_fileDescr; }
|
||||
bool attrScClocked() const { return m_scClocked; }
|
||||
bool attrSFormat() const { return m_attrSFormat; }
|
||||
@@ -945,6 +973,14 @@ struct AstModule : public AstNodeModule {
|
||||
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 {
|
||||
// A package declaration
|
||||
AstPackage(FileLine* fl, const string& name)
|
||||
@@ -1602,7 +1638,7 @@ public:
|
||||
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
|
||||
// Also used as "real" function for /*verilator sformat*/ functions
|
||||
string m_text;
|
||||
@@ -1859,6 +1895,45 @@ public:
|
||||
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 {
|
||||
// Parents: expr
|
||||
// Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs
|
||||
@@ -1970,6 +2045,18 @@ struct AstContinue : public AstNodeStmt {
|
||||
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 {
|
||||
AstReturn(FileLine* fileline, AstNode* lhsp=NULL)
|
||||
: AstNodeStmt (fileline) {
|
||||
@@ -2413,6 +2500,20 @@ struct AstTime : public AstNodeTermop {
|
||||
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 {
|
||||
// User's $c function
|
||||
// Perhaps this should be a AstNodeListop; but there's only one list math right now
|
||||
@@ -2438,19 +2539,32 @@ struct AstUCFunc : public AstNodeMath {
|
||||
//======================================================================
|
||||
// Unary ops
|
||||
|
||||
struct AstUnaryMin : public AstNodeUniop {
|
||||
AstUnaryMin(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
struct AstNegate : public AstNodeUniop {
|
||||
AstNegate(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
ASTNODE_NODE_FUNCS(UnaryMin, UNARYMIN)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opUnaryMin(lhs); }
|
||||
ASTNODE_NODE_FUNCS(Negate, NEGATE)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegate(lhs); }
|
||||
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 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 {
|
||||
AstRedAnd(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedAnd, REDAND)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); }
|
||||
virtual string emitVerilog() { return "%f(& %l)"; }
|
||||
@@ -2460,7 +2574,7 @@ struct AstRedAnd : public AstNodeUniop {
|
||||
};
|
||||
struct AstRedOr : public AstNodeUniop {
|
||||
AstRedOr(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedOr, REDOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); }
|
||||
virtual string emitVerilog() { return "%f(| %l)"; }
|
||||
@@ -2470,7 +2584,7 @@ struct AstRedOr : public AstNodeUniop {
|
||||
};
|
||||
struct AstRedXor : public AstNodeUniop {
|
||||
AstRedXor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedXor, REDXOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); }
|
||||
virtual string emitVerilog() { return "%f(^ %l)"; }
|
||||
@@ -2484,7 +2598,7 @@ struct AstRedXor : public AstNodeUniop {
|
||||
struct AstRedXnor : public AstNodeUniop {
|
||||
// AstRedXnors are replaced with AstRedXors in V3Const.
|
||||
AstRedXnor(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
width(1,1); }
|
||||
width(1,1); numeric(AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(RedXnor, REDXNOR)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); }
|
||||
virtual string emitVerilog() { return "%f(~^ %l)"; }
|
||||
@@ -2542,7 +2656,7 @@ struct AstExtendS : public AstNodeUniop {
|
||||
struct AstSigned : public AstNodeUniop {
|
||||
// $signed(lhs)
|
||||
AstSigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
isSigned(true);
|
||||
numeric(AstNumeric::SIGNED);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Signed, SIGNED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
|
||||
@@ -2555,7 +2669,7 @@ struct AstSigned : public AstNodeUniop {
|
||||
struct AstUnsigned : public AstNodeUniop {
|
||||
// $unsigned(lhs)
|
||||
AstUnsigned(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
isSigned(false);
|
||||
numeric(AstNumeric::UNSIGNED);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(Unsigned, UNSIGNED)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); out.isSigned(false); }
|
||||
@@ -2565,6 +2679,63 @@ struct AstUnsigned : public AstNodeUniop {
|
||||
virtual bool sizeMattersLhs() {return true;} // Eliminated before matters
|
||||
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 {
|
||||
AstCLog2(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {}
|
||||
ASTNODE_NODE_FUNCS(CLog2, CLOG2)
|
||||
@@ -2682,7 +2853,7 @@ struct AstFEof : public AstNodeUniop {
|
||||
ASTNODE_NODE_FUNCS(FEof, FEOF)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
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 sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*16; }
|
||||
@@ -2695,13 +2866,97 @@ struct AstFGetC : public AstNodeUniop {
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; }
|
||||
virtual string emitVerilog() { return "%f$fgetc(%l)"; }
|
||||
// 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 sizeMattersLhs() {return false;}
|
||||
virtual int instrCount() const { return widthInstrs()*64; }
|
||||
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
|
||||
|
||||
@@ -2817,6 +3072,20 @@ struct AstEq : public AstNodeBiCom {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
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 {
|
||||
AstNeq(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiCom(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2829,6 +3098,20 @@ struct AstNeq : public AstNodeBiCom {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
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 {
|
||||
AstLt(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2841,6 +3124,20 @@ struct AstLt : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
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 {
|
||||
AstLtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2866,6 +3163,20 @@ struct AstGt : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
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 {
|
||||
AstGtS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2891,6 +3202,20 @@ struct AstGte : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
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 {
|
||||
AstGteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2916,6 +3241,20 @@ struct AstLte : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return true;} virtual bool cleanRhs() {return true;}
|
||||
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 {
|
||||
AstLteS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
width(1,1); }
|
||||
@@ -2984,6 +3323,20 @@ struct AstAdd : public AstNodeBiComAsv {
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
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 {
|
||||
AstSub(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -2996,6 +3349,20 @@ struct AstSub : public AstNodeBiop {
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
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 {
|
||||
AstMul(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3009,6 +3376,20 @@ struct AstMul : public AstNodeBiComAsv {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
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 {
|
||||
AstMulS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiComAsv(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3035,6 +3416,20 @@ struct AstDiv : public AstNodeBiop {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return true;}
|
||||
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 {
|
||||
AstDivS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3085,6 +3480,19 @@ struct AstPow : public AstNodeBiop {
|
||||
virtual bool sizeMattersLhs() {return true;} virtual bool sizeMattersRhs() {return false;}
|
||||
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 {
|
||||
AstPowS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
||||
if (lhsp) widthSignedFrom(lhsp); }
|
||||
@@ -3181,9 +3589,9 @@ struct AstBufIf1 : public AstNodeBiop {
|
||||
ASTNODE_NODE_FUNCS(BufIf1, BUFIF1)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opBufIf1(lhs,rhs); }
|
||||
virtual string emitVerilog() { return "bufif(%r,%l)"; }
|
||||
virtual string emitC() { V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual string emitSimpleOperator() { V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual bool cleanOut() {V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual string emitC() { V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
virtual string emitSimpleOperator() { 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 sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
};
|
||||
@@ -3621,25 +4029,6 @@ struct AstCReturn : public AstNodeStmt {
|
||||
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 {
|
||||
private:
|
||||
bool m_cleanOut;
|
||||
|
||||
+8
-4
@@ -148,17 +148,19 @@ private:
|
||||
|
||||
bool isCaseTreeFast(AstCase* nodep) {
|
||||
int width = 0;
|
||||
bool opaque = false;
|
||||
m_caseItems = 0;
|
||||
m_caseNoOverlapsAllCovered = true;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp; itemp=itemp->nextp()->castCaseItem()) {
|
||||
for (AstNode* icondp = itemp->condsp(); icondp!=NULL; icondp=icondp->nextp()) {
|
||||
if (icondp->width() > width) width = icondp->width();
|
||||
if (icondp->isDouble()) opaque = true;
|
||||
if (!icondp->castConst()) width = CASE_BARF; // Can't parse; not a constant
|
||||
m_caseItems++;
|
||||
}
|
||||
}
|
||||
m_caseWidth = width;
|
||||
if (width==0 || width > CASE_OVERLAP_WIDTH) {
|
||||
if (width==0 || width > CASE_OVERLAP_WIDTH || opaque) {
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
return false; // Too wide for analysis
|
||||
}
|
||||
@@ -348,7 +350,9 @@ private:
|
||||
and1p = cexprp->cloneTree(false);
|
||||
and2p = icondp;
|
||||
}
|
||||
AstEq* condp = new AstEq(itemp->fileline(), and1p, and2p);
|
||||
AstNodeBiop* condp = (and1p->isDouble()
|
||||
? (new AstEqD(itemp->fileline(), and1p, and2p))->castNodeBiop()
|
||||
: (new AstEq(itemp->fileline(), and1p, and2p))->castNodeBiop());
|
||||
if (!ifexprp) {
|
||||
ifexprp = condp;
|
||||
} else {
|
||||
@@ -448,10 +452,10 @@ private:
|
||||
if (isCaseTreeFast(nodep) && v3Global.opt.oCase()) {
|
||||
// It's a simple priority encoder or complete statement
|
||||
// we can make a tree of statements to avoid extra comparisons
|
||||
m_statCaseFast++;
|
||||
++m_statCaseFast;
|
||||
replaceCaseFast(nodep); nodep=NULL;
|
||||
} else {
|
||||
m_statCaseSlow++;
|
||||
++m_statCaseSlow;
|
||||
replaceCaseComplicated(nodep); nodep=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ private:
|
||||
insureLower32Cast(nodep);
|
||||
nodep->user1(1);
|
||||
}
|
||||
virtual void visit(AstUnaryMin* nodep, AstNUser*) {
|
||||
virtual void visit(AstNegate* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
if (nodep->lhsp()->widthMin()==1) {
|
||||
|
||||
+30
-6
@@ -46,6 +46,8 @@
|
||||
#include "V3EmitV.h"
|
||||
#include "V3File.h"
|
||||
|
||||
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
|
||||
|
||||
//######################################################################
|
||||
|
||||
class CdcBaseVisitor : public AstNVisitor {
|
||||
@@ -314,7 +316,9 @@ private:
|
||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||
//if (debug()>6) m_graph.dump();
|
||||
if (debug()>6) m_graph.dumpDotFilePrefixed("cdc_pre");
|
||||
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
||||
//
|
||||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights
|
||||
//
|
||||
m_graph.dumpDotFilePrefixed("cdc_simp");
|
||||
//
|
||||
analyzeReset();
|
||||
@@ -411,12 +415,15 @@ private:
|
||||
CdcEitherVertex* eToVertexp = (CdcEitherVertex*)edgep->top();
|
||||
if (!eToVertexp) targetp = eToVertexp;
|
||||
if (CdcLogicVertex* vvertexp = dynamic_cast<CdcLogicVertex*>(eToVertexp)) {
|
||||
if (vvertexp->isFlop()) {
|
||||
if (vvertexp->isFlop() // IE the target flop that is upsetting us
|
||||
&& edgep->weight() >= CDC_WEIGHT_ASYNC) { // And this signal feeds an async reset line
|
||||
targetp = eToVertexp;
|
||||
//UINFO(9," targetasync "<<targetp->name()<<" "<<" from "<<vertexp->name()<<endl);
|
||||
break;
|
||||
}
|
||||
} // else it might be random logic that's not relevant
|
||||
}
|
||||
//UINFO(9," finalflop "<<targetp->name()<<" "<<targetp->nodep()->fileline()<<endl);
|
||||
warnAndFile(markp->nodep(),V3ErrorCode::CDCRSTLOGIC,"Logic in path that feeds async reset, via signal: "+nodep->prettyName());
|
||||
dumpAsyncRecurse(targetp, "", " ",0);
|
||||
}
|
||||
@@ -469,6 +476,12 @@ private:
|
||||
|
||||
void edgeReport() {
|
||||
// Make report of all signal names and what clock edges they have
|
||||
//
|
||||
// Due to flattening, many interesting direct-connect signals are
|
||||
// lost, so we can't make a report showing I/Os for a low level
|
||||
// module. Disabling flattening though makes us consider each
|
||||
// signal in it's own unique clock domain.
|
||||
|
||||
UINFO(3,__FUNCTION__<<": "<<endl);
|
||||
|
||||
// Trace all sources and sinks
|
||||
@@ -498,6 +511,10 @@ private:
|
||||
|
||||
ostringstream os;
|
||||
os.setf(ios::left);
|
||||
// Module name - doesn't work due to flattening having lost the original
|
||||
// so we assume the modulename matches the filebasename
|
||||
string fname = vvertexp->varScp()->fileline()->filebasename() + ":";
|
||||
os<<" "<<setw(20)<<fname;
|
||||
os<<" "<<setw(8)<<whatp;
|
||||
os<<" "<<setw(40)<<vvertexp->varScp()->prettyName();
|
||||
os<<" SRC=";
|
||||
@@ -618,8 +635,9 @@ private:
|
||||
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
|
||||
CdcVarVertex* varvertexp = makeVarVertex(varscp);
|
||||
UINFO(5," VARREF to "<<varscp<<endl);
|
||||
// We use weight of one; if we ref the var more than once, when we simplify,
|
||||
// the weight will increase
|
||||
// We use weight of one for normal edges,
|
||||
// Weight of CDC_WEIGHT_ASYNC to indicate feeds async (for reporting)
|
||||
// When simplify we'll take the MAX weight
|
||||
if (nodep->lvalue()) {
|
||||
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
|
||||
if (m_inDly) {
|
||||
@@ -628,7 +646,13 @@ private:
|
||||
varvertexp->srcDomainSet(true);
|
||||
}
|
||||
} else {
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||
if (varvertexp->cntAsyncRst()) {
|
||||
//UINFO(9," edgeasync "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, CDC_WEIGHT_ASYNC);
|
||||
} else {
|
||||
//UINFO(9," edgena "<<varvertexp->name()<<" to "<<m_logicVertexp<<endl);
|
||||
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -725,7 +749,7 @@ public:
|
||||
|
||||
nodep->accept(*this);
|
||||
analyze();
|
||||
//edgeReport(); // Not useful at the moment
|
||||
if (debug()>=1) edgeReport(); // Not useful to users at the moment
|
||||
|
||||
if (0) { *m_ofp<<"\nDBG-test-dumper\n"; V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ",40,NULL,true); *m_ofp<<endl; }
|
||||
}
|
||||
|
||||
+2
-1
@@ -315,6 +315,7 @@ public:
|
||||
m_exprp = exprp;
|
||||
m_original = original;
|
||||
m_state = STATE_UNKNOWN;
|
||||
m_cloning = false;
|
||||
if (debug()>=9) nodep->dumpTree(cout," GateBodyIn: ");
|
||||
nodep->bodysp()->iterateAndNext(*this);
|
||||
if (debug()>=9) nodep->dumpTree(cout," GateBodyOut: ");
|
||||
@@ -696,7 +697,7 @@ class GaterVisitor : public GaterBaseVisitor {
|
||||
// Blow old statements from new body
|
||||
GaterBodyVisitor(alwp,exprp,false);
|
||||
|
||||
m_statGaters++;
|
||||
++m_statGaters;
|
||||
if (debug()>=9) alwp->dumpTree(cout," new: ");
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -70,8 +70,8 @@ protected:
|
||||
virtual ~CombBaseVisitor() {}
|
||||
|
||||
//***** optimization levels
|
||||
bool emptyFunctionDeletion() { return true; }
|
||||
bool duplicateFunctionCombine() { return true; }
|
||||
static bool emptyFunctionDeletion() { return true; }
|
||||
static bool duplicateFunctionCombine() { return true; }
|
||||
// Note this is disabled, it still needed work
|
||||
// Also repair it for DPI functions; when make __common need to insure proper
|
||||
// flags get inherited from the old to new AstCFunc, and that AstText doesn't
|
||||
@@ -146,7 +146,9 @@ private:
|
||||
}
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
CombCallVisitor() {}
|
||||
CombCallVisitor() {
|
||||
m_find = false;
|
||||
}
|
||||
virtual ~CombCallVisitor() {}
|
||||
void main(AstNetlist* nodep) {
|
||||
nodep->accept(*this);
|
||||
@@ -257,7 +259,7 @@ private:
|
||||
UINFO(5," DupFunc "<<hex<<V3Hash(newfuncp->user4p())<<" "<<newfuncp<<endl);
|
||||
UINFO(5," and "<<hex<<V3Hash(oldfuncp->user4p())<<" "<<oldfuncp<<endl);
|
||||
// Mark user3p on entire old tree, so we don't process it more
|
||||
m_statCombs++;
|
||||
++m_statCombs;
|
||||
CombMarkVisitor visitor(oldfuncp);
|
||||
m_call.replaceFunc(oldfuncp, newfuncp);
|
||||
oldfuncp->unlinkFrBack();
|
||||
|
||||
+16
-5
@@ -37,7 +37,6 @@
|
||||
#include "V3Const.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3Width.h"
|
||||
#include "V3Signed.h"
|
||||
#include "V3Simulate.h"
|
||||
|
||||
//######################################################################
|
||||
@@ -822,7 +821,9 @@ private:
|
||||
AstNodeAssign* asn2ap=nodep->cloneType(lc2p, sel2p)->castNodeAssign();
|
||||
asn1ap->width(msb1-lsb1+1,msb1-lsb1+1);
|
||||
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1ap);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn2ap);
|
||||
} else {
|
||||
if (!m_modp) nodep->v3fatalSrc("Not under module");
|
||||
@@ -853,12 +854,16 @@ private:
|
||||
asn2ap->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
asn2bp->width(msb2-lsb2+1,msb2-lsb2+1);
|
||||
// This order matters
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1ap);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn2ap);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn1bp);
|
||||
// cppcheck-suppress nullPointer // addNext deals with it
|
||||
newp = newp->addNext(asn2bp);
|
||||
}
|
||||
if (debug()>=9) newp->dumpTreeAndNext(cout," _new: ");
|
||||
if (debug()>=9 && newp) newp->dumpTreeAndNext(cout," _new: ");
|
||||
nodep->addNextHere(newp);
|
||||
// Cleanup
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
@@ -1519,7 +1524,7 @@ private:
|
||||
if (!inPct && ch=='%') {
|
||||
inPct = true;
|
||||
fmt = ch;
|
||||
} else if (inPct && isdigit(ch)) {
|
||||
} else if (inPct && (isdigit(ch) || ch=='.')) {
|
||||
fmt += ch;
|
||||
} else if (inPct) {
|
||||
inPct = false;
|
||||
@@ -1535,7 +1540,7 @@ private:
|
||||
UINFO(9," DispConst: "<<fmt<<" -> "<<out<<" for "<<argp<<endl);
|
||||
{ // fmt = out w/ replace % with %% as it must be literal.
|
||||
fmt = "";
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); pos++) {
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
||||
if (*pos == '%') fmt += '%';
|
||||
fmt += *pos;
|
||||
}
|
||||
@@ -1664,7 +1669,7 @@ private:
|
||||
TREEOP ("AstShiftRS{$lhsp.isZero, $rhsp}", "replaceZero(nodep)");
|
||||
TREEOP ("AstXor {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
TREEOP ("AstXnor {$lhsp.isZero, $rhsp}", "AstNot{$rhsp}");
|
||||
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstUnaryMin{$rhsp}");
|
||||
TREEOP ("AstSub {$lhsp.isZero, $rhsp}", "AstNegate{$rhsp}");
|
||||
TREEOP ("AstAdd {$lhsp, $rhsp.isZero}", "replaceWLhs(nodep)");
|
||||
TREEOP ("AstAnd {$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd{$lhsp, $rhsp.isZero}", "replaceZero(nodep)");
|
||||
@@ -1783,17 +1788,23 @@ private:
|
||||
TREEOP ("AstXnor {operandsSame($lhsp,,$rhsp)}", "replaceAllOnes(nodep)");
|
||||
TREEOP ("AstXor {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstEq {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||
TREEOP ("AstEqD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)"); // We let X==X -> 1, although in a true 4-state sim it's X.
|
||||
TREEOP ("AstEqCase {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstEqWild {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstGte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstGteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLt {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLtD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLtS {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLte {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLteD {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstLteS {operandsSame($lhsp,,$rhsp)}", "replaceNum(nodep,1)");
|
||||
TREEOP ("AstNeq {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqD {operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqCase{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstNeqWild{operandsSame($lhsp,,$rhsp)}", "replaceZero(nodep)");
|
||||
TREEOP ("AstLogAnd {operandsSame($lhsp,,$rhsp), $lhsp.width1}", "replaceWLhs(nodep)");
|
||||
|
||||
@@ -97,7 +97,7 @@ private:
|
||||
removep->unlinkFrBack(); pushDeletep(removep); removep=NULL;
|
||||
// Remove node from comparison so don't hit it again
|
||||
hashed.erase(dupit);
|
||||
m_statToggleJoins++;
|
||||
++m_statToggleJoins;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +122,12 @@ private:
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
if (nodep->packagep()) {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep, AstNUser*) {
|
||||
nodep->iterateChildren(*this);
|
||||
m_vscsp.push_back(nodep);
|
||||
|
||||
+1
-3
@@ -224,7 +224,6 @@ private:
|
||||
}
|
||||
//
|
||||
//=== Setting/not setting boolean: __Vdlyvset__
|
||||
bool sharedVset = false;
|
||||
AstVarScope* setvscp;
|
||||
|
||||
if (nodep->user3p()) {
|
||||
@@ -232,9 +231,8 @@ private:
|
||||
// then we told this nodep->user3 we can use its Vdlyvset rather than making a new one.
|
||||
// This is good for code like:
|
||||
// for (i=0; i<5; i++) vector[i] <= something;
|
||||
sharedVset = true;
|
||||
setvscp = nodep->user3p()->castNode()->castVarScope();
|
||||
m_statSharedSet++;
|
||||
++m_statSharedSet;
|
||||
} else { // Create new one
|
||||
string setvarname = (string("__Vdlyvset__")+oldvarp->shortName()+"__v"+cvtToStr(modVecNum));
|
||||
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1);
|
||||
|
||||
+55
-12
@@ -55,9 +55,9 @@ public:
|
||||
}
|
||||
|
||||
// ACCESSORS
|
||||
int splitFilenum() { return m_splitFilenum; }
|
||||
int splitFilenum() const { return m_splitFilenum; }
|
||||
int splitFilenumInc() { m_splitSize = 0; return ++m_splitFilenum; }
|
||||
int splitSize() { return m_splitSize; }
|
||||
int splitSize() const { return m_splitSize; }
|
||||
void splitSizeInc(AstNode* nodep) { m_splitSize += EmitCBaseCounterVisitor(nodep).count(); }
|
||||
bool splitNeeded() { return (splitSize() && v3Global.opt.outputSplit() > 1
|
||||
&& v3Global.opt.outputSplit() < splitSize()); }
|
||||
@@ -127,6 +127,7 @@ public:
|
||||
nodep->lhsp()->iterateAndNext(*this); puts(", ");
|
||||
} else if (nodep->isWide()
|
||||
&& nodep->lhsp()->castVarRef()
|
||||
&& !nodep->rhsp()->castCMath()
|
||||
&& !nodep->rhsp()->castVarRef()
|
||||
&& !nodep->rhsp()->castArraySel()) {
|
||||
// Wide functions assign into the array directly, don't need separate assign statement
|
||||
@@ -343,13 +344,11 @@ public:
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFClose* nodep, AstNUser*) {
|
||||
puts("if (");
|
||||
puts("VL_FCLOSE_I(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fclose (VL_CVT_Q_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); ");
|
||||
puts("); ");
|
||||
nodep->filep()->iterateAndNext(*this); // For saftey, so user doesn't later WRITE with it.
|
||||
puts("=0; }\n");
|
||||
puts("=0;\n");
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep, AstNUser*) {
|
||||
if (!nodep->filep()) {
|
||||
@@ -357,11 +356,35 @@ public:
|
||||
} else {
|
||||
puts("if (");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(") { fflush (VL_CVT_Q_FP(");
|
||||
puts(") { fflush (VL_CVT_I_FP(");
|
||||
nodep->filep()->iterateAndNext(*this);
|
||||
puts(")); }\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSystemT* nodep, AstNUser*) {
|
||||
puts("(void)VL_SYSTEM_I");
|
||||
emitIQW(nodep->lhsp());
|
||||
puts("(");
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
puts(cvtToStr(nodep->lhsp()->widthWords()));
|
||||
putbs(", ");
|
||||
}
|
||||
checkMaxWords(nodep->lhsp());
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstSystemF* nodep, AstNUser*) {
|
||||
puts("VL_SYSTEM_I");
|
||||
emitIQW(nodep->lhsp());
|
||||
puts("(");
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
puts(cvtToStr(nodep->lhsp()->widthWords()));
|
||||
putbs(", ");
|
||||
}
|
||||
checkMaxWords(nodep->lhsp());
|
||||
nodep->lhsp()->iterateAndNext(*this);
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep, AstNUser*) {
|
||||
puts("goto __Vlabel"+cvtToStr(nodep->labelp()->labelNum())+";\n");
|
||||
}
|
||||
@@ -546,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(0)));
|
||||
} else if (nodep->isDouble()) {
|
||||
ofp()->printf("%.17g", nodep->num().toDouble());
|
||||
} else if (nodep->isQuad()) {
|
||||
vluint64_t num = nodep->toUQuad();
|
||||
if (num<10) ofp()->printf("VL_ULL(%" VL_PRI64 "d)", num);
|
||||
@@ -829,6 +854,8 @@ class EmitCImp : EmitCStmts {
|
||||
public:
|
||||
EmitCImp() {
|
||||
m_modp = NULL;
|
||||
m_slow = false;
|
||||
m_fast = false;
|
||||
}
|
||||
virtual ~EmitCImp() {}
|
||||
void main(AstNodeModule* modp, bool slow, bool fast);
|
||||
@@ -1211,6 +1238,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
switch (tolower(pos[0])) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
// Digits, like %5d, etc.
|
||||
vfmt += pos[0];
|
||||
inPct = true; // Get more digits
|
||||
@@ -1229,6 +1257,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
case 'h':
|
||||
case 'x': displayArg(nodep,&elistp,isScan, vfmt,'x'); break;
|
||||
case 's': displayArg(nodep,&elistp,isScan, vfmt,'s'); break;
|
||||
case 'e': displayArg(nodep,&elistp,isScan, vfmt,'e'); break;
|
||||
case 'f': displayArg(nodep,&elistp,isScan, vfmt,'f'); break;
|
||||
case 'g': displayArg(nodep,&elistp,isScan, vfmt,'g'); break;
|
||||
case 'm': {
|
||||
if (!scopenamep) nodep->v3fatalSrc("Display with %m but no AstScopeName");
|
||||
string suffix = scopenamep->scopePrettyName();
|
||||
@@ -1419,6 +1450,7 @@ void EmitCImp::emitStaticDecl(AstNodeModule* modp) {
|
||||
// Need implementation here. Be careful of alignment code; needs to be uniquified
|
||||
// with module name to avoid multiple symbols.
|
||||
//emitVarList(modp->stmtsp(), EVL_ALL, modp->name());
|
||||
puts(""); // NOP for cppcheck, otherwise const function
|
||||
}
|
||||
|
||||
void EmitCImp::emitTextSection(AstType type) {
|
||||
@@ -1619,7 +1651,12 @@ void EmitCImp::emitInt(AstNodeModule* modp) {
|
||||
if (v3Global.needHInlines()) { // Set by V3EmitCInlines; should have been called before us
|
||||
puts("#include \""+topClassName()+"__Inlines.h\"\n");
|
||||
}
|
||||
// No __Dpi.h needed, we've shimmed it all into the interface
|
||||
if (v3Global.dpi()) {
|
||||
// do this before including our main .h file so that any references to
|
||||
// types defined in svdpi.h are available
|
||||
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// Declare foreign instances up front to make C++ happy
|
||||
puts("class "+symClassName()+";\n");
|
||||
@@ -1797,8 +1834,10 @@ void EmitCImp::emitImp(AstNodeModule* modp) {
|
||||
|
||||
// Us
|
||||
puts("#include \""+ symClassName() +".h\"\n");
|
||||
|
||||
if (v3Global.dpi()) {
|
||||
puts("#include \""+ topClassName() +"__Dpi.h\"\n");
|
||||
puts("\n");
|
||||
puts("#include \"verilated_dpi.h\"\n");
|
||||
}
|
||||
|
||||
if (optSystemPerl() && (splitFilenum() || !m_fast)) {
|
||||
@@ -2003,7 +2042,9 @@ class EmitCTrace : EmitCStmts {
|
||||
return varp->isSc() && varp->isScBv();
|
||||
}
|
||||
void emitTraceInitOne(AstTraceDecl* nodep) {
|
||||
if (nodep->isWide()) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->declDouble");
|
||||
} else if (nodep->isWide()) {
|
||||
puts("vcdp->declArray");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->declQuad ");
|
||||
@@ -2032,7 +2073,9 @@ class EmitCTrace : EmitCStmts {
|
||||
string full = ((m_funcp->funcType() == AstCFuncType::TRACE_FULL
|
||||
|| m_funcp->funcType() == AstCFuncType::TRACE_FULL_SUB)
|
||||
? "full":"chg");
|
||||
if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
if (nodep->isDouble()) {
|
||||
puts("vcdp->"+full+"Double");
|
||||
} else if (nodep->isWide() || emitTraceIsScBv(nodep)) {
|
||||
puts("vcdp->"+full+"Array");
|
||||
} else if (nodep->isQuad()) {
|
||||
puts("vcdp->"+full+"Quad ");
|
||||
|
||||
+4
-2
@@ -519,13 +519,15 @@ void EmitCSyms::emitDpiHdr() {
|
||||
puts("// Manually include this file where DPI .c import functions are declared to insure\n");
|
||||
puts("// the C functions match the expectations of the DPI imports.\n");
|
||||
puts("\n");
|
||||
puts("#include \"svdpi.h\"\n");
|
||||
puts("\n");
|
||||
puts("#ifdef __cplusplus\n");
|
||||
puts("extern \"C\" {\n");
|
||||
puts("#endif\n");
|
||||
puts("\n");
|
||||
|
||||
bool firstExp = false;
|
||||
bool firstImp = false;
|
||||
int firstExp = 0;
|
||||
int firstImp = 0;
|
||||
for (vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) {
|
||||
AstCFunc* nodep = *it;
|
||||
if (nodep->dpiExportWrapper()) {
|
||||
|
||||
+9
-4
@@ -84,10 +84,15 @@ public:
|
||||
if (v3Global.opt.systemPerl()) {
|
||||
putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC
|
||||
}
|
||||
else if (v3Global.opt.trace()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_c.cpp");
|
||||
if (v3Global.opt.systemC()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
|
||||
else {
|
||||
if (v3Global.opt.coverage()) {
|
||||
putMakeClassEntry(of, "SpCoverage.cpp");
|
||||
}
|
||||
if (v3Global.opt.trace()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_c.cpp");
|
||||
if (v3Global.opt.systemC()) {
|
||||
putMakeClassEntry(of, "verilated_vcd_sc.cpp");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +217,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
}
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstDisable* nodep, AstNUser*) {
|
||||
putbs("disable "+nodep->name()+";\n");
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep, AstNUser*) {
|
||||
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
}
|
||||
@@ -480,6 +483,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
putfs(nodep,nodep->prettyName());
|
||||
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*) {
|
||||
if (nodep->dotted()!="") { putfs(nodep,nodep->dotted()); puts("."); puts(nodep->prettyName()); }
|
||||
else { putfs(nodep,nodep->prettyName()); }
|
||||
|
||||
+40
-7
@@ -34,8 +34,6 @@
|
||||
//======================================================================
|
||||
// Statics
|
||||
|
||||
FileLine FileLine::s_defaultFileLine = FileLine(EmptySecret());
|
||||
|
||||
int V3Error::s_errCount = 0;
|
||||
int V3Error::s_warnCount = 0;
|
||||
int V3Error::s_debugDefault = 0;
|
||||
@@ -66,12 +64,28 @@ V3ErrorCode::V3ErrorCode(const char* msgp) {
|
||||
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::FileLine(FileLine::EmptySecret) {
|
||||
// Sort of a singleton
|
||||
m_lineno=0;
|
||||
m_filename="COMMAND_LINE";
|
||||
m_filenameno=singleton().nameToNumber("AstRoot");
|
||||
|
||||
m_warnOn=0;
|
||||
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 {
|
||||
char numbuf[20]; sprintf(numbuf, "%d", lineno());
|
||||
char levelbuf[20]; sprintf(levelbuf, "%d", enterExit);
|
||||
@@ -262,6 +289,7 @@ void FileLine::deleteAllRemaining() {
|
||||
// Eventually the list will be empty and terminate the loop.
|
||||
}
|
||||
fileLineLeakChecks.clear();
|
||||
FileLineSingleton::clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -304,13 +332,18 @@ void V3Error::incErrors() {
|
||||
|
||||
void V3Error::abortIfErrors() {
|
||||
if (errorCount()) {
|
||||
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
|
||||
abortIfWarnings();
|
||||
}
|
||||
}
|
||||
|
||||
void V3Error::abortIfWarnings() {
|
||||
if (v3Global.opt.warnFatal() ? errorOrWarnCount() : errorCount()) {
|
||||
v3fatal ("Exiting due to "<<dec<<errorOrWarnCount()<<" warning(s)\n");
|
||||
bool exwarn = v3Global.opt.warnFatal() && warnCount();
|
||||
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) {
|
||||
#ifdef __COVERITY__
|
||||
#if defined(__COVERITY__) || defined(__cppcheck__)
|
||||
if (s_errorCode==V3ErrorCode::EC_FATAL) __coverity_panic__(x);
|
||||
#endif
|
||||
if (!s_errorSuppressed
|
||||
|
||||
+62
-19
@@ -28,6 +28,8 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
|
||||
//######################################################################
|
||||
|
||||
@@ -46,13 +48,15 @@ public:
|
||||
I_LINT, // All lint messages
|
||||
I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE)
|
||||
// Error codes:
|
||||
E_BLKLOOPINIT, // Error: Delayed assignment to array inside for loops
|
||||
E_MULTITOP, // Error: Multiple top level modules
|
||||
E_TASKNSVAR, // Error: Task I/O not simple
|
||||
E_BLKLOOPINIT, // Error: Delayed assignment to array inside for loops
|
||||
//
|
||||
// Warning codes:
|
||||
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
|
||||
BLKSEQ, // Blocking assignments in sequential block
|
||||
CASEINCOMPLETE, // Case statement has missing values
|
||||
@@ -73,6 +77,7 @@ public:
|
||||
LITENDIAN, // Little bit endian vector
|
||||
MODDUP, // Duplicate module
|
||||
MULTIDRIVEN, // Driven from multiple blocks
|
||||
REALCVT, // Real conversion
|
||||
REDEFMACRO, // Redefining existing define macro
|
||||
STMTDLY, // Delayed statement
|
||||
SYMRSVDWORD, // Symbol is Reserved Word
|
||||
@@ -89,7 +94,7 @@ public:
|
||||
// ***Add new elements below also***
|
||||
};
|
||||
enum en m_e;
|
||||
inline V3ErrorCode () {}
|
||||
inline V3ErrorCode () : m_e(EC_MIN) {}
|
||||
inline V3ErrorCode (en _e) : m_e(_e) {}
|
||||
V3ErrorCode (const char* msgp); // Matching code or ERROR
|
||||
explicit inline V3ErrorCode (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
@@ -101,9 +106,10 @@ public:
|
||||
// Boolean
|
||||
" I_COVERAGE", " I_TRACING", " I_LINT", " I_DEF_NETTYPE_WIRE",
|
||||
// Errors
|
||||
"MULTITOP", "TASKNSVAR", "BLKLOOPINIT",
|
||||
"BLKLOOPINIT", "MULTITOP", "TASKNSVAR",
|
||||
// Warnings
|
||||
" EC_FIRST_WARN",
|
||||
"ASSIGNDLY", "ASSIGNIN",
|
||||
"BLKANDNBLK", "BLKSEQ",
|
||||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CMPCONST",
|
||||
"COMBDLY", "DEFPARAM", "DECLFILENAME",
|
||||
@@ -111,7 +117,7 @@ public:
|
||||
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
|
||||
"LITENDIAN", "MODDUP",
|
||||
"MULTIDRIVEN",
|
||||
"REDEFMACRO",
|
||||
"REALCVT", "REDEFMACRO",
|
||||
"STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
|
||||
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
|
||||
@@ -125,7 +131,8 @@ public:
|
||||
bool dangerous() const { return ( m_e==COMBDLY ); }
|
||||
// Warnings we'll present to the user as errors
|
||||
// Later -Werror- options may make more of these.
|
||||
bool pretendError() const { return ( m_e==BLKANDNBLK || m_e==IMPURE || 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
|
||||
bool mentionManual() const { return ( m_e==EC_FATALSRC || pretendError() ); }
|
||||
|
||||
@@ -135,10 +142,12 @@ public:
|
||||
|| m_e==CMPCONST
|
||||
|| m_e==IMPLICIT
|
||||
|| m_e==LITENDIAN
|
||||
|| m_e==REALCVT
|
||||
|| m_e==UNSIGNED
|
||||
|| m_e==WIDTH); }
|
||||
// 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==DECLFILENAME
|
||||
|| 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 {
|
||||
// File and line number of an object, mostly for error reporting
|
||||
int m_lineno;
|
||||
string m_filename;
|
||||
int m_filenameno;
|
||||
bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
|
||||
// Consider moving opt.language() into here, so can know language per-node
|
||||
static FileLine s_defaultFileLine;
|
||||
|
||||
private:
|
||||
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:
|
||||
// User routines should never need to change line numbers
|
||||
// We are storing pointers, so we CAN'T change them after initial reading.
|
||||
friend class FileLineSingleton;
|
||||
friend class V3ParseImp;
|
||||
friend class V3PreLex;
|
||||
friend class V3PreProcImp;
|
||||
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 linenoInc() { m_lineno++; }
|
||||
void linenoIncInPlace() { m_lineno++; }
|
||||
FileLine* copyOrSameFileLine();
|
||||
public:
|
||||
FileLine (const string& filename, int lineno) { m_lineno=lineno; m_filename = filename; m_warnOn=s_defaultFileLine.m_warnOn; }
|
||||
FileLine (FileLine* fromp) { m_lineno=fromp->lineno(); m_filename = fromp->filename(); m_warnOn=fromp->m_warnOn; }
|
||||
FileLine (const string& filename, int lineno) {
|
||||
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() { }
|
||||
FileLine* create(const string& filename, int lineno) { return new FileLine(filename,lineno); }
|
||||
@@ -277,7 +315,8 @@ public:
|
||||
|
||||
int lineno () const { return m_lineno; }
|
||||
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 filebasenameNoExt () const;
|
||||
const string profileFuncname() const;
|
||||
@@ -289,7 +328,7 @@ public:
|
||||
void warnLintOff(bool flag);
|
||||
void warnStyleOff(bool flag);
|
||||
void warnStateFrom(const FileLine& from) { m_warnOn=from.m_warnOn; }
|
||||
void warnResetDefault() { warnStateFrom(s_defaultFileLine); }
|
||||
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
|
||||
|
||||
// Specific flag ACCESSORS/METHODS
|
||||
bool coverageOn() const { return m_warnOn.test(V3ErrorCode::I_COVERAGE); }
|
||||
@@ -298,10 +337,14 @@ public:
|
||||
void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING,flag); }
|
||||
|
||||
// METHODS - Global
|
||||
static void globalWarnLintOff(bool flag) { s_defaultFileLine.warnLintOff(flag); }
|
||||
static void globalWarnStyleOff(bool flag) { s_defaultFileLine.warnStyleOff(flag); }
|
||||
static void globalWarnOff(V3ErrorCode code, bool flag) { s_defaultFileLine.warnOff(code, flag); }
|
||||
static bool globalWarnOff(const string& code, bool flag) { return s_defaultFileLine.warnOff(code, flag); }
|
||||
static void globalWarnLintOff(bool flag) {
|
||||
defaultFileLine().warnLintOff(flag); }
|
||||
static void globalWarnStyleOff(bool 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
|
||||
// Merge warning disables from another fileline
|
||||
@@ -313,8 +356,8 @@ public:
|
||||
|
||||
// OPERATORS
|
||||
void v3errorEnd(ostringstream& str);
|
||||
inline bool operator==(FileLine rhs) {
|
||||
return (m_lineno==rhs.m_lineno && m_filename==rhs.m_filename && m_warnOn==rhs.m_warnOn);
|
||||
inline bool operator==(FileLine rhs) const {
|
||||
return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno && m_warnOn==rhs.m_warnOn);
|
||||
}
|
||||
};
|
||||
ostream& operator<<(ostream& os, FileLine* fileline);
|
||||
|
||||
+2
-3
@@ -696,8 +696,7 @@ private:
|
||||
int lhswidth = lhsp->widthMin();
|
||||
if (lhswidth==1) {
|
||||
UINFO(8," REPLICATE(w1) "<<nodep<<endl);
|
||||
newp = new AstUnaryMin (nodep->fileline(),
|
||||
lhsp);
|
||||
newp = new AstNegate (nodep->fileline(), lhsp);
|
||||
} else {
|
||||
UINFO(8," REPLICATE "<<nodep<<endl);
|
||||
AstConst* constp = nodep->rhsp()->castConst();
|
||||
@@ -731,7 +730,7 @@ private:
|
||||
for (int w=0; w<rhsp->widthWords(); w++) {
|
||||
AstNode* newp;
|
||||
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);
|
||||
} else {
|
||||
newp = newAstWordSelClone (lhsp, w);
|
||||
|
||||
@@ -327,6 +327,7 @@ private:
|
||||
#endif
|
||||
}
|
||||
|
||||
// cppcheck-suppress functionConst
|
||||
void checkFilter(bool hang) {
|
||||
#ifdef INFILTER_PIPE
|
||||
if (!m_pidExited && waitpid(m_pid, &m_pidStatus, hang?0:WNOHANG)) {
|
||||
@@ -355,6 +356,7 @@ private:
|
||||
|| errno == EWOULDBLOCK
|
||||
#endif
|
||||
) {
|
||||
// cppcheck-suppress obsoleteFunctionsusleep
|
||||
checkFilter(false); usleep(1000); continue;
|
||||
} else { m_readEof = true; break; }
|
||||
}
|
||||
@@ -390,6 +392,7 @@ private:
|
||||
|| errno == EWOULDBLOCK
|
||||
#endif
|
||||
) {
|
||||
// cppcheck-suppress obsoleteFunctionsusleep
|
||||
checkFilter(false); usleep(1000); continue;
|
||||
}
|
||||
else break;
|
||||
|
||||
+2
-2
@@ -535,7 +535,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
||||
AstNode* substp = okVisitor.substTree();
|
||||
if (debug()>=5) logicp->dumpTree(cout,"\telimVar: ");
|
||||
if (debug()>=5) substp->dumpTree(cout,"\t subst: ");
|
||||
m_statSigs++;
|
||||
++m_statSigs;
|
||||
while (V3GraphEdge* edgep = vvertexp->outBeginp()) {
|
||||
GateLogicVertex* consumeVertexp = dynamic_cast<GateLogicVertex*>(edgep->top());
|
||||
AstNode* consumerp = consumeVertexp->nodep();
|
||||
@@ -557,7 +557,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
||||
}
|
||||
// Remove the edge
|
||||
edgep->unlinkDelete(); edgep=NULL;
|
||||
m_statRefs++;
|
||||
++m_statRefs;
|
||||
}
|
||||
// Remove input links
|
||||
while (V3GraphEdge* edgep = vvertexp->inBeginp()) {
|
||||
|
||||
+4
-4
@@ -70,7 +70,7 @@ private:
|
||||
// MEMBERS
|
||||
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
|
||||
int debug() { return 0; }
|
||||
static int debug() { return 0; }
|
||||
|
||||
// METHODS
|
||||
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
|
||||
@@ -94,7 +94,7 @@ private:
|
||||
}
|
||||
|
||||
// Hashing
|
||||
uint32_t hashVertex(V3GraphVertex* vertexp) {
|
||||
static uint32_t hashVertex(V3GraphVertex* vertexp) {
|
||||
union { void* up; struct {uint32_t upper; uint32_t lower;} l;} u;
|
||||
u.l.upper=0; u.l.lower=0; u.up=vertexp;
|
||||
return u.l.upper ^ u.l.lower;
|
||||
@@ -362,7 +362,7 @@ void DfaGraph::nfaToDfa() {
|
||||
class DfaGraphReduce : GraphAlg {
|
||||
private:
|
||||
// METHODS
|
||||
int debug() { return 0; }
|
||||
static int debug() { return 0; }
|
||||
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
|
||||
|
||||
bool isDead(DfaVertex* vertexp) {
|
||||
@@ -507,7 +507,7 @@ private:
|
||||
DfaVertex* m_tempNewerReject;
|
||||
|
||||
// METHODS
|
||||
int debug() { return 9; }
|
||||
static int debug() { return 9; }
|
||||
DfaGraph* graphp() { return static_cast<DfaGraph*>(m_graphp); }
|
||||
|
||||
void add_complement_edges() {
|
||||
|
||||
@@ -326,6 +326,7 @@ public:
|
||||
|
||||
class V3GraphTestImport : public V3GraphTest {
|
||||
|
||||
// cppcheck-suppress functionConst
|
||||
void dotImport();
|
||||
|
||||
public:
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ private:
|
||||
if (m_cellp) nodep->v3error("Cloning should have already been done bottom-up");
|
||||
UINFO(5," Inline CELL "<<nodep<<endl);
|
||||
UINFO(5," To MOD "<<m_modp<<endl);
|
||||
m_statCells++;
|
||||
++m_statCells;
|
||||
|
||||
// Before cloning simplify pin assignments
|
||||
// Better off before, as if module has multiple instantiations
|
||||
|
||||
@@ -293,6 +293,7 @@ private:
|
||||
// LIFE MAP
|
||||
// For each basic block, we'll make a new map of what variables that if/else is changing
|
||||
typedef std::map<AstVarScope*, LifeVarEntry> LifeMap;
|
||||
// cppcheck-suppress memleak // cppcheck bug - it is deleted
|
||||
LifeBlock* m_lifep; // Current active lifetime map for current scope
|
||||
|
||||
// METHODS
|
||||
@@ -455,6 +456,8 @@ public:
|
||||
m_sideEffect = false;
|
||||
m_noopt = false;
|
||||
{
|
||||
// Cpp check bug, it is deleted
|
||||
// cppcheck-suppress leak
|
||||
m_lifep = new LifeBlock (NULL, m_statep);
|
||||
nodep->accept(*this);
|
||||
delete m_lifep; m_lifep=NULL;
|
||||
|
||||
+1
-1
@@ -157,7 +157,7 @@ private:
|
||||
// Mark so LifePostElimVisitor will get it
|
||||
rhsp->varScopep()->user4p(lhsp->varScopep());
|
||||
nodep->unlinkFrBack()->deleteTree(); nodep=NULL;
|
||||
m_statAssnDel++;
|
||||
++m_statAssnDel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-3
@@ -134,7 +134,7 @@ private:
|
||||
nodep->packagep(packageFor(varp));
|
||||
}
|
||||
else if (AstEnumItem* valuep = foundp->castEnumItem()) {
|
||||
AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep);
|
||||
AstNode* newp = new AstEnumItemRef(nodep->fileline(), valuep, packageFor(valuep));
|
||||
nodep->replaceWith(newp);
|
||||
nodep->deleteTree(); nodep=NULL;
|
||||
return true; // Edited
|
||||
@@ -428,7 +428,7 @@ private:
|
||||
if (dtypep) dtypep->unlinkFrBack();
|
||||
else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC);
|
||||
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->trace(false); // Not user visible
|
||||
newvarp->attrIsolateAssign(nodep->attrIsolateAssign());
|
||||
@@ -563,8 +563,13 @@ private:
|
||||
nodep->v3fatalSrc("Cell has unlinked module"); // V3LinkCell should have errored out
|
||||
}
|
||||
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
|
||||
if (m_idState==ID_RESOLVE) {
|
||||
else if (m_idState==ID_RESOLVE) {
|
||||
m_cellVarsp = nodep->modp()->user4p()->castSymTable();
|
||||
UINFO(4,"(Backto) Link Cell: "<<nodep<<endl);
|
||||
//if (debug()) { nodep->dumpTree(cout,"linkcell:"); }
|
||||
|
||||
+12
-2
@@ -135,7 +135,15 @@ private:
|
||||
AstNodeModule* modp = vvertexp->modp();
|
||||
modp->level(vvertexp->rank()+1);
|
||||
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();
|
||||
if (!modp) {
|
||||
// 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);
|
||||
parser.parseFile(nodep->fileline(), nodep->modName(), false);
|
||||
parser.parseFile(nodep->fileline(), nodep->modName(), false, "");
|
||||
V3Error::abortIfErrors();
|
||||
// We've read new modules, grab new pointers to their names
|
||||
readModNames();
|
||||
|
||||
+31
-5
@@ -47,7 +47,7 @@ private:
|
||||
typedef vector<AstBegin*> BeginStack;
|
||||
|
||||
// STATE
|
||||
AstModule* m_modp; // Current module
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNodeFTask* m_ftaskp; // Current function/task
|
||||
AstWhile* m_loopp; // Current loop
|
||||
bool m_loopInc; // In loop increment
|
||||
@@ -82,6 +82,11 @@ private:
|
||||
nodep->v3fatalSrc("Unknown jump point for break/disable/continue");
|
||||
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) {
|
||||
nodep->v3fatalSrc("Break/disable/continue not under expected statement");
|
||||
@@ -109,7 +114,7 @@ private:
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstModule* nodep, AstNUser*) {
|
||||
virtual void visit(AstNodeModule* nodep, AstNUser*) {
|
||||
m_modp = nodep;
|
||||
m_repeatNum = 0;
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -135,8 +140,8 @@ private:
|
||||
// Spec says value is integral, if negative is ignored
|
||||
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
|
||||
AstLogicPacked(), 32);
|
||||
varp->isSigned(true);
|
||||
varp->dtypep()->isSigned(true);
|
||||
varp->numeric(AstNumeric::SIGNED);
|
||||
varp->dtypep()->numeric(AstNumeric::SIGNED);
|
||||
varp->usedLoopIdx(true);
|
||||
m_modp->addStmtp(varp);
|
||||
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),
|
||||
new AstSub(nodep->fileline(), new AstVarRef(nodep->fileline(), varp, false),
|
||||
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),
|
||||
zerosp);
|
||||
AstNode* bodysp = nodep->bodysp(); if (bodysp) bodysp->unlinkFrBackWithNext();
|
||||
@@ -211,6 +216,27 @@ private:
|
||||
}
|
||||
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*) {
|
||||
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
|
||||
}
|
||||
|
||||
+12
-1
@@ -45,6 +45,7 @@ private:
|
||||
|
||||
// STATE
|
||||
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
|
||||
|
||||
// METHODS
|
||||
@@ -64,9 +65,13 @@ private:
|
||||
if (nodep->varp()) {
|
||||
if (nodep->lvalue() && nodep->varp()->isInOnly()) {
|
||||
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);
|
||||
}
|
||||
@@ -222,6 +227,11 @@ private:
|
||||
}
|
||||
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*) {
|
||||
m_ftaskp = nodep;
|
||||
nodep->iterateChildren(*this);
|
||||
@@ -259,6 +269,7 @@ public:
|
||||
LinkLValueVisitor(AstNode* nodep, bool start) {
|
||||
m_setRefLvalue = start;
|
||||
m_ftaskp = NULL;
|
||||
m_initialp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~LinkLValueVisitor() {}
|
||||
|
||||
@@ -326,6 +326,11 @@ private:
|
||||
m_varp->attrSFormat(true);
|
||||
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*) {
|
||||
|
||||
@@ -95,6 +95,9 @@ private:
|
||||
nodep->dtypeSkipRefp()->castArrayDType())) {
|
||||
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 (nodep->isSigModPublic()) {
|
||||
nodep->sigModPublic(false); // We're done with this attribute
|
||||
@@ -254,6 +257,7 @@ private:
|
||||
switch (tolower(ch)) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '.':
|
||||
inPct = true;
|
||||
break;
|
||||
case '%': break; // %% - just output a %
|
||||
|
||||
+7
-4
@@ -60,7 +60,7 @@ private:
|
||||
T m_nextp; // Pointer to next element, NULL=end
|
||||
T m_prevp; // Pointer to previous element, NULL=beginning
|
||||
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
|
||||
// Use that to determine a structure offset, then apply to the new base
|
||||
// to get our new pointer information
|
||||
@@ -80,7 +80,8 @@ public:
|
||||
// METHODS
|
||||
void pushBack (V3List<T>& listr, T 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;
|
||||
if (!listr.m_headp) listr.m_headp = newp;
|
||||
m_prevp = listr.m_tailp;
|
||||
@@ -89,7 +90,8 @@ public:
|
||||
}
|
||||
void pushFront (V3List<T>& listr, T 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;
|
||||
if (m_nextp) baseToListEnt(m_nextp,offset)->m_prevp = newp;
|
||||
listr.m_headp = newp;
|
||||
@@ -99,7 +101,8 @@ public:
|
||||
// Unlink from side
|
||||
void unlink (V3List<T>& listr, T 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;
|
||||
else listr.m_tailp = m_prevp;
|
||||
if (m_prevp) baseToListEnt(m_prevp,offset)->m_nextp = m_nextp;
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ private:
|
||||
&& nodep->user1p()) { // Single cfunc
|
||||
// We don't need to test for tracing; it would be in the tracefunc if it was needed
|
||||
UINFO(4," ModVar->BlkVar "<<nodep<<endl);
|
||||
m_statLocVars++;
|
||||
++m_statLocVars;
|
||||
AstCFunc* newfuncp = nodep->user1p()->castNode()->castCFunc();
|
||||
nodep->unlinkFrBack();
|
||||
newfuncp->addInitsp(nodep);
|
||||
|
||||
+145
-39
@@ -25,33 +25,19 @@
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include "V3Number.h"
|
||||
|
||||
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
|
||||
|
||||
//######################################################################
|
||||
// Read class functions
|
||||
// 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) {
|
||||
// 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);
|
||||
m_fromString = true;
|
||||
for (unsigned pos=0; pos<str.length(); ++pos) {
|
||||
@@ -298,6 +284,24 @@ V3Number& V3Number::setLong(uint32_t value) {
|
||||
m_value[0] = value;
|
||||
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) {
|
||||
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);
|
||||
@@ -306,12 +310,12 @@ V3Number& V3Number::setSingleBits(char value) {
|
||||
}
|
||||
|
||||
V3Number& V3Number::setAllBits0() {
|
||||
for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; }
|
||||
return *this;
|
||||
for (int i=0; i<words(); i++) { m_value[i] = m_valueX[i]=0; }
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setAllBits1() {
|
||||
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
|
||||
return *this;
|
||||
for (int i=0; i<words(); i++) { m_value[i]= ~0; m_valueX[i] = 0; }
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setAllBitsX() {
|
||||
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 {
|
||||
ostringstream out;
|
||||
|
||||
if (isDouble()) {
|
||||
out.precision(17);
|
||||
out<<toDouble();
|
||||
return out.str();
|
||||
}
|
||||
if (prefixed) {
|
||||
if (sized()) {
|
||||
out<<width()<<"'";
|
||||
@@ -375,6 +384,9 @@ bool V3Number::displayedFmtLegal(char format) {
|
||||
case 'b': return true;
|
||||
case 'c': return true;
|
||||
case 'd': return true; // Unsigned decimal
|
||||
case 'e': return true;
|
||||
case 'f': return true;
|
||||
case 'g': return true;
|
||||
case 'h': return true;
|
||||
case 'o': return true;
|
||||
case 's': return true;
|
||||
@@ -388,9 +400,9 @@ bool V3Number::displayedFmtLegal(char format) {
|
||||
string V3Number::displayed(const string& vformat) const {
|
||||
string::const_iterator pos = vformat.begin();
|
||||
UASSERT(pos != vformat.end() && pos[0]=='%', "display with non format argument "<<*this);
|
||||
pos++;
|
||||
++pos;
|
||||
string fmtsize;
|
||||
for (; pos != vformat.end() && isdigit(pos[0]); pos++) {
|
||||
for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); ++pos) {
|
||||
fmtsize += pos[0];
|
||||
}
|
||||
string str;
|
||||
@@ -472,9 +484,20 @@ string V3Number::displayed(const string& vformat) const {
|
||||
str = cvtToStr(toUQuad());
|
||||
}
|
||||
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;
|
||||
}
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g': {
|
||||
char tmp[MAX_SPRINTF_DOUBLE_SIZE];
|
||||
sprintf(tmp, vformat.c_str(), toDouble());
|
||||
return tmp;
|
||||
}
|
||||
default:
|
||||
m_fileline->v3fatalSrc("Unknown $display format code for number: %"<<pos[0]);
|
||||
return "ERR";
|
||||
@@ -490,6 +513,18 @@ uint32_t V3Number::toUInt() const {
|
||||
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 {
|
||||
if (isSigned()) {
|
||||
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) {
|
||||
// L(lhs) bit return
|
||||
// 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();
|
||||
setZero();
|
||||
uint32_t rhsval = rhs.toUInt();
|
||||
@@ -1079,12 +1114,12 @@ V3Number& V3Number::opAbsS (const V3Number& lhs) {
|
||||
// op i, L(lhs) bit return
|
||||
if (lhs.isFourState()) return setAllBitsX();
|
||||
if (lhs.isNegative()) {
|
||||
return opUnaryMin(lhs);
|
||||
return opNegate(lhs);
|
||||
} else {
|
||||
return opAssign(lhs);
|
||||
}
|
||||
}
|
||||
V3Number& V3Number::opUnaryMin (const V3Number& lhs) {
|
||||
V3Number& V3Number::opNegate (const V3Number& lhs) {
|
||||
// op i, L(lhs) bit return
|
||||
if (lhs.isFourState()) return setAllBitsX();
|
||||
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
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
V3Number negrhs (rhs.m_fileline, rhs.width());
|
||||
negrhs.opUnaryMin(rhs);
|
||||
negrhs.opNegate(rhs);
|
||||
return opAdd(lhs, negrhs);
|
||||
}
|
||||
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) {
|
||||
// Signed multiply
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opMul(lhsNoSign,rhsNoSign);
|
||||
if ((lhs.isNegative() && !rhs.isNegative())
|
||||
|| (!lhs.isNegative() && rhs.isNegative())) {
|
||||
opUnaryMin(qNoSign);
|
||||
opNegate(qNoSign);
|
||||
} else {
|
||||
opAssign(qNoSign);
|
||||
}
|
||||
@@ -1169,13 +1204,13 @@ V3Number& V3Number::opDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
//UINFO(9, ">>divs-start "<<lhs<<" "<<rhs<<endl);
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opDiv(lhsNoSign,rhsNoSign);
|
||||
//UINFO(9, " >divs-mid "<<lhs<<" "<<rhs<<" "<<qNoSign<<endl);
|
||||
if ((lhs.isNegative() && !rhs.isNegative())
|
||||
|| (!lhs.isNegative() && rhs.isNegative())) {
|
||||
opUnaryMin(qNoSign);
|
||||
opNegate(qNoSign);
|
||||
} else {
|
||||
opAssign(qNoSign);
|
||||
}
|
||||
@@ -1198,11 +1233,11 @@ V3Number& V3Number::opModDivS (const V3Number& lhs, const V3Number& rhs) {
|
||||
// Signed moddiv
|
||||
if (lhs.isFourState() || rhs.isFourState()) return setAllBitsX();
|
||||
if (rhs.isEqZero()) return setAllBitsX();
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opUnaryMin(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opUnaryMin(rhs);
|
||||
V3Number lhsNoSign = lhs; if (lhs.isNegative()) lhsNoSign.opNegate(lhs);
|
||||
V3Number rhsNoSign = rhs; if (rhs.isNegative()) rhsNoSign.opNegate(rhs);
|
||||
V3Number qNoSign = opModDiv(lhsNoSign,rhsNoSign);
|
||||
if (lhs.isNegative()) { // Just lhs' sign (*DIFFERENT FROM PERL, which uses rhs sign*)
|
||||
opUnaryMin(qNoSign);
|
||||
opNegate(qNoSign);
|
||||
} else {
|
||||
opAssign(qNoSign);
|
||||
}
|
||||
@@ -1434,3 +1469,74 @@ V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3
|
||||
}
|
||||
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
@@ -35,13 +35,13 @@ class V3Number {
|
||||
int m_width; // Width as specified/calculated.
|
||||
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_double:1; // True if double real value
|
||||
bool m_fromString:1; // True if from string
|
||||
bool m_autoExtend:1; // True if SystemVerilog extend-to-any-width
|
||||
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_valueX; // Each bit is true if it's X or Z, 10=z, 11=x
|
||||
// METHODS
|
||||
void init(FileLine* fileline, int width);
|
||||
V3Number& setSingleBits(char value);
|
||||
void opCleanThis();
|
||||
public:
|
||||
@@ -50,6 +50,8 @@ public:
|
||||
V3Number& setZero();
|
||||
V3Number& setQuad(vluint64_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!
|
||||
if (bit>=m_width) return;
|
||||
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(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
|
||||
V3Number& setAllBitsX();
|
||||
V3Number& setAllBitsZ();
|
||||
@@ -132,6 +155,7 @@ public:
|
||||
bool autoExtend() const { return m_autoExtend; }
|
||||
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 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 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;}
|
||||
@@ -143,7 +167,6 @@ public:
|
||||
bool isEqAllOnes(int optwidth=0) const;
|
||||
bool isCaseEq(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; }
|
||||
bool isUnknown() const;
|
||||
uint32_t toUInt() const;
|
||||
@@ -151,6 +174,7 @@ public:
|
||||
vluint64_t toUQuad() const;
|
||||
vlsint64_t toSQuad() const;
|
||||
string toString() const;
|
||||
double toDouble() const;
|
||||
uint32_t toHash() const;
|
||||
uint32_t dataWord(int word) const;
|
||||
uint32_t countOnes() const;
|
||||
@@ -203,7 +227,7 @@ public:
|
||||
V3Number& opLogAnd (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opLogOr (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opAbsS (const V3Number& lhs);
|
||||
V3Number& opUnaryMin(const V3Number& lhs);
|
||||
V3Number& opNegate (const V3Number& lhs);
|
||||
V3Number& opAdd (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opSub (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& 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(); }
|
||||
|
||||
|
||||
@@ -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=="~") gotnum.opNot (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.opSub (lhnum,rhnum);
|
||||
else if (op=="*") gotnum.opMul (lhnum,rhnum);
|
||||
@@ -96,8 +96,8 @@ int main() {
|
||||
test("32'b0x","|","32'b10","32'b1x");
|
||||
test("32'b10","&","32'b11","32'b10");
|
||||
test("32'b10","+","32'b10","32'b100");
|
||||
test("3'b000","unaryMin","","3'b000");
|
||||
test("3'b001","unaryMin","","3'b111");
|
||||
test("3'b000","negate","","3'b000");
|
||||
test("3'b001","negate","","3'b111");
|
||||
test("32'b11","-","32'b001","32'b10");
|
||||
test("3'b000","-","3'b111","3'b001");
|
||||
test("3'b000","-","3'b000","3'b000");
|
||||
|
||||
+93
-46
@@ -51,17 +51,29 @@ struct V3OptionsImp {
|
||||
|
||||
// STATE
|
||||
list<string> m_allArgs; // List of every argument encountered
|
||||
list<string> m_incDirs; // Include directories (ordered)
|
||||
set<string> m_incDirSet; // Include directories (for removing duplicates)
|
||||
list<string> m_incDirUsers; // Include directories (ordered)
|
||||
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)
|
||||
set<string> m_libExtSet; // Library extensions (for removing duplicates)
|
||||
DirMap m_dirMap; // Directory listing
|
||||
|
||||
// ACCESSOR METHODS
|
||||
void addIncDir(const string& incdir) {
|
||||
if (m_incDirSet.find(incdir) == m_incDirSet.end()) {
|
||||
m_incDirSet.insert(incdir);
|
||||
m_incDirs.push_back(incdir);
|
||||
void addIncDirUser(const string& incdir) {
|
||||
if (m_incDirUserSet.find(incdir) == m_incDirUserSet.end()) {
|
||||
m_incDirUserSet.insert(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) {
|
||||
@@ -73,8 +85,11 @@ struct V3OptionsImp {
|
||||
V3OptionsImp() {}
|
||||
};
|
||||
|
||||
void V3Options::addIncDir(const string& incdir) {
|
||||
m_impp->addIncDir(incdir);
|
||||
void V3Options::addIncDirUser(const string& incdir) {
|
||||
m_impp->addIncDirUser(incdir);
|
||||
}
|
||||
void V3Options::addIncDirFallback(const string& incdir) {
|
||||
m_impp->addIncDirFallback(incdir);
|
||||
}
|
||||
void V3Options::addLibExt(const string& libext) {
|
||||
m_impp->addLibExt(libext);
|
||||
@@ -288,42 +303,68 @@ string V3Options::fileExists (const string& filename) {
|
||||
return filenameOut;
|
||||
}
|
||||
|
||||
string V3Options::filePath (FileLine* fl, const string& modname, const string& errmsg) {
|
||||
// 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_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);
|
||||
string exists = fileExists(fn);
|
||||
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);
|
||||
}
|
||||
}
|
||||
string V3Options::filePathCheckOneDir(const string& modname, const string& dirname) {
|
||||
for (list<string>::iterator extIter=m_impp->m_libExts.begin(); extIter!=m_impp->m_libExts.end(); ++extIter) {
|
||||
string fn = filenameFromDirBase(dirname, modname+*extIter);
|
||||
string exists = fileExists(fn);
|
||||
if (exists!="") {
|
||||
// Strip ./, it just looks ugly
|
||||
if (exists.substr(0,2)=="./") exists.erase(0,2);
|
||||
return exists;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (DIR* dirp = opendir(dir.c_str())) {
|
||||
while (struct dirent* direntp = readdir(dirp)) {
|
||||
@@ -528,6 +569,11 @@ string V3Options::version() {
|
||||
return ver;
|
||||
}
|
||||
|
||||
void V3Options::throwSigsegv() {
|
||||
// cppcheck-suppress nullPointer
|
||||
char* zp=NULL; *zp=0;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// V3 Options utilities
|
||||
|
||||
@@ -561,7 +607,7 @@ void V3Options::parseOpts (FileLine* fl, int argc, char** argv) {
|
||||
if (modPrefix()=="") m_modPrefix = prefix();
|
||||
|
||||
// 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+")));
|
||||
}
|
||||
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)) {
|
||||
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 ( !strcmp (sw, "-debug-abort") ) { abort(); } // Undocumented, see also --debug-sigsegv
|
||||
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 ( onoff (sw, "-dump-tree", flag/*ref*/) ) { m_dumpTree = 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]);
|
||||
}
|
||||
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 ) {
|
||||
shift;
|
||||
@@ -747,7 +793,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
}
|
||||
else if ( !strcmp (sw, "-Mdir") && (i+1)<argc ) {
|
||||
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 ) {
|
||||
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 ) {
|
||||
shift; addIncDir (parseFileArg(optdir,string (argv[i])));
|
||||
shift; addIncDirUser (parseFileArg(optdir,string (argv[i])));
|
||||
}
|
||||
else {
|
||||
fl->v3fatal ("Invalid Option: "<<argv[i]);
|
||||
@@ -973,6 +1019,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) {
|
||||
break; // Ignore to EOL
|
||||
} else if (*pos=='/' && *(pos+1)=='*') {
|
||||
inCmt = true;
|
||||
// cppcheck-suppress StlMissingComparison
|
||||
++pos;
|
||||
} else {
|
||||
oline += *pos;
|
||||
@@ -1127,7 +1174,7 @@ V3Options::V3Options() {
|
||||
addLibExt(".v");
|
||||
addLibExt(".sv");
|
||||
// Default -I
|
||||
addIncDir("."); // Looks better than {long_cwd_path}/...
|
||||
addIncDirFallback("."); // Looks better than {long_cwd_path}/...
|
||||
}
|
||||
|
||||
V3Options::~V3Options() {
|
||||
|
||||
+8
-2
@@ -178,10 +178,11 @@ class V3Options {
|
||||
|
||||
private:
|
||||
// METHODS
|
||||
void addArg(const string& incdir);
|
||||
void addArg(const string& flag);
|
||||
void addDefine(const string& defline);
|
||||
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 optimize(int level);
|
||||
void showVersion(bool verbose);
|
||||
@@ -189,6 +190,7 @@ class V3Options {
|
||||
bool onoff(const char* sw, const char* arg, bool& flag);
|
||||
bool suffixed(const char* sw, const char* arg);
|
||||
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 string getenvStr(const string& envvar, const string& defaultValue);
|
||||
@@ -345,8 +347,12 @@ class V3Options {
|
||||
// METHODS (file utilities using these options)
|
||||
string fileExists (const string& filename);
|
||||
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 fileStatNormal (const string& filename);
|
||||
|
||||
// METHODS (other OS)
|
||||
static void throwSigsegv();
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
+6
-3
@@ -148,7 +148,7 @@ private:
|
||||
|
||||
public:
|
||||
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(); }
|
||||
OrderLoopId inLoop() const { return m_inLoop; }
|
||||
AstSenTree* domainp() const { return m_domainp; }
|
||||
@@ -391,8 +391,8 @@ private:
|
||||
void nodeMarkCircular(OrderVarVertex* vertexp, OrderEdge* edgep) {
|
||||
AstVarScope* nodep = vertexp->varScp();
|
||||
nodep->circular(true);
|
||||
m_statCut[vertexp->type()]++;
|
||||
if (edgep) m_statCut[edgep->type()]++;
|
||||
++m_statCut[vertexp->type()];
|
||||
if (edgep) ++m_statCut[edgep->type()];
|
||||
if (vertexp->isClock()) {
|
||||
// Seems obvious; no warning yet
|
||||
//nodep->v3warn(GENCLK,"Signal unoptimizable: Generated clock: "<<nodep->prettyName());
|
||||
@@ -715,6 +715,9 @@ public:
|
||||
m_settleDomainp = NULL;
|
||||
m_settleVxp = NULL;
|
||||
m_inputsVxp = NULL;
|
||||
m_activeSenVxp = NULL;
|
||||
m_logicVxp = NULL;
|
||||
m_pomNewFuncp = NULL;
|
||||
m_loopIdMax = LOOPID_FIRST;
|
||||
m_pomNewStmts = 0;
|
||||
if (debug()) m_graph.debug(5); // 3 is default if global debug; we want acyc debugging
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ struct OrderVEdgeType {
|
||||
return names[m_e];
|
||||
}
|
||||
enum en m_e;
|
||||
inline OrderVEdgeType () {}
|
||||
inline OrderVEdgeType () : m_e(VERTEX_UNKNOWN) {}
|
||||
inline OrderVEdgeType (en _e) : m_e(_e) {}
|
||||
explicit inline OrderVEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
#include "V3Case.h"
|
||||
#include "V3Const.h"
|
||||
#include "V3Width.h"
|
||||
#include "V3Signed.h"
|
||||
#include "V3Unroll.h"
|
||||
|
||||
//######################################################################
|
||||
|
||||
+2
-1
@@ -45,7 +45,8 @@ public:
|
||||
|
||||
// METHODS
|
||||
// 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
|
||||
static void ppPushText(V3ParseImp* impp, const string& text);
|
||||
|
||||
+13
-4
@@ -89,7 +89,8 @@ size_t V3ParseImp::ppInputToLex(char* buf, size_t max_size) {
|
||||
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);
|
||||
|
||||
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
|
||||
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()) {
|
||||
// Create output file with all the preprocessor output we buffered up
|
||||
@@ -157,8 +165,9 @@ V3Parse::V3Parse(AstNetlist* rootp, V3InFilter* filterp) {
|
||||
V3Parse::~V3Parse() {
|
||||
delete m_impp; m_impp = NULL;
|
||||
}
|
||||
void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary) {
|
||||
m_impp->parseFile(fileline, modname, inLibrary);
|
||||
void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary,
|
||||
const string& errmsg) {
|
||||
m_impp->parseFile(fileline, modname, inLibrary, errmsg);
|
||||
}
|
||||
void V3Parse::ppPushText(V3ParseImp* impp, const string& text) {
|
||||
impp->ppPushText(text);
|
||||
|
||||
+12
-9
@@ -254,9 +254,10 @@ public:
|
||||
void verilatorCmtLintSave();
|
||||
void verilatorCmtLintRestore();
|
||||
void verilatorCmtBad(const char* text);
|
||||
double parseDouble(const char* text, size_t length);
|
||||
void pushBeginKeywords(int state) { m_inBeginKwd++; m_lastVerilogState=state; }
|
||||
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);
|
||||
|
||||
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
|
||||
FileLine* fileline() { return m_fileline; }
|
||||
AstNetlist* rootp() { return m_rootp; }
|
||||
FileLine* fileline() const { return m_fileline; }
|
||||
AstNetlist* rootp() const { return m_rootp; }
|
||||
FileLine* copyOrSameFileLine() { return fileline()->copyOrSameFileLine(); }
|
||||
bool inCellDefine() { return m_inCellDefine; }
|
||||
bool inCellDefine() const { return m_inCellDefine; }
|
||||
void inCellDefine(bool flag) { m_inCellDefine = flag; }
|
||||
bool inLibrary() { return m_inLibrary; }
|
||||
bool inLibrary() const { return m_inLibrary; }
|
||||
|
||||
// Interactions with parser
|
||||
int bisonParse();
|
||||
@@ -305,8 +306,8 @@ public:
|
||||
void lexDestroy();
|
||||
void stateExitPsl(); // Parser -> lexer communication
|
||||
void statePushVlg(); // Parser -> lexer communication
|
||||
void statePop(); // Parser -> lexer communication
|
||||
int stateVerilogRecent(); // Parser -> lexer communication
|
||||
void statePop(); // Parser -> lexer communication
|
||||
static int stateVerilogRecent(); // Parser -> lexer communication
|
||||
size_t flexPpInputToLex(char* buf, size_t max_size) { return ppInputToLex(buf,max_size); }
|
||||
|
||||
//==== Symbol tables
|
||||
@@ -315,7 +316,8 @@ public:
|
||||
public:
|
||||
// CREATORS
|
||||
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_inCellDefine = false;
|
||||
m_inLibrary = false;
|
||||
@@ -331,7 +333,8 @@ public:
|
||||
// Preprocess and read the Verilog file specified into the netlist database
|
||||
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:
|
||||
void lexFile(const string& modname);
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ public:
|
||||
void V3ParseImp::stateExitPsl() { parsep()->m_lexerp->stateExitPsl(); }
|
||||
void V3ParseImp::statePushVlg() { parsep()->m_lexerp->stateExitPsl(); }
|
||||
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
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ class V3PreLex {
|
||||
/// Called by V3PreProc.cpp to get data from lexer
|
||||
YY_BUFFER_STATE currentBuffer();
|
||||
int lex();
|
||||
int currentStartState();
|
||||
int currentStartState() const;
|
||||
void dumpSummary();
|
||||
void dumpStack();
|
||||
void unused();
|
||||
|
||||
+2
-1
@@ -488,7 +488,7 @@ YY_BUFFER_STATE V3PreLex::currentBuffer() {
|
||||
return YY_CURRENT_BUFFER;
|
||||
}
|
||||
|
||||
int V3PreLex::currentStartState() {
|
||||
int V3PreLex::currentStartState() const {
|
||||
return YY_START;
|
||||
}
|
||||
|
||||
@@ -538,6 +538,7 @@ void V3PreLex::unused() {
|
||||
if (0) {
|
||||
// Prevent unused warnings
|
||||
yy_top_state();
|
||||
yyerror((char*)"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -127,7 +127,7 @@ struct V3PreProcImp : public V3PreProc {
|
||||
ps_DEFNAME_IFDEF, ps_DEFNAME_IFNDEF, ps_DEFNAME_ELSIF,
|
||||
ps_DEFFORM, ps_DEFVALUE, ps_DEFPAREN, ps_DEFARG,
|
||||
ps_INCNAME, ps_ERRORNAME, ps_JOIN, ps_STRIFY };
|
||||
const char* procStateName(ProcState s) {
|
||||
static const char* procStateName(ProcState s) {
|
||||
static const char* states[]
|
||||
= {"ps_TOP",
|
||||
"ps_DEFNAME_UNDEF", "ps_DEFNAME_DEFINE",
|
||||
@@ -251,6 +251,10 @@ public:
|
||||
m_finAtBol = true;
|
||||
m_defDepth = 0;
|
||||
m_defPutJoin = false;
|
||||
m_finToken = 0;
|
||||
m_finFilelinep = NULL;
|
||||
m_lexp = NULL;
|
||||
m_preprocp = NULL;
|
||||
}
|
||||
void configure(FileLine* filelinep) {
|
||||
// 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")))) {
|
||||
cp+=strlen("cadence");
|
||||
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")))) {
|
||||
cp+=strlen("ambit synthesis");
|
||||
synth = true;
|
||||
|
||||
+4
-4
@@ -67,10 +67,10 @@ public:
|
||||
|
||||
// CONTROL METHODS
|
||||
// These options control how the parsing proceeds
|
||||
int keepComments() { return 2; } // Return comments, 0=no, 1=yes, 2=callback
|
||||
bool keepWhitespace() { return false; }
|
||||
bool lineDirectives() { return true; } // Insert `line directives
|
||||
bool pedantic() { return false; } // Obey standard; Don't substitute `error
|
||||
static int keepComments() { return 2; } // Return comments, 0=no, 1=yes, 2=callback
|
||||
static bool keepWhitespace() { return false; }
|
||||
static bool lineDirectives() { return true; } // Insert `line directives
|
||||
static bool pedantic() { return false; } // Obey standard; Don't substitute `error
|
||||
static bool optPsl();
|
||||
|
||||
// CALLBACK METHODS
|
||||
|
||||
+14
-6
@@ -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
|
||||
|
||||
// Preprocess the given module, putting output in vppFilename
|
||||
@@ -82,11 +83,14 @@ protected:
|
||||
|
||||
// Preprocess
|
||||
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()) {
|
||||
string line = s_preprocp->getline();
|
||||
V3Parse::ppPushText(parsep, line);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void preprocInclude (FileLine* fl, const string& modname) {
|
||||
@@ -96,17 +100,20 @@ protected:
|
||||
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,
|
||||
// then convert them properly.
|
||||
string ppmodname = s_preprocp->removeDefines (modname);
|
||||
|
||||
// Open include or master file
|
||||
string filename = v3Global.opt.filePath (fl, ppmodname, errmsg);
|
||||
if (filename=="") return; // Not found
|
||||
if (filename=="") return false; // Not found
|
||||
|
||||
UINFO(2," Reading "<<filename<<endl);
|
||||
s_preprocp->openFile(fl, filterp, filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
// CONSTRUCTORS
|
||||
@@ -124,8 +131,9 @@ V3InFilter* V3PreShellImp::s_filterp = NULL;
|
||||
void V3PreShell::boot(char** env) {
|
||||
V3PreShellImp::s_preImp.boot(env);
|
||||
}
|
||||
void V3PreShell::preproc(FileLine* fl, const string& modname, V3InFilter* filterp, V3ParseImp* parsep) {
|
||||
V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep);
|
||||
bool V3PreShell::preproc(FileLine* fl, const string& modname, V3InFilter* filterp,
|
||||
V3ParseImp* parsep, const string& errmsg) {
|
||||
return V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep, errmsg);
|
||||
}
|
||||
void V3PreShell::preprocInclude(FileLine* fl, const string& modname) {
|
||||
V3PreShellImp::s_preImp.preprocInclude(fl, modname);
|
||||
|
||||
+2
-1
@@ -36,7 +36,8 @@ class V3PreShell {
|
||||
// Static class for calling preprocessor
|
||||
public:
|
||||
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 string dependFiles() { return ""; } // Perl only
|
||||
static void defineCmdLine(const string& name, const string& value);
|
||||
|
||||
+6
-6
@@ -208,12 +208,12 @@ private:
|
||||
// Then over shifting gives the sign bit, not all zeros
|
||||
// Note *NOT* clean output -- just like normal shift!
|
||||
// Create equivalent of VL_SIGNONES_(node_width)
|
||||
constzerop = new AstUnaryMin (nodep->fileline(),
|
||||
new AstShiftR(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
new AstConst(nodep->fileline(),
|
||||
nodep->widthMin()-1),
|
||||
nodep->width()));
|
||||
constzerop = new AstNegate (nodep->fileline(),
|
||||
new AstShiftR(nodep->fileline(),
|
||||
nodep->lhsp()->cloneTree(false),
|
||||
new AstConst(nodep->fileline(),
|
||||
nodep->widthMin()-1),
|
||||
nodep->width()));
|
||||
} else {
|
||||
V3Number zeronum (nodep->fileline(), nodep->width(), 0);
|
||||
constzerop = new AstConst(nodep->fileline(), zeronum);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
+8
-4
@@ -53,6 +53,7 @@ class SliceCloneVisitor : public AstNVisitor {
|
||||
// Inputs:
|
||||
// AstArraySel::user1p() -> AstVarRef. The VarRef that the final ArraySel points to
|
||||
// AstNodeAssign::user2() -> int. The number of clones needed for this assign
|
||||
// AstArraySel::user3() -> bool. Error detected
|
||||
|
||||
// ENUMS
|
||||
enum RedOp { // The type of unary operation to be expanded
|
||||
@@ -221,6 +222,7 @@ class SliceVisitor : public AstNVisitor {
|
||||
// AstNode::user2() -> int. The number of clones needed for this node
|
||||
AstUser1InUse m_inuser1;
|
||||
AstUser2InUse m_inuser2;
|
||||
AstUser3InUse m_inuser3;
|
||||
|
||||
// TYPEDEFS
|
||||
typedef pair<uint32_t, uint32_t> ArrayDimensions; // Array Dimensions (packed, unpacked)
|
||||
@@ -328,11 +330,11 @@ class SliceVisitor : public AstNVisitor {
|
||||
m_assignp->v3error("Unsupported: Assignment between a constant and an array slice");
|
||||
m_assignError = true;
|
||||
}
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
|
||||
virtual void visit(AstArraySel* nodep, AstNUser*) {
|
||||
if (!m_assignp) return;
|
||||
if (nodep->user3()) return; // Prevent recursion on just created nodes
|
||||
unsigned dim = explicitDimensions(nodep);
|
||||
AstVarRef* refp = nodep->user1p()->castNode()->castVarRef();
|
||||
pair<uint32_t,uint32_t> arrDim = refp->varp()->dimensions();
|
||||
@@ -340,16 +342,18 @@ class SliceVisitor : public AstNVisitor {
|
||||
if (implicit > 0) {
|
||||
AstArraySel* newp = insertImplicit(nodep->cloneTree(false), dim+1, implicit);
|
||||
nodep->replaceWith(newp); nodep = newp;
|
||||
nodep->user3(true);
|
||||
}
|
||||
int clones = countClones(nodep);
|
||||
if (m_assignp->user2() > 0 && m_assignp->user2() != clones) {
|
||||
m_assignp->v3error("Slices of arrays in assignments must have the same unpacked dimensions");
|
||||
} else if (m_assignp->user2() == 0 && !m_assignError) {
|
||||
if (m_extend && clones > 1) {
|
||||
} else if (!m_assignp->user2()) {
|
||||
if (m_extend && clones > 1 && !m_assignError) {
|
||||
m_assignp->v3error("Unsupported: Assignment between packed arrays of different dimensions");
|
||||
m_assignError = true;
|
||||
}
|
||||
if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp() && !m_assignp->castAssignDly()) {
|
||||
if (clones > 1 && !refp->lvalue() && refp->varp() == m_lhsVarRefp->varp()
|
||||
&& !m_assignp->castAssignDly() && !m_assignError) {
|
||||
// LHS Var != RHS Var for a non-delayed assignment
|
||||
m_assignp->v3error("Unsupported: Slices in a non-delayed assignment with the same Var on both sides");
|
||||
m_assignError = true;
|
||||
|
||||
+25
-9
@@ -229,6 +229,7 @@ private:
|
||||
|
||||
// STATE
|
||||
bool m_reorder; // Reorder statements vs. just splitting
|
||||
string m_noReorderWhy; // Reason we can't reorder
|
||||
VStack m_stmtStackps; // Current statements being tracked
|
||||
SplitPliVertex* m_pliVertexp; // Element specifying PLI ordering
|
||||
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
||||
@@ -249,6 +250,7 @@ private:
|
||||
m_graph.clear();
|
||||
m_stmtStackps.clear();
|
||||
m_pliVertexp = NULL;
|
||||
m_noReorderWhy = "";
|
||||
AstNode::user1ClearTree();
|
||||
AstNode::user2ClearTree();
|
||||
AstNode::user3ClearTree();
|
||||
@@ -336,6 +338,7 @@ private:
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Add hard orderings between all nodes of same color, in the order they appeared
|
||||
@@ -413,7 +416,7 @@ private:
|
||||
newListp = newListp->addNext(nextp);
|
||||
}
|
||||
if (splitAlwaysp) {
|
||||
m_statSplits++;
|
||||
++m_statSplits;
|
||||
AstAlways* alwaysp = new AstAlways(newListp->fileline(), NULL, NULL);
|
||||
addAfterp->addNextHere(alwaysp); addAfterp=alwaysp;
|
||||
alwaysp->addStmtp(newListp);
|
||||
@@ -445,14 +448,18 @@ private:
|
||||
UINFO(9," processBlock "<<nodep<<endl);
|
||||
// Process block and followers
|
||||
scanBlock(nodep);
|
||||
// Reorder statements in this block
|
||||
cleanupBlockGraph(nodep);
|
||||
reorderBlock(nodep);
|
||||
// Delete old vertexes and edges only applying to this block
|
||||
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);
|
||||
if (m_noReorderWhy != "") { // Jump or something nasty
|
||||
UINFO(9," NoReorderBlock because "<<m_noReorderWhy<<endl);
|
||||
} else {
|
||||
// Reorder statements in this block
|
||||
cleanupBlockGraph(nodep);
|
||||
reorderBlock(nodep);
|
||||
// Delete old vertexes and edges only applying to this block
|
||||
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.
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -185,7 +185,7 @@ private:
|
||||
// Now isolate the always
|
||||
if (m_splitVscp) {
|
||||
splitAlways(nodep);
|
||||
m_statSplits++;
|
||||
++m_statSplits;
|
||||
} else {
|
||||
nodep->user1(true);
|
||||
}
|
||||
|
||||
+1
-1
@@ -309,7 +309,7 @@ private:
|
||||
if (debug()>5) newp->dumpTree(cout," w_new: ");
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
m_statSubsts++;
|
||||
++m_statSubsts;
|
||||
}
|
||||
virtual void visit(AstWordSel* nodep, AstNUser*) {
|
||||
nodep->rhsp()->accept(*this);
|
||||
|
||||
+2
-2
@@ -176,8 +176,8 @@ public:
|
||||
private:
|
||||
void createTable(AstAlways* nodep) {
|
||||
// We've determined this table of nodes is optimizable, do it.
|
||||
m_modTables++;
|
||||
m_statTablesCre++;
|
||||
++m_modTables;
|
||||
++m_statTablesCre;
|
||||
|
||||
// Index into our table
|
||||
AstVar* indexVarp = new AstVar (nodep->fileline(), AstVarType::BLOCKTEMP,
|
||||
|
||||
+20
-5
@@ -408,6 +408,7 @@ private:
|
||||
AstAssign* assp = new AstAssign (pinp->fileline(),
|
||||
pinp,
|
||||
new AstVarRef(outvscp->fileline(), outvscp, false));
|
||||
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
|
||||
// Put assignment BEHIND of all other statements
|
||||
beginp->addNext(assp);
|
||||
}
|
||||
@@ -418,6 +419,7 @@ private:
|
||||
AstAssign* assp = new AstAssign (pinp->fileline(),
|
||||
new AstVarRef(inVscp->fileline(), inVscp, true),
|
||||
pinp);
|
||||
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
|
||||
// Put assignment in FRONT of all other statements
|
||||
if (AstNode* afterp = beginp->nextp()) {
|
||||
afterp->unlinkFrBackWithNext();
|
||||
@@ -507,6 +509,7 @@ private:
|
||||
AstAssign* assp = new AstAssign (pinp->fileline(),
|
||||
pinp,
|
||||
new AstVarRef(outvscp->fileline(), outvscp, false));
|
||||
assp->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); // Ok if in <= block
|
||||
// Put assignment BEHIND of all other statements
|
||||
beginp->addNext(assp);
|
||||
}
|
||||
@@ -587,8 +590,12 @@ private:
|
||||
// Someday we'll have better type support, and this can make variables and casts.
|
||||
// But for now, we'll just text-bash it.
|
||||
if (bitvec) {
|
||||
// We only support quads, so don't need to sweat longer stuff
|
||||
stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")";
|
||||
if (portp->isWide()) {
|
||||
stmt += ("VL_SET_SVBV_W("+cvtToStr(portp->width())
|
||||
+", "+portp->name()+toSuffix+", "+portp->name()+frSuffix+")");
|
||||
} else {
|
||||
stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")";
|
||||
}
|
||||
} else {
|
||||
if (isPtr) stmt += "*"; // DPI outputs are pointers
|
||||
stmt += portp->name()+toSuffix+" = ";
|
||||
@@ -605,7 +612,7 @@ private:
|
||||
return new AstCStmt(portp->fileline(), stmt);
|
||||
}
|
||||
|
||||
AstNode* createAssignDpiToInternal(AstVarScope* portvscp, const string& frName) {
|
||||
AstNode* createAssignDpiToInternal(AstVarScope* portvscp, const string& frName, bool cvt) {
|
||||
// Create assignment from DPI temporary into internal format
|
||||
AstVar* portp = portvscp->varp();
|
||||
string stmt;
|
||||
@@ -614,6 +621,14 @@ private:
|
||||
stmt += "VL_CVT_VP_Q(";
|
||||
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
|
||||
&& 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 += frName;
|
||||
stmt += ket;
|
||||
// Use a AstCMath, as we want V3Clean to mask off bits that don't make sense.
|
||||
@@ -680,7 +695,7 @@ private:
|
||||
argnodesp = argnodesp->addNextNull(refp);
|
||||
|
||||
if (portp->isInput()) {
|
||||
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name()));
|
||||
dpip->addStmtsp(createAssignDpiToInternal(outvscp, portp->name(), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -795,7 +810,7 @@ private:
|
||||
if (AstVar* portp = stmtp->castVar()) {
|
||||
if (portp->isIO() && (portp->isOutput() || portp->isFuncReturn())) {
|
||||
AstVarScope* portvscp = portp->user2p()->castNode()->castVarScope(); // Remembered when we created it earlier
|
||||
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt"));
|
||||
cfuncp->addStmtsp(createAssignDpiToInternal(portvscp,portp->name()+"__Vcvt",true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -71,19 +71,19 @@ class TraceActivityVertex : public V3GraphVertex {
|
||||
bool m_activityCodeValid;
|
||||
bool m_slow; // If always slow, we can use the same code
|
||||
public:
|
||||
enum { ACTIVITY_NEVER =((1UL<<31) - 1) };
|
||||
enum { ACTIVITY_ALWAYS=((1UL<<31) - 2) };
|
||||
enum { ACTIVITY_SLOW=0 };
|
||||
TraceActivityVertex(V3Graph* graphp, AstNode* nodep, bool slow)
|
||||
: V3GraphVertex(graphp), m_insertp(nodep) {
|
||||
m_activityCode = 0;
|
||||
m_activityCodeValid = false;
|
||||
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)
|
||||
: V3GraphVertex(graphp) {
|
||||
activityCode(code);
|
||||
: V3GraphVertex(graphp), m_insertp(NULL) {
|
||||
m_activityCode = code;
|
||||
m_activityCodeValid = true;
|
||||
m_slow = false;
|
||||
}
|
||||
virtual ~TraceActivityVertex() {}
|
||||
@@ -484,7 +484,7 @@ private:
|
||||
nodep->code(m_code);
|
||||
m_code += nodep->codeInc();
|
||||
m_statUniqCodes += nodep->codeInc();
|
||||
m_statUniqSigs++;
|
||||
++m_statUniqSigs;
|
||||
}
|
||||
return nodep->code();
|
||||
}
|
||||
@@ -517,7 +517,7 @@ private:
|
||||
if (!codePreassigned) {
|
||||
// Add to trace cfuncs
|
||||
if (needChg) {
|
||||
m_statChgSigs++;
|
||||
++m_statChgSigs;
|
||||
incAddp = nodep->cloneTree(true);
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -103,6 +103,7 @@ private:
|
||||
} else {
|
||||
basep->v3fatalSrc("Strange base function type");
|
||||
}
|
||||
// cppcheck-suppress nullPointer // above fatal prevents it
|
||||
AstCCall* callp = new AstCCall(funcp->fileline(), funcp);
|
||||
callp->argTypes("vlSymsp, vcdp, code");
|
||||
basep->addStmtsp(callp);
|
||||
@@ -137,12 +138,12 @@ private:
|
||||
if (showname.substr(0,4) == "TOP ") showname.replace(0,4,"");
|
||||
if (!m_initSubFuncp) nodep->v3fatalSrc("NULL");
|
||||
if (varIgnoreTrace(varp)) {
|
||||
m_statIgnSigs++;
|
||||
++m_statIgnSigs;
|
||||
m_initSubFuncp->addStmtsp(
|
||||
new AstComment(nodep->fileline(),
|
||||
"Tracing: "+showname+" // Ignored: "+varIgnoreTrace(varp)));
|
||||
} else {
|
||||
m_statSigs++;
|
||||
++m_statSigs;
|
||||
AstNode* valuep = NULL;
|
||||
if (nodep->valuep()) valuep=nodep->valuep()->cloneTree(true);
|
||||
else valuep = new AstVarRef(nodep->fileline(), nodep, false);
|
||||
|
||||
+15
-4
@@ -76,8 +76,8 @@ public:
|
||||
private:
|
||||
// METHODS
|
||||
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 drivenFlag(int bit) { return m_drivenWhole || m_flags[bit*FLAGS_PER_BIT + FLAG_DRIVEN]; }
|
||||
inline bool usedFlag(int bit) const { return m_usedWhole || m_flags[bit*FLAGS_PER_BIT + FLAG_USED]; }
|
||||
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 };
|
||||
string bitNames(BitNamesWhich which) {
|
||||
string bits="";
|
||||
@@ -217,6 +217,7 @@ private:
|
||||
// STATE
|
||||
vector<UndrivenVarEntry*> m_entryps; // Nodes to delete when we are finished
|
||||
bool m_markBoth; // Mark as driven+used
|
||||
AstNodeFTask* m_taskp; // Current task
|
||||
|
||||
// METHODS
|
||||
static int debug() {
|
||||
@@ -241,12 +242,14 @@ private:
|
||||
virtual void visit(AstVar* nodep, AstNUser*) {
|
||||
UndrivenVarEntry* entryp = getEntryp (nodep);
|
||||
if (nodep->isInput()
|
||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()) {
|
||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
||||
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
||||
entryp->drivenWhole();
|
||||
}
|
||||
if (nodep->isOutput()
|
||||
|| nodep->isSigPublic() || nodep->isSigUserRWPublic()
|
||||
|| nodep->isSigUserRdPublic()) {
|
||||
|| nodep->isSigUserRdPublic()
|
||||
|| (m_taskp && (m_taskp->dpiImport() || m_taskp->dpiExport()))) {
|
||||
entryp->usedWhole();
|
||||
}
|
||||
// Discover variables used in bit definitions, etc
|
||||
@@ -284,6 +287,13 @@ private:
|
||||
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
|
||||
virtual void visit(AstPrimitive* nodep, AstNUser*) {}
|
||||
|
||||
@@ -303,6 +313,7 @@ public:
|
||||
// CONSTUCTORS
|
||||
UndrivenVisitor(AstNetlist* nodep) {
|
||||
m_markBoth = false;
|
||||
m_taskp = NULL;
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~UndrivenVisitor() {
|
||||
|
||||
+1
-1
@@ -289,7 +289,7 @@ private:
|
||||
AstVar* newvarp
|
||||
= new AstVar (nodep->fileline(), AstVarType::XTEMP, newvarname,
|
||||
AstLogicPacked(), nodep->width());
|
||||
m_statUnkVars++;
|
||||
++m_statUnkVars;
|
||||
AstNRelinker replaceHandle;
|
||||
nodep->unlinkFrBack(&replaceHandle);
|
||||
AstNodeVarRef* newref1p = new AstVarRef(nodep->fileline(), newvarp, false);
|
||||
|
||||
+5
-2
@@ -241,14 +241,17 @@ private:
|
||||
}
|
||||
if (precondsp) {
|
||||
precondsp->unlinkFrBackWithNext();
|
||||
// cppcheck-suppress nullPointer // addNextNull deals with it
|
||||
stmtsp = stmtsp->addNextNull(precondsp);
|
||||
}
|
||||
if (bodysp) {
|
||||
bodysp->unlinkFrBackWithNext();
|
||||
// cppcheck-suppress nullPointer // addNextNull deals with it
|
||||
stmtsp = stmtsp->addNextNull(bodysp); // Maybe null if no body
|
||||
}
|
||||
if (incp && !nodep->castGenFor()) { // Generates don't need to increment loop index
|
||||
incp->unlinkFrBackWithNext();
|
||||
// cppcheck-suppress nullPointer // addNextNull deals with it
|
||||
stmtsp = stmtsp->addNextNull(incp); // Maybe null if no body
|
||||
}
|
||||
// Mark variable to disable some later warnings
|
||||
@@ -259,7 +262,7 @@ private:
|
||||
loopValue.opAssign(numInit);
|
||||
|
||||
AstNode* newbodysp = NULL;
|
||||
m_statLoops++;
|
||||
++m_statLoops;
|
||||
if (stmtsp) {
|
||||
int times = 0;
|
||||
while (1) {
|
||||
@@ -287,7 +290,7 @@ private:
|
||||
if (newbodysp) newbodysp->addNext(oneloopp);
|
||||
else newbodysp = oneloopp;
|
||||
|
||||
m_statIters++;
|
||||
++m_statIters;
|
||||
if (++times > unrollCount()*3) {
|
||||
nodep->v3error("Loop unrolling took too long; probably this is an infinite loop, or set --unroll-count above "<<unrollCount());
|
||||
break;
|
||||
|
||||
+1079
-558
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,6 @@ public:
|
||||
static void width(AstNetlist* nodep);
|
||||
// Smaller step... Only do a single node for parameter propagation
|
||||
static AstNode* widthParamsEdit(AstNode* nodep);
|
||||
static AstNode* widthParamsEditIfNeed(AstNode* nodep);
|
||||
// Final step... Mark all widths as equal
|
||||
static void widthCommit(AstNetlist* nodep);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user