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 |
@@ -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)
|
||||
|
||||
+95
-37
@@ -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
|
||||
@@ -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>...
|
||||
|
||||
@@ -715,7 +721,8 @@ Backward compatible alias for "--pins-bv 65". Note that's a 65, not a 64.
|
||||
Specifies SystemC inputs/outputs of greater than or equal to I<width> bits
|
||||
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
|
||||
@@ -936,8 +943,8 @@ enabled), but do not affect style messages. This is equivalent to
|
||||
=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) {
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -2375,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
|
||||
@@ -2948,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
|
||||
@@ -3145,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?
|
||||
|
||||
|
||||
@@ -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([])
|
||||
|
||||
@@ -333,7 +333,9 @@ void _vl_vsformat(string& output, const char* formatp, va_list ap) {
|
||||
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);
|
||||
@@ -596,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);
|
||||
@@ -924,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;
|
||||
@@ -1079,6 +1103,7 @@ VerilatedScope::VerilatedScope() {
|
||||
m_callbacksp = NULL;
|
||||
m_namep = NULL;
|
||||
m_funcnumMax = 0;
|
||||
m_symsp = NULL;
|
||||
m_varsp = NULL;
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -349,6 +349,10 @@ 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
|
||||
@@ -383,9 +387,9 @@ static inline QData VL_CVT_Q_D(double lhs) { union { double d; QData q; } u; u.
|
||||
/// 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)(trunc(lhs))); }
|
||||
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)(round(lhs))); }
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -98,7 +98,9 @@ class VerilatedVpioCb : public VerilatedVpio {
|
||||
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() {}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
-13
@@ -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
|
||||
@@ -250,8 +253,6 @@ $(TGT): V3Ast__gen_classes.h $(OBJS)
|
||||
@echo " Linking $@..."
|
||||
-rm -rf $@ [email protected]
|
||||
${LINK} ${LDFLAGS} -o $@ $(OBJS) $(CCMALLOC) ${LIBS}
|
||||
@-(cp [email protected] $@ || true)
|
||||
# ok if cp failes on linux, it's there to insure executable works on NT
|
||||
|
||||
V3Number_test: V3Number_test.o
|
||||
${LINK} ${LDFLAGS} -o $@ $^ ${LIBS}
|
||||
@@ -262,9 +263,9 @@ V3Number_test: V3Number_test.o
|
||||
$(PERL) $(ASTGEN) -I$(srcdir) $*.cpp
|
||||
|
||||
%.o: %.cpp
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGS} -c $<
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGSWALL} -c $<
|
||||
%.o: %.c
|
||||
$(OBJCACHE) ${CC} ${CPPFLAGS} -c $<
|
||||
$(OBJCACHE) ${CC} ${CPPFLAGSWALL} -c $<
|
||||
|
||||
V3ParseLex.o: V3ParseLex.cpp V3Lexer.yy.cpp V3ParseBison.c
|
||||
$(OBJCACHE) ${CXX} ${CPPFLAGSNOWALL} -c $<
|
||||
|
||||
+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*) {
|
||||
|
||||
+2
-2
@@ -430,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] ":"");
|
||||
@@ -947,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();
|
||||
|
||||
+24
-13
@@ -27,6 +27,7 @@
|
||||
#include "V3Error.h"
|
||||
#include "V3Number.h"
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "V3Ast__gen_classes.h" // From ./astgen
|
||||
// Things like:
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
inline AstNumeric () {}
|
||||
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; }
|
||||
@@ -89,6 +90,7 @@ public:
|
||||
class AstPragmaType {
|
||||
public:
|
||||
enum en {
|
||||
ILLEGAL,
|
||||
COVERAGE_BLOCK_OFF,
|
||||
INLINE_MODULE,
|
||||
NO_INLINE_MODULE,
|
||||
@@ -97,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; }
|
||||
@@ -120,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; }
|
||||
@@ -188,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; }
|
||||
@@ -202,6 +204,7 @@ public:
|
||||
class AstAttrType {
|
||||
public:
|
||||
enum en {
|
||||
ILLEGAL,
|
||||
EXPR_BITS, // V3Const converts to constant
|
||||
//
|
||||
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
||||
@@ -212,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; }
|
||||
@@ -238,6 +242,7 @@ public:
|
||||
class AstBasicDTypeKwd {
|
||||
public:
|
||||
enum en {
|
||||
UNKNOWN,
|
||||
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
|
||||
DOUBLE, SHORTINT, FLOAT, TIME,
|
||||
// Closer to a class type, but limited usage
|
||||
@@ -250,6 +255,7 @@ public:
|
||||
enum en m_e;
|
||||
const char* ascii() const {
|
||||
static const char* names[] = {
|
||||
"%E-unk",
|
||||
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
||||
"real", "shortint", "shortreal", "time",
|
||||
"string",
|
||||
@@ -260,6 +266,7 @@ public:
|
||||
};
|
||||
const char* dpiType() const {
|
||||
static const char* names[] = {
|
||||
"%E-unk",
|
||||
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
||||
"double", "short int", "float", "long long",
|
||||
"const char*",
|
||||
@@ -268,7 +275,7 @@ public:
|
||||
};
|
||||
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; }
|
||||
@@ -351,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; }
|
||||
@@ -409,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; }
|
||||
@@ -431,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; }
|
||||
@@ -641,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;}
|
||||
|
||||
@@ -754,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:
|
||||
@@ -819,6 +827,7 @@ public:
|
||||
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
|
||||
|
||||
@@ -945,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);
|
||||
@@ -1012,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) { }
|
||||
};
|
||||
|
||||
@@ -1274,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) { }
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
@@ -501,7 +501,7 @@ 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();
|
||||
|
||||
+138
-32
@@ -461,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?
|
||||
@@ -587,6 +587,7 @@ 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_fileDescr:1; // File descriptor
|
||||
@@ -601,7 +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_attrClockEn=false; m_attrScBv=false; m_attrIsolateAssign=false; m_attrSFormat=false;
|
||||
m_fileDescr=false; m_isConst=false; m_isStatic=false;
|
||||
m_trace=false;
|
||||
}
|
||||
@@ -664,6 +665,7 @@ 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 usedClock(bool flag) { m_usedClock = flag; }
|
||||
@@ -724,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; }
|
||||
@@ -970,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)
|
||||
@@ -1457,15 +1468,6 @@ struct AstCondBound : public AstNodeCond {
|
||||
ASTNODE_NODE_FUNCS(CondBound, CONDBOUND)
|
||||
};
|
||||
|
||||
struct AstCondD : public AstNodeCond {
|
||||
// Conditional ?: statement, double rhs/lhs/out
|
||||
// Parents: MATH
|
||||
// Children: MATH
|
||||
AstCondD(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
||||
: AstNodeCond(fl, condp, expr1p, expr2p) { numeric(AstNumeric::DOUBLE); }
|
||||
ASTNODE_NODE_FUNCS(CondD, CONDD)
|
||||
};
|
||||
|
||||
struct AstCoverDecl : public AstNodeStmt {
|
||||
// Coverage analysis point declaration
|
||||
// Parents: {statement list}
|
||||
@@ -1893,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
|
||||
@@ -2832,6 +2873,90 @@ struct AstFGetC : public AstNodeUniop {
|
||||
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
|
||||
|
||||
@@ -3465,7 +3590,7 @@ struct AstBufIf1 : public AstNodeBiop {
|
||||
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 "";} // Lclean || Rclean
|
||||
virtual string emitSimpleOperator() { V3ERROR_NA; return false;} // Lclean || Rclean
|
||||
virtual string emitSimpleOperator() { V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
virtual bool cleanOut() {V3ERROR_NA; return "";} // Lclean || Rclean
|
||||
virtual bool cleanLhs() {return false;} virtual bool cleanRhs() {return false;}
|
||||
virtual bool sizeMattersLhs() {return false;} virtual bool sizeMattersRhs() {return false;}
|
||||
@@ -3904,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;
|
||||
|
||||
+2
-2
@@ -452,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;
|
||||
}
|
||||
}
|
||||
|
||||
+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();
|
||||
|
||||
+8
-2
@@ -821,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");
|
||||
@@ -852,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;
|
||||
@@ -1534,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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+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);
|
||||
|
||||
+30
-3
@@ -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()); }
|
||||
@@ -361,6 +361,30 @@ public:
|
||||
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,7 +570,7 @@ public:
|
||||
}
|
||||
ofp()->printf(",0x%08" VL_PRI64 "x)", (vluint64_t)(nodep->num().dataWord(0)));
|
||||
} else if (nodep->isDouble()) {
|
||||
ofp()->printf("%g", nodep->num().toDouble());
|
||||
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);
|
||||
@@ -830,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);
|
||||
@@ -1424,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) {
|
||||
|
||||
+2
-2
@@ -526,8 +526,8 @@ void EmitCSyms::emitDpiHdr() {
|
||||
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()) {
|
||||
|
||||
+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
|
||||
|
||||
+59
-18
@@ -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
|
||||
@@ -90,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)) {}
|
||||
@@ -102,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",
|
||||
@@ -126,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() ); }
|
||||
|
||||
@@ -140,7 +146,8 @@ public:
|
||||
|| 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
|
||||
@@ -244,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); }
|
||||
@@ -279,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;
|
||||
@@ -291,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); }
|
||||
@@ -300,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
|
||||
@@ -315,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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -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();
|
||||
|
||||
+7
-2
@@ -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);
|
||||
|
||||
@@ -65,7 +65,7 @@ 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()
|
||||
|
||||
@@ -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*) {
|
||||
|
||||
+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);
|
||||
|
||||
+8
-24
@@ -25,6 +25,7 @@
|
||||
#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)
|
||||
@@ -33,28 +34,10 @@
|
||||
// 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_double = 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) {
|
||||
@@ -355,6 +338,7 @@ string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
|
||||
ostringstream out;
|
||||
|
||||
if (isDouble()) {
|
||||
out.precision(17);
|
||||
out<<toDouble();
|
||||
return out.str();
|
||||
}
|
||||
@@ -416,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[0]=='.'); pos++) {
|
||||
for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); ++pos) {
|
||||
fmtsize += pos[0];
|
||||
}
|
||||
string str;
|
||||
@@ -1493,12 +1477,12 @@ V3Number& V3Number::opIToRD (const V3Number& lhs) {
|
||||
return setDouble(lhs.toSInt());
|
||||
}
|
||||
V3Number& V3Number::opRToIS (const V3Number& lhs) {
|
||||
double v = trunc(lhs.toDouble());
|
||||
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 = round(lhs.toDouble());
|
||||
double v = VL_ROUND(lhs.toDouble());
|
||||
vlsint32_t i = (vlsint32_t)v; // C converts from double to vlsint32
|
||||
return setLongS(i);
|
||||
}
|
||||
|
||||
+21
-2
@@ -42,7 +42,6 @@ class V3Number {
|
||||
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:
|
||||
@@ -118,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();
|
||||
@@ -147,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;
|
||||
|
||||
+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; }
|
||||
|
||||
+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);
|
||||
|
||||
+11
-9
@@ -257,7 +257,7 @@ public:
|
||||
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); }
|
||||
@@ -291,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();
|
||||
@@ -306,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
|
||||
@@ -316,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;
|
||||
@@ -332,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*)"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-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
|
||||
|
||||
+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);
|
||||
|
||||
+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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -618,6 +621,11 @@ 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
|
||||
|
||||
+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;
|
||||
|
||||
+42
-17
@@ -208,6 +208,13 @@ private:
|
||||
virtual void visit(AstPowD* nodep, AstNUser* vup) { visit_math_Or_LRr(nodep,vup); }
|
||||
// Signed/Real: Output real or signed iff LHS signed/real
|
||||
virtual void visit(AstNegateD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
|
||||
// Real: Output real
|
||||
virtual void visit(AstCeilD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
|
||||
virtual void visit(AstExpD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
|
||||
virtual void visit(AstFloorD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
|
||||
virtual void visit(AstLogD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
|
||||
virtual void visit(AstLog10D* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
|
||||
virtual void visit(AstSqrtD* nodep, AstNUser* vup) { visit_math_Or_Lr(nodep,vup); }
|
||||
|
||||
// Widths: out signed/unsigned width = lhs width, input un|signed
|
||||
virtual void visit(AstSigned* nodep, AstNUser* vup) { visit_Ous_Lus_Wforce(nodep,vup,AstNumeric::SIGNED); }
|
||||
@@ -642,10 +649,11 @@ private:
|
||||
V3Width::widthParamsEdit(nodep->dtypep()); // MAY CHANGE dtypep()
|
||||
AstBasicDType* basicp = nodep->dtypep()->basicp(); if (!basicp) nodep->v3fatalSrc("Unimplemented: Casting non-simple data type");
|
||||
nodep->widthSignedFrom(basicp);
|
||||
AstNode* newp = nodep->lhsp()->unlinkFrBack();
|
||||
if (!basicp->isDouble() && !newp->isDouble()) {
|
||||
widthCheck(nodep,"Cast",newp,nodep->width(),nodep->width(),true);
|
||||
if (!basicp->isDouble() && !nodep->lhsp()->isDouble()) {
|
||||
// Note widthCheck might modify nodep->lhsp()
|
||||
widthCheck(nodep,"Cast",nodep->lhsp(),nodep->width(),nodep->width(),true);
|
||||
}
|
||||
AstNode* newp = nodep->lhsp()->unlinkFrBack();
|
||||
if (basicp->numeric() == newp->numeric()) {
|
||||
newp = newp; // Can just remove cast
|
||||
} else if (basicp->isDouble() && !newp->isDouble()) {
|
||||
@@ -687,7 +695,7 @@ private:
|
||||
bool implicitParam = nodep->isParam() && bdtypep && bdtypep->implicit();
|
||||
if (implicitParam) {
|
||||
AstNumeric rs = AstNumeric::UNSIGNED;
|
||||
int width=0; int mwidth=0;
|
||||
int width=0;
|
||||
if (nodep->valuep()) {
|
||||
nodep->valuep()->iterateAndNext(*this,WidthVP(width,0,PRELIM).p());
|
||||
// Although nodep will get a different width for parameters just below,
|
||||
@@ -697,11 +705,10 @@ private:
|
||||
rs = nodep->numeric();
|
||||
if (!rs.isDouble()) {
|
||||
if (nodep->valuep()->widthSized()) {
|
||||
width = mwidth = nodep->valuep()->width();
|
||||
width = nodep->valuep()->width();
|
||||
} else {
|
||||
if (nodep->valuep()->width()>32) nodep->valuep()->v3warn(WIDTH,"Assigning >32 bit to unranged parameter (defaults to 32 bits)");
|
||||
width = 32;
|
||||
mwidth = nodep->valuep()->widthMin();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1034,6 +1041,14 @@ private:
|
||||
virtual void visit(AstSysIgnore* nodep, AstNUser* vup) {
|
||||
nodep->exprsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
}
|
||||
virtual void visit(AstSystemF* nodep, AstNUser*) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->numeric(AstNumeric::UNSIGNED);
|
||||
nodep->width(32,32);
|
||||
}
|
||||
virtual void visit(AstSystemT* nodep, AstNUser*) {
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
}
|
||||
virtual void visit(AstReadMem* nodep, AstNUser*) {
|
||||
nodep->filenamep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->memp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
@@ -1130,6 +1145,13 @@ private:
|
||||
}
|
||||
virtual void visit(AstCell* nodep, AstNUser*) {
|
||||
if (!m_paramsOnly) {
|
||||
if (nodep->modp()->castNotFoundModule()) {
|
||||
// We've resolved parameters and hit a module that we couldn't resolve. It's
|
||||
// finally time to report it.
|
||||
// Note only here in V3Width as this is first visitor after V3Dead.
|
||||
nodep->v3error("Cannot find file containing module: "<<nodep->modName());
|
||||
v3Global.opt.filePathLookedMsg(nodep->fileline(), nodep->modName());
|
||||
}
|
||||
if (nodep->rangep()) {
|
||||
m_cellRangep = nodep->rangep();
|
||||
nodep->rangep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
@@ -1188,14 +1210,14 @@ private:
|
||||
nodep->taskp()->iterate(*this);
|
||||
//
|
||||
// And do the arguments to the task/function too
|
||||
for (int accept_mode=1; accept_mode>=0; accept_mode--) { // Avoid duplicate code; just do inner stuff twice
|
||||
for (int accept_mode=0; accept_mode<3; accept_mode++) { // Avoid duplicate code; just do inner stuff several times
|
||||
reloop:
|
||||
V3TaskConnects tconnects = V3Task::taskConnects(nodep, nodep->taskp()->stmtsp());
|
||||
bool lastloop = false;
|
||||
for (V3TaskConnects::iterator it=tconnects.begin(); !lastloop && it!=tconnects.end(); ++it) {
|
||||
for (V3TaskConnects::iterator it=tconnects.begin(); it!=tconnects.end(); ++it) {
|
||||
AstVar* portp = it->first;
|
||||
AstNode* pinp = it->second;
|
||||
if (pinp!=NULL) { // Else argument error we'll find later
|
||||
if (accept_mode) {
|
||||
if (accept_mode==0) {
|
||||
// Prelim may cause the node to get replaced; we've lost our
|
||||
// pointer, so need to iterate separately later
|
||||
if (portp->attrSFormat()
|
||||
@@ -1214,7 +1236,7 @@ private:
|
||||
}
|
||||
handle.relink(newp);
|
||||
// Connection list is now incorrect (has extra args in it).
|
||||
lastloop = true; // so exit early; next loop will correct it
|
||||
goto reloop; // so exit early; next loop will correct it
|
||||
}
|
||||
else if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING
|
||||
&& !pinp->castCvtPackString()
|
||||
@@ -1228,7 +1250,12 @@ private:
|
||||
pinp = newp;
|
||||
}
|
||||
pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),PRELIM).p()); pinp=NULL;
|
||||
} else {
|
||||
} else if (accept_mode==1) {
|
||||
// Change data types based on above accept completion
|
||||
if (portp->isDouble()) {
|
||||
spliceCvtD(pinp); pinp=NULL;
|
||||
}
|
||||
} else if (accept_mode==2) {
|
||||
// Do PRELIM again, because above accept may have exited early due to node replacement
|
||||
pinp->accept(*this,WidthVP(portp->width(),portp->widthMin(),BOTH).p());
|
||||
if ((portp->isOutput() || portp->isInout())
|
||||
@@ -1585,20 +1612,18 @@ private:
|
||||
}
|
||||
void visit_math_Or_LRr(AstNodeBiop* nodep, AstNUser* vup) {
|
||||
if (vup->c()->prelim()) { // First stage evaluation
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
checkCvtD(nodep->lhsp());
|
||||
checkCvtD(nodep->rhsp());
|
||||
nodep->numeric(AstNumeric::DOUBLE);
|
||||
// Determine expression widths only relying on what's in the subops
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
nodep->rhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
}
|
||||
}
|
||||
void visit_math_Or_Lr(AstNodeUniop* nodep, AstNUser* vup) {
|
||||
if (vup->c()->prelim()) { // First stage evaluation
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
checkCvtD(nodep->lhsp());
|
||||
nodep->numeric(AstNumeric::DOUBLE);
|
||||
// Determine expression widths only relying on what's in the subops
|
||||
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -106,7 +106,8 @@ void V3Global::readFiles() {
|
||||
for (V3StringList::const_iterator it = v3Global.opt.vFiles().begin();
|
||||
it != v3Global.opt.vFiles().end(); ++it) {
|
||||
string filename = *it;
|
||||
parser.parseFile(new FileLine("CommandLine",0), filename, false);
|
||||
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, false,
|
||||
"Cannot find file containing module: ");
|
||||
}
|
||||
|
||||
// Read libraries
|
||||
@@ -115,7 +116,8 @@ void V3Global::readFiles() {
|
||||
for (V3StringSet::const_iterator it = v3Global.opt.libraryFiles().begin();
|
||||
it != v3Global.opt.libraryFiles().end(); ++it) {
|
||||
string filename = *it;
|
||||
parser.parseFile(new FileLine("CommandLine",0), filename, true);
|
||||
parser.parseFile(new FileLine("COMMAND_LINE",0), filename, true,
|
||||
"Cannot find file containing library module: ");
|
||||
}
|
||||
//v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree"));
|
||||
V3Error::abortIfErrors();
|
||||
|
||||
+118
-9
@@ -7,28 +7,36 @@ use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw ($Debug @Types %Classes);
|
||||
use vars qw ($Debug @Types %Classes %Children %ClassRefs %Stages);
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
$Debug = 0;
|
||||
my $opt_classes;
|
||||
my $opt_report;
|
||||
my @Opt_Cpt;
|
||||
my @Opt_I;
|
||||
Getopt::Long::config ("pass_through", "no_auto_abbrev");
|
||||
if (! GetOptions (
|
||||
"help" => \&usage,
|
||||
"debug" => \&debug,
|
||||
"classes!" => \$opt_classes,
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
"help" => \&report,
|
||||
"debug" => \&debug,
|
||||
"classes!" => \$opt_classes,
|
||||
"report!" => \$opt_report,
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
usage();
|
||||
}
|
||||
|
||||
read_types("$Opt_I[0]/V3Ast.h");
|
||||
read_types("$Opt_I[0]/V3AstNodes.h");
|
||||
read_stages("$Opt_I[0]/Verilator.cpp");
|
||||
read_refs(glob("$Opt_I[0]/*.y"), glob("$Opt_I[0]/*.h"), glob("$Opt_I[0]/*.cpp"));
|
||||
if ($opt_report) {
|
||||
write_report(undef);
|
||||
}
|
||||
if ($opt_classes) {
|
||||
write_report("V3Ast__gen_report.txt");
|
||||
write_classes("V3Ast__gen_classes.h");
|
||||
write_visitor("V3Ast__gen_visitor.h");
|
||||
write_intf("V3Ast__gen_interface.h");
|
||||
@@ -42,7 +50,7 @@ foreach my $cpt (@Opt_Cpt) {
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -80,11 +88,50 @@ sub read_types {
|
||||
$class =~ s/^Ast//;
|
||||
$inh =~ s/^Ast//;
|
||||
$Classes{$class} = $inh;
|
||||
$Children{$inh}{$class} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub read_stages {
|
||||
my $filename = shift;
|
||||
|
||||
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
|
||||
my $n = 0;
|
||||
while (defined (my $line = $fh->getline())) {
|
||||
$line =~ s/\/\/.*$//;
|
||||
next if $line =~ /^\s*$/;
|
||||
if ($line =~ /^\s*([A-Za-z0-9]+)::/) {
|
||||
my $stage = $1.".cpp";
|
||||
if (!defined ($Stages{$stage})) {
|
||||
$Stages{$stage} = $n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub read_refs {
|
||||
my @filenames = @_;
|
||||
|
||||
foreach my $filename (@filenames) {
|
||||
(my $basename = $filename) =~ s!.*/!!;
|
||||
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
|
||||
while (defined (my $line = $fh->getline())) {
|
||||
$line =~ s/\/\/.*$//;
|
||||
while ($line =~ /\bnew\s*(Ast[A-Za-z0-9_]+)/g) {
|
||||
$ClassRefs{$1}{newed}{$basename} = 1;
|
||||
}
|
||||
while ($line =~ /\b(Ast[A-Za-z0-9_]+)/g) {
|
||||
$ClassRefs{$1}{used}{$basename} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#use Data::Dumper;print Dumper(\%ClassRefs);
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub open_file {
|
||||
my $filename = shift;
|
||||
my $fh = IO::File->new($filename,"w") or die "%Error: $! $filename,";
|
||||
@@ -106,8 +153,66 @@ sub subclasses_of {
|
||||
return (reverse @cllist);
|
||||
}
|
||||
|
||||
sub children_of {
|
||||
my $type = shift;
|
||||
|
||||
my @cllist;
|
||||
my @todo;
|
||||
push @todo, $type;
|
||||
while (my $subclass = shift @todo) {
|
||||
foreach my $child (sort keys %{$::Children{$subclass}}) {
|
||||
push @todo, $child;
|
||||
push @cllist, $child;
|
||||
}
|
||||
}
|
||||
|
||||
return (@cllist);
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub write_report {
|
||||
my $filename = shift;
|
||||
my $fh = defined($filename) ? open_file($filename) : \*STDOUT;
|
||||
|
||||
$fh->print("Processing stages (approximate, based on order in Verilator.cpp):\n");
|
||||
foreach my $class (sort {$Stages{$a} <=> $Stages{$b}} keys %Stages) {
|
||||
$fh->print("\t$class\n");
|
||||
}
|
||||
|
||||
$fh->print("\nProcessing stages (approximate, based on order in Verilator.cpp):\n");
|
||||
foreach my $type (sort (keys %Classes)) {
|
||||
printf $fh " class %-20s\n", "Ast${type}";
|
||||
$fh->print("\tparent:\t");
|
||||
foreach my $subclass (subclasses_of($type)) {
|
||||
next if $subclass eq 'Node';
|
||||
printf $fh "Ast%-12s ",$subclass;
|
||||
}
|
||||
printf $fh "\n";
|
||||
$fh->print("\tchilds:\t");
|
||||
foreach my $subclass (children_of($type)) {
|
||||
next if $subclass eq 'Node';
|
||||
printf $fh "Ast%-12s ",$subclass;
|
||||
}
|
||||
printf $fh "\n";
|
||||
if (my $refs = $ClassRefs{"Ast${type}"}) {
|
||||
$fh->print("\tnewed:\t");
|
||||
foreach my $stage (sort {($Stages{$a}||-1) <=> ($Stages{$b}||-1)}
|
||||
keys %{$refs->{newed}}) {
|
||||
$fh->print($stage." ");
|
||||
}
|
||||
$fh->print("\n");
|
||||
$fh->print("\tused:\t");
|
||||
foreach my $stage (sort {($Stages{$a}||-1) <=> ($Stages{$b}||-1)}
|
||||
keys %{$refs->{used}}) {
|
||||
$fh->print($stage." ");
|
||||
}
|
||||
$fh->print("\n");
|
||||
}
|
||||
$fh->print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
sub write_classes {
|
||||
my $fh = open_file(@_);
|
||||
foreach my $type (sort (keys %Classes)) {
|
||||
@@ -501,7 +606,11 @@ Displays this message and program version and exits.
|
||||
|
||||
=item --classes
|
||||
|
||||
Makes class declaration files
|
||||
Makes class declaration files.
|
||||
|
||||
=item --report
|
||||
|
||||
Makes a report report.
|
||||
|
||||
=back
|
||||
|
||||
@@ -526,5 +635,5 @@ Wilson Snyder <[email protected]>
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "./astgen "
|
||||
### compile-command: "./astgen -I. --report"
|
||||
### End:
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ process();
|
||||
|
||||
sub usage {
|
||||
print "Version $VERSION\n";
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
+4
-28
@@ -25,41 +25,17 @@
|
||||
//**********************************************************************
|
||||
//**** Version and host name
|
||||
|
||||
#define DTVERSION "Verilator 3.820 2011/07/28"
|
||||
// Autoconf substitutes this with the strings from AC_INIT.
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
#define DTVERSION PACKAGE_STRING
|
||||
|
||||
//**********************************************************************
|
||||
//**** Functions
|
||||
|
||||
// Set define if we have function: strdup (string)
|
||||
#define HAVE_STRDUP 0
|
||||
|
||||
//**********************************************************************
|
||||
//**** Headers
|
||||
|
||||
// Set define if we have header: <fcntl.h>
|
||||
#define HAVE_FCNTL_H 0
|
||||
|
||||
// Set define if we have header: <math.h>
|
||||
#define HAVE_MATH_H 1
|
||||
|
||||
// Set define if we have header: <unistd.h>
|
||||
#define HAVE_UNISTD_H 0
|
||||
|
||||
// Set define if we have header: <sys/time.h>
|
||||
#define HAVE_SYS_TIME_H 0
|
||||
|
||||
// Set define if we have header: <sys/un.h>
|
||||
#define HAVE_SYS_UN_H 0
|
||||
|
||||
// Set define if we have header: <stdint.h>
|
||||
#define HAVE_STDINT_H 0
|
||||
|
||||
// Set define if we have header: <mingw/stdint.h>
|
||||
#define HAVE_MINGW_STDINT_H 0
|
||||
|
||||
// Set define if we have header: <inttypes.h>
|
||||
#define HAVE_INTTYPES_H 0
|
||||
|
||||
//**********************************************************************
|
||||
//**** Default environment
|
||||
|
||||
|
||||
+124
-18
@@ -134,7 +134,7 @@ void yyerrorf(const char* format, ...) {
|
||||
|
||||
%s V95 V01 V05 S05 S09
|
||||
%s STRING ATTRMODE TABLE
|
||||
%s PSL VLT
|
||||
%s VA5 SA9 PSL VLT
|
||||
%s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR
|
||||
%s IGNORE
|
||||
|
||||
@@ -168,14 +168,16 @@ word [a-zA-Z0-9_]+
|
||||
|
||||
/************************************************************************/
|
||||
/* Verilog 1995 */
|
||||
<V95,V01,V05,S05,S09,PSL>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9,PSL>{
|
||||
{ws} { } /* otherwise ignore white-space */
|
||||
{crnl} { NEXTLINE(); } /* Count line numbers */
|
||||
/* Extensions to Verilog set, some specified by PSL */
|
||||
"$c"[0-9]* { FL; return yD_C; } /*Verilator only*/
|
||||
/* System Tasks */
|
||||
"$bitstoreal" { FL; return yD_BITSTOREAL; }
|
||||
"$ceil" { FL; return yD_CEIL; }
|
||||
"$display" { FL; return yD_DISPLAY; }
|
||||
"$exp" { FL; return yD_EXP; }
|
||||
"$fclose" { FL; return yD_FCLOSE; }
|
||||
"$fdisplay" { FL; return yD_FDISPLAY; }
|
||||
"$feof" { FL; return yD_FEOF; }
|
||||
@@ -183,14 +185,18 @@ word [a-zA-Z0-9_]+
|
||||
"$fgetc" { FL; return yD_FGETC; }
|
||||
"$fgets" { FL; return yD_FGETS; }
|
||||
"$finish" { FL; return yD_FINISH; }
|
||||
"$floor" { FL; return yD_FLOOR; }
|
||||
"$fopen" { FL; return yD_FOPEN; }
|
||||
"$fscanf" { FL; return yD_FSCANF; }
|
||||
"$fullskew" { FL; return yaTIMINGSPEC; }
|
||||
"$fwrite" { FL; return yD_FWRITE; }
|
||||
"$hold" { FL; return yaTIMINGSPEC; }
|
||||
"$itor" { FL; return yD_ITOR; }
|
||||
"$ln" { FL; return yD_LN; }
|
||||
"$log10" { FL; return yD_LOG10; }
|
||||
"$nochange" { FL; return yaTIMINGSPEC; }
|
||||
"$period" { FL; return yaTIMINGSPEC; }
|
||||
"$pow" { FL; return yD_POW; }
|
||||
"$random" { FL; return yD_RANDOM; }
|
||||
"$readmemb" { FL; return yD_READMEMB; }
|
||||
"$readmemh" { FL; return yD_READMEMH; }
|
||||
@@ -204,10 +210,12 @@ word [a-zA-Z0-9_]+
|
||||
"$setuphold" { FL; return yaTIMINGSPEC; }
|
||||
"$sformat" { FL; return yD_SFORMAT; }
|
||||
"$skew" { FL; return yaTIMINGSPEC; }
|
||||
"$sqrt" { FL; return yD_SQRT; }
|
||||
"$sscanf" { FL; return yD_SSCANF; }
|
||||
"$stime" { FL; return yD_STIME; }
|
||||
"$stop" { FL; return yD_STOP; }
|
||||
"$swrite" { FL; return yD_SWRITE; }
|
||||
"$system" { FL; return yD_SYSTEM; }
|
||||
"$test$plusargs" { FL; return yD_TESTPLUSARGS; }
|
||||
"$time" { FL; return yD_TIME; }
|
||||
"$timeskew" { FL; return yaTIMINGSPEC; }
|
||||
@@ -333,7 +341,7 @@ word [a-zA-Z0-9_]+
|
||||
}
|
||||
|
||||
/* Verilog 2001 */
|
||||
<V01,V05,S05,S09,PSL>{
|
||||
<V01,V05,VA5,S05,S09,SA9,PSL>{
|
||||
/* System Tasks */
|
||||
"$signed" { FL; return yD_SIGNED; }
|
||||
"$unsigned" { FL; return yD_UNSIGNED; }
|
||||
@@ -364,7 +372,7 @@ word [a-zA-Z0-9_]+
|
||||
}
|
||||
|
||||
/* Verilog 2005 */
|
||||
<V05,S05,S09,PSL>{
|
||||
<V05,S05,S09,SA9,PSL>{
|
||||
/* Keywords */
|
||||
"uwire" { FL; return yWIRE; }
|
||||
}
|
||||
@@ -523,7 +531,7 @@ word [a-zA-Z0-9_]+
|
||||
}
|
||||
|
||||
/* Default PLI rule */
|
||||
<V95,V01,V05,S05,S09,PSL>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9,PSL>{
|
||||
"$"[a-zA-Z_$][a-zA-Z0-9_$]* { string str (yytext,yyleng);
|
||||
yylval.strp = PARSEP->newString(AstNode::encodeName(str));
|
||||
// Lookup unencoded name including the $, to avoid hitting normal signals
|
||||
@@ -533,11 +541,104 @@ word [a-zA-Z0-9_]+
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* AMS */
|
||||
|
||||
<VA5,SA9>{
|
||||
/* Generic unsupported warnings */
|
||||
"above" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"abs" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"absdelay" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"abstol" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"ac_stim" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"access" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"acos" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"acosh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"aliasparam" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"analog" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"analysis" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"asin" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"asinh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"assert" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"atan" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"atan2" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"atanh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"branch" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"ceil" { FL; return yD_CEIL; }
|
||||
"connect" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"connectmodule" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"connectrules" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"continuous" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"cos" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"cosh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"cross" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"ddt" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"ddt_nature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"ddx" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"discipline" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"discrete" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"domain" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"driver_update" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"endconnectrules" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"enddiscipline" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"endnature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"endparamset" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"exclude" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"exp" { FL; return yD_EXP; }
|
||||
"final_step" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"flicker_noise" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"floor" { FL; return yD_FLOOR; }
|
||||
"flow" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"from" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"ground" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"hypot" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"idt" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"idt_nature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"idtmod" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"inf" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"initial_step" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"laplace_nd" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"laplace_np" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"laplace_zd" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"laplace_zp" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"last_crossing" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"limexp" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"ln" { FL; return yD_LN; }
|
||||
"log" { FL; return yD_LOG10; }
|
||||
"max" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"merged" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"min" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"nature" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"net_resolution" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"noise_table" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"paramset" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"potential" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"pow" { FL; return yD_POW; }
|
||||
"resolveto" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"sin" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"sinh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"slew" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"split" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"sqrt" { FL; return yD_SQRT; }
|
||||
"string" { FL; return ySTRING; }
|
||||
"tan" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"tanh" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"timer" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"transition" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"units" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"white_noise" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"wreal" { FL; return yWREAL; }
|
||||
"zi_nd" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"zi_np" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"zi_zd" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
"zi_zp" { yyerrorf("Unsupported: AMS reserved word not implemented: %s",yytext); }
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* PSL */
|
||||
|
||||
/*Entry into PSL; mode change */
|
||||
<V95,V01,V05,S05,S09>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9>{
|
||||
"psl" { yy_push_state(PSL); FL; return yPSL; }
|
||||
}
|
||||
|
||||
@@ -626,7 +727,7 @@ word [a-zA-Z0-9_]+
|
||||
/* Meta comments */
|
||||
|
||||
/* Converted from //{cmt}verilator ...{cmt} by preprocessor */
|
||||
<V95,V01,V05,S05,S09,PSL>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9,PSL>{
|
||||
"/*verilator"{ws}*"*/" {} /* Ignore empty comments, may be `endif // verilator */
|
||||
"/*verilator clock_enable*/" { FL; return yVL_CLOCK_ENABLE; }
|
||||
"/*verilator coverage_block_off*/" { FL; return yVL_COVERAGE_BLOCK_OFF; }
|
||||
@@ -642,6 +743,7 @@ word [a-zA-Z0-9_]+
|
||||
"/*verilator public_flat_rw*/" { FL; return yVL_PUBLIC_FLAT_RW; } // The @(edge) is converted by the preproc
|
||||
"/*verilator public_module*/" { FL; return yVL_PUBLIC_MODULE; }
|
||||
"/*verilator sc_clock*/" { FL; return yVL_CLOCK; }
|
||||
"/*verilator sc_bv*/" { FL; return yVL_SC_BV; }
|
||||
"/*verilator sformat*/" { FL; return yVL_SFORMAT; }
|
||||
"/*verilator systemc_clock*/" { FL; return yVL_CLOCK; }
|
||||
"/*verilator tracing_off*/" {PARSEP->fileline()->tracingOn(false); }
|
||||
@@ -660,11 +762,11 @@ word [a-zA-Z0-9_]+
|
||||
/************************************************************************/
|
||||
|
||||
/* Single character operator thingies */
|
||||
<V95,V01,V05,S05,S09>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9>{
|
||||
"{" { FL; return yytext[0]; }
|
||||
"}" { FL; return yytext[0]; }
|
||||
}
|
||||
<V95,V01,V05,S05,S09,PSL>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9,PSL>{
|
||||
"!" { FL; return yytext[0]; }
|
||||
"#" { FL; return yytext[0]; }
|
||||
"$" { FL; return yytext[0]; }
|
||||
@@ -696,7 +798,7 @@ word [a-zA-Z0-9_]+
|
||||
/* Operators and multi-character symbols */
|
||||
|
||||
/* Verilog 1995 Operators */
|
||||
<V95,V01,V05,S05,S09,PSL>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9,PSL>{
|
||||
"&&" { FL; return yP_ANDAND; }
|
||||
"||" { FL; return yP_OROR; }
|
||||
"<=" { FL; return yP_LTE; }
|
||||
@@ -718,7 +820,7 @@ word [a-zA-Z0-9_]+
|
||||
}
|
||||
|
||||
/* Verilog 2001 Operators */
|
||||
<V01,V05,S05,S09,PSL>{
|
||||
<V01,V05,VA5,S05,S09,SA9,PSL>{
|
||||
"<<<" { FL; return yP_SLEFT; }
|
||||
">>>" { FL; return yP_SSRIGHT; }
|
||||
"**" { FL; return yP_POW; }
|
||||
@@ -777,7 +879,7 @@ word [a-zA-Z0-9_]+
|
||||
}
|
||||
|
||||
/* Identifiers and numbers */
|
||||
<V95,V01,V05,S05,S09,PSL,VLT>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9,PSL,VLT>{
|
||||
{escid} { FL; yylval.strp = PARSEP->newString
|
||||
(AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash
|
||||
return yaID__LEX;
|
||||
@@ -852,8 +954,9 @@ word [a-zA-Z0-9_]+
|
||||
|
||||
/************************************************************************/
|
||||
/* Attributes */
|
||||
<V95,V01,V05,S05,S09>{
|
||||
"(*"/{ws}*[^)] { yymore(); yy_push_state(ATTRMODE); } // Doesn't match (*)
|
||||
/* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
|
||||
<V95,V01,V05,VA5,S05,S09,SA9>{
|
||||
"(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } // Doesn't match (*), but (* attr_spec
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
@@ -869,7 +972,7 @@ word [a-zA-Z0-9_]+
|
||||
/* Preprocessor */
|
||||
/* Common for all SYSC header states */
|
||||
/* OPTIMIZE: we return one per line, make it one for the entire block */
|
||||
<V95,V01,V05,S05,S09,PSL,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9,PSL,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
|
||||
"`accelerate" { } // Verilog-XL compatibility
|
||||
"`autoexpand_vectornets" { } // Verilog-XL compatibility
|
||||
"`celldefine" { PARSEP->inCellDefine(true); }
|
||||
@@ -910,9 +1013,11 @@ word [a-zA-Z0-9_]+
|
||||
"`begin_keywords"[ \t]*\"1364-2001\" { yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"1364-2001-noconfig\" { yy_push_state(V01); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"1364-2005\" { yy_push_state(V05); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"VAMS[-0-9.]*\" { yy_push_state(VA5); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"1800-2009\" { yy_push_state(S09); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
|
||||
"`begin_keywords"[ \t]*\"1800+VAMS\" { yy_push_state(SA9); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
|
||||
|
||||
/* Verilator */
|
||||
"`systemc_ctor" { BEGIN SYSCCTOR; }
|
||||
@@ -942,7 +1047,7 @@ word [a-zA-Z0-9_]+
|
||||
/************************************************************************/
|
||||
/* Default rules - leave last */
|
||||
|
||||
<V95,V01,V05,S05,S09,PSL,VLT>{
|
||||
<V95,V01,V05,VA5,S05,S09,SA9,PSL,VLT>{
|
||||
"`"[a-zA-Z_0-9]+ { FL; yyerrorf("Define or directive not defined: %s",yytext); }
|
||||
"//"[^\n]* { } /* throw away single line comments */
|
||||
. { FL; return yytext[0]; } /* return single char ops. */
|
||||
@@ -963,7 +1068,8 @@ double V3ParseImp::parseDouble(const char* textp, size_t length) {
|
||||
*dp++ = '\0';
|
||||
char* endp = strgp;
|
||||
double d = strtod(strgp, &endp);
|
||||
if ((endp-strgp) != length) { yyerrorf("Syntax error parsing real: %s",strgp); }
|
||||
size_t parsed_len = endp-strgp;
|
||||
if (parsed_len != length) { yyerrorf("Syntax error parsing real: %s",strgp); }
|
||||
delete strgp;
|
||||
return d;
|
||||
}
|
||||
|
||||
+33
-6
@@ -71,7 +71,7 @@ public:
|
||||
m_varIO = AstVarType::UNKNOWN;
|
||||
m_varDTypep = NULL;
|
||||
m_pinNum = -1;
|
||||
m_instModule;
|
||||
m_instModule = "";
|
||||
m_instParamp = NULL;
|
||||
m_modp = NULL;
|
||||
m_modTypeImpNum = 0;
|
||||
@@ -380,16 +380,19 @@ class AstSenTree;
|
||||
%token<fl> yVOID "void"
|
||||
%token<fl> yWHILE "while"
|
||||
%token<fl> yWIRE "wire"
|
||||
%token<fl> yWREAL "wreal"
|
||||
%token<fl> yXNOR "xnor"
|
||||
%token<fl> yXOR "xor"
|
||||
|
||||
%token<fl> yD_BITS "$bits"
|
||||
%token<fl> yD_BITSTOREAL "$bitstoreal"
|
||||
%token<fl> yD_C "$c"
|
||||
%token<fl> yD_CEIL "$ceil"
|
||||
%token<fl> yD_CLOG2 "$clog2"
|
||||
%token<fl> yD_COUNTONES "$countones"
|
||||
%token<fl> yD_DISPLAY "$display"
|
||||
%token<fl> yD_ERROR "$error"
|
||||
%token<fl> yD_EXP "$exp"
|
||||
%token<fl> yD_FATAL "$fatal"
|
||||
%token<fl> yD_FCLOSE "$fclose"
|
||||
%token<fl> yD_FDISPLAY "$fdisplay"
|
||||
@@ -398,14 +401,18 @@ class AstSenTree;
|
||||
%token<fl> yD_FGETC "$fgetc"
|
||||
%token<fl> yD_FGETS "$fgets"
|
||||
%token<fl> yD_FINISH "$finish"
|
||||
%token<fl> yD_FLOOR "$floor"
|
||||
%token<fl> yD_FOPEN "$fopen"
|
||||
%token<fl> yD_FSCANF "$fscanf"
|
||||
%token<fl> yD_FWRITE "$fwrite"
|
||||
%token<fl> yD_INFO "$info"
|
||||
%token<fl> yD_ISUNKNOWN "$isunknown"
|
||||
%token<fl> yD_ITOR "$itor"
|
||||
%token<fl> yD_LN "$ln"
|
||||
%token<fl> yD_LOG10 "$log10"
|
||||
%token<fl> yD_ONEHOT "$onehot"
|
||||
%token<fl> yD_ONEHOT0 "$onehot0"
|
||||
%token<fl> yD_POW "$pow"
|
||||
%token<fl> yD_RANDOM "$random"
|
||||
%token<fl> yD_READMEMB "$readmemb"
|
||||
%token<fl> yD_READMEMH "$readmemh"
|
||||
@@ -414,10 +421,12 @@ class AstSenTree;
|
||||
%token<fl> yD_RTOI "$rtoi"
|
||||
%token<fl> yD_SFORMAT "$sformat"
|
||||
%token<fl> yD_SIGNED "$signed"
|
||||
%token<fl> yD_SQRT "$sqrt"
|
||||
%token<fl> yD_SSCANF "$sscanf"
|
||||
%token<fl> yD_STIME "$stime"
|
||||
%token<fl> yD_STOP "$stop"
|
||||
%token<fl> yD_SWRITE "$swrite"
|
||||
%token<fl> yD_SYSTEM "$system"
|
||||
%token<fl> yD_TESTPLUSARGS "$test$plusargs"
|
||||
%token<fl> yD_TIME "$time"
|
||||
%token<fl> yD_UNIT "$unit"
|
||||
@@ -440,6 +449,7 @@ class AstSenTree;
|
||||
%token<fl> yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/"
|
||||
%token<fl> yVL_NO_INLINE_MODULE "/*verilator no_inline_module*/"
|
||||
%token<fl> yVL_NO_INLINE_TASK "/*verilator no_inline_task*/"
|
||||
%token<fl> yVL_SC_BV "/*verilator sc_bv*/"
|
||||
%token<fl> yVL_SFORMAT "/*verilator sformat*/"
|
||||
%token<fl> yVL_PARALLEL_CASE "/*verilator parallel_case*/"
|
||||
%token<fl> yVL_PUBLIC "/*verilator public*/"
|
||||
@@ -1078,6 +1088,8 @@ non_integer_type<bdtypep>: // ==IEEE: non_integer_type
|
||||
yREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
|
||||
| yREALTIME { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); }
|
||||
//UNSUP ySHORTREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::FLOAT); }
|
||||
// // VAMS - somewhat hackish
|
||||
| yWREAL { $$ = new AstBasicDType($1,AstBasicDTypeKwd::DOUBLE); VARDECL(WIRE); }
|
||||
;
|
||||
|
||||
signingE<signstate>: // IEEE: signing - plus empty
|
||||
@@ -1520,7 +1532,7 @@ assignOne<nodep>:
|
||||
|
||||
delayE:
|
||||
/* empty */ { }
|
||||
| delay_control { } /* ignored */
|
||||
| delay_control { $1->v3warn(ASSIGNDLY,"Unsupported: Ignoring delay on this assignment/primitive."); } /* ignored */
|
||||
;
|
||||
|
||||
delay_control<fl>: //== IEEE: delay_control
|
||||
@@ -1589,6 +1601,7 @@ sigAttr<nodep>:
|
||||
| yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW);
|
||||
$$ = $$->addNext(new AstAlwaysPublic($1,$2,NULL)); }
|
||||
| yVL_ISOLATE_ASSIGNMENTS { $$ = new AstAttrOf($1,AstAttrType::VAR_ISOLATE_ASSIGNMENTS); }
|
||||
| yVL_SC_BV { $$ = new AstAttrOf($1,AstAttrType::VAR_SC_BV); }
|
||||
| yVL_SFORMAT { $$ = new AstAttrOf($1,AstAttrType::VAR_SFORMAT); }
|
||||
;
|
||||
|
||||
@@ -1759,8 +1772,8 @@ event_control<sentreep>: // ==IEEE: event_control
|
||||
|
||||
event_expression<senitemp>: // IEEE: event_expression - split over several
|
||||
senitem { $$ = $1; }
|
||||
| event_expression yOR senitem { $$ = $1;$1->addNext($3); }
|
||||
| event_expression ',' senitem { $$ = $1;$1->addNext($3); } /* Verilog 2001 */
|
||||
| event_expression yOR senitem { $$ = $1;$1->addNextNull($3); }
|
||||
| event_expression ',' senitem { $$ = $1;$1->addNextNull($3); } /* Verilog 2001 */
|
||||
;
|
||||
|
||||
senitem<senitemp>: // IEEE: part of event_expression, non-'OR' ',' terms
|
||||
@@ -1769,6 +1782,11 @@ senitem<senitemp>: // IEEE: part of event_expression, non-'OR' ',' terms
|
||||
| '(' senitemVar ')' { $$ = $2; }
|
||||
//UNSUP expr { UNSUP }
|
||||
//UNSUP expr yIFF expr { UNSUP }
|
||||
// Since expr is unsupported we allow and ignore constants (removed in V3Const)
|
||||
| yaINTNUM { $$ = NULL; }
|
||||
| yaFLOATNUM { $$ = NULL; }
|
||||
| '(' yaINTNUM ')' { $$ = NULL; }
|
||||
| '(' yaFLOATNUM ')' { $$ = NULL; }
|
||||
;
|
||||
|
||||
senitemVar<senitemp>:
|
||||
@@ -1922,7 +1940,7 @@ statement_item<nodep>: // IEEE: statement_item
|
||||
//
|
||||
//UNSUP par_block { $$ = $1; }
|
||||
// // IEEE: procedural_timing_control_statement + procedural_timing_control
|
||||
| delay_control stmtBlock { $$ = $2; $1->v3warn(STMTDLY,"Ignoring delay on this delayed statement."); }
|
||||
| delay_control stmtBlock { $$ = $2; $1->v3warn(STMTDLY,"Unsupported: Ignoring delay on this delayed statement."); }
|
||||
//UNSUP event_control stmtBlock { UNSUP }
|
||||
//UNSUP cycle_delay stmtBlock { UNSUP }
|
||||
//
|
||||
@@ -2111,7 +2129,7 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||
| yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); }
|
||||
| yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
|
||||
| yD_FFLUSH parenE { $1->v3error("Unsupported: $fflush of all handles does not map to C++."); }
|
||||
| yD_FFLUSH '(' idClassSel ')' { $$ = new AstFClose($1, $3); }
|
||||
| yD_FFLUSH '(' idClassSel ')' { $$ = new AstFFlush($1, $3); }
|
||||
| yD_FINISH parenE { $$ = new AstFinish($1); }
|
||||
| yD_FINISH '(' expr ')' { $$ = new AstFinish($1); }
|
||||
| yD_STOP parenE { $$ = new AstStop($1); }
|
||||
@@ -2119,6 +2137,7 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
||||
//
|
||||
| yD_SFORMAT '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
|
||||
| yD_SWRITE '(' expr ',' str commaEListE ')' { $$ = new AstSFormat($1,$3,*$5,$6); }
|
||||
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1,$3); }
|
||||
//
|
||||
| yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,"", NULL,NULL); }
|
||||
| yD_DISPLAY '(' str commaEListE ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY,*$3,NULL,$4); }
|
||||
@@ -2152,6 +2171,13 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
| yaD_DPI parenE { $$ = new AstFuncRef($<fl>1,*$1,NULL); }
|
||||
| yaD_DPI '(' exprList ')' { $$ = new AstFuncRef($2,*$1,$3); }
|
||||
//
|
||||
| yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); }
|
||||
| yD_EXP '(' expr ')' { $$ = new AstExpD($1,$3); }
|
||||
| yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); }
|
||||
| yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); }
|
||||
| yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); }
|
||||
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD($1,$3,$5); }
|
||||
| yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); }
|
||||
| yD_BITS '(' expr ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
|
||||
| yD_BITS '(' data_type ')' { $$ = new AstAttrOf($1,AstAttrType::EXPR_BITS,$3); }
|
||||
| yD_BITSTOREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); }
|
||||
@@ -2163,6 +2189,7 @@ system_f_call<nodep>: // IEEE: system_tf_call (as func)
|
||||
| yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); }
|
||||
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); }
|
||||
| yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); }
|
||||
| yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); }
|
||||
| yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1,$3); }
|
||||
| yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); }
|
||||
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); }
|
||||
|
||||
+1
-3
@@ -19,11 +19,9 @@ include Vtop.mk
|
||||
# Compile flags
|
||||
|
||||
CPPFLAGS += -DVL_DEBUG=1
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1) # Local... Else don't burden users
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
CPPFLAGS += -DVL_THREADED=1
|
||||
CPPFLAGS += -W -Werror -Wall
|
||||
#CPPFLAGS += -Wno-unused-variable # Instead, add VL_ATTR_UNUSED in gen'ed code
|
||||
#CPPFLAGS += -pedantic-errors
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
|
||||
+3
-3
@@ -13,10 +13,10 @@
|
||||
|
||||
Vtop *top; // Instantiation of module
|
||||
|
||||
unsigned int main_time = 0; // Current simulation time
|
||||
vluint64_t main_time = 0; // Current simulation time (64-bit unsigned)
|
||||
|
||||
double sc_time_stamp () { // Called by $time in Verilog
|
||||
return main_time;
|
||||
return main_time; // Note does conversion to real, to match SystemC
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
@@ -59,7 +59,7 @@ int main(int argc, char **argv, char **env) {
|
||||
#endif
|
||||
|
||||
// Read outputs
|
||||
VL_PRINTF ("[%d] %x %x %x %x %x_%08x_%08x\n",
|
||||
VL_PRINTF ("[%" VL_PRI64 "d] %x %x %x %x %x_%08x_%08x\n",
|
||||
main_time, top->clk, top->reset_l, top->passed,
|
||||
top->out_small, top->out_wide[2], top->out_wide[1], top->out_wide[0]);
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ endif
|
||||
|
||||
PRODUCTS += --vlt
|
||||
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1)
|
||||
# Run tests in parallel. Requires Parallel::Forker to be installed.
|
||||
ifeq ($(CFG_WITH_LONGTESTS),yes)
|
||||
DRIVER_FLAGS += -j 0
|
||||
endif
|
||||
|
||||
|
||||
@@ -25,13 +25,6 @@ VPATH += ../../$(VM_USER_DIR)
|
||||
|
||||
#######################################################################
|
||||
|
||||
ifeq ($(VERILATOR_AUTHOR_SITE),1)
|
||||
#OBJCACHE := objcache --read --write
|
||||
#OBJCACHE_HOSTS :=
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
|
||||
# Needed by DPI tests
|
||||
CPPFLAGS += -DVERILATOR=1
|
||||
|
||||
|
||||
+12
-3
@@ -39,6 +39,7 @@ autoflush STDERR 1;
|
||||
|
||||
our @Orig_ARGV = @ARGV;
|
||||
our @Orig_ARGV_Sw; foreach (@Orig_ARGV) { push @Orig_ARGV_Sw, $_ if /^-/ && !/^-j/; }
|
||||
our $Start = time();
|
||||
|
||||
$Debug = 0;
|
||||
my $opt_atsim;
|
||||
@@ -64,6 +65,7 @@ Getopt::Long::config ("pass_through");
|
||||
if (! GetOptions (
|
||||
"benchmark:i" => sub { $opt_benchmark = $_[1] ? $_[1] : 1; },
|
||||
"debug" => \&debug,
|
||||
#debugi see parameter()
|
||||
"atsim|athdl!"=> \$opt_atsim,
|
||||
"gdb!" => \$opt_gdb,
|
||||
"gdbbt!" => \$opt_gdbbt,
|
||||
@@ -83,6 +85,7 @@ if (! GetOptions (
|
||||
"vcs!" => \$opt_vcs,
|
||||
"verbose!" => \$opt_verbose,
|
||||
"verilated_debug!" => \$Opt_Verilated_Debug,
|
||||
#W see parameter()
|
||||
"<>" => \¶meter,
|
||||
)) {
|
||||
die "%Error: Bad usage, try '$0 --help'\n";
|
||||
@@ -178,7 +181,7 @@ exit(10) if $failcnt;
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
sub usage {
|
||||
pod2usage(-verbose=>2, -exitval => 2);
|
||||
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -204,6 +207,9 @@ sub parameter {
|
||||
push @Opt_Driver_Verilator_Flags, $param;
|
||||
$_Parameter_Next_Level = $param;
|
||||
}
|
||||
elsif ($param =~ /^-?-W/) {
|
||||
push @Opt_Driver_Verilator_Flags, $param;
|
||||
}
|
||||
else {
|
||||
die "%Error: Unknown parameter: $param\n";
|
||||
}
|
||||
@@ -228,14 +234,17 @@ sub report {
|
||||
$fh = IO::File->new(">$filename") or die "%Error: $! writing $filename,";
|
||||
}
|
||||
|
||||
my $delta = time() - $Start;
|
||||
$fh->print("\n");
|
||||
$fh->print("="x70,"\n");
|
||||
$fh->print("TESTS Passed $okcnt Skipped $skcnt Failed $failcnt\n");
|
||||
$fh->printf("TESTS Passed $okcnt Skipped $skcnt Failed $failcnt Time %d:%02d\n",
|
||||
int($delta/60),$delta%60);
|
||||
foreach my $f (@$fails) {
|
||||
chomp $f;
|
||||
$fh->print("$f\n");
|
||||
}
|
||||
$fh->print("TESTS Passed $okcnt Skipped $skcnt Failed $failcnt\n");
|
||||
$fh->printf("TESTS Passed $okcnt Skipped $skcnt Failed $failcnt Time %d:%02d\n",
|
||||
int($delta/60),$delta%60);
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Use this file as a template for submitting bugs, etc.
|
||||
// This module takes a single clock input, and should either
|
||||
// $write("*-* All Finished *-*\n");
|
||||
// $finish
|
||||
// $finish;
|
||||
// on success, or $stop.
|
||||
//
|
||||
// The code as shown applies a random vector to the Test
|
||||
|
||||
@@ -11,7 +11,7 @@ module t (/*AUTOARG*/
|
||||
input clk;
|
||||
integer cyc; initial cyc=1;
|
||||
|
||||
reg [31:0] a, b, c, d, e;
|
||||
reg [31:0] a, b, c, d, e, f, g;
|
||||
|
||||
always @ (*) begin // Test Verilog 2001 (*)
|
||||
// verilator lint_off COMBDLY
|
||||
@@ -25,6 +25,14 @@ module t (/*AUTOARG*/
|
||||
always @ ((d)) begin // always bug 2008/4/18
|
||||
e = d;
|
||||
end
|
||||
|
||||
parameter CONSTANT = 1;
|
||||
always @ (e, 1'b0, CONSTANT) begin // not technically legal, see bug412
|
||||
f = e;
|
||||
end
|
||||
always @ (1'b0, CONSTANT, f) begin // not technically legal, see bug412
|
||||
g = f;
|
||||
end
|
||||
//always @ ((posedge b) or (a or b)) begin // note both illegal
|
||||
|
||||
always @ (posedge clk) begin
|
||||
@@ -38,7 +46,7 @@ module t (/*AUTOARG*/
|
||||
if (c != 32'hfeedface) $stop;
|
||||
end
|
||||
if (cyc==3) begin
|
||||
if (e != 32'hfeedface) $stop;
|
||||
if (g != 32'hfeedface) $stop;
|
||||
end
|
||||
if (cyc==7) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
||||
@@ -11,7 +11,7 @@ compile (
|
||||
verilator_flags2 => ["--stats"],
|
||||
);
|
||||
|
||||
if ($Self->{v3}) {
|
||||
if ($Self->{vlt}) {
|
||||
file_grep ($Self->{stats}, qr/Optimizations, Split always\s+6/i);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ compile (
|
||||
verilator_flags2 => ["--stats"],
|
||||
);
|
||||
|
||||
if ($Self->{v3}) {
|
||||
if ($Self->{vlt}) {
|
||||
file_grep ($Self->{stats}, qr/Optimizations, Split always\s+0/i);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Self->{v3}?'--assert':($Self->{nc}?'+assert':'')],
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
);
|
||||
|
||||
execute (
|
||||
|
||||
@@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
top_filename("t/t_assert_basic.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Self->{v3}?'--assert --sp --coverage-user':''],
|
||||
verilator_flags2 => ['--assert --sp --coverage-user'],
|
||||
);
|
||||
|
||||
execute (
|
||||
|
||||
@@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
top_filename("t/t_assert_cover.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Self->{v3}?'--assert --sp --coverage-user':''],
|
||||
verilator_flags2 => ['--assert --sp --coverage-user'],
|
||||
nc_flags2 => ["+nccovoverwrite +nccoverage+all +nccovtest+$Self->{name}"]
|
||||
);
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Self->{v3}?'--assert':($Self->{nc}?'+assert':'')],
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
);
|
||||
|
||||
execute (
|
||||
|
||||
@@ -10,8 +10,9 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
top_filename("t/t_assert_synth.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Self->{v3}?'--assert':($Self->{nc}?'+assert':''),
|
||||
'+define+FAILING_FULL',],
|
||||
v_flags2 => ['+define+FAILING_FULL'],
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
);
|
||||
|
||||
execute (
|
||||
|
||||
@@ -10,8 +10,9 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
||||
top_filename("t/t_assert_synth.v");
|
||||
|
||||
compile (
|
||||
v_flags2 => [$Self->{v3}?'--assert':($Self->{nc}?'+assert':''),
|
||||
'+define+FAILING_PARALLEL',],
|
||||
v_flags2 => ['+define+FAILING_PARALLEL'],
|
||||
verilator_flags2 => ['--assert'],
|
||||
nc_flags2 => ['+assert'],
|
||||
);
|
||||
|
||||
execute (
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 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.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user