'Merge from master for release.'

This commit is contained in:
Wilson Snyder 2020-02-08 09:15:27 -05:00
commit 61e14aa827
331 changed files with 8244 additions and 4680 deletions

1
.gitignore vendored
View File

@ -17,6 +17,7 @@
README
TAGS
autom4te.cache
compile_commands.json
config.cache
config.status
configure

View File

@ -16,6 +16,7 @@ env:
- VERILATOR_ROOT=$PWD
- VERILATOR_NUM_JOBS=$(echo `nproc` + 1 | bc)
- VERILATOR_CONFIG_FLAGS="--enable-maintainer-mode --enable-longtests"
- VERILATOR_AUTHOR_SITE=1
- OBJCACHE=ccache
cache:
@ -26,6 +27,7 @@ before_install:
# Perl modules needed for testing
- yes yes | sudo cpan -fi Unix::Processors Parallel::Forker Bit::Vector
- sudo apt-get install gdb gtkwave
- sudo apt-get install libgoogle-perftools-dev
before_script:
- bash -x ci/build_vcddiff.sh
- bash -x ci/build_verilator.sh

50
Changes
View File

@ -2,6 +2,50 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.028 2020-02-08
** Support attributes (public, isolate_assignments, etc.) in configuration files.
** Add -match to lint_off to waive warnings. [Philipp Wagner]
*** Link Verilator binary partially statically, #2146. [Geza Lore]
*** Verilation speed improvements, #2133, #2138. [Geza Lore]
*** Support libgoogle-perftools-dev's libtcmalloc if available, #2137. [Geza Lore]
*** Support $readmem/$writemem with assoc arrarys, #2100. [agrobman]
**** Support type(expression) operator and $typename, #1650.
**** Support left justified $display, #2101. [Pieter Kapsenberg]
**** Support string character access via indexing.
**** Support enum.next(k) with constant k > 1, #2125. [Tobias Rosenkranz]
**** Support parameter access from arrays of interfaces, #2155. [Todd Strader]
**** Add parameter values in XML. #2110. [Pieter Kapsenberg]
**** Add loc column location in XML (replaces fl), #2122. [Pieter Kapsenberg]
**** Add error on misused define. [Topa Tota]
**** Add parameter to set maximum signal width, #2082. [Øyvind Harboe]
**** Add warning on genvar in normal for loop, #2143. [yurivict]
**** Fix VPI scope naming for public modules. [Nandu Raj]
**** Fix FST tracing of enums inside structs. [fsiegle]
**** Fix WIDTH warning on </<= of narrower value, #2141. [agrobman]
**** Fix OpenSolaris issues, #2154. [brancoliticus]
* Verilator 4.026 2020-01-11
** Docker images are now available for Verilator releases.
@ -128,10 +172,10 @@ The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.020 2019-10-06
*** Support $fseek, $ftell, $frewind, #1496. [Howard Su]
*** Add --public-flat-rw, #1511. [Stefan Wallentowitz]
*** Support $fseek, $ftell, $frewind, #1496. [Howard Su]
*** Support vpiModule, #1469. [Stefan Wallentowitz]
**** Make Syms file honor --output-split-cfuncs, #1499. [Todd Strader]
@ -152,6 +196,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
**** Fix case statements with strings, #1536. [Philipp Wagner]
**** Fix some coverage lost when multithreaded, #2151.
* Verilator 4.018 2019-08-29

View File

@ -19,14 +19,15 @@
\.codacy\.yml
\.travis\.yml
/build/
/obj_dir/
/obj_dbg/
/obj_dir/
/obj_dist/
/obj_iv/
/obj_nc/
/obj_opt/
/obj_vcs/
/obj_vlt/
/obj_vltmt/
/obj_dist/
/INCA_libs/
/cov_work/
/logs/

View File

@ -148,6 +148,7 @@ DISTFILES_INC = $(INFOS) .gitignore \
docs/install.adoc \
docs/internals.adoc \
docs/verilator_logo.png \
docs/xml.adoc \
install-sh configure *.pod \
include/*.[chv]* \
include/*.in \

View File

@ -16,6 +16,7 @@ ifndef::env-github[]
:link_verilator_contributing: https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc
:link_verilator_install: https://verilator.org/install
endif::[]
:link_verilator_commercial_support: https://verilator.org/verilator_commercial_support
== Welcome to Verilator
@ -38,12 +39,18 @@ endif::[]
+++ <br/> +++ &bullet; Out-of-the-box support from Arm, and RISC-V vendor IP
<.^|image:https://www.veripool.org/img/verilator_usage_400x200-min.png[,400,200]
>.^|image:https://www.veripool.org/img/chips_alliance_logo_225x75-min.png[CHIPS Alliance,link=https://chipsalliance.org]
image:https://www.veripool.org/img/osi_logo_125x125-min.png[,125,125]
>.^|image:https://www.veripool.org/img/verilator_community_400x125-min.png[,400,125]
^.^| *Community Driven & Openly Licensed*
+++ <br/> +++ &bullet; Guided by the https://chipsalliance.org/[CHIPS Alliance] and https://www.linuxfoundation.org/[Linux Foundation]
+++ <br/> +++ &bullet; Open, and free as in both speech and beer
+++ <br/> +++ &bullet; More simulation for your verification budget
^.^| *Commercial Support Available*
+++ <br/> +++ &bullet; Commercial support contracts
+++ <br/> +++ &bullet; Design support contracts
+++ <br/> +++ &bullet; Enhancement contracts
<.^|image:https://www.veripool.org/img/verilator_support_400x125-min.png[,400,125]
|===
== What Verilator Does
@ -109,7 +116,7 @@ or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)]
* https://verilator.org/issues[Verilator Issues]
== Community Supported
== Support
Verilator is a community project, guided by the
https://chipsalliance.org/[CHIPS Alliance] under the
@ -120,6 +127,10 @@ We appreciate and welcome your contributions in whatever form; please see
https://verilator.org/verilator_doc.html#CONTRIBUTORS[Contributors and
Sponsors].
Verilator also supports and encourages commercial support models and
organizations; please see {link_verilator_commercial_support}[Verilator
Commercial Support].
== Related Projects
* http://gtkwave.sourceforge.net/[GTKwave] - Waveform viewer for Verilator

View File

@ -323,6 +323,7 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--language <lang> Default language standard to parse
+libext+<ext>+[ext]... Extensions for finding modules
--lint-only Lint, but do not make output
--max-num-width <value> Maximum number width (default: 64K)
--MMD Create .d dependency files
--MP Create phony dependency targets
--Mdir <directory> Name of output object directory
@ -968,6 +969,11 @@ stylistic and not enabled by default.
If the design is not to be completely Verilated see also the --bbox-sys and
--bbox-unsup options.
=item --max-num-width I<value>
Set the maximum number literal width (e.g. in 1024'd22 this it the 1024).
Defaults to 64K.
=item --MMD
=item --no-MMD
@ -2769,6 +2775,8 @@ purposes.
=item lint_off [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
=item lint_off [-rule <message>] [-file "<filename>"] [-match "<string>"]
Enable/disables the specified lint warning, in the specified filename (or
wildcard with '*' or '?', or all files if omitted) and range of line
numbers (or all lines if omitted).
@ -2780,6 +2788,10 @@ If the -rule is omitted, all lint warnings (see list in -Wno-lint) are
enabled/disabled. This will override all later lint warning enables for
the specified region.
If -match is set the linter warnings are matched against this (wildcard)
string and are waived in case they match iff rule and file (with wildcard)
also match.
In previous versions -rule was named -msg. The latter is deprecated, but
still works with a deprecation info, it may be removed in future versions.
@ -2794,6 +2806,124 @@ and range of line numbers (or all lines if omitted).
For tracing_off, cells below any module in the files/ranges specified will
also not be traced.
=item clock_enable -module "<modulename>" -signal "<signame>"
Indicate the signal is used to gate a clock, and the user takes responsibility
for insuring there are no races related to it.
Same as /*verilator clock_enable*/, see L</"LANGUAGE EXTENSIONS"> for
more information and an example.
=item clocker -module "<modulename>" [-task "<taskname>"] -signal "<signame>"
=item clocker -module "<modulename>" [-function "<funcname>"] -signal "<signame>"
=item no_clocker -module "<modulename>" [-task "<taskname>"] -signal "<signame>"
=item no_clocker -module "<modulename>" [-function "<funcname>"] -signal "<signame>"
Indicate the signal is used as clock or not. This information is used by
Verilator to mark the signal as clocker and propagate the clocker attribute
automatically to derived signals. See C<--clk> for more information.
Same as /*verilator clocker*/, see L</"LANGUAGE EXTENSIONS"> for more
information.
=item coverage_block_off -module "<modulename>" -block "<blockname>"
=item coverage_block_off -file "<filename>" -line <lineno>
Specifies the entire begin/end block should be ignored for coverage
analysis purposes. Can either be specified as a named block or as a
filename and line number.
Same as /*verilator coverage_block_off*/, see L</"LANGUAGE
EXTENSIONS"> for more information.
=item full_case -file "<filename>" -lines <lineno>
=item parallel_case -file "<filename>" -lines <lineno>
Same as "//synopsys full_case" and "//synopsys parallel_case". When
these synthesis directives are discovered, Verilator will either
formally prove the directive to be true, or failing that, will insert
the appropriate code to detect failing cases at simulation runtime and
print an "Assertion failed" error message.
=item inline -module "<modulename>"
Specifies the module may be inlined into any modules that use this
module. This is useful to speed up simulation runtime with some small
loss of trace visibility and modularity. Note signals under inlined
submodules will be named I<submodule>__DOT__I<subsignal> as C++ does
not allow "." in signal names. When tracing such signals the tracing
routines will replace the __DOT__ with the period.
Same as /*verilator inline_module*/, see L</"LANGUAGE EXTENSIONS"> for
more information.
=item isolate_assignments -module "<modulename>" [-task "<taskname>"] -signal "<signame>"
=item isolate_assignments -module "<modulename>" [-function "<funcname>"] -signal "<signame>"
=item isolate_assignments -module "<modulename>" -function "<fname>"
Used to indicate the assignments to this signal in any blocks should be
isolated into new blocks. When there is a large combinatorial block that
is resulting in a UNOPTFLAT warning, attaching this to the signal causing
a false loop may clear up the problem.
Same as /* verilator isolate_assignments */, see L</"LANGUAGE
EXTENSIONS"> for more information.
=item no_inline -module "<modulename>"
Specifies the module should not be inlined into any modules that use
this module. This is useful especially at the top level module to
reduce the size of the interface class, to aid compile time at a small
performance loss.
Same as /*verilator no_inline_module*/, see L</"LANGUAGE EXTENSIONS">
for more information.
=item no_inline [-module "<modulename>"] -task "<taskname>"
=item no_inline [-module "<modulename>"] -function "<funcname>"
Specify the function or task should not be inlined into where it is
used. This may reduce the size of the final executable when a task is
used a very large number of times. For this flag to work, the task
and tasks below it must be pure; they cannot reference any variables
outside the task itself.
Same as /*verilator no_inline_task*/, see L</"LANGUAGE EXTENSIONS">
for more information.
=item sc_bv -module "<modulename>" [-task "<taskname>"] -signal "<signame>"
=item sc_bv -module "<modulename>" [-function "<funcname>"] -signal "<signame>"
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 parameterized 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 decreases
significantly.
Same as /*verilator sc_bv*/, see L</"LANGUAGE EXTENSIONS"> for more
information.
=item sformat [-module "<modulename>"] [-task "<taskname>"] -signal "<signame>"
=item sformat [-module "<modulename>"] [-function "<funcname>"] -signal "<signame>"
Final input of a function or task "input string" to indicate the
function or task should pass all remaining arguments through
$sformatf. This allows creation of DPI functions with $display like
behavior. See the test_regress/t/t_dpi_display.v file for an example.
Same as /*verilator sformat*/, see L</"LANGUAGE EXTENSIONS"> for more
information.
=back
@ -2929,7 +3059,8 @@ per the C standard (it's unspecified in Verilog).
Specifies the entire begin/end block should be ignored for coverage
analysis. Must be inside a basic block, e.g. within a begin/end pair.
Same as /* verilator coverage_block_off */.
Same as /* verilator coverage_block_off */ and C<coverage_block_off> in
L</"CONFIGURATION FILES">.
=item `systemc_header
@ -3019,7 +3150,10 @@ analysis.) For example:
The clock_enable attribute will cause the clock gate to be ignored in the
scheduling algorithm, sometimes required for correct clock behavior, and
always improving performance. It's also a good idea to enable the
IMPERFECTSCH warning, to insure all clock enables are properly recognized.
IMPERFECTSCH warning, to ensure all clock enables are properly recognized.
Same as C<clock_enable> in configuration files, see L</"CONFIGURATION
FILES"> for more information.
=item /*verilator clocker*/
@ -3030,11 +3164,17 @@ not. This information is used by Verilator to mark the signal as clocker
and propagate the clocker attribute automatically to derived signals. See
C<--clk> for more information.
Same as C<clocker> and C<no_clocker> in configuration files, see
L</"CONFIGURATION FILES"> for more information.
=item /*verilator coverage_block_off*/
Specifies the entire begin/end block should be ignored for coverage
analysis purposes.
Same as C<coverage_block_off> in configuration files, see
L</"CONFIGURATION FILES"> for more information.
=item /*verilator coverage_off*/
Specifies that following lines of code should have coverage disabled.
@ -3055,6 +3195,9 @@ submodules will be named I<submodule>__DOT__I<subsignal> as C++ does not
allow "." in signal names. When tracing such signals the tracing routines
will replace the __DOT__ with the period.
Same as C<inline> in configuration files, see L</"CONFIGURATION FILES">
for more information.
=item /*verilator isolate_assignments*/
Used after a signal declaration to indicate the assignments to this signal
@ -3091,6 +3234,9 @@ It would then internally break it into (sort of):
end
end
Same as C<isolate_assignments> in configuration files, see
L</"CONFIGURATION FILES"> for more information.
=item /*verilator lint_off I<msg>*/
Disable the specified warning message for any warnings following the comment.
@ -3126,6 +3272,9 @@ modules that use this module. This is useful especially at the top level
module to reduce the size of the interface class, to aid compile time at a
small performance loss.
Same as C<no_inline> in configuration files, see L</"CONFIGURATION
FILES"> for more information.
=item /*verilator no_inline_task*/
Used in a function or task variable definition section to specify the
@ -3134,6 +3283,9 @@ reduce the size of the final executable when a task is used a very large
number of times. For this flag to work, the task and tasks below it must
be pure; they cannot reference any variables outside the task itself.
Same as C<no_inline> in configuration files, see L</"CONFIGURATION
FILES"> for more information.
=item /*verilator public*/ (parameter)
Used after a parameter declaration to indicate the emitted C code should
@ -3161,6 +3313,9 @@ Instead of using public variables, consider instead making a DPI or public
function that accesses the variable. This is nicer as it provides an
obvious entry point that is also compatible across simulators.
Same as C<public> in configuration files, see L</"CONFIGURATION FILES">
for more information.
=item /*verilator public*/ (task/function)
Used inside the declaration section of a function or task declaration to
@ -3183,6 +3338,9 @@ the model will NOT notice changes made to variables in these functions.
You may want to use DPI exports instead, as it's compatible with other
simulators.
Same as C<public> in configuration files, see L</"CONFIGURATION FILES">
for more information.
=item /*verilator public_flat*/ (variable)
Used after an input, output, register, or wire declaration to indicate the
@ -3191,11 +3349,17 @@ signal. This will not declare this module public, which means the name of
the signal or path to it may change based upon the module inlining which
takes place.
Same as C<public_flat> in configuration files, see L</"CONFIGURATION
FILES"> for more information.
=item /*verilator public_flat_rd*/ (variable)
Used after an input, output, register, or wire declaration to indicate the
signal should be declared public_flat (see above), but read-only.
Same as C<public_flat_rd> in configuration files, see L</"CONFIGURATION
FILES"> for more information.
=item /*verilator public_flat_rw @(<edge_list>) */ (variable)
Used after an input, output, register, or wire declaration to indicate the
@ -3204,6 +3368,9 @@ where writes should be considered to have the timing specified by the given
sensitivity edge list. Set for all variables, ports and wires using the
--public-flat-rw switch.
Same as C<public_flat_rw> in configuration files, see L</"CONFIGURATION
FILES"> for more information.
=item /*verilator public_module*/
Used after a module statement to indicate the module should not be inlined
@ -3212,9 +3379,12 @@ Verilator automatically sets this attribute when the module contains any
public signals or `systemc_ directives. Also set for all modules when
using the --public switch.
Same as C<public> in configuration files, see L</"CONFIGURATION FILES">
for more information.
=item /*verilator sc_clock*/
Rarely needed. Used after an input declaration to indicate the signal
Deprecated. Used after an input declaration to indicate the signal
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.
@ -3226,7 +3396,10 @@ type, instead of bool, vluint32_t or vluint64_t. This may be useful if
the port width is parameterized 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.
usage of sc_bv the performance decreases significantly.
Same as C<sc_bv> in configuration files, see L</"CONFIGURATION FILES">
for more information.
=item /*verilator sformat*/
@ -3235,6 +3408,9 @@ indicate the function or task should pass all remaining arguments through
$sformatf. This allows creation of DPI functions with $display like
behavior. See the test_regress/t/t_dpi_display.v file for an example.
Same as C<sformat> in configuration files, see L</"CONFIGURATION FILES">
for more information.
=item /*verilator tag <text...>*/
Attached after a variable or structure member to indicate opaque (to
@ -4476,6 +4652,37 @@ that is not yet supported in Verilator. See the Limitations chapter.
=back
=head1 DEPRECATIONS
The following deprecated items are scheduled for future removal:
=over 4
=item Pre-C++11 compiler support
Verilator supports pre-C++11 compilers for non-threaded models when
configured with --enable-prec11. This flag will be removed and C++11
compilers will be required for both compiling Verilator and compiling
Verilated models no sooner than September 2020.
=item SystemC 2.1 and earlier support
Support for SystemC versions 2.1 and earlier and the related sc_clock
variable attribute will be removed no sooner than July 2020.
=item Configuration File -msg
The -msg argument to lint_off has been replaced with -rule. -msg is
planned for removal no sooner than January 2021.
=item XML locations
The XML C<fl> attribute has been replaced with C<loc>. C<fl> is planned
for removal no sooner than January 2021.
=back
=head1 FAQ/FREQUENTLY ASKED QUESTIONS
=over 4
@ -4707,7 +4914,7 @@ Most synthesis tools similarly define SYNTHESIS for you.
=item Why do I get "unexpected `do'" or "unexpected `bit'" errors?
Do, bit, ref, return, and other words are now SystemVerilog keywords. You
should change your code to not use them to insure it works with newer
should change your code to not use them to ensure it works with newer
tools. Alternatively, surround them by the Verilog 2005/SystemVerilog
begin_keywords pragma to indicate Verilog 2001 code.

12
ci/docker/run/hooks/post_push Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
# DESCRIPTION: Docker hub hook to tag the latest release (stable)
#
# Copyright 2020 by Stefan Wallentowitz. 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.FROM ubuntu:18.04
if [ "$SOURCE_BRANCH"="stable" ]; then
docker tag $IMAGE_NAME $DOCKER_REPO:latest
docker push $DOCKER_REPO:latest
fi

View File

@ -6,7 +6,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[4.026 2020-01-11],
AC_INIT([Verilator],[4.028 2020-02-06],
[https://verilator.org],
[verilator],[https://verilator.org])
# When releasing, also update header of Changes file
@ -25,11 +25,43 @@ AC_ARG_ENABLE([maintainer-mode],
AC_ARG_ENABLE([silent-rules],
[AS_HELP_STRING([--disable-silent-rules], [ignored])])
# Flag to enable linking specific libraries statically
AC_MSG_CHECKING(whether to perform partial static linking of Verilator binary)
AC_ARG_ENABLE([partial-static],
[AS_HELP_STRING([--disable-partial-static],
[By default, for Verilation peformance, Verilator
is linked against some of its dependencies
statically. Use this to link the Verilator binary
fully dynamically.])],
[case "${enableval}" in
yes) CFG_ENABLE_PARTIAL_STATIC=yes ;;
no) CFG_ENABLE_PARTIAL_STATIC=no ;;
*) AC_MSG_ERROR([bad value '${enableval}' for --disable-partial-static]) ;;
esac],
CFG_ENABLE_PARTIAL_STATIC=yes)
AC_MSG_RESULT($CFG_ENABLE_PARTIAL_STATIC)
# Flag to enable linking Verilator with tcmalloc if available
AC_MSG_CHECKING(whether to use tcmalloc)
AC_ARG_ENABLE([tcmalloc],
[AS_HELP_STRING([--enable-tcmalloc],
[Use libtcmalloc_minimal for faster dynamic memory
management in Verilator binary@<:@default=check@:>@])],
[case "${enableval}" in
yes) CFG_WITH_TCMALLOC=yes ;;
no) CFG_WITH_TCMALLOC=no ;;
*) AC_MSG_ERROR([bad value '${enableval}' for --enable-tcmalloc]) ;;
esac],
[CFG_WITH_TCMALLOC=check;])
AC_MSG_RESULT($CFG_WITH_TCMALLOC)
# Special Substitutions - CFG_WITH_DEFENV
AC_MSG_CHECKING(whether to use 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)])],
[disable using some hardcoded data paths extracted
from some default environment variables (the default
is to use hardcoded paths) in Verilator binary])],
[case "${enableval}" in
yes) CFG_WITH_DEFENV=yes ;;
no) CFG_WITH_DEFENV=no ;;
@ -43,7 +75,8 @@ AC_MSG_RESULT($CFG_WITH_DEFENV)
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])],
[enable showing and stopping on compilation warnings
in Verilator binrary and Verilated makefiles])],
[case "${enableval}" in
yes) CFG_WITH_CCWARN=yes ;;
no) CFG_WITH_CCWARN=no ;;
@ -79,7 +112,8 @@ AC_MSG_RESULT($CFG_WITH_LONGTESTS)
AC_MSG_CHECKING(whether allow pre-C++11)
AC_ARG_ENABLE([prec11],
[AS_HELP_STRING([--enable-prec11],
[enable pre-C++11 compilers])],
[enable pre-C++11 compilers for Verilator binary
and Verilated makefiles])],
[case "${enableval}" in
yes) CFG_WITH_PREC11=yes ;;
no) CFG_WITH_PREC11=no ;;
@ -209,15 +243,26 @@ AC_DEFUN([_MY_LDLIBS_CHECK_FLAG],
LIBS="$ACO_SAVE_LIBS"
])
AC_DEFUN([_MY_LDLIBS_CHECK_OPT],
[# _MY_LDLIBS_CHECK_OPT(flag) -- Check if linker supports specific options
# If it does, append flag to variable
_MY_LDLIBS_CHECK_FLAG($2)
AC_DEFUN([_MY_LDLIBS_CHECK_IFELSE],
[# _MY_LDLIBS_CHECK_IFELSE(flag,action-if-supported,action-if-not-supported)
# Check if linker supports specific flag, if it does do action-if-supported
# otherwise do action-if-not-supported
_MY_LDLIBS_CHECK_FLAG($1)
if test "$_my_result" = "yes" ; then
$1="$$1 $2"
true
$2
else
true
$3
fi
])
AC_DEFUN([_MY_LDLIBS_CHECK_OPT],
[# _MY_LDLIBS_CHECK_OPT(variable, flag) -- Check if linker supports specific
# options. If it does, append flag to variable.
_MY_LDLIBS_CHECK_IFELSE($2, $1="$$1 $2")
])
# Flag to select newest language standard supported
# Macros work such that first option that passes is the one we take
# gnu++17 code is clean, but SystemC in 2018 doesn't link with it (bug1339)
@ -310,6 +355,39 @@ m4_foreach([ldflag], [
AC_SUBST(CFG_LDLIBS_THREADS)
AC_SUBST(CFG_LDFLAGS_THREADS_CMAKE)
# When linking partially statically
if test "$CFG_ENABLE_PARTIAL_STATIC" = "yes"; then
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libgcc)
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libstdc++)
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -Xlinker -gc-sections)
LTCMALLOC=-l:libtcmalloc_minimal.a
else
LTCMALLOC=-ltcmalloc_minimal
fi
AC_SUBST(CFG_LDFLAGS_SRC)
# The pthread library is required by tcmalloc, so add it if it exists. If it
# does not, the tcmalloc check below will fail anyway, and linking against
# pthreads is harmless otherwise.
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lpthread)
# Check if tcmalloc is available based on --enable-tcmalloc
_MY_LDLIBS_CHECK_IFELSE(
$LTCMALLOC,
[if test "$CFG_WITH_TCMALLOC" != "no"; then
CFG_LIBS="$LTCMALLOC $CFG_LIBS";
# If using tcmalloc, add some extra options to make the compiler not assume
# it is using it's own versions of the standard library functions
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-malloc)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-calloc)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-realloc)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-free)
fi],
[if test "$CFG_WITH_TCMALLOC" = "yes"; then
AC_MSG_ERROR([--enable-tcmalloc was given but test for ${LTCMALLOC} failed])
fi])
AC_SUBST(CFG_LIBS)
# Set CFG_WITH_THREADED if can support threading
AC_MSG_CHECKING(whether $CXX supports Verilated threads)
ACO_SAVE_CXXFLAGS="$CXXFLAGS"

View File

@ -11,7 +11,7 @@ contributions flow more efficiently.
https://verilator.org/issues[Verilator Issues].
* If you're unable to find an open issue addressing the problem,
https://verilator.org/issues/new[open a new issue].
https://verilator.org/issues/new[open a new Verilator issue].
** Be sure to include a **code sample** or an **executable test case**
demonstrating the bug and expected behavior that is not occurring.

View File

@ -11,6 +11,7 @@ Chris Randall
Driss Hafdi
Eric Rippey
Garrett Smith
Geza Lore
Gianfranco Costamagna
Howard Su
Iztok Jeras
@ -24,12 +25,14 @@ Lukasz Dalek
Maarten De Braekeleer
Matthew Ballance
Mike Popoloski
Peter Monsson
Patrick Stewart
Peter Monsson
Philipp Wagner
Pieter Kapsenberg
Richard Myers
Sebastien Van Cauwenberghe
Stefan Wallentowitz
Tobias Rosenkranz
Todd Strader
Wilson Snyder
Yutetsu TAKATSUKASA

View File

@ -84,6 +84,10 @@ To build Verilator you will need to install some standard packages:
sudo apt-get install autoconf
sudo apt-get install flex bison
The following are optional, but improve compilation speed:
sudo apt-get install libgoogle-perftools-dev
Additionally, to build or run Verilator you need these standard packages:
sudo apt-get install perl python3

View File

@ -70,7 +70,10 @@ The AST is represented at the top level by the class `AstNode`. This
abstract class has derived classes for the individual components
(e.g. `AstGenerate` for a generate block) or groups of components
(e.g. `AstNodeFTask` for functions and tasks, which in turn has `AstFunc`
and `AstTask` as derived classes).
and `AstTask` as derived classes). An important property of the `AstNode`
type hierarchy is that all non-final subclasses of `AstNode` (i.e.: those
which themselves have subclasses) must be abstract as well, and be named
with the prefix `AstNode*`. The `astgen` (see below) script relies on this.
Each `AstNode` has pointers to up to four children, accessed by the `op1p`
through `op4p` methods. These methods are then abstracted in a specific
@ -394,7 +397,7 @@ e.g. threads.
We will work with contributors to fix up indentation style issues, but it
is appreciated if you could match our style:
* All files should contain the magic header to insure standard indentation:
* All files should contain the magic header to ensure standard indentation:
+
// -*- mode: C++; c-file-style: "cc-mode" -*-
+
@ -959,7 +962,8 @@ src/VParseGrammar.y, as this grammar supports the full SystemVerilog
language and has a lot of back-and-forth with Verilator's grammar. Copy
the appropriate rules to src/verilog.y and modify the productions.
. If a new Ast type is needed, add it to V3AstNodes.h.
. If a new Ast type is needed, add it to V3AstNodes.h. Follow the convention
described above about the AstNode type hierarchy.
. Now you can run "test_regress/t/t_{new testcase}.pl --debug" and it'll
probably fail but you'll see a test_regress/obj_dir/t_{newtestcase}/*.tree

65
docs/xml.adoc Normal file
View File

@ -0,0 +1,65 @@
= Verilator XML Output
:toc: right
// Github doesn't render unless absolute URL
image::https://www.veripool.org/img/verilator_256_200_min.png[Logo,256,200,role="right"]
== Introduction
This document describes Verilator's XML output. For more general information
please see https://verilator.org[verilator.org].
== General
Verilator's XML output is enabled with the `--xml-only` flag. It contains
limited information about the elaborated design including files, modules,
instance hierarchy, logic and data types. There is no formal schema since part
of the structure of the XML document matches the compiled code which would
require the schema to describe legal SystemVerilog structure. The intended
usage is to enable other downstream tools to take advantage of Verilator's
parser.
== Structure
The XML document is consists of 4 sections within the top level `verilator_xml`
element:
`<files>`...`</files>`::
This section contains a list of all design files read, including the
built-in constructs and the command line as their own entries. Each
`<file>` has an attribute `id` which is a short ASCII string unique to that
file. Other elements' `loc` attributes use this id to refer to a particular
file.
`<module_files>`...`</module_files>`::
All files containing Verilog module definitions are listed in this section.
This element's contents is a subset of the `<files>` element's contents.
`<cells>`...`</cells>`::
The cells section of the XML document contains the design instance
hierarchy. Each instance is represented with the `<cell>` element with the
following attributes:
* `fl` (deprecated): The file id and line number where the module was
instanced. Use `loc` instead.
* `loc`: The file id, first line number, last line number, first column
number and last column number of the identifier where the module was
instanced, separated by commas.
* `name`: The instance name.
* `submodname`: The module name uniquified with particular parameter values (if any).
* `hier`: The full hierarchy path.
`<netlist>`...`</netlist>`::
The netlist section contains a number of `<module>`...`</module>` elements,
each describing the contents of that module, and a single `<typetable>`...
`</typetable>` element which lists all used types used within the
modules. Each type has a numeric `id` attribute that is referred to by
elements in the `<module>` elements using the `dtype_id` attribute.

View File

@ -418,9 +418,7 @@ static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_limit = ip + length;
flzuint8* op = (flzuint8*) output;
#ifdef FASTLZ_SAFE
flzuint8* op_limit = op + maxout;
#endif
flzuint32 ctrl = (*ip++) & 31;
int loop = 1;

View File

@ -33,9 +33,6 @@
#else
#include <malloc.h>
#endif
#elif defined(_MSC_VER)
#include <malloc.h>
#define alloca _alloca
#endif
#define wave_alloca alloca
#endif

View File

@ -618,7 +618,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
const char* pctp = NULL; // Most recent %##.##g format
bool inPct = false;
bool widthSet = false;
int width = 0;
bool left = false;
size_t width = 0;
for (const char* pos = formatp; *pos; ++pos) {
if (!inPct && pos[0]=='%') {
pctp = pos;
@ -643,6 +644,10 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
widthSet = true;
width = width*10 + (fmt - '0');
break;
case '-':
left = true;
inPct = true; // Get more digits
break;
case '.':
inPct = true; // Get more digits
break;
@ -662,8 +667,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
case '@': { // Verilog/C++ string
va_arg(ap, int); // # bits is ignored
const std::string* cstrp = va_arg(ap, const std::string*);
if (width > cstrp->size()) output += std::string(width - cstrp->size(), ' ');
output += *cstrp;
std::string padding;
if (width > cstrp->size()) padding.append(width - cstrp->size(), ' ');
output += left ? (*cstrp + padding) : (padding + *cstrp);
break;
}
case 'e':
@ -721,8 +727,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
IData charval = VL_BITRSHIFT_W(lwp, lsb) & 0xff;
field += (charval==0)?' ':charval;
}
if (width > field.size()) output += std::string(width - field.size(), ' ');
output += field;
std::string padding;
if (width > field.size()) padding.append(width - field.size(), ' ');
output += left ? (field + padding) : (padding + field);
break;
}
case 'd': { // Signed decimal
@ -743,14 +750,15 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
digits = append.length();
}
int needmore = width-digits;
std::string padding;
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { // %0
output.append(needmore, '0'); // Pre-pad zero
padding.append(needmore, '0'); // Pre-pad zero
} else {
output.append(needmore, ' '); // Pre-pad spaces
padding.append(needmore, ' '); // Pre-pad spaces
}
}
output += append;
output += left ? (append + padding) : (padding + append);
break;
}
case '#': { // Unsigned decimal
@ -764,14 +772,15 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
digits = append.length();
}
int needmore = width-digits;
std::string padding;
if (needmore>0) {
if (pctp && pctp[0] && pctp[1]=='0') { // %0
output.append(needmore, '0'); // Pre-pad zero
padding.append(needmore, '0'); // Pre-pad zero
} else {
output.append(needmore, ' '); // Pre-pad spaces
padding.append(needmore, ' '); // Pre-pad spaces
}
}
output += append;
output += left ? (append + padding) : (padding + append);
break;
}
case 't': { // Time
@ -786,8 +795,9 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
VL_FATAL_MT(__FILE__, __LINE__, "", "Unsupported VL_TIME_MULTIPLIER");
}
int needmore = width-digits;
if (needmore>0) output.append(needmore, ' '); // Pre-pad spaces
output += tmp;
std::string padding;
if (needmore>0) padding.append(needmore, ' '); // Pad with spaces
output += left ? (tmp + padding) : (padding + tmp);
break;
}
case 'b':
@ -1320,146 +1330,6 @@ IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_
return got;
}
void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData filename, const void* memp, IData start,
IData end) VL_MT_SAFE {
WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename);
return VL_WRITEMEM_W(hex, width, depth, array_lsb, VL_WQ_WORDS_E, fnw, memp, start, end);
}
void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP filenamep, const void* memp, IData start,
IData end) VL_MT_SAFE {
char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
_VL_VINT_TO_STRING(fnwords * VL_EDATASIZE, filenamez, filenamep);
std::string filenames(filenamez);
return VL_WRITEMEM_N(hex, width, depth, array_lsb, filenames, memp, start, end);
}
const char* memhFormat(int nBits) {
assert((nBits >= 1) && (nBits <= 32));
static char buf[32];
switch ((nBits - 1) / 4) {
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
case 2: VL_SNPRINTF(buf, 32, "%%03x"); break;
case 3: VL_SNPRINTF(buf, 32, "%%04x"); break;
case 4: VL_SNPRINTF(buf, 32, "%%05x"); break;
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
default: assert(false); break; // LCOV_EXCL_LINE
}
return buf;
}
void VL_WRITEMEM_N(
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& filename, // Output file name
const void* memp, // Array state
IData start, // First array row address to write
IData end // Last address to write, or ~0 when not specified
) VL_MT_SAFE {
if (VL_UNLIKELY(!hex)) {
VL_FATAL_MT(filename.c_str(), 0, "",
"VL_WRITEMEM_N only supports hex format for now, sorry!");
return;
}
// Calculate row address limits
size_t row_min = array_lsb;
size_t row_max = row_min + depth - 1;
// Normalize the last address argument: ~0 => row_max
size_t nend = (end == ~0u) ? row_max : end;
// Bounds check the write address range
if (VL_UNLIKELY((start < row_min) || (start > row_max)
|| (nend < row_min) || (nend > row_max))) {
VL_FATAL_MT(filename.c_str(), 0, "",
"$writemem specified address out-of-bounds");
return;
}
if (VL_UNLIKELY(start > nend)) {
VL_FATAL_MT(filename.c_str(), 0, "",
"$writemem invalid address range");
return;
}
// Calculate row offset range
size_t row_start = start - row_min;
size_t row_end = nend - row_min;
// Bail out on possible 32-bit size_t overflow
if (VL_UNLIKELY(row_end + 1 == 0)) {
VL_FATAL_MT(filename.c_str(), 0, "", "$writemem address is too large");
return;
}
FILE* fp = fopen(filename.c_str(), "w");
if (VL_UNLIKELY(!fp)) {
VL_FATAL_MT(filename.c_str(), 0, "", "$writemem file not found");
// cppcheck-suppress resourceLeak // fp is NULL - bug in cppcheck
return;
}
for (size_t row_offset = row_start; row_offset <= row_end; ++row_offset) {
if (width <= 8) {
const CData* datap
= &(reinterpret_cast<const CData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 16) {
const SData* datap
= &(reinterpret_cast<const SData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 32) {
const IData* datap
= &(reinterpret_cast<const IData*>(memp))[row_offset];
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
fprintf(fp, "\n");
} else if (width <= 64) {
const QData* datap
= &(reinterpret_cast<const QData*>(memp))[row_offset];
vluint64_t value = VL_MASK_Q(width) & *datap;
vluint32_t lo = value & 0xffffffff;
vluint32_t hi = value >> 32;
fprintf(fp, memhFormat(width - 32), hi);
fprintf(fp, "%08x\n", lo);
} else {
WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
WDataInP datap = &memDatap[row_offset * VL_WORDS_I(width)];
// output as a sequence of VL_EDATASIZE'd words
// from MSB to LSB. Mask off the MSB word which could
// contain junk above the top of valid data.
int word_idx = ((width - 1) / VL_EDATASIZE);
bool first = true;
while (word_idx >= 0) {
EData data = datap[word_idx];
if (first) {
data &= VL_MASK_E(width);
int top_word_nbits = ((width - 1) & (VL_EDATASIZE - 1)) + 1;
fprintf(fp, memhFormat(top_word_nbits), data);
} else {
fprintf(fp, "%08x", data);
}
word_idx--;
first = false;
}
fprintf(fp, "\n");
}
}
fclose(fp);
}
IData VL_FREAD_I(int width, int array_lsb, int array_size,
void* memp, IData fpi, IData start, IData count) VL_MT_SAFE {
// While threadsafe, each thread can only access different file handles
@ -1469,14 +1339,14 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size,
// Prep for reading
IData read_count = 0;
IData read_elements = 0;
int start_shift = (width-1) & ~7; // bit+7:bit gets first character
int start_shift = (width - 1) & ~7; // bit+7:bit gets first character
int shift = start_shift;
// Read the data
// We process a character at a time, as then we don't need to deal
// with changing buffer sizes dynamically, etc.
while (1) {
int c = fgetc(fp);
if (VL_UNLIKELY(c==EOF)) break;
if (VL_UNLIKELY(c == EOF)) break;
// Shift value in
IData entry = read_elements + start - array_lsb;
if (width <= 8) {
@ -1513,144 +1383,6 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size,
return read_count;
}
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
QData filename, void* memp, IData start, IData end) VL_MT_SAFE {
WData fnw[VL_WQ_WORDS_E]; VL_SET_WQ(fnw, filename);
return VL_READMEM_W(hex, width, depth, array_lsb, VL_WQ_WORDS_E, fnw, memp, start, end);
}
void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP filenamep, void* memp, IData start, IData end) VL_MT_SAFE {
char filenamez[VL_TO_STRING_MAX_WORDS * VL_EDATASIZE + 1];
_VL_VINT_TO_STRING(fnwords * VL_EDATASIZE, filenamez, filenamep);
std::string filenames(filenamez);
return VL_READMEM_N(hex, width, depth, array_lsb, filenames, memp, start, end);
}
void VL_READMEM_N(
bool hex, // Hex format, else binary
int width, // Width of each array row
int depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& filename, // Input file name
void* memp, // Array state
IData start, // First array row address to read
IData end // Last row address to read
) VL_MT_SAFE {
FILE* fp = fopen(filename.c_str(), "r");
if (VL_UNLIKELY(!fp)) {
// We don't report the Verilog source filename as it slow to have to pass it down
VL_FATAL_MT(filename.c_str(), 0, "", "$readmem file not found");
// cppcheck-suppress resourceLeak // fp is NULL - bug in cppcheck
return;
}
// Prep for reading
IData addr = start;
int linenum = 1;
bool innum = false;
bool ignore_to_eol = false;
bool ignore_to_cmt = false;
bool needinc = false;
bool reading_addr = false;
int lastc = ' ';
// Read the data
// We process a character at a time, as then we don't need to deal
// with changing buffer sizes dynamically, etc.
while (1) {
int c = fgetc(fp);
if (VL_UNLIKELY(c==EOF)) break;
//printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n",
// linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc);
if (c=='\n') {
linenum++; ignore_to_eol = false;
if (innum) reading_addr = false;
innum = false;
}
else if (c=='\t' || c==' ' || c=='\r' || c=='\f') {
if (innum) reading_addr = false;
innum = false;
}
// Skip // comments and detect /* comments
else if (ignore_to_cmt && lastc=='*' && c=='/') {
ignore_to_cmt = false; if (innum) reading_addr=false; innum=false;
} else if (!ignore_to_eol && !ignore_to_cmt) {
if (lastc=='/' && c=='*') { ignore_to_cmt = true; }
else if (lastc=='/' && c=='/') { ignore_to_eol = true; }
else if (c=='/') {} // Part of /* or //
else if (c=='#') { ignore_to_eol = true; }
else if (c=='_') {}
else if (c=='@') { reading_addr = true; innum=false; needinc=false; }
// Check for hex or binary digits as file format requests
else if (isxdigit(c) || (!reading_addr && (c=='x' || c=='X'))) {
c = tolower(c);
int value = (c >= 'a' ? (c=='x' ? VL_RAND_RESET_I(4) : (c-'a'+10)) : (c-'0'));
if (!innum) { // Prep for next number
if (needinc) { addr++; needinc=false; }
}
if (reading_addr) {
// Decode @ addresses
if (!innum) addr=0;
addr = (addr<<4) + value;
} else {
needinc = true;
//printf(" Value width=%d @%x = %c\n", width, addr, c);
if (VL_UNLIKELY(addr >= static_cast<IData>(depth+array_lsb)
|| addr < static_cast<IData>(array_lsb))) {
VL_FATAL_MT(filename.c_str(), linenum, "",
"$readmem file address beyond bounds of array");
} else {
int entry = addr - array_lsb;
QData shift = hex ? VL_ULL(4) : VL_ULL(1);
// Shift value in
if (width<=8) {
CData* datap = &(reinterpret_cast<CData*>(memp))[entry];
if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
} else if (width<=16) {
SData* datap = &(reinterpret_cast<SData*>(memp))[entry];
if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
} else if (width <= VL_IDATASIZE) {
IData* datap = &(reinterpret_cast<IData*>(memp))[entry];
if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(width);
} else if (width<=VL_QUADSIZE) {
QData* datap = &(reinterpret_cast<QData*>(memp))[entry];
if (!innum) { *datap = 0; }
*datap = ((*datap << static_cast<QData>(shift))
+ static_cast<QData>(value)) & VL_MASK_Q(width);
} else {
WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))
[ entry*VL_WORDS_I(width) ];
if (!innum) { VL_ZERO_RESET_W(width, datap); }
_VL_SHIFTL_INPLACE_W(width, datap, static_cast<IData>(shift));
datap[0] |= value;
}
if (VL_UNLIKELY(value>=(1<<shift))) {
VL_FATAL_MT(filename.c_str(), linenum, "",
"$readmemb (binary) file contains hex characters");
}
}
}
innum = true;
}
else {
VL_FATAL_MT(filename.c_str(), linenum, "", "$readmem file syntax error");
}
}
lastc = c;
}
if (needinc) { addr++; }
// Final checks
fclose(fp);
if (VL_UNLIKELY(end != VL_UL(0xffffffff) && addr != (end+1))) {
VL_FATAL_MT(filename.c_str(), linenum, "",
"$readmem file ended before specified ending-address");
}
}
IData VL_SYSTEM_IQ(QData lhs) VL_MT_SAFE {
WData lhsw[VL_WQ_WORDS_E]; VL_SET_WQ(lhsw, lhs);
return VL_SYSTEM_IW(VL_WQ_WORDS_E, lhsw);
@ -1795,6 +1527,9 @@ std::string VL_TO_STRING(IData lhs) {
std::string VL_TO_STRING(QData lhs) {
return VL_SFORMATF_NX("'h%0x", 64, lhs);
}
std::string VL_TO_STRING_W(int words, WDataInP obj) {
return VL_SFORMATF_NX("'h%0x", words * VL_EDATASIZE, obj);
}
std::string VL_TOLOWER_NN(const std::string& ld) VL_MT_SAFE {
std::string out = ld;
@ -1867,6 +1602,315 @@ IData VL_ATOI_N(const std::string& str, int base) VL_PURE {
return static_cast<IData>(v);
}
//===========================================================================
// Readmem/writemem
static const char* memhFormat(int nBits) {
assert((nBits >= 1) && (nBits <= 32));
static char buf[32];
switch ((nBits - 1) / 4) {
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
case 2: VL_SNPRINTF(buf, 32, "%%03x"); break;
case 3: VL_SNPRINTF(buf, 32, "%%04x"); break;
case 4: VL_SNPRINTF(buf, 32, "%%05x"); break;
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
default: assert(false); break; // LCOV_EXCL_LINE
}
return buf;
}
VlReadMem::VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end)
: m_hex(hex)
, m_bits(bits)
, m_filename(filename)
, m_end(end)
, m_addr(start)
, m_linenum(0) {
m_fp = fopen(filename.c_str(), "r");
if (VL_UNLIKELY(!m_fp)) {
// We don't report the Verilog source filename as it slow to have to pass it down
VL_FATAL_MT(filename.c_str(), 0, "", "$readmem file not found");
// cppcheck-suppress resourceLeak // m_fp is NULL - bug in cppcheck
return;
}
}
VlReadMem::~VlReadMem() {
if (m_fp) { fclose(m_fp); m_fp = NULL; }
}
bool VlReadMem::get(QData& addrr, std::string& valuer) {
if (VL_UNLIKELY(!m_fp)) return false;
valuer = "";
// Prep for reading
bool indata = false;
bool ignore_to_eol = false;
bool ignore_to_cmt = false;
bool reading_addr = false;
int lastc = ' ';
// Read the data
// We process a character at a time, as then we don't need to deal
// with changing buffer sizes dynamically, etc.
while (1) {
int c = fgetc(m_fp);
if (VL_UNLIKELY(c == EOF)) break;
// printf("%d: Got '%c' Addr%lx IN%d IgE%d IgC%d\n",
// m_linenum, c, m_addr, indata, ignore_to_eol, ignore_to_cmt);
// See if previous data value has completed, and if so return
if (c == '_') continue; // Ignore _ e.g. inside a number
if (indata && !isxdigit(c) && c != 'x' && c != 'X') {
// printf("Got data @%lx = %s\n", m_addr, valuer.c_str());
indata = false;
ungetc(c, m_fp);
addrr = m_addr;
++m_addr;
return true;
}
// Parse line
if (c == '\n') {
++m_linenum; ignore_to_eol = false;
reading_addr = false;
} else if (c == '\t' || c == ' ' || c == '\r' || c == '\f') {
reading_addr = false;
}
// Skip // comments and detect /* comments
else if (ignore_to_cmt && lastc == '*' && c == '/') {
ignore_to_cmt = false;
reading_addr = false;
} else if (!ignore_to_eol && !ignore_to_cmt) {
if (lastc == '/' && c == '*') { ignore_to_cmt = true; }
else if (lastc == '/' && c == '/') { ignore_to_eol = true; }
else if (c == '/') {} // Part of /* or //
else if (c == '#') { ignore_to_eol = true; }
else if (c == '@') { reading_addr = true; m_addr = 0; }
// Check for hex or binary digits as file format requests
else if (isxdigit(c) || (!reading_addr && (c == 'x' || c == 'X'))) {
c = tolower(c);
int value = (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c-'a'+10)) : (c-'0'));
if (reading_addr) {
// Decode @ addresses
m_addr = (m_addr << 4) + value;
} else {
indata = true;
valuer += c;
// printf(" Value width=%d @%x = %c\n", width, m_addr, c);
if (VL_UNLIKELY(value > 1 && !m_hex)) {
VL_FATAL_MT(m_filename.c_str(), m_linenum, "",
"$readmemb (binary) file contains hex characters");
}
}
} else {
VL_FATAL_MT(m_filename.c_str(), m_linenum, "", "$readmem file syntax error");
}
}
lastc = c;
}
if (VL_UNLIKELY(m_end != ~VL_ULL(0) && m_addr <= m_end)) {
VL_FATAL_MT(m_filename.c_str(), m_linenum, "",
"$readmem file ended before specified final address (IEEE 2017 21.4)");
}
return false; // EOF
}
void VlReadMem::setData(void* valuep, const std::string& rhs) {
QData shift = m_hex ? VL_ULL(4) : VL_ULL(1);
bool innum = false;
// Shift value in
for (std::string::const_iterator it = rhs.begin(); it != rhs.end(); ++it) {
char c = tolower(*it);
int value = (c >= 'a' ? (c == 'x' ? VL_RAND_RESET_I(4) : (c - 'a' + 10)) : (c - '0'));
if (m_bits <= 8) {
CData* datap = reinterpret_cast<CData*>(valuep);
if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(m_bits);
} else if (m_bits <= 16) {
SData* datap = reinterpret_cast<SData*>(valuep);
if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(m_bits);
} else if (m_bits <= VL_IDATASIZE) {
IData* datap = reinterpret_cast<IData*>(valuep);
if (!innum) { *datap = 0; }
*datap = ((*datap << shift) + value) & VL_MASK_I(m_bits);
} else if (m_bits <= VL_QUADSIZE) {
QData* datap = reinterpret_cast<QData*>(valuep);
if (!innum) { *datap = 0; }
*datap = ((*datap << static_cast<QData>(shift)) + static_cast<QData>(value))
& VL_MASK_Q(m_bits);
} else {
WDataOutP datap = reinterpret_cast<WDataOutP>(valuep);
if (!innum) { VL_ZERO_RESET_W(m_bits, datap); }
_VL_SHIFTL_INPLACE_W(m_bits, datap, static_cast<IData>(shift));
datap[0] |= value;
}
innum = true;
}
}
VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end)
: m_bits(bits)
, m_addr(0) {
if (VL_UNLIKELY(!hex)) {
VL_FATAL_MT(filename.c_str(), 0, "",
"Unsupported: $writemem binary format (suggest hex format)");
return;
}
if (VL_UNLIKELY(start > end)) {
VL_FATAL_MT(filename.c_str(), 0, "", "$writemem invalid address range");
return;
}
m_fp = fopen(filename.c_str(), "w");
if (VL_UNLIKELY(!m_fp)) {
VL_FATAL_MT(filename.c_str(), 0, "", "$writemem file not found");
// cppcheck-suppress resourceLeak // m_fp is NULL - bug in cppcheck
return;
}
}
VlWriteMem::~VlWriteMem() {
if (m_fp) { fclose(m_fp); m_fp = NULL; }
}
void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
if (VL_UNLIKELY(!m_fp)) return;
if (addr != m_addr && addrstamp) { // Only assoc has time stamps
fprintf(m_fp, "@%" VL_PRI64 "x\n", addr);
}
m_addr = addr + 1;
if (m_bits <= 8) {
const CData* datap = reinterpret_cast<const CData*>(valuep);
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
} else if (m_bits <= 16) {
const SData* datap = reinterpret_cast<const SData*>(valuep);
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
} else if (m_bits <= 32) {
const IData* datap = reinterpret_cast<const IData*>(valuep);
fprintf(m_fp, memhFormat(m_bits), VL_MASK_I(m_bits) & *datap);
fprintf(m_fp, "\n");
} else if (m_bits <= 64) {
const QData* datap = reinterpret_cast<const QData*>(valuep);
vluint64_t value = VL_MASK_Q(m_bits) & *datap;
vluint32_t lo = value & 0xffffffff;
vluint32_t hi = value >> 32;
fprintf(m_fp, memhFormat(m_bits - 32), hi);
fprintf(m_fp, "%08x\n", lo);
} else {
WDataInP datap = reinterpret_cast<WDataInP>(valuep);
// output as a sequence of VL_EDATASIZE'd words
// from MSB to LSB. Mask off the MSB word which could
// contain junk above the top of valid data.
int word_idx = ((m_bits - 1) / VL_EDATASIZE);
bool first = true;
while (word_idx >= 0) {
EData data = datap[word_idx];
if (first) {
data &= VL_MASK_E(m_bits);
int top_word_nbits = VL_BITBIT_E(m_bits - 1) + 1;
fprintf(m_fp, memhFormat(top_word_nbits), data);
} else {
fprintf(m_fp, "%08x", data);
}
word_idx--;
first = false;
}
fprintf(m_fp, "\n");
}
}
void VL_READMEM_N(bool hex, // Hex format, else binary
int bits, // M_Bits of each array row
QData depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& filename, // Input file name
void* memp, // Array state
QData start, // First array row address to read
QData end // Last row address to read
) VL_MT_SAFE {
QData addr_max = array_lsb + depth - 1;
if (start < array_lsb) start = array_lsb;
QData addr_end = end;
if (addr_end > addr_max) addr_end = addr_max;
VlReadMem rmem(hex, bits, filename, start, end);
if (VL_UNLIKELY(!rmem.isOpen())) return;
while (1) {
QData addr;
std::string value;
if (rmem.get(addr /*ref*/, value/*ref*/)) {
if (VL_UNLIKELY(addr < static_cast<QData>(array_lsb)
|| addr >= static_cast<QData>(array_lsb + depth))) {
VL_FATAL_MT(filename.c_str(), rmem.linenum(), "",
"$readmem file address beyond bounds of array");
} else {
QData entry = addr - array_lsb;
if (bits <= 8) {
CData* datap = &(reinterpret_cast<CData*>(memp))[entry];
rmem.setData(datap, value);
} else if (bits <= 16) {
SData* datap = &(reinterpret_cast<SData*>(memp))[entry];
rmem.setData(datap, value);
} else if (bits <= VL_IDATASIZE) {
IData* datap = &(reinterpret_cast<IData*>(memp))[entry];
rmem.setData(datap, value);
} else if (bits <= VL_QUADSIZE) {
QData* datap = &(reinterpret_cast<QData*>(memp))[entry];
rmem.setData(datap, value);
} else {
WDataOutP datap = &(reinterpret_cast<WDataOutP>(memp))
[ entry*VL_WORDS_I(bits) ];
rmem.setData(datap, value);
}
}
} else {
break;
}
}
}
void VL_WRITEMEM_N(bool hex, // Hex format, else binary
int bits, // Width of each array row
QData depth, // Number of rows
int array_lsb, // Index of first row. Valid row addresses
// // range from array_lsb up to (array_lsb + depth - 1)
const std::string& filename, // Output file name
const void* memp, // Array state
QData start, // First array row address to write
QData end // Last address to write, or ~0 when not specified
) VL_MT_SAFE {
QData addr_max = array_lsb + depth - 1;
if (start < array_lsb) start = array_lsb;
if (end > addr_max) end = addr_max;
VlWriteMem wmem(hex, bits, filename, start, end);
if (VL_UNLIKELY(!wmem.isOpen())) return;
for (QData addr = start; addr <= end; ++addr) {
QData row_offset = addr - array_lsb;
if (bits <= 8) {
const CData* datap = &(reinterpret_cast<const CData*>(memp))[row_offset];
wmem.print(addr, false, datap);
} else if (bits <= 16) {
const SData* datap = &(reinterpret_cast<const SData*>(memp))[row_offset];
wmem.print(addr, false, datap);
} else if (bits <= 32) {
const IData* datap = &(reinterpret_cast<const IData*>(memp))[row_offset];
wmem.print(addr, false, datap);
} else if (bits <= 64) {
const QData* datap = &(reinterpret_cast<const QData*>(memp))[row_offset];
wmem.print(addr, false, datap);
} else {
WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
WDataInP datap = &memDatap[row_offset * VL_WORDS_I(bits)];
wmem.print(addr, false, datap);
}
}
}
//===========================================================================
// Timescale conversion
@ -2352,9 +2396,9 @@ VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTIN
void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
// Slowpath - Called only when find has failed
std::string msg = (std::string("Testbench C called '")
+VerilatedImp::exportName(funcnum)
+"' but scope wasn't set, perhaps due to dpi import call without 'context'");
std::string msg = (std::string("Testbench C called '") + VerilatedImp::exportName(funcnum)
+ "' but scope wasn't set, perhaps due to dpi import call without "
+ "'context', or missing svSetScope. See IEEE 1800-2017 35.5.3.");
VL_FATAL_MT("unknown", 0, "", msg.c_str());
return NULL;
}

View File

@ -630,22 +630,6 @@ extern void VL_FCLOSE_I(IData fdi);
extern IData VL_FREAD_I(int width, int array_lsb, int array_size,
void* memp, IData fpi, IData start, IData count);
extern void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP filenamep, void* memp, IData start, IData end);
extern void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
QData filename, void* memp, IData start, IData end);
inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords,
IData filename, void* memp, IData start, IData end) VL_MT_SAFE {
VL_READMEM_Q(hex, width, depth, array_lsb, fnwords, filename, memp, start, end); }
extern void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
WDataInP filenamep, const void* memp, IData start, IData end);
extern void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
QData filename, const void* memp, IData start, IData end);
inline void VL_WRITEMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords,
IData filename, const void* memp, IData start, IData end) VL_MT_SAFE {
VL_WRITEMEM_Q(hex, width, depth, array_lsb, fnwords, filename, memp, start, end); }
extern void VL_WRITEF(const char* formatp, ...);
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);

View File

@ -73,12 +73,12 @@ private:
public:
// METHODS
// cppcheck-suppress truncLongCastReturn
virtual vluint64_t count() const { return *m_countp; }
virtual void zero() const { *m_countp = 0; }
virtual vluint64_t count() const VL_OVERRIDE { return *m_countp; }
virtual void zero() const VL_OVERRIDE { *m_countp = 0; }
// CONSTRUCTORS
// cppcheck-suppress noExplicitConstructor
VerilatedCoverItemSpec(T* countp) : m_countp(countp) { *m_countp = 0; }
virtual ~VerilatedCoverItemSpec() {}
virtual ~VerilatedCoverItemSpec() VL_OVERRIDE {}
};
//=============================================================================
@ -222,7 +222,7 @@ private:
void clearGuts() VL_REQUIRES(m_mutex) {
for (ItemList::const_iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it);
delete itemp;
VL_DO_DANGLING(delete itemp, itemp);
}
m_items.clear();
m_indexValues.clear();
@ -244,7 +244,7 @@ public:
for (ItemList::iterator it=m_items.begin(); it!=m_items.end(); ++it) {
VerilatedCovImpItem* itemp = *(it);
if (!itemMatchesString(itemp, matchp)) {
delete itemp;
VL_DO_DANGLING(delete itemp, itemp);
} else {
newlist.push_back(itemp);
}

View File

@ -20,6 +20,7 @@
//=============================================================================
// SPDIFF_OFF
#define __STDC_LIMIT_MACROS // UINT64_MAX
#include "verilatedos.h"
#include "verilated.h"
#include "verilated_fst_c.h"
@ -47,6 +48,7 @@
#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
# include <io.h>
#else
# include <stdint.h>
# include <unistd.h>
#endif

View File

@ -42,6 +42,38 @@ extern std::string VL_TO_STRING(SData obj);
extern std::string VL_TO_STRING(IData obj);
extern std::string VL_TO_STRING(QData obj);
inline std::string VL_TO_STRING(const std::string& obj) { return "\"" + obj + "\""; }
extern std::string VL_TO_STRING_W(int words, WDataInP obj);
//===================================================================
// Readmem/Writemem operation classes
class VlReadMem {
bool m_hex; // Hex format
int m_bits; // Bit width of values
const std::string& m_filename; // Filename
QData m_end; // End address (as specified by user)
FILE* m_fp; // File handle for filename
QData m_addr; // Next address to read
int m_linenum; // Line number last read from file
public:
VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end);
~VlReadMem();
bool isOpen() const { return m_fp != NULL; }
int linenum() const { return m_linenum; }
bool get(QData& addrr, std::string& valuer);
void setData(void* valuep, const std::string& rhs);
};
class VlWriteMem {
int m_bits; // Bit width of values
FILE* m_fp; // File handle for filename
QData m_addr; // Next address to write
public:
VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end);
~VlWriteMem();
bool isOpen() const { return m_fp != NULL; }
void print(QData addr, bool addrstamp, const void* valuep);
};
//===================================================================
// Verilog array container
@ -72,6 +104,10 @@ VlWide<T_Words>& VL_CVT_W_A(WDataInP inp, const VlWide<T_Words>&) {
return *((VlWide<T_Words>*)inp);
}
template <std::size_t T_Words>
std::string VL_TO_STRING(const VlWide<T_Words>& obj) {
return VL_TO_STRING_W(T_Words, obj.data());
}
//===================================================================
// Verilog associative array container
@ -180,6 +216,34 @@ std::string VL_TO_STRING(const VlAssocArray<T_Key, T_Value>& obj) {
return obj.to_string();
}
template <class T_Key, class T_Value>
void VL_READMEM_N(bool hex, int bits, const std::string& filename,
VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
VlReadMem rmem(hex, bits, filename, start, end);
if (VL_UNLIKELY(!rmem.isOpen())) return;
while (1) {
QData addr;
std::string data;
if (rmem.get(addr /*ref*/, data /*ref*/)) {
rmem.setData(&(obj.at(addr)), data);
} else {
break;
}
}
}
template <class T_Key, class T_Value>
void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename,
const VlAssocArray<T_Key, T_Value>& obj, QData start, QData end) VL_MT_SAFE {
VlWriteMem wmem(hex, bits, filename, start, end);
if (VL_UNLIKELY(!wmem.isOpen())) return;
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = obj.begin(); it != obj.end();
++it) {
QData addr = it->first;
if (addr >= start && addr <= end) wmem.print(addr, true, &(it->second));
}
}
//===================================================================
// Verilog queue container
// There are no multithreaded locks on this; the base variable must
@ -312,12 +376,12 @@ extern std::string VL_TOLOWER_NN(const std::string& ld);
extern std::string VL_TOUPPER_NN(const std::string& ld);
extern IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE;
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb,
const std::string& filename,
void* memp, IData start, IData end) VL_MT_SAFE;
extern void VL_WRITEMEM_N(bool hex, int width, int depth, int array_lsb,
const std::string& filename,
const void* memp, IData start, IData end) VL_MT_SAFE;
extern void VL_READMEM_N(bool hex, int bits, QData depth, int array_lsb,
const std::string& filename, void* memp, QData start,
QData end) VL_MT_SAFE;
extern void VL_WRITEMEM_N(bool hex, int bits, QData depth, int array_lsb,
const std::string& filename, const void* memp, QData start,
QData end) VL_MT_SAFE;
extern IData VL_SSCANF_INX(int lbits, const std::string& ld,
const char* formatp, ...) VL_MT_SAFE;
extern void VL_SFORMAT_X(int obits_ignored, std::string& output,

View File

@ -164,12 +164,12 @@ private:
public:
// CONSTRUCTORS
VerilatedSave() { m_fd = -1; }
virtual ~VerilatedSave() { close(); }
virtual ~VerilatedSave() VL_OVERRIDE { close(); }
// METHODS
void open(const char* filenamep) VL_MT_UNSAFE_ONE; ///< Open the file; call isOpen() to see if errors
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
virtual void close() VL_MT_UNSAFE_ONE;
virtual void flush() VL_MT_UNSAFE_ONE;
virtual void close() VL_OVERRIDE VL_MT_UNSAFE_ONE;
virtual void flush() VL_OVERRIDE VL_MT_UNSAFE_ONE;
};
//=============================================================================
@ -183,14 +183,14 @@ private:
public:
// CONSTRUCTORS
VerilatedRestore() { m_fd = -1; }
virtual ~VerilatedRestore() { close(); }
virtual ~VerilatedRestore() VL_OVERRIDE { close(); }
// METHODS
void open(const char* filenamep) VL_MT_UNSAFE_ONE; ///< Open the file; call isOpen() to see if errors
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
virtual void close() VL_MT_UNSAFE_ONE;
virtual void flush() VL_MT_UNSAFE_ONE {}
virtual void fill() VL_MT_UNSAFE_ONE;
virtual void close() VL_OVERRIDE VL_MT_UNSAFE_ONE;
virtual void flush() VL_OVERRIDE VL_MT_UNSAFE_ONE {}
virtual void fill() VL_OVERRIDE VL_MT_UNSAFE_ONE;
};
//=============================================================================

View File

@ -212,7 +212,7 @@ public:
}
}
~vl_unordered_set() {
delete [] m_bucketsp; VL_DANGLING(m_bucketsp);
VL_DO_DANGLING(delete [] m_bucketsp, m_bucketsp);
}
vl_unordered_set& operator=(const vl_unordered_set& other) {

View File

@ -1993,7 +1993,7 @@ PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
}
if (!_error_info_p) return 0; // no error occured
return _error_info_p->level; // return error severity level
};
}
PLI_INT32 vpi_free_object(vpiHandle object) {
VerilatedVpiImp::assertOneCheck();
@ -2008,7 +2008,7 @@ PLI_INT32 vpi_release_handle(vpiHandle object) {
_VL_VPI_ERROR_RESET();
if (VL_UNLIKELY(!vop)) return 0;
vpi_remove_cb(object); // May not be a callback, but that's ok
delete vop;
VL_DO_DANGLING(delete vop, vop);
return 1;
}

View File

@ -154,11 +154,19 @@
#define VL_UL(c) (static_cast<IData>(c##UL)) ///< Add appropriate suffix to 32-bit constant
#if defined(VL_CPPCHECK) || defined(__clang_analyzer__)
# define VL_DANGLING(v)
# define VL_DANGLING(var)
#else
# define VL_DANGLING(v) do { (v) = NULL; } while(0) ///< After e.g. delete, set variable to NULL to indicate must not use later
///< After e.g. delete, set variable to NULL to indicate must not use later
# define VL_DANGLING(var) do { (var) = NULL; } while(0)
#endif
///< Perform an e.g. delete, then set variable to NULL to indicate must not use later.
///< Unlike VL_DO_CLEAR the setting of the variable is only for debug reasons.
#define VL_DO_DANGLING(stmt, var) do { do { stmt; } while(0); VL_DANGLING(var); } while(0)
///< Perform an e.g. delete, then set variable to NULL as a requirement
#define VL_DO_CLEAR(stmt, stmt2) do { do { stmt; } while(0); do { stmt2; } while(0); } while(0)
//=========================================================================
// C++-2011
@ -176,11 +184,15 @@
# define VL_INCLUDE_UNORDERED_MAP <unordered_map>
# define VL_INCLUDE_UNORDERED_SET <unordered_set>
# endif
# define VL_FINAL final
# define VL_OVERRIDE override
#else
# define VL_EQ_DELETE
# define vl_unique_ptr std::auto_ptr
# define VL_INCLUDE_UNORDERED_MAP "verilated_unordered_set_map.h"
# define VL_INCLUDE_UNORDERED_SET "verilated_unordered_set_map.h"
# define VL_FINAL
# define VL_OVERRIDE
#endif
//=========================================================================
@ -261,6 +273,10 @@ typedef signed __int32 ssize_t; ///< signed size_t; returned fro
#else // Linux or compliant Unix flavors, -m64
// The inttypes supplied with some GCC versions requires STDC_FORMAT_MACROS
// to be declared in order to get the PRIxx macros used by fstapi.c
#define __STDC_FORMAT_MACROS
# include <inttypes.h> // Solaris
# include <stdint.h> // Linux and most flavors
# include <sys/types.h> // __WORDSIZE
@ -324,6 +340,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#define VL_QUADSIZE 64 ///< Bits in a QData / quadword
#define VL_EDATASIZE 32 ///< Bits in a EData (WData entry)
#define VL_EDATASIZE_LOG2 5 ///< log2(VL_EDATASIZE)
#define VL_CACHE_LINE_BYTES 64 ///< Bytes in a cache line (for alignment)
/// Bytes this number of bits needs (1 bit=1 byte)
#define VL_BYTES_I(nbits) (((nbits) + (VL_BYTESIZE - 1)) / VL_BYTESIZE)

View File

@ -68,6 +68,8 @@ CFG_CXXFLAGS_SRC = @CFG_CXXFLAGS_SRC@
CFG_CXXFLAGS_PARSER = @CFG_CXXFLAGS_PARSER@
# Compiler flags that turn on extra warnings
CFG_CXXFLAGS_WEXTRA = @CFG_CXXFLAGS_WEXTRA@
CFG_LDFLAGS_SRC = @CFG_LDFLAGS_SRC@
CFG_LIBS = @CFG_LIBS@
#### End of system configuration section. ####
@ -91,8 +93,7 @@ endif
#CCMALLOC = /usr/local/lib/ccmalloc-gcc.o -lccmalloc -ldl
# -lfl not needed as Flex invoked with %nowrap option
# -lstdc++ needed for clang, believed harmless with gcc
LIBS = -lm -lstdc++
LIBS = $(CFG_LIBS) -lm
CPPFLAGS += -MMD
CPPFLAGS += -I. -I$(bldsrc) -I$(srcdir) -I$(incdir) -I../../include
@ -106,6 +107,7 @@ CPPFLAGS += -W -Wall $(CFG_CXXFLAGS_WEXTRA) $(CFG_CXXFLAGS_SRC) -Werror
else
CPPFLAGS += $(CFG_CXXFLAGS_SRC)
endif
LDFLAGS += $(CFG_LDFLAGS_SRC)
CPPFLAGSWALL = $(CPPFLAGS)
CPPFLAGSPARSER = $(CPPFLAGS) $(CFG_CXXFLAGS_PARSER)
@ -164,6 +166,7 @@ RAW_OBJS = \
V3Branch.o \
V3Broken.o \
V3CCtors.o \
V3CUse.o \
V3Case.o \
V3Cast.o \
V3Cdc.o \
@ -193,6 +196,7 @@ RAW_OBJS = \
V3FileLine.o \
V3Gate.o \
V3GenClk.o \
V3Global.o \
V3Graph.o \
V3GraphAlg.o \
V3GraphAcyc.o \

View File

@ -70,7 +70,7 @@ private:
m_scopep->addActivep(nodep);
}
// VISITORS
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
m_scopep = nodep;
m_iActivep = NULL;
m_cActivep = NULL;
@ -79,15 +79,15 @@ private:
iterateChildren(nodep);
// Don't clear scopep, the namer persists beyond this visit
}
virtual void visit(AstSenTree* nodep) {
virtual void visit(AstSenTree* nodep) VL_OVERRIDE {
// Simplify sensitivity list
V3Const::constifyExpensiveEdit(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(V3Const::constifyExpensiveEdit(nodep), nodep);
}
// Empty visitors, speed things up
virtual void visit(AstNodeStmt* nodep) { }
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE { }
//--------------------
// Default
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}
@ -163,7 +163,7 @@ private:
AstNode* m_alwaysp; // Always we're under
AstNode* m_assignp; // In assign
// VISITORS
virtual void visit(AstAssignDly* nodep) {
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
if (m_check != CT_SEQ) {
// Convert to a non-delayed assignment
UINFO(5," ASSIGNDLY "<<nodep<<endl);
@ -181,10 +181,10 @@ private:
nodep->lhsp()->unlinkFrBack(),
nodep->rhsp()->unlinkFrBack());
nodep->replaceWith(newp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
virtual void visit(AstAssign* nodep) {
virtual void visit(AstAssign* nodep) VL_OVERRIDE {
if (m_check == CT_SEQ) {
AstNode* las = m_assignp;
m_assignp = nodep;
@ -192,7 +192,7 @@ private:
m_assignp = las;
}
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
AstVar* varp = nodep->varp();
if (m_check == CT_SEQ
&& m_assignp
@ -210,7 +210,7 @@ private:
}
}
//--------------------
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -240,7 +240,7 @@ private:
bool m_itemSequent; // Found a SenItem sequential
// VISITORS
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
// Create required actives and add to scope
UINFO(4," SCOPE "<<nodep<<endl);
// Clear last scope's names, and collect this scope's existing names
@ -248,10 +248,10 @@ private:
m_scopeFinalp = NULL;
iterateChildren(nodep);
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
// Actives are being formed, so we can ignore any already made
}
virtual void visit(AstInitial* nodep) {
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
// Relink to IACTIVE, unless already under it
UINFO(4," INITIAL "<<nodep<<endl);
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
@ -259,32 +259,32 @@ private:
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstAssignAlias* nodep) {
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
// Relink to CACTIVE, unless already under it
UINFO(4," ASSIGNW "<<nodep<<endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstAssignW* nodep) {
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
// Relink to CACTIVE, unless already under it
UINFO(4," ASSIGNW "<<nodep<<endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstCoverToggle* nodep) {
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
// Relink to CACTIVE, unless already under it
UINFO(4," COVERTOGGLE "<<nodep<<endl);
AstActive* wantactivep = m_namer.getCActive(nodep->fileline());
nodep->unlinkFrBack();
wantactivep->addStmtsp(nodep);
}
virtual void visit(AstFinal* nodep) {
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
// Relink to CFUNC for the final
UINFO(4," FINAL "<<nodep<<endl);
if (!nodep->bodysp()) { // Empty, Kill it.
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_INITIAL);
@ -303,7 +303,7 @@ private:
nodep->unlinkFrBack();
m_scopeFinalp->addStmtsp(new AstComment(nodep->fileline(), nodep->typeName(), true));
m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext());
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
// METHODS
@ -316,7 +316,7 @@ private:
// Never executing. Kill it.
UASSERT_OBJ(!oldsensesp->sensesp()->nextp(), nodep,
"Never senitem should be alone, else the never should be eliminated.");
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
@ -353,7 +353,7 @@ private:
// Delete sensitivity list
if (oldsensesp) {
oldsensesp->unlinkFrBackWithNext()->deleteTree(); VL_DANGLING(oldsensesp);
VL_DO_DANGLING(oldsensesp->unlinkFrBackWithNext()->deleteTree(), oldsensesp);
}
// Move node to new active
@ -372,25 +372,25 @@ private:
ActiveDlyVisitor dlyvisitor (nodep, ActiveDlyVisitor::CT_SEQ);
}
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALW "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
if (!nodep->bodysp()) {
// Empty always. Kill it.
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
}
virtual void visit(AstAlwaysPublic* nodep) {
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
// Move always to appropriate ACTIVE based on its sense list
UINFO(4," ALWPub "<<nodep<<endl);
//if (debug()>=9) nodep->dumpTree(cout, " Alw: ");
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
}
virtual void visit(AstSenGate* nodep) {
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
AstSenItem* subitemp = nodep->sensesp();
UASSERT_OBJ(subitemp->edgeType() == VEdgeType::ET_ANYEDGE
|| subitemp->edgeType() == VEdgeType::ET_POSEDGE
@ -398,12 +398,12 @@ private:
nodep, "Strange activity type under SenGate");
iterateChildren(nodep);
}
virtual void visit(AstSenItem* nodep) {
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
if (nodep->edgeType() == VEdgeType::ET_ANYEDGE) {
m_itemCombo = true;
// Delete the sensitivity
// We'll add it as a generic COMBO SenItem in a moment.
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else if (nodep->varrefp()) {
// V3LinkResolve should have cleaned most of these up
if (!nodep->varrefp()->width1()) {
@ -416,10 +416,10 @@ private:
}
// Empty visitors, speed things up
virtual void visit(AstNodeMath* nodep) {}
virtual void visit(AstVarScope* nodep) {}
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {}
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {}
//--------------------
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -56,19 +56,19 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstTopScope* nodep) {
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
m_topscopep = nodep;
m_finder.main(m_topscopep);
iterateChildren(nodep);
m_topscopep = NULL;
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Create required actives and add to module
// We can start ordering at a module, or a scope
UINFO(4," MOD "<<nodep<<endl);
iterateChildren(nodep);
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
UINFO(4," ACTIVE "<<nodep<<endl);
V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change!
AstSenTree* sensesp = nodep->sensesp();
@ -79,7 +79,7 @@ private:
// Never executing. Kill it.
UASSERT_OBJ(!sensesp->sensesp()->nextp(), nodep,
"Never senitem should be alone, else the never should be eliminated.");
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
// Copy combo tree to settlement tree with duplicated statements
@ -113,29 +113,29 @@ private:
// No need to do statements under it, they're already moved.
//iterateChildren(nodep);
}
virtual void visit(AstInitial* nodep) { // LCOV_EXCL_LINE
virtual void visit(AstInitial* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
nodep->v3fatalSrc("Node should have been under ACTIVE");
}
virtual void visit(AstAssignAlias* nodep) { // LCOV_EXCL_LINE
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
nodep->v3fatalSrc("Node should have been under ACTIVE");
}
virtual void visit(AstAssignW* nodep) { // LCOV_EXCL_LINE
virtual void visit(AstAssignW* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
nodep->v3fatalSrc("Node should have been under ACTIVE");
}
virtual void visit(AstAlways* nodep) { // LCOV_EXCL_LINE
virtual void visit(AstAlways* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
nodep->v3fatalSrc("Node should have been under ACTIVE");
}
virtual void visit(AstAlwaysPublic* nodep) { // LCOV_EXCL_LINE
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
nodep->v3fatalSrc("Node should have been under ACTIVE");
}
virtual void visit(AstFinal* nodep) { // LCOV_EXCL_LINE
virtual void visit(AstFinal* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
nodep->v3fatalSrc("Node should have been deleted");
}
// Empty visitors, speed things up
virtual void visit(AstNodeMath* nodep) {}
virtual void visit(AstVarScope* nodep) {}
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {}
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {}
//--------------------
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -115,9 +115,9 @@ private:
if (failsp) failsp->unlinkFrBackWithNext();
if (nodep->immediate()) {
UASSERT_OBJ(!sentreep, nodep, "Immediate assertions don't have sensivity");
UASSERT_OBJ(!sentreep, nodep, "Immediate assertions don't have sensitivity");
} else {
UASSERT_OBJ(sentreep, nodep, "Concurrent assertions must have sensivity");
UASSERT_OBJ(sentreep, nodep, "Concurrent assertions must have sensitivity");
sentreep->unlinkFrBack();
}
//
@ -164,17 +164,17 @@ private:
if (selfDestruct) {
// Delete it after making the tree. This way we can tell the user
// if it wasn't constructed nicely or has other errors without needing --coverage.
newp->deleteTree();
VL_DO_DANGLING(newp->deleteTree(), newp);
nodep->unlinkFrBack();
} else {
nodep->replaceWith(newp);
}
// Bye
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
// VISITORS
virtual void visit(AstIf* nodep) {
virtual void visit(AstIf* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return;
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
AstNodeIf* ifp = nodep;
@ -234,7 +234,7 @@ private:
}
//========== Case assertions
virtual void visit(AstCase* nodep) {
virtual void visit(AstCase* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (!nodep->user1SetOnce()) {
bool has_default = false;
@ -296,7 +296,7 @@ private:
}
//========== Past
virtual void visit(AstPast* nodep) {
virtual void visit(AstPast* nodep) VL_OVERRIDE {
iterateChildren(nodep);
uint32_t ticks = 1;
if (nodep->ticksp()) {
@ -326,9 +326,13 @@ private:
}
nodep->replaceWith(inp);
}
virtual void visit(AstSampled* nodep) VL_OVERRIDE {
nodep->replaceWith(nodep->exprp()->unlinkFrBack());
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
//========== Statements
virtual void visit(AstDisplay* nodep) {
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// Replace the special types with standard text
if (nodep->displayType()==AstDisplayType::DT_INFO) {
@ -341,29 +345,32 @@ private:
}
}
virtual void visit(AstAssert* nodep) {
virtual void visit(AstAssert* nodep) VL_OVERRIDE {
iterateChildren(nodep);
newPslAssertion(nodep, nodep->failsp());
}
virtual void visit(AstCover* nodep) {
virtual void visit(AstCover* nodep) VL_OVERRIDE {
iterateChildren(nodep);
newPslAssertion(nodep, NULL);
}
virtual void visit(AstRestrict* nodep) {
virtual void visit(AstRestrict* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// IEEE says simulator ignores these
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
}
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
m_modPastNum = 0;
//
iterateChildren(nodep);
// Reset defaults
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
unsigned origPastNum = m_modPastNum;
{
m_modp = nodep;
m_modPastNum = 0;
iterateChildren(nodep);
}
m_modp = origModp;
m_modPastNum = origPastNum;
}
virtual void visit(AstBegin* nodep) {
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
// This code is needed rather than a visitor in V3Begin,
// because V3Assert is called before V3Begin
AstBegin* lastp = m_beginp;
@ -374,7 +381,7 @@ private:
m_beginp = lastp;
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -71,7 +71,7 @@ private:
// VISITORS
//========== Statements
virtual void visit(AstClocking* nodep) {
virtual void visit(AstClocking* nodep) VL_OVERRIDE {
UINFO(8," CLOCKING"<<nodep<<endl);
// Store the new default clock, reset on new module
m_seniDefaultp = nodep->sensesp();
@ -81,9 +81,9 @@ private:
} else {
nodep->unlinkFrBack();
}
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->sensesp());
if (nodep->sensesp()) {
m_seniAlwaysp = nodep->sensesp()->sensesp();
@ -92,7 +92,7 @@ private:
m_seniAlwaysp = NULL;
}
virtual void visit(AstNodeCoverOrAssert* nodep) {
virtual void visit(AstNodeCoverOrAssert* nodep) VL_OVERRIDE {
if (nodep->sentreep()) return; // Already processed
clearAssertInfo();
// Find Clocking's buried under nodep->exprsp
@ -102,12 +102,12 @@ private:
}
clearAssertInfo();
}
virtual void visit(AstPast* nodep) {
virtual void visit(AstPast* nodep) VL_OVERRIDE {
if (nodep->sentreep()) return; // Already processed
iterateChildren(nodep);
nodep->sentreep(newSenTree(nodep));
}
virtual void visit(AstPropClocked* nodep) {
virtual void visit(AstPropClocked* nodep) VL_OVERRIDE {
// No need to iterate the body, once replace will get iterated
iterateAndNextNull(nodep->sensesp());
if (m_senip) {
@ -130,14 +130,14 @@ private:
// Unlink and just keep a pointer to it, convert to sentree as needed
m_senip = nodep->sensesp();
nodep->replaceWith(blockp);
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// Reset defaults
m_seniDefaultp = NULL;
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -865,10 +865,10 @@ AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) {
// track, then delete it on completion
AstBegin* tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", nodep);
{
tempp->stmtsp()->accept(v); VL_DANGLING(nodep); // nodep to null as may be replaced
VL_DO_DANGLING(tempp->stmtsp()->accept(v), nodep); // nodep to null as may be replaced
}
nodep = tempp->stmtsp()->unlinkFrBackWithNext();
tempp->deleteTree(); VL_DANGLING(tempp);
VL_DO_DANGLING(tempp->deleteTree(), tempp);
} else {
// Use back to determine who's pointing at us (IE assume new node
// grafts into same place as old one)
@ -880,7 +880,7 @@ AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) {
else if (this->m_backp->m_nextp == this) nextnodepp = &(this->m_backp->m_nextp);
UASSERT_OBJ(nextnodepp, this, "Node's back doesn't point to forward to node itself");
{
nodep->accept(v); VL_DANGLING(nodep); // nodep to null as may be replaced
VL_DO_DANGLING(nodep->accept(v), nodep); // nodep to null as may be replaced
}
nodep = *nextnodepp; // Grab new node from point where old was connected
}

View File

@ -51,15 +51,18 @@ typedef std::set<int> MTaskIdSet; // Set of mtaskIds for Var sorting
//######################################################################
// For broken() function, return error string if have a match
#define BROKEN_RTN(test) do { if (VL_UNCOVERABLE(test)) return # test; } while(0)
#define BROKEN_RTN(test) \
do { \
if (VL_UNCOVERABLE(test)) return #test; \
} while (0)
// (V)erilator (N)ode is: True if AstNode is of a a given AstType
#define VN_IS(nodep,nodetypename) (AstNode::privateIs ## nodetypename(nodep))
#define VN_IS(nodep,nodetypename) (AstNode::privateIs<Ast ## nodetypename>(nodep))
// (V)erilator (N)ode cast: Cast to given type if can; effectively
// dynamic_cast<nodetypename>(nodep)
#define VN_CAST(nodep,nodetypename) (AstNode::privateCast ## nodetypename(nodep))
#define VN_CAST_CONST(nodep,nodetypename) (AstNode::privateConstCast ## nodetypename(nodep) )
#define VN_CAST(nodep,nodetypename) (AstNode::privateCast<Ast ## nodetypename>(nodep))
#define VN_CAST_CONST(nodep,nodetypename) (AstNode::privateConstCast<Ast ## nodetypename>(nodep))
// (V)erilator (N)ode deleted: Reference to deleted child (for assertions only)
#define VN_DELETED(nodep) VL_UNLIKELY((vluint64_t)(nodep) == 0x1)
@ -79,11 +82,11 @@ public:
inline AstType(en _e) : m_e(_e) {}
explicit inline AstType(int _e) : m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};
inline bool operator==(AstType lhs, AstType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstType lhs, AstType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(AstType::en lhs, AstType rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const AstType& rhs) { return os<<rhs.ascii(); }
};
inline bool operator==(const AstType& lhs, const AstType& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const AstType& lhs, AstType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(AstType::en lhs, const AstType& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const AstType& rhs) { return os << rhs.ascii(); }
//######################################################################
@ -108,7 +111,7 @@ public:
"UNSIGNED", "SIGNED", "NOSIGN"
};
return names[m_e];
};
}
inline AstNumeric() : m_e(UNSIGNED) {}
// cppcheck-suppress noExplicitConstructor
inline AstNumeric(en _e) : m_e(_e) {}
@ -125,11 +128,13 @@ public:
inline bool isSigned() const { return m_e==SIGNED; }
inline bool isNosign() const { return m_e==NOSIGN; }
// No isUnsigned() as it's ambiguous if NOSIGN should be included or not.
};
inline bool operator==(AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const AstNumeric& rhs) { return os<<rhs.ascii(); }
};
inline bool operator==(const AstNumeric& lhs, const AstNumeric& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const AstNumeric& lhs, AstNumeric::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(AstNumeric::en lhs, const AstNumeric& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const AstNumeric& rhs) {
return os << rhs.ascii();
}
//######################################################################
@ -142,7 +147,10 @@ public:
NO_INLINE_MODULE,
NO_INLINE_TASK,
PUBLIC_MODULE,
PUBLIC_TASK
PUBLIC_TASK,
FULL_CASE,
PARALLEL_CASE,
ENUM_SIZE
};
enum en m_e;
inline AstPragmaType() : m_e(ILLEGAL) {}
@ -150,10 +158,12 @@ public:
inline AstPragmaType(en _e) : m_e(_e) {}
explicit inline AstPragmaType(int _e) : m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};
inline bool operator==(AstPragmaType lhs, AstPragmaType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstPragmaType lhs, AstPragmaType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(AstPragmaType::en lhs, AstPragmaType rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const AstPragmaType& lhs, const AstPragmaType& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const AstPragmaType& lhs, AstPragmaType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(AstPragmaType::en lhs, const AstPragmaType& rhs) { return lhs == rhs.m_e; }
//######################################################################
@ -178,10 +188,12 @@ public:
bool isTrace() const { return (m_e==TRACE_INIT || m_e==TRACE_INIT_SUB
|| m_e==TRACE_FULL || m_e==TRACE_FULL_SUB
|| m_e==TRACE_CHANGE || m_e==TRACE_CHANGE_SUB); }
};
inline bool operator==(AstCFuncType lhs, AstCFuncType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstCFuncType lhs, AstCFuncType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(AstCFuncType::en lhs, AstCFuncType rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const AstCFuncType& lhs, const AstCFuncType& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const AstCFuncType& lhs, AstCFuncType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(AstCFuncType::en lhs, const AstCFuncType& rhs) { return lhs == rhs.m_e; }
//######################################################################
@ -267,10 +279,10 @@ public:
inline VEdgeType(en _e) : m_e(_e) {}
explicit inline VEdgeType(int _e) : m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};
inline bool operator==(VEdgeType lhs, VEdgeType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VEdgeType lhs, VEdgeType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VEdgeType::en lhs, VEdgeType rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const VEdgeType& lhs, const VEdgeType& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const VEdgeType& lhs, VEdgeType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VEdgeType::en lhs, const VEdgeType& rhs) { return lhs == rhs.m_e; }
//######################################################################
@ -301,6 +313,8 @@ public:
//
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
//
TYPENAME, // V3Width processes
//
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
VAR_CLOCK, // V3LinkParse moves to AstVar::attrScClocked
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
@ -324,22 +338,25 @@ public:
"ENUM_BASE", "ENUM_FIRST", "ENUM_LAST", "ENUM_NUM",
"ENUM_NEXT", "ENUM_PREV", "ENUM_NAME",
"MEMBER_BASE",
"TYPENAME",
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD", "VAR_PUBLIC_FLAT_RW",
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT", "VAR_CLOCKER",
"VAR_NO_CLOCKER"
};
return names[m_e];
};
}
inline AstAttrType() : m_e(ILLEGAL) {}
// cppcheck-suppress noExplicitConstructor
inline AstAttrType(en _e) : m_e(_e) {}
explicit inline AstAttrType(int _e) : m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};
inline bool operator==(AstAttrType lhs, AstAttrType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstAttrType lhs, AstAttrType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(AstAttrType::en lhs, AstAttrType rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const AstAttrType& lhs, const AstAttrType& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const AstAttrType& lhs, AstAttrType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(AstAttrType::en lhs, const AstAttrType& rhs) { return lhs == rhs.m_e; }
//######################################################################
@ -373,7 +390,7 @@ public:
" MAX"
};
return names[m_e];
};
}
const char* dpiType() const {
static const char* const names[] = {
"%E-unk",
@ -386,7 +403,7 @@ public:
" MAX"
};
return names[m_e];
};
}
static void selfTest() {
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"), "SelfTest: Enum mismatch");
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"), "SelfTest: Enum mismatch");
@ -463,10 +480,16 @@ public:
}
bool isDouble() const { return m_e==DOUBLE; }
bool isString() const { return m_e==STRING; }
};
inline bool operator==(AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstBasicDTypeKwd lhs, AstBasicDTypeKwd::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(AstBasicDTypeKwd::en lhs, AstBasicDTypeKwd rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const AstBasicDTypeKwd& lhs, const AstBasicDTypeKwd& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const AstBasicDTypeKwd& lhs, AstBasicDTypeKwd::en rhs) {
return lhs.m_e == rhs;
}
inline bool operator==(AstBasicDTypeKwd::en lhs, const AstBasicDTypeKwd& rhs) {
return lhs == rhs.m_e;
}
//######################################################################
@ -508,11 +531,13 @@ public:
bool isWritable() const { return m_e == OUTPUT || m_e == INOUT
|| m_e == REF; }
bool isRefOrConstRef() const { return m_e == REF || m_e == CONSTREF; }
};
inline bool operator==(VDirection lhs, VDirection rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VDirection lhs, VDirection::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VDirection::en lhs, VDirection rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) { return os<<rhs.ascii(); }
};
inline bool operator==(const VDirection& lhs, const VDirection& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const VDirection& lhs, VDirection::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VDirection::en lhs, const VDirection& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) {
return os << rhs.ascii();
}
//######################################################################
@ -535,14 +560,25 @@ public:
static const char* const names[] = {
"FALSE", "TRUE", "UNK"};
return names[m_e]; }
bool trueU() const { return m_e == BU_TRUE || m_e == BU_UNKNOWN; }
bool falseU() const { return m_e == BU_FALSE || m_e == BU_UNKNOWN; }
bool trueKnown() const { return m_e == BU_TRUE; }
bool trueUnknown() const { return m_e == BU_TRUE || m_e == BU_UNKNOWN; }
bool falseKnown() const { return m_e == BU_FALSE; }
bool falseUnknown() const { return m_e == BU_FALSE || m_e == BU_UNKNOWN; }
bool unknown() const { return m_e == BU_UNKNOWN; }
};
inline bool operator==(VBoolOrUnknown lhs, VBoolOrUnknown rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VBoolOrUnknown lhs, VBoolOrUnknown::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VBoolOrUnknown::en lhs, VBoolOrUnknown rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const VBoolOrUnknown& rhs) { return os<<rhs.ascii(); }
void setTrueOrFalse(bool flag) { m_e = flag ? BU_TRUE : BU_FALSE; }
};
inline bool operator==(const VBoolOrUnknown& lhs, const VBoolOrUnknown& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const VBoolOrUnknown& lhs, VBoolOrUnknown::en rhs) {
return lhs.m_e == rhs;
}
inline bool operator==(VBoolOrUnknown::en lhs, const VBoolOrUnknown& rhs) {
return lhs == rhs.m_e;
}
inline std::ostream& operator<<(std::ostream& os, const VBoolOrUnknown& rhs) {
return os << rhs.ascii();
}
//######################################################################
@ -607,11 +643,13 @@ public:
bool isTemp() const {
return (m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP || m_e==XTEMP);
}
};
inline bool operator==(AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(AstVarType::en lhs, AstVarType rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const AstVarType& rhs) { return os<<rhs.ascii(); }
};
inline bool operator==(const AstVarType& lhs, const AstVarType& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const AstVarType& lhs, AstVarType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(AstVarType::en lhs, const AstVarType& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const AstVarType& rhs) {
return os << rhs.ascii();
}
//######################################################################
@ -642,11 +680,15 @@ public:
static const char* const names[] = {
"", "VL_LIKELY", "VL_UNLIKELY"};
return names[m_e]; }
};
inline bool operator==(VBranchPred lhs, VBranchPred rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VBranchPred lhs, VBranchPred::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VBranchPred::en lhs, VBranchPred rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) { return os<<rhs.ascii(); }
};
inline bool operator==(const VBranchPred& lhs, const VBranchPred& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const VBranchPred& lhs, VBranchPred::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VBranchPred::en lhs, const VBranchPred& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) {
return os << rhs.ascii();
}
//######################################################################
@ -675,11 +717,19 @@ public:
static const char* const names[] = {
"", "clker", "non_clker"};
return names[m_e]; }
};
inline bool operator==(VVarAttrClocker lhs, VVarAttrClocker rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VVarAttrClocker lhs, VVarAttrClocker::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VVarAttrClocker::en lhs, VVarAttrClocker rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const VVarAttrClocker& rhs) { return os<<rhs.ascii(); }
};
inline bool operator==(const VVarAttrClocker& lhs, const VVarAttrClocker& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const VVarAttrClocker& lhs, VVarAttrClocker::en rhs) {
return lhs.m_e == rhs;
}
inline bool operator==(VVarAttrClocker::en lhs, const VVarAttrClocker& rhs) {
return lhs == rhs.m_e;
}
inline std::ostream& operator<<(std::ostream& os, const VVarAttrClocker& rhs) {
return os << rhs.ascii();
}
//######################################################################
@ -701,10 +751,10 @@ public:
static const char* const names[] = {
"always", "always_ff", "always_latch", "always_comb"};
return names[m_e]; }
};
inline bool operator==(VAlwaysKwd lhs, VAlwaysKwd rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VAlwaysKwd lhs, VAlwaysKwd::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VAlwaysKwd::en lhs, VAlwaysKwd rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const VAlwaysKwd& lhs, const VAlwaysKwd& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const VAlwaysKwd& lhs, VAlwaysKwd::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VAlwaysKwd::en lhs, const VAlwaysKwd& rhs) { return lhs == rhs.m_e; }
//######################################################################
@ -722,10 +772,10 @@ public:
inline VCaseType(en _e) : m_e(_e) {}
explicit inline VCaseType(int _e) : m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};
inline bool operator==(VCaseType lhs, VCaseType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VCaseType lhs, VCaseType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VCaseType::en lhs, VCaseType rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const VCaseType& lhs, const VCaseType& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const VCaseType& lhs, VCaseType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs == rhs.m_e; }
//######################################################################
@ -751,10 +801,16 @@ public:
static const char* const names[] = {
"display", "write", "info", "error", "warning", "fatal"};
return names[m_e]; }
};
inline bool operator==(AstDisplayType lhs, AstDisplayType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstDisplayType lhs, AstDisplayType::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(AstDisplayType::en lhs, AstDisplayType rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const AstDisplayType& lhs, const AstDisplayType& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const AstDisplayType& lhs, AstDisplayType::en rhs) {
return lhs.m_e == rhs;
}
inline bool operator==(AstDisplayType::en lhs, const AstDisplayType& rhs) {
return lhs == rhs.m_e;
}
//######################################################################
@ -774,11 +830,15 @@ public:
static const char* const names[] = {
"", "TEXT", "PREDOT"};
return names[m_e]; }
};
inline bool operator==(VParseRefExp lhs, VParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VParseRefExp lhs, VParseRefExp::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VParseRefExp::en lhs, VParseRefExp rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) { return os<<rhs.ascii(); }
};
inline bool operator==(const VParseRefExp& lhs, const VParseRefExp& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const VParseRefExp& lhs, VParseRefExp::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VParseRefExp::en lhs, const VParseRefExp& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) {
return os << rhs.ascii();
}
//######################################################################
// VNumRange - Structure containing numeric range information
@ -840,6 +900,36 @@ inline std::ostream& operator<<(std::ostream& os, const VNumRange& rhs) { rhs.du
//######################################################################
class VUseType {
public:
enum en {
IMP_INCLUDE, // Implementation (.cpp) needs an include
INT_INCLUDE, // Interface (.h) needs an include
IMP_FWD_CLASS, // Implementation (.cpp) needs a forward class declaration
INT_FWD_CLASS, // Interface (.h) needs a forward class declaration
};
enum en m_e;
inline VUseType() : m_e(IMP_FWD_CLASS) {}
// cppcheck-suppress noExplicitConstructor
inline VUseType(en _e) : m_e(_e) {}
explicit inline VUseType(int _e) : m_e(static_cast<en>(_e)) {}
bool isInclude() const { return m_e == IMP_INCLUDE || m_e == INT_INCLUDE; }
bool isFwdClass() const { return m_e == IMP_FWD_CLASS || m_e == INT_FWD_CLASS; }
operator en() const { return m_e; }
const char* ascii() const {
static const char* const names[] = {"IMP_INC", "INT_INC", "IMP_FWD", "INT_FWD"};
return names[m_e];
}
};
inline bool operator==(const VUseType& lhs, const VUseType& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const VUseType& lhs, VUseType::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(VUseType::en lhs, const VUseType& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const VUseType& rhs) {
return os << rhs.ascii();
}
//######################################################################
class VBasicTypeKey {
public:
int m_width; // From AstNodeDType: Bit width of operation
@ -934,14 +1024,14 @@ protected:
clearcnt(id, cntGblRef, userBusyRef); // Includes a checkUse for us
userBusyRef = false;
}
static void clearcnt(int id, uint32_t& cntGblRef, bool& userBusyRef) {
static void clearcnt(int id, uint32_t& cntGblRef, const bool& userBusyRef) {
UASSERT_STATIC(userBusyRef, "Clear of User"+cvtToStr(id)+"() not under AstUserInUse");
// If this really fires and is real (after 2^32 edits???)
// we could just walk the tree and clear manually
++cntGblRef;
UASSERT_STATIC(cntGblRef, "User*() overflowed!");
}
static void checkcnt(int id, uint32_t&, bool& userBusyRef) {
static void checkcnt(int id, uint32_t&, const bool& userBusyRef) {
UASSERT_STATIC(userBusyRef, "Check of User"+cvtToStr(id)+"() failed, not under AstUserInUse");
}
};
@ -1106,7 +1196,7 @@ public:
explicit V3Hash(VNUser u) { m_both = u.toInt(); }
V3Hash operator+= (const V3Hash& rh) {
setBoth(depth()+rh.depth(), (hshval()*31+rh.hshval()));
return *this; };
return *this; }
// Creating from raw data (sameHash functions)
V3Hash() { setBoth(1, 0); }
// cppcheck-suppress noExplicitConstructor
@ -1153,6 +1243,8 @@ class AstNode {
AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list
const AstType m_type; // Node sub-type identifier
FileLine* m_fileline; // Where it was declared
vluint64_t m_editCount; // When it was last edited
static vluint64_t s_editCntGbl; // Global edit counter
@ -1207,8 +1299,10 @@ public:
protected:
// CONSTRUCTORS
AstNode() { init(); }
explicit AstNode(FileLine* fileline) {init(); m_fileline = fileline; }
AstNode(AstType t)
: m_type(t) { init(); }
AstNode(AstType t, FileLine* fl)
: m_type(t) { init(); m_fileline = fl; }
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
virtual void cloneRelink() {}
void cloneRelinkTree();
@ -1239,7 +1333,7 @@ protected:
public:
// ACCESSORS
virtual AstType type() const = 0;
inline AstType type() const { return m_type; }
const char* typeName() const { return type().ascii(); } // See also prettyTypeName
AstNode* nextp() const { return m_nextp; }
AstNode* backp() const { return m_backp; }
@ -1295,7 +1389,7 @@ public:
static string vcdName(const string& namein); // Name for printing out to vcd files
string prettyName() const { return prettyName(name()); }
string prettyNameQ() const { return prettyNameQ(name()); }
string prettyTypeName() const; // "VARREF" for error messages
string prettyTypeName() const; // "VARREF" for error messages (NOT dtype's pretty name)
virtual string prettyOperatorName() const { return "operator "+prettyTypeName(); }
FileLine* fileline() const { return m_fileline; }
void fileline(FileLine* fl) { m_fileline = fl; }
@ -1529,11 +1623,22 @@ private:
// CONVERSION
public:
#include "V3Ast__gen_interface.h" // From ./astgen
// Things like:
// AstAlways* castAlways();
// These for use by VN_IS macro only
template<class T>
static bool privateIs(const AstNode* nodep);
// These for use by VN_CAST macro only
template<class T>
static T* privateCast(AstNode* nodep);
// These for use by VN_CAST_CONST macro only
template<class T>
static const T* privateConstCast(const AstNode* nodep);
};
// Specialisations of privateIs/privateCast
#include "V3Ast__gen_impl.h" // From ./astgen
inline std::ostream& operator<<(std::ostream& os, const AstNode* rhs) {
if (!rhs) os<<"NULL"; else rhs->dump(os); return os;
}
@ -1553,8 +1658,8 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
class AstNodeMath : public AstNode {
// Math -- anything that's part of an expression tree
public:
explicit AstNodeMath(FileLine* fl)
: AstNode(fl) {}
AstNodeMath(AstType t, FileLine* fl)
: AstNode(t, fl) {}
ASTNODE_BASE_FUNCS(NodeMath)
// METHODS
virtual bool hasDType() const { return true; }
@ -1570,8 +1675,8 @@ public:
class AstNodeTermop : public AstNodeMath {
// Terminal operator -- a operator with no "inputs"
public:
explicit AstNodeTermop(FileLine* fl)
: AstNodeMath(fl) {}
AstNodeTermop(AstType t, FileLine* fl)
: AstNodeMath(t, fl) {}
ASTNODE_BASE_FUNCS(NodeTermop)
// Know no children, and hot function, so skip iterator for speed
// See checkTreeIter also that asserts no children
@ -1582,8 +1687,8 @@ public:
class AstNodeUniop : public AstNodeMath {
// Unary math
public:
AstNodeUniop(FileLine* fl, AstNode* lhsp)
: AstNodeMath(fl) {
AstNodeUniop(AstType t, FileLine* fl, AstNode* lhsp)
: AstNodeMath(t, fl) {
dtypeFrom(lhsp);
setOp1p(lhsp); }
ASTNODE_BASE_FUNCS(NodeUniop)
@ -1604,8 +1709,8 @@ public:
class AstNodeBiop : public AstNodeMath {
// Binary math
public:
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeMath(fl) {
AstNodeBiop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeMath(t, fl) {
setOp1p(lhs); setOp2p(rhs); }
ASTNODE_BASE_FUNCS(NodeBiop)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0; // Clone single node, just get same type back.
@ -1631,8 +1736,8 @@ public:
class AstNodeTriop : public AstNodeMath {
// Trinary math
public:
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNodeMath(fl) {
AstNodeTriop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNodeMath(t, fl) {
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
ASTNODE_BASE_FUNCS(NodeTriop)
AstNode* lhsp() const { return op1p(); }
@ -1659,22 +1764,22 @@ public:
class AstNodeBiCom : public AstNodeBiop {
// Binary math with commutative properties
public:
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiop(fl, lhs, rhs) {}
AstNodeBiCom(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiop(t, fl, lhs, rhs) {}
ASTNODE_BASE_FUNCS(NodeBiCom)
};
class AstNodeBiComAsv : public AstNodeBiCom {
// Binary math with commutative & associative properties
public:
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiCom(fl, lhs, rhs) {}
AstNodeBiComAsv(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
: AstNodeBiCom(t, fl, lhs, rhs) {}
ASTNODE_BASE_FUNCS(NodeBiComAsv)
};
class AstNodeCond : public AstNodeTriop {
public:
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeTriop(fl, condp, expr1p, expr2p) {
AstNodeCond(AstType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
: AstNodeTriop(t, fl, condp, expr1p, expr2p) {
if (expr1p) dtypeFrom(expr1p);
else if (expr2p) dtypeFrom(expr2p);
}
@ -1700,8 +1805,8 @@ public:
class AstNodePreSel : public AstNode {
// Something that becomes an AstSel
public:
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNode(fl) {
AstNodePreSel(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
: AstNode(t, fl) {
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
ASTNODE_BASE_FUNCS(NodePreSel)
AstNode* lhsp() const { return op1p(); }
@ -1720,20 +1825,23 @@ public:
class AstNodeStmt : public AstNode {
// Statement -- anything that's directly under a function
bool m_statement; // Really a statement (e.g. not a function with return)
public:
explicit AstNodeStmt(FileLine* fl)
: AstNode(fl) {}
AstNodeStmt(AstType t, FileLine* fl, bool statement = true)
: AstNode(t, fl)
, m_statement(statement) {}
ASTNODE_BASE_FUNCS(NodeStmt)
// METHODS
virtual bool isStatement() const { return true; } // Really a statement
bool isStatement() const { return m_statement; } // Really a statement
void statement(bool flag) { m_statement = flag; }
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
};
class AstNodeAssign : public AstNodeStmt {
public:
AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeStmt(fl) {
AstNodeAssign(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeStmt(t, fl) {
setOp1p(rhsp); setOp2p(lhsp);
dtypeFrom(lhsp);
}
@ -1755,9 +1863,9 @@ public:
class AstNodeFor : public AstNodeStmt {
public:
AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
AstNodeFor(AstType t, FileLine* fl, AstNode* initsp, AstNode* condp,
AstNode* incsp, AstNode* bodysp)
: AstNodeStmt(fileline) {
: AstNodeStmt(t, fl) {
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
}
ASTNODE_BASE_FUNCS(NodeFor)
@ -1775,8 +1883,8 @@ class AstNodeIf : public AstNodeStmt {
private:
VBranchPred m_branchPred; // Branch prediction as taken/untaken?
public:
AstNodeIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
: AstNodeStmt(fl) {
AstNodeIf(AstType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
: AstNodeStmt(t, fl) {
setOp1p(condp); addNOp2p(ifsp); addNOp3p(elsesp);
}
ASTNODE_BASE_FUNCS(NodeIf)
@ -1797,8 +1905,8 @@ public:
class AstNodeCase : public AstNodeStmt {
public:
AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp)
: AstNodeStmt(fl) {
AstNodeCase(AstType t, FileLine* fl, AstNode* exprp, AstNode* casesp)
: AstNodeStmt(t, fl) {
setOp1p(exprp); addNOp2p(casesp);
}
ASTNODE_BASE_FUNCS(NodeCase)
@ -1813,7 +1921,8 @@ public:
class AstNodeSenItem : public AstNode {
// An AstSenItem or AstSenGate
public:
explicit AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
AstNodeSenItem(AstType t, FileLine* fl)
: AstNode(t, fl) {}
ASTNODE_BASE_FUNCS(NodeSenItem)
virtual bool isClocked() const = 0;
virtual bool isCombo() const = 0;
@ -1834,14 +1943,14 @@ private:
bool m_hierThis; // Hiername points to "this" function
void init();
public:
AstNodeVarRef(FileLine* fl, const string& name, bool lvalue)
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL),
m_packagep(NULL), m_name(name), m_hierThis(false) {
AstNodeVarRef(AstType t, FileLine* fl, const string& name, bool lvalue)
: AstNodeMath(t, fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL)
, m_packagep(NULL), m_name(name), m_hierThis(false) {
init();
}
AstNodeVarRef(FileLine* fl, const string& name, AstVar* varp, bool lvalue)
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL),
m_packagep(NULL), m_name(name), m_hierThis(false) {
AstNodeVarRef(AstType t, FileLine* fl, const string& name, AstVar* varp, bool lvalue)
: AstNodeMath(t, fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL)
, m_packagep(NULL), m_name(name), m_hierThis(false) {
// May have varp==NULL
init();
}
@ -1876,8 +1985,8 @@ private:
string m_text;
public:
// Node that simply puts text into the output stream
AstNodeText(FileLine* fileline, const string& textp)
: AstNode(fileline) {
AstNodeText(AstType t, FileLine* fl, const string& textp)
: AstNode(t, fl) {
m_text = textp; // Copy it
}
ASTNODE_BASE_FUNCS(NodeText)
@ -1902,7 +2011,8 @@ private:
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
public:
// CONSTRUCTORS
explicit AstNodeDType(FileLine* fl) : AstNode(fl) {
AstNodeDType(AstType t, FileLine* fl)
: AstNode(t, fl) {
m_width = 0; m_widthMin = 0; m_generic = false;
}
ASTNODE_BASE_FUNCS(NodeDType)
@ -1924,6 +2034,8 @@ public:
virtual bool similarDType(AstNodeDType* samep) const = 0; // Assignable equivalence. Call skipRefp() on this and samep before calling
virtual AstNodeDType* subDTypep() const { return NULL; } // Iff has a non-null subDTypep(), as generic node function
virtual bool isFourstate() const;
virtual string prettyDTypeName() const { return prettyTypeName(); } // Ideally an IEEE $typename
string prettyDTypeNameQ() const { return "'" + prettyDTypeName() + "'"; }
//
// Changing the width may confuse the data type resolution, so must clear
// TypeTable cache after use.
@ -1962,8 +2074,8 @@ private:
bool m_isFourstate;
MemberNameMap m_members;
public:
AstNodeUOrStructDType(FileLine* fl, AstNumeric numericUnpack)
: AstNodeDType(fl) {
AstNodeUOrStructDType(AstType t, FileLine* fl, AstNumeric numericUnpack)
: AstNodeDType(t, fl) {
// AstNumeric::NOSIGN overloaded to indicate not packed
m_packed = (numericUnpack != AstNumeric::NOSIGN);
m_isFourstate = false; // V3Width computes
@ -2013,7 +2125,8 @@ private:
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
public:
explicit AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
AstNodeArrayDType(AstType t, FileLine* fl)
: AstNodeDType(t, fl) {
m_refDTypep = NULL;
}
ASTNODE_BASE_FUNCS(NodeArrayDType)
@ -2064,8 +2177,8 @@ public:
class AstNodeSel : public AstNodeBiop {
// Single bit range extraction, perhaps with non-constant selection or array selection
public:
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
: AstNodeBiop(fl, fromp, bitp) {}
AstNodeSel(AstType t, FileLine* fl, AstNode* fromp, AstNode* bitp)
: AstNodeBiop(t, fl, fromp, bitp) {}
ASTNODE_BASE_FUNCS(NodeSel)
AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing)
void fromp(AstNode* nodep) { setOp1p(nodep); }
@ -2078,7 +2191,8 @@ public:
class AstNodeStream : public AstNodeBiop {
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
public:
AstNodeStream(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
AstNodeStream(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: AstNodeBiop(t, fl, lhsp, rhsp) {
if (lhsp->dtypep()) {
dtypeSetLogicSized(lhsp->dtypep()->width(), AstNumeric::UNSIGNED);
}
@ -2104,8 +2218,8 @@ private:
bool m_dpiTask:1; // DPI import task (vs. void function)
bool m_pure:1; // DPI import pure
public:
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
: AstNode(fileline)
AstNodeFTask(AstType t, FileLine* fl, const string& name, AstNode* stmtsp)
: AstNode(t, fl)
, m_name(name)
, m_dpiOpenParent(0), m_taskPublic(false)
, m_attrIsolateAssign(false), m_prototype(false)
@ -2167,13 +2281,13 @@ private:
string m_inlinedDots; // Dotted hierarchy flattened out
AstPackage* m_packagep; // Package hierarchy
public:
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
: AstNodeStmt(fl)
AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp)
: AstNodeStmt(t, fl, statement)
, m_taskp(NULL), m_packagep(NULL) {
setOp1p(namep); addNOp2p(pinsp);
}
AstNodeFTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
: AstNodeStmt(fl)
AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, const string& name, AstNode* pinsp)
: AstNodeStmt(t, fl, statement)
, m_taskp(NULL), m_name(name), m_packagep(NULL) {
addNOp2p(pinsp);
}
@ -2224,8 +2338,8 @@ private:
int m_varNum; // Incrementing variable number
int m_typeNum; // Incrementing implicit type number
public:
AstNodeModule(FileLine* fl, const string& name)
: AstNode(fl)
AstNodeModule(AstType t, FileLine* fl, const string& name)
: AstNode(t, fl)
, m_name(name), m_origName(name)
, m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false)
, m_internal(false), m_recursive(false), m_recursiveClone(false)
@ -2238,7 +2352,7 @@ public:
AstActive* activesp() const { return VN_CAST(op3p(), Active); } // op3 = List of i/sblocks
// METHODS
void addInlinesp(AstNode* nodep) { addOp1p(nodep); }
void addStmtp(AstNode* nodep) { addOp2p(nodep); }
void addStmtp(AstNode* nodep) { addNOp2p(nodep); }
void addActivep(AstNode* nodep) { addOp3p(nodep); }
// ACCESSORS
virtual void name(const string& name) { m_name = name; }
@ -2269,18 +2383,14 @@ public:
class AstNodeRange : public AstNode {
// A range, sized or unsized
public:
explicit AstNodeRange(FileLine* fl) : AstNode(fl) { }
AstNodeRange(AstType t, FileLine* fl)
: AstNode(t, fl) {}
ASTNODE_BASE_FUNCS(NodeRange)
};
//######################################################################
#include "V3AstNodes.h"
#include "V3Ast__gen_impl.h" // From ./astgen
// Things like:
// inline AstAlways* AstNode::castAlways() { return dynamic_cast<AstAlways*>(this); }
// inline bool AstNode::privateIsaAlways(const AstNode* nodep) { return nodep && nodep->type() == AstType::atAlways; }
#include "V3AstNodes__gen.h"
//######################################################################
// Inline AstNVisitor METHODS

View File

@ -168,11 +168,11 @@ AstNodeBiop* AstEqWild::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
}
AstExecGraph::AstExecGraph(FileLine* fileline)
: AstNode(fileline) {
: AstNode(AstType::atExecGraph, fileline) {
m_depGraphp = new V3Graph;
}
AstExecGraph::~AstExecGraph() {
delete m_depGraphp; VL_DANGLING(m_depGraphp);
VL_DO_DANGLING(delete m_depGraphp, m_depGraphp);
}
bool AstVar::isSigPublic() const {
@ -630,7 +630,7 @@ std::pair<uint32_t,uint32_t> AstNodeDType::dimensions(bool includeBasic) {
else if (const AstBasicDType* adtypep = VN_CAST(dtypep, BasicDType)) {
if (includeBasic && (adtypep->isRanged() || adtypep->isString())) packed++;
}
else if (const AstStructDType* sdtypep = VN_CAST(dtypep, StructDType)) {
else if (VN_IS(dtypep, StructDType)) {
packed++;
}
break;
@ -798,7 +798,7 @@ AstBasicDType* AstTypeTable::findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd)
// check the detailed map for this same node
// Also adds this new node to the detailed map
AstBasicDType* newp = findInsertSameDType(new1p);
if (newp != new1p) new1p->deleteTree();
if (newp != new1p) VL_DO_DANGLING(new1p->deleteTree(), new1p);
else addTypesp(newp);
//
m_basicps[kwd] = newp;
@ -809,7 +809,7 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kw
int width, int widthMin, AstNumeric numeric) {
AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, width, widthMin);
AstBasicDType* newp = findInsertSameDType(new1p);
if (newp != new1p) new1p->deleteTree();
if (newp != new1p) VL_DO_DANGLING(new1p->deleteTree(), new1p);
else addTypesp(newp);
return newp;
}
@ -818,7 +818,7 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kw
VNumRange range, int widthMin, AstNumeric numeric) {
AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, range, widthMin);
AstBasicDType* newp = findInsertSameDType(new1p);
if (newp != new1p) new1p->deleteTree();
if (newp != new1p) VL_DO_DANGLING(new1p->deleteTree(), new1p);
else addTypesp(newp);
return newp;
}
@ -943,6 +943,14 @@ void AstBasicDType::dump(std::ostream& str) const {
str<<" kwd="<<keyword().ascii();
if (isRanged() && !rangep()) str<<" range=["<<left()<<":"<<right()<<"]";
}
string AstBasicDType::prettyDTypeName() const {
std::ostringstream os;
os << keyword().ascii();
if (isRanged() && !rangep() && keyword().width() <= 1) {
os << "[" << left() << ":" << right() << "]";
}
return os.str();
}
void AstCCast::dump(std::ostream& str) const {
this->AstNode::dump(str);
str<<" sz"<<size();
@ -999,6 +1007,12 @@ void AstJumpGo::dump(std::ostream& str) const {
if (labelp()) { labelp()->dump(str); }
else { str<<"%Error:UNLINKED"; }
}
void AstMemberSel::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " -> ";
if (varp()) { varp()->dump(str); }
else { str << "%Error:UNLINKED"; }
}
void AstModportFTaskRef::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isExport()) str<<" EXPORT";
@ -1073,6 +1087,24 @@ void AstNodeArrayDType::dump(std::ostream& str) const {
this->AstNodeDType::dump(str);
str<<" "<<declRange();
}
string AstPackArrayDType::prettyDTypeName() const {
std::ostringstream os;
os << subDTypep()->prettyDTypeName() << declRange();
return os.str();
}
string AstUnpackArrayDType::prettyDTypeName() const {
std::ostringstream os;
string ranges = cvtToStr(declRange());
// Unfortunately we need a single $ for the first unpacked, and all
// dimensions shown in "reverse" order
AstNodeDType* subp = subDTypep()->skipRefp();
while (AstUnpackArrayDType* adtypep = VN_CAST(subp, UnpackArrayDType)) {
ranges += cvtToStr(adtypep->declRange());
subp = adtypep->subDTypep()->skipRefp();
}
os << subp->prettyDTypeName() << "$" << ranges;
return os.str();
}
void AstNodeModule::dump(std::ostream& str) const {
this->AstNode::dump(str);
str<<" L"<<level();
@ -1133,10 +1165,18 @@ void AstAssocArrayDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str<<"[assoc-"<<(void*)keyDTypep()<<"]";
}
string AstAssocArrayDType::prettyDTypeName() const {
return subDTypep()->prettyDTypeName() + "[" + keyDTypep()->prettyDTypeName() + "]";
}
void AstQueueDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str<<"[queue]";
}
string AstQueueDType::prettyDTypeName() const {
string str = subDTypep()->prettyDTypeName() + "[$";
if (boundConst()) str += ":" + cvtToStr(boundConst());
return str + "]";
}
void AstUnsizedArrayDType::dumpSmall(std::ostream& str) const {
this->AstNodeDType::dumpSmall(str);
str<<"[]";
@ -1296,8 +1336,15 @@ void AstCFunc::dump(std::ostream& str) const {
if (slow()) str<<" [SLOW]";
if (pure()) str<<" [PURE]";
if (isStatic().unknown()) str<<" [STATICU]";
else if (isStatic().trueU()) str<<" [STATIC]";
else if (isStatic().trueUnknown()) str<<" [STATIC]";
if (dpiImport()) str<<" [DPII]";
if (dpiExport()) str<<" [DPIX]";
if (dpiExportWrapper()) str<<" [DPIXWR]";
if (isConstructor()) str<<" [CTOR]";
if (isDestructor()) str<<" [DTOR]";
if (isVirtual()) str<<" [VIRT]";
}
void AstCUse::dump(std::ostream& str) const {
this->AstNode::dump(str);
str << " [" << useType() << "]";
}

File diff suppressed because it is too large Load Diff

View File

@ -72,20 +72,21 @@ private:
AstNodeFTask* m_ftaskp; // Current function/task
string m_namedScope; // Name of begin blocks above us
string m_unnamedScope; // Name of begin blocks, including unnamed blocks
int m_repeatNum; // Repeat counter
int m_ifDepth; // Current if depth
// METHODS
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
m_repeatNum = 0;
iterateChildren(nodep);
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
UINFO(8," "<<nodep<<endl);
// Rename it
if (m_unnamedScope != "") {
@ -110,7 +111,7 @@ private:
m_namedScope = oldScope;
m_unnamedScope = oldUnnamed;
}
virtual void visit(AstBegin* nodep) {
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
// Begin blocks were only useful in variable creation, change names and delete
UINFO(8," "<<nodep<<endl);
string oldScope = m_namedScope;
@ -157,9 +158,9 @@ private:
} else {
nodep->unlinkFrBack();
}
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
if (m_unnamedScope != "") {
// Rename it
nodep->name(m_unnamedScope+"__DOT__"+nodep->name());
@ -170,7 +171,7 @@ private:
else m_modp->addStmtp(nodep);
}
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
UINFO(8," CELL "<<nodep<<endl);
if (m_namedScope != "") {
m_statep->userMarkChanged(nodep);
@ -183,14 +184,14 @@ private:
}
iterateChildren(nodep);
}
virtual void visit(AstVarXRef* nodep) {
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
UINFO(9, " VARXREF "<<nodep<<endl);
if (m_namedScope != "" && nodep->inlinedDots() == "") {
nodep->inlinedDots(m_namedScope);
UINFO(9, " rescope to "<<nodep<<endl);
}
}
virtual void visit(AstScopeName* nodep) {
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
// If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Inline
if (nodep->user1SetOnce()) return; // Don't double-add text's
@ -203,13 +204,13 @@ private:
}
iterateChildren(nodep);
}
virtual void visit(AstCoverDecl* nodep) {
virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE {
// Don't need to fix path in coverage statements, they're not under
// any BEGINs, but V3Coverage adds them all under the module itself.
iterateChildren(nodep);
}
// VISITORS - LINT CHECK
virtual void visit(AstIf* nodep) { // Note not AstNodeIf; other types don't get covered
virtual void visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered
// Check IFDEPTH warning - could be in other transform files if desire
int prevIfDepth = m_ifDepth;
if (m_ifDepth == -1 || v3Global.opt.ifDepth()<1) { // Turned off
@ -223,7 +224,7 @@ private:
iterateChildren(nodep);
m_ifDepth = prevIfDepth;
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -232,7 +233,6 @@ public:
m_statep = statep;
m_modp = NULL;
m_ftaskp = NULL;
m_repeatNum = 0;
m_ifDepth = 0;
iterate(nodep);
}
@ -249,21 +249,21 @@ private:
// AstNodeFTask::user1p // Node replaced, rename it
// VISITORS
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
if (nodep->taskp()->user1()) { // It was converted
UINFO(9, " relinkFTask "<<nodep<<endl);
nodep->name(nodep->taskp()->name());
}
iterateChildren(nodep);
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (nodep->varp()->user1()) { // It was converted
UINFO(9, " relinVarRef "<<nodep<<endl);
nodep->name(nodep->varp()->name());
}
iterateChildren(nodep);
}
virtual void visit(AstIfaceRefDType* nodep) {
virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE {
// May have changed cell names
// TypeTable is always after all modules, so names are stable
UINFO(8," IFACEREFDTYPE "<<nodep<<endl);
@ -272,7 +272,7 @@ private:
iterateChildren(nodep);
}
//--------------------
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -70,7 +70,7 @@ private:
}
// VISITORS
virtual void visit(AstNodeIf* nodep) {
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
UINFO(4," IF: "<<nodep<<endl);
int lastLikely = m_likely;
int lastUnlikely = m_unlikely;
@ -96,17 +96,17 @@ private:
m_likely = lastLikely;
m_unlikely = lastUnlikely;
}
virtual void visit(AstCCall* nodep) {
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
checkUnlikely(nodep);
nodep->funcp()->user1Inc();
iterateChildren(nodep);
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
checkUnlikely(nodep);
m_cfuncsp.push_back(nodep);
iterateChildren(nodep);
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
checkUnlikely(nodep);
iterateChildren(nodep);
}

View File

@ -209,7 +209,7 @@ private:
iterateChildrenConst(nodep);
}
// VISITORS
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
processAndIterate(nodep);
}
public:
@ -257,7 +257,7 @@ private:
iterateChildrenConst(nodep);
BrokenTable::setUnder(nodep, false);
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
processAndIterate(nodep);
UASSERT_OBJ(!(v3Global.assertDTypesResolved()
&& nodep->brokeLhsMustBeLvalue()
@ -265,7 +265,7 @@ private:
&& !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue()),
nodep, "Assignment LHS is not an lvalue");
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
processAndIterate(nodep);
}
public:

125
src/V3CUse.cpp Normal file
View File

@ -0,0 +1,125 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Handle SV classes
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
// V3Class's Transformations:
//
// Each module:
// Each cell:
// Create CUse for cell forward declaration
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include "V3Global.h"
#include "V3CUse.h"
#include "V3Ast.h"
#include "V3EmitCBase.h"
#include VL_INCLUDE_UNORDERED_MAP
//######################################################################
class CUseState {
private:
// MEMBERS
AstNodeModule* m_modInsertp; // Current module to insert AstCUse under
typedef std::pair<VUseType, string> UseString;
std::map<UseString, AstCUse*> m_didUse; // What we already used
// NODE STATE
// Entire netlist:
// AstClass::user1() -> bool. True if class needs to_string dumper
AstUser1InUse m_inuser1;
// METHODS
VL_DEBUG_FUNC; // Declare debug()
public:
AstCUse* newUse(AstNode* nodep, VUseType useType, const string& name) {
UseString key(useType, name);
if (m_didUse.find(key) == m_didUse.end()) {
AstCUse* newp = new AstCUse(nodep->fileline(), useType, name);
m_modInsertp->addStmtp(newp);
UINFO(8, "Insert " << newp << endl);
m_didUse[key] = newp;
}
return m_didUse[key];
}
// CONSTRUCTORS
explicit CUseState(AstNodeModule* nodep)
: m_modInsertp(nodep) {}
virtual ~CUseState() {}
VL_UNCOPYABLE(CUseState);
};
class CUseVisitor : public AstNVisitor {
// MEMBERS
CUseState m_state; // Inserter state
// METHODS
VL_DEBUG_FUNC; // Declare debug()
// Module use builders
void makeUseCells(AstNodeModule* nodep) {
for (AstNode* itemp = nodep->stmtsp(); itemp; itemp = itemp->nextp()) {
if (AstCell* cellp = VN_CAST(itemp, Cell)) {
// Currently no include because we include __Syms which has them all
m_state.newUse(nodep, VUseType::INT_FWD_CLASS, cellp->modp()->name());
}
}
}
// VISITORS
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
if (v3Global.opt.trace()) {
AstCUse* usep
= m_state.newUse(nodep, VUseType::INT_FWD_CLASS, v3Global.opt.traceClassBase());
usep->protect(false);
}
makeUseCells(nodep);
}
virtual void visit(AstNode* nodep) VL_OVERRIDE {} // All in AstNodeModule
public:
// CONSTRUCTORS
explicit CUseVisitor(AstNodeModule* nodep)
: m_state(nodep) {
iterate(nodep);
}
virtual ~CUseVisitor() {}
VL_UNCOPYABLE(CUseVisitor);
};
//######################################################################
// Class class functions
void V3CUse::cUseAll(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ": " << endl);
// Call visitor separately for each module, so visitor state is cleared
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp;
modp = VN_CAST(modp->nextp(), NodeModule)) {
// Insert under this module; someday we should e.g. make Ast
// for each output file and put under that
CUseVisitor visitor(modp);
}
V3Global::dumpCheckGlobalTree("cuse", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
}

37
src/V3CUse.h Normal file
View File

@ -0,0 +1,37 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Pre C-Emit stage changes
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#ifndef _V3CUSE_H_
#define _V3CUSE_H_ 1
#include "config_build.h"
#include "verilatedos.h"
#include "V3Error.h"
#include "V3Ast.h"
//============================================================================
class V3CUse {
public:
static void cUseAll(AstNetlist* nodep);
};
#endif // Guard

View File

@ -62,7 +62,7 @@ private:
// METHODS
VL_DEBUG_FUNC; // Declare debug()
virtual void visit(AstNodeCase* nodep) {
virtual void visit(AstNodeCase* nodep) VL_OVERRIDE {
if (VN_IS(nodep, Case) && VN_CAST(nodep, Case)->casex()) {
nodep->v3warn(CASEX, "Suggest casez (with ?'s) in place of casex (with X's)");
}
@ -89,7 +89,7 @@ private:
m_caseExprp = NULL;
}
}
virtual void visit(AstConst* nodep) {
virtual void visit(AstConst* nodep) VL_OVERRIDE {
// See also neverItem
if (m_caseExprp && nodep->num().isFourState()) {
if (VN_IS(m_caseExprp, GenCase)) {
@ -106,7 +106,7 @@ private:
}
}
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -250,7 +250,7 @@ private:
if (m_valueItem[a] != m_valueItem[b]) { same = false; break; }
}
if (same) {
tree1p->deleteTree(); VL_DANGLING(tree1p);
VL_DO_DANGLING(tree1p->deleteTree(), tree1p);
return tree0p;
}
@ -299,8 +299,8 @@ private:
if (ifrootp) nodep->replaceWith(ifrootp);
else nodep->unlinkFrBack();
nodep->deleteTree(); VL_DANGLING(nodep);
cexprp->deleteTree(); VL_DANGLING(cexprp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
VL_DO_DANGLING(cexprp->deleteTree(), cexprp);
if (debug()>=9) ifrootp->dumpTree(cout, " _simp: ");
}
@ -331,7 +331,7 @@ private:
AstConst* iconstp = VN_CAST(icondp, Const);
if (iconstp && neverItem(nodep, iconstp)) {
// X in casez can't ever be executed
icondp->deleteTree(); VL_DANGLING(icondp); VL_DANGLING(iconstp);
VL_DO_DANGLING(icondp->deleteTree(), icondp); VL_DANGLING(iconstp);
// For simplicity, make expression that is not equal, and let later
// optimizations remove it
condp = new AstConst(itemp->fileline(), AstConst::LogicFalse());
@ -357,7 +357,7 @@ private:
AstNode* and2p = new AstAnd(itemp->fileline(),
new AstConst(itemp->fileline(), numval),
new AstConst(itemp->fileline(), nummask));
icondp->deleteTree(); VL_DANGLING(icondp); VL_DANGLING(iconstp);
VL_DO_DANGLING(icondp->deleteTree(), icondp); VL_DANGLING(iconstp);
condp = AstEq::newTyped(itemp->fileline(), and1p, and2p);
} else {
// Not a caseX mask, we can simply build CASEEQ(cexpr icond)
@ -375,7 +375,7 @@ private:
itemp->condsp(ifexprp);
}
}
cexprp->deleteTree(); VL_DANGLING(cexprp);
VL_DO_DANGLING(cexprp->deleteTree(), cexprp);
if (!hadDefault) {
// If there was no default, add a empty one, this greatly simplifies below code
// and constant propagation will just eliminate it for us later.
@ -418,7 +418,7 @@ private:
{ // Make the new lower IF and attach in the tree
AstNode* itemexprp = ifexprp; VL_DANGLING(ifexprp);
if (depth == (CASE_ENCODER_GROUP_DEPTH)) { // End of group - can skip the condition
itemexprp->deleteTree(); VL_DANGLING(itemexprp);
VL_DO_DANGLING(itemexprp->deleteTree(), itemexprp);
itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
}
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
@ -434,7 +434,7 @@ private:
if (debug()>=9 && grouprootp) grouprootp->dumpTree(cout, " _new: ");
if (grouprootp) nodep->replaceWith(grouprootp);
else nodep->unlinkFrBack();
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceCaseParallel(AstCase* nodep, bool noOverlapsAllCovered) {
@ -460,7 +460,7 @@ private:
}
// VISITORS
virtual void visit(AstCase* nodep) {
virtual void visit(AstCase* nodep) VL_OVERRIDE {
V3Case::caseLint(nodep);
iterateChildren(nodep);
if (debug()>=9) nodep->dumpTree(cout, " case_old: ");
@ -468,15 +468,15 @@ private:
// It's a simple priority encoder or complete statement
// we can make a tree of statements to avoid extra comparisons
++m_statCaseFast;
replaceCaseFast(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceCaseFast(nodep), nodep);
} else {
++m_statCaseSlow;
replaceCaseComplicated(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceCaseComplicated(nodep), nodep);
}
}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -75,7 +75,7 @@ private:
relinkHandle.relink(castp);
//if (debug()>8) castp->dumpTree(cout, "-castins: ");
//
insureLower32Cast(castp);
ensureLower32Cast(castp);
nodep->user1(1); // Now must be of known size
}
int castSize(AstNode* nodep) {
@ -84,13 +84,13 @@ private:
else if (nodep->width() <= 16) return 16;
else return VL_IDATASIZE;
}
void insureCast(AstNode* nodep) {
void ensureCast(AstNode* nodep) {
if (castSize(nodep->backp()) != castSize(nodep)
|| !nodep->user1()) {
insertCast(nodep, castSize(nodep->backp()));
}
}
void insureLower32Cast(AstCCast* nodep) {
void ensureLower32Cast(AstCCast* nodep) {
// If we have uint64 = CAST(uint64(x)) then the upcasting
// really needs to be CAST(uint64(CAST(uint32(x))).
// Otherwise a (uint64)(a>b) would return wrong value, as
@ -102,33 +102,33 @@ private:
}
// VISITORS
virtual void visit(AstNodeUniop* nodep) {
virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->user1(nodep->lhsp()->user1());
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
}
virtual void visit(AstNodeBiop* nodep) {
virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->user1(nodep->lhsp()->user1()
| nodep->rhsp()->user1());
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp());
}
virtual void visit(AstNodeTriop* nodep) {
virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->user1(nodep->lhsp()->user1()
| nodep->rhsp()->user1()
| nodep->thsp()->user1());
if (nodep->sizeMattersLhs()) insureCast(nodep->lhsp());
if (nodep->sizeMattersRhs()) insureCast(nodep->rhsp());
if (nodep->sizeMattersThs()) insureCast(nodep->thsp());
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp());
if (nodep->sizeMattersThs()) ensureCast(nodep->thsp());
}
virtual void visit(AstCCast* nodep) {
virtual void visit(AstCCast* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureLower32Cast(nodep);
ensureLower32Cast(nodep);
nodep->user1(1);
}
virtual void visit(AstNegate* nodep) {
virtual void visit(AstNegate* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->user1(nodep->lhsp()->user1());
if (nodep->lhsp()->widthMin()==1) {
@ -137,10 +137,10 @@ private:
// out = {32{a<b}} => out = - (a<b)
insertCast(nodep->lhsp(), castSize(nodep));
} else {
insureCast(nodep->lhsp());
ensureCast(nodep->lhsp());
}
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (!nodep->lvalue()
&& !VN_IS(nodep->backp(), CCast)
&& VN_IS(nodep->backp(), NodeMath)
@ -153,7 +153,7 @@ private:
}
nodep->user1(1);
}
virtual void visit(AstConst* nodep) {
virtual void visit(AstConst* nodep) VL_OVERRIDE {
// Constants are of unknown size if smaller than 33 bits, because
// we're too lazy to wrap every constant in the universe in
// ((IData)#).
@ -161,11 +161,11 @@ private:
}
// NOPs
virtual void visit(AstVar* nodep) {}
virtual void visit(AstVar* nodep) VL_OVERRIDE {}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -136,7 +136,7 @@ private:
std::ofstream* m_ofp; // Output file
string m_prefix;
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
*m_ofp<<m_prefix;
if (nodep->user3()) *m_ofp<<" %%";
else *m_ofp<<" ";
@ -170,7 +170,7 @@ private:
int m_maxLineno;
size_t m_maxFilenameLen;
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// Keeping line+filename lengths separate is much faster than calling ascii().length()
if (nodep->fileline()->lineno() >= m_maxLineno) {
@ -608,19 +608,22 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
iterateChildren(nodep);
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
UINFO(4," SCOPE "<<nodep<<endl);
m_scopep = nodep;
m_logicVertexp = NULL;
iterateChildren(nodep);
m_scopep = NULL;
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
// Create required blocks and add to module
UINFO(4," BLOCK "<<nodep<<endl);
AstNode::user2ClearTree();
@ -631,7 +634,7 @@ private:
m_domainp = NULL;
AstNode::user2ClearTree();
}
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
if (m_scopep) {
UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block");
AstVarScope* varscp = nodep->varScopep();
@ -659,72 +662,72 @@ private:
}
}
}
virtual void visit(AstAssignDly* nodep) {
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
m_inDly = true;
iterateChildren(nodep);
m_inDly = false;
}
virtual void visit(AstSenItem* nodep) {
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
// Note we look at only AstSenItems, not AstSenGate's
// The gating term of a AstSenGate is normal logic
m_inSenItem = true;
iterateChildren(nodep);
m_inSenItem = false;
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
iterateNewStmt(nodep);
}
virtual void visit(AstAlwaysPublic* nodep) {
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
// CDC doesn't care about public variables
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
iterateNewStmt(nodep);
}
virtual void visit(AstSenGate* nodep) {
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
// First handle the clock part will be handled in a minute by visit AstSenItem
// The logic gating term is dealt with as logic
iterateNewStmt(nodep);
}
virtual void visit(AstAssignAlias* nodep) {
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
iterateNewStmt(nodep);
}
virtual void visit(AstAssignW* nodep) {
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
iterateNewStmt(nodep);
}
// Math that shouldn't cause us to clear hazard
virtual void visit(AstConst* nodep) { }
virtual void visit(AstReplicate* nodep) {
virtual void visit(AstConst* nodep) VL_OVERRIDE { }
virtual void visit(AstReplicate* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
virtual void visit(AstConcat* nodep) {
virtual void visit(AstConcat* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
virtual void visit(AstNot* nodep) {
virtual void visit(AstNot* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
virtual void visit(AstSel* nodep) {
virtual void visit(AstSel* nodep) VL_OVERRIDE {
if (!VN_IS(nodep->lsbp(), Const)) setNodeHazard(nodep);
iterateChildren(nodep);
}
virtual void visit(AstNodeSel* nodep) {
virtual void visit(AstNodeSel* nodep) VL_OVERRIDE {
if (!VN_IS(nodep->bitp(), Const)) setNodeHazard(nodep);
iterateChildren(nodep);
}
// Ignores
virtual void visit(AstInitial* nodep) { }
virtual void visit(AstTraceInc* nodep) { }
virtual void visit(AstCoverToggle* nodep) { }
virtual void visit(AstNodeDType* nodep) { }
virtual void visit(AstInitial* nodep) VL_OVERRIDE { }
virtual void visit(AstTraceInc* nodep) VL_OVERRIDE { }
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { }
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { }
//--------------------
// Default
virtual void visit(AstNodeMath* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
setNodeHazard(nodep);
iterateChildren(nodep);
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
@ -761,7 +764,7 @@ public:
}
}
virtual ~CdcVisitor() {
if (m_ofp) { delete m_ofp; m_ofp = NULL; }
if (m_ofp) VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
}
};

View File

@ -97,7 +97,7 @@ public:
new AstLogOr(m_scopetopp->fileline(), callp,
returnp->lhsp()->unlinkFrBack()));
returnp->replaceWith(newp);
returnp->deleteTree(); VL_DANGLING(returnp);
VL_DO_DANGLING(returnp->deleteTree(), returnp);
}
m_numStmts = 0;
}
@ -148,13 +148,13 @@ private:
m_statep->m_numStmts += visitor.count();
}
virtual void visit(AstBasicDType* nodep) {
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE {
newChangeDet();
}
virtual void visit(AstPackArrayDType* nodep) {
virtual void visit(AstPackArrayDType* nodep) VL_OVERRIDE {
newChangeDet();
}
virtual void visit(AstUnpackArrayDType* nodep) {
virtual void visit(AstUnpackArrayDType* nodep) VL_OVERRIDE {
for (int index=0; index < nodep->elementsConst(); ++index) {
AstNode* origVEp = m_varEqnp;
AstNode* origNLEp = m_newLvEqnp;
@ -175,7 +175,7 @@ private:
m_newRvEqnp = origNREp;
}
}
virtual void visit(AstNodeUOrStructDType* nodep) {
virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE {
if (nodep->packedUnsup()) {
newChangeDet();
} else {
@ -185,7 +185,7 @@ private:
<<m_vscp->varp()->prettyNameQ());
}
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (debug()) nodep->dumpTree(cout, "-DETECTARRAY-general-");
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
@ -247,7 +247,7 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
UINFO(4," MOD "<<nodep<<endl);
if (nodep->isTop()) {
m_statep->m_topModp = nodep;
@ -255,7 +255,7 @@ private:
iterateChildren(nodep);
}
virtual void visit(AstTopScope* nodep) {
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
UINFO(4," TS "<<nodep<<endl);
// Clearing
AstNode::user1ClearTree();
@ -279,7 +279,7 @@ private:
iterateChildren(nodep);
}
virtual void visit(AstVarScope* nodep) {
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {
if (nodep->isCircular()) {
UINFO(8," CIRC "<<nodep<<endl);
if (!nodep->user1SetOnce()) {
@ -287,12 +287,12 @@ private:
}
}
}
virtual void visit(AstNodeMath* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
// Short-circuit
}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -135,15 +135,15 @@ private:
cleanp->dtypeFrom(nodep); // Otherwise the AND normally picks LHS
relinkHandle.relink(cleanp);
}
void insureClean(AstNode* nodep) {
void ensureClean(AstNode* nodep) {
computeCppWidth(nodep);
if (!isClean(nodep)) insertClean(nodep);
}
void insureCleanAndNext(AstNode* nodep) {
void ensureCleanAndNext(AstNode* nodep) {
// Editing list, careful looping!
for (AstNode* exprp = nodep; exprp; ) {
AstNode* nextp = exprp->nextp();
insureClean(exprp);
ensureClean(exprp);
exprp = nextp;
}
}
@ -153,10 +153,10 @@ private:
iterateChildren(nodep);
computeCppWidth(nodep);
if (nodep->cleanLhs()) {
insureClean(nodep->lhsp());
ensureClean(nodep->lhsp());
}
if (nodep->cleanRhs()) {
insureClean(nodep->rhsp());
ensureClean(nodep->rhsp());
}
//no setClean.. must do it in each user routine.
}
@ -164,70 +164,73 @@ private:
iterateChildren(nodep);
computeCppWidth(nodep);
if (nodep->cleanLhs()) {
insureClean(nodep->lhsp());
ensureClean(nodep->lhsp());
}
if (nodep->cleanRhs()) {
insureClean(nodep->rhsp());
ensureClean(nodep->rhsp());
}
if (nodep->cleanThs()) {
insureClean(nodep->thsp());
ensureClean(nodep->thsp());
}
//no setClean.. must do it in each user routine.
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
iterateChildren(nodep);
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstNodeUniop* nodep) {
virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE {
iterateChildren(nodep);
computeCppWidth(nodep);
if (nodep->cleanLhs()) {
insureClean(nodep->lhsp());
ensureClean(nodep->lhsp());
}
setClean(nodep, nodep->cleanOut());
}
virtual void visit(AstNodeBiop* nodep) {
virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE {
operandBiop(nodep);
setClean(nodep, nodep->cleanOut());
}
virtual void visit(AstAnd* nodep) {
virtual void visit(AstAnd* nodep) VL_OVERRIDE {
operandBiop(nodep);
setClean(nodep, isClean(nodep->lhsp()) || isClean(nodep->rhsp()));
}
virtual void visit(AstXor* nodep) {
virtual void visit(AstXor* nodep) VL_OVERRIDE {
operandBiop(nodep);
setClean(nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
}
virtual void visit(AstOr* nodep) {
virtual void visit(AstOr* nodep) VL_OVERRIDE {
operandBiop(nodep);
setClean(nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
}
virtual void visit(AstNodeMath* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
iterateChildren(nodep);
computeCppWidth(nodep);
setClean(nodep, nodep->cleanOut());
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
iterateChildren(nodep);
computeCppWidth(nodep);
if (nodep->cleanRhs()) {
insureClean(nodep->rhsp());
ensureClean(nodep->rhsp());
}
}
virtual void visit(AstText* nodep) {
virtual void visit(AstText* nodep) VL_OVERRIDE {
setClean(nodep, true);
}
virtual void visit(AstScopeName* nodep) {
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
setClean(nodep, true);
}
virtual void visit(AstSel* nodep) {
virtual void visit(AstSel* nodep) VL_OVERRIDE {
operandTriop(nodep);
setClean(nodep, nodep->cleanOut());
}
virtual void visit(AstUCFunc* nodep) {
virtual void visit(AstUCFunc* nodep) VL_OVERRIDE {
iterateChildren(nodep);
computeCppWidth(nodep);
setClean(nodep, false);
@ -235,66 +238,66 @@ private:
if (!VN_IS(nodep->backp(), And)) {
insertClean(nodep);
}
insureCleanAndNext(nodep->bodysp());
ensureCleanAndNext(nodep->bodysp());
}
virtual void visit(AstTraceDecl* nodep) {
virtual void visit(AstTraceDecl* nodep) VL_OVERRIDE {
// No cleaning, or would loose pointer to enum
iterateChildren(nodep);
}
virtual void visit(AstTraceInc* nodep) {
virtual void visit(AstTraceInc* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureCleanAndNext(nodep->valuep());
ensureCleanAndNext(nodep->valuep());
}
virtual void visit(AstTypedef* nodep) {
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
// No cleaning, or would loose pointer to enum
iterateChildren(nodep);
}
virtual void visit(AstParamTypeDType* nodep) {
virtual void visit(AstParamTypeDType* nodep) VL_OVERRIDE {
// No cleaning, or would loose pointer to enum
iterateChildren(nodep);
}
// Control flow operators
virtual void visit(AstNodeCond* nodep) {
virtual void visit(AstNodeCond* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureClean(nodep->condp());
ensureClean(nodep->condp());
setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p()));
}
virtual void visit(AstWhile* nodep) {
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureClean(nodep->condp());
ensureClean(nodep->condp());
}
virtual void visit(AstNodeIf* nodep) {
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureClean(nodep->condp());
ensureClean(nodep->condp());
}
virtual void visit(AstSFormatF* nodep) {
virtual void visit(AstSFormatF* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureCleanAndNext(nodep->exprsp());
ensureCleanAndNext(nodep->exprsp());
setClean(nodep, true); // generates a string, so not relevant
}
virtual void visit(AstUCStmt* nodep) {
virtual void visit(AstUCStmt* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureCleanAndNext(nodep->bodysp());
ensureCleanAndNext(nodep->bodysp());
}
virtual void visit(AstCCall* nodep) {
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureCleanAndNext(nodep->argsp());
ensureCleanAndNext(nodep->argsp());
setClean(nodep, true);
}
virtual void visit(AstCMethodCall* nodep) {
virtual void visit(AstCMethodHard* nodep) VL_OVERRIDE {
iterateChildren(nodep);
insureCleanAndNext(nodep->pinsp());
ensureCleanAndNext(nodep->pinsp());
setClean(nodep, true);
}
virtual void visit(AstIntfRef* nodep) {
virtual void visit(AstIntfRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
setClean(nodep, true); // generates a string, so not relevant
}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
computeCppWidth(nodep);
}

View File

@ -189,7 +189,7 @@ private:
}
// VISITORS
virtual void visit(AstTopScope* nodep) {
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
UINFO(4," TOPSCOPE "<<nodep<<endl);
m_topScopep = nodep;
m_scopep = nodep->scopep();
@ -254,13 +254,16 @@ private:
m_topScopep = NULL;
m_scopep = NULL;
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
//UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep;
iterateChildren(nodep);
m_modp= NULL;
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
//UINFO(4," SCOPE "<<nodep<<endl);
m_scopep = nodep;
iterateChildren(nodep);
@ -271,25 +274,25 @@ private:
}
m_scopep = NULL;
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) {
stmtsp->unlinkFrBackWithNext();
cmtp->addNextHere(stmtsp);
}
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstAlwaysPost* nodep) {
virtual void visit(AstAlwaysPost* nodep) VL_OVERRIDE {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) {
stmtsp->unlinkFrBackWithNext();
cmtp->addNextHere(stmtsp);
}
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstCoverToggle* nodep) {
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
//nodep->dumpTree(cout, "ct:");
//COVERTOGGLE(INC, ORIG, CHANGE) ->
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
@ -307,18 +310,18 @@ private:
newp->addIfsp(new AstAssign(nodep->fileline(),
changep->cloneTree(false),
origp->cloneTree(false)));
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstInitial* nodep) {
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
nodep->replaceWith(cmtp);
if (AstNode* stmtsp = nodep->bodysp()) {
stmtsp->unlinkFrBackWithNext();
cmtp->addNextHere(stmtsp);
}
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// Link to global function
if (nodep->formCallTree()) {
@ -328,7 +331,7 @@ private:
m_finalFuncp->addStmtsp(callp);
}
}
virtual void visit(AstSenTree* nodep) {
virtual void visit(AstSenTree* nodep) VL_OVERRIDE {
// Delete it later; Actives still pointing to it
nodep->unlinkFrBack();
pushDeletep(nodep);
@ -342,14 +345,14 @@ private:
void addToInitial(AstNode* stmtsp) {
m_initFuncp->addStmtsp(stmtsp); // add to top level function
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
// Careful if adding variables here, ACTIVES can be under other ACTIVES
// Need to save and restore any member state in AstUntilStable block
if (!m_topScopep || !nodep->stmtsp()) {
// Not at the top or empty block...
// Only empty blocks should be leftover on the non-top. Killem.
UASSERT_OBJ(!nodep->stmtsp(), nodep, "Non-empty lower active");
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else if (m_mtaskBodyp) {
UINFO(4," TR ACTIVE "<<nodep<<endl);
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
@ -374,7 +377,7 @@ private:
clearLastSen();
m_mtaskBodyp->addStmtsp(stmtsp);
}
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else {
UINFO(4," ACTIVE "<<nodep<<endl);
AstNode* stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
@ -407,10 +410,10 @@ private:
// Move statements to function
addToEvalLoop(stmtsp);
}
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
}
virtual void visit(AstExecGraph* nodep) {
virtual void visit(AstExecGraph* nodep) VL_OVERRIDE {
for (m_mtaskBodyp = VN_CAST(nodep->op1p(), MTaskBody);
m_mtaskBodyp;
m_mtaskBodyp = VN_CAST(m_mtaskBodyp->nextp(), MTaskBody)) {
@ -427,7 +430,7 @@ private:
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -66,7 +66,7 @@ protected:
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
// Also repair it for DPI functions; when make __common need to ensure proper
// flags get inherited from the old to new AstCFunc, and that AstText doesn't
// get split between functions causing the text to have a dangling reference.
bool statementCombine() { return false; } // duplicateFunctionCombine();
@ -107,7 +107,7 @@ public:
callp->unlinkFrBack();
}
callp->user3(true); // Dead now
pushDeletep(callp); VL_DANGLING(callp);
VL_DO_DANGLING(pushDeletep(callp), callp);
m_callMmap.erase(eqit); // Fix the table
}
}
@ -131,13 +131,13 @@ public:
}
private:
// VISITORS
virtual void visit(AstCCall* nodep) {
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
addCall(nodep);
}
// Speed things up
virtual void visit(AstNodeAssign* nodep) {}
virtual void visit(AstNodeMath* nodep) {}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {}
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -160,7 +160,7 @@ private:
// OUTPUT:
// AstNode::user3() -> bool. True to indicate duplicated
// VISITORS
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
nodep->user3(true);
iterateChildren(nodep);
}
@ -228,7 +228,7 @@ private:
CombMarkVisitor visitor(oldfuncp);
m_call.replaceFunc(oldfuncp, NULL);
oldfuncp->unlinkFrBack();
pushDeletep(oldfuncp); VL_DANGLING(oldfuncp);
VL_DO_DANGLING(pushDeletep(oldfuncp), oldfuncp);
}
}
}
@ -260,7 +260,7 @@ private:
CombMarkVisitor visitor(oldfuncp);
m_call.replaceFunc(oldfuncp, newfuncp);
oldfuncp->unlinkFrBack();
pushDeletep(oldfuncp); VL_DANGLING(oldfuncp);
VL_DO_DANGLING(pushDeletep(oldfuncp), oldfuncp);
}
void replaceOnlyCallFunc(AstCCall* nodep) {
if (AstCFunc* oldfuncp = VN_CAST(nodep->backp(), CFunc)) {
@ -272,7 +272,7 @@ private:
UINFO(9," Function only has call "<<oldfuncp<<endl);
m_call.deleteCall(nodep);
CombMarkVisitor visitor(oldfuncp);
replaceFuncWFunc(oldfuncp, nodep->funcp()); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceFuncWFunc(oldfuncp, nodep->funcp()), nodep);
}
}
}
@ -384,12 +384,12 @@ private:
m_call.addCall(call2p);
// If either new statement makes a func with only a single call, replace
// the above callers to call it directly
replaceOnlyCallFunc(call1p); VL_DANGLING(call1p);
replaceOnlyCallFunc(call2p); VL_DANGLING(call2p);
VL_DO_DANGLING(replaceOnlyCallFunc(call1p), call1p);
VL_DO_DANGLING(replaceOnlyCallFunc(call2p), call2p);
}
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Track all callers of each function
m_call.main(nodep);
//
@ -398,7 +398,7 @@ private:
// Required so that a module instantiating another can benefit from collapsing.
iterateChildrenBackwards(nodep);
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep;
m_modNFuncs = 0;
@ -427,7 +427,7 @@ private:
}
m_modp = NULL;
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
m_funcp = nodep;
if (!nodep->dontCombine()) {
if (m_state == STATE_HASH) {
@ -438,7 +438,7 @@ private:
}
m_funcp = NULL;
}
virtual void visit(AstNodeStmt* nodep) {
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {
if (!nodep->isStatement()) {
iterateChildren(nodep);
return;
@ -453,10 +453,10 @@ private:
//--------------------
// Default: Just iterate
virtual void visit(AstVar*) {}
virtual void visit(AstTraceDecl*) {}
virtual void visit(AstTraceInc*) {}
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar*) VL_OVERRIDE {}
virtual void visit(AstTraceDecl*) VL_OVERRIDE {}
virtual void visit(AstTraceInc*) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -30,133 +30,489 @@
#include <string>
//######################################################################
// Resolve wildcards in files, modules, ftasks or variables
class V3ConfigLine {
// Template for a class that serves as a map for entities that can be specified
// as wildcards and are accessed by a resolved name. It rebuilds a name lookup
// cache of resolved entities. Entities stored in this container need an update
// function that takes a reference of this type to join multiple entities into one.
template <typename T> class V3ConfigWildcardResolver {
typedef std::map<string, T> Map;
Map m_mapWildcard; // Wildcard strings to entities
Map m_mapResolved; // Resolved strings to converged entities
public:
int m_lineno; // Line number to make change at
V3ErrorCode m_code; // Error code
bool m_on; // True to enable message
V3ConfigLine(V3ErrorCode code, int lineno, bool on)
: m_lineno(lineno), m_code(code), m_on(on) {}
~V3ConfigLine() {}
inline bool operator< (const V3ConfigLine& rh) const {
if (m_lineno<rh.m_lineno) return true;
if (m_lineno>rh.m_lineno) return false;
if (m_code<rh.m_code) return true;
if (m_code>rh.m_code) return false;
V3ConfigWildcardResolver() {}
~V3ConfigWildcardResolver() {}
/// Update into maps from other
void update(const V3ConfigWildcardResolver& other) {
typename Map::const_iterator it;
for (it = other.m_mapResolved.begin(); it != other.m_mapResolved.end(); ++it) {
m_mapResolved[it->first].update(it->second);
}
for (it = other.m_mapWildcard.begin(); it != other.m_mapWildcard.end(); ++it) {
m_mapWildcard[it->first].update(it->second);
}
}
// Access and create a (wildcard) entity
T& at(const string& name) {
// Don't store into wildcards if the name is not a wildcard string
return m_mapWildcard[name];
}
// Access an entity and resolve wildcards that match it
T* resolve(const string& name) {
// Lookup if it was resolved before, typically not
typename Map::iterator it = m_mapResolved.find(name);
if (VL_UNLIKELY(it != m_mapResolved.end())) { return &it->second; }
T* newp = NULL;
// Cannot be resolved, create if matched
// Update this entity with all matches in the wildcards
for (it = m_mapWildcard.begin(); it != m_mapWildcard.end(); ++it) {
if (VString::wildmatch(name, it->first)) {
if (!newp) {
newp = &m_mapResolved[name]; // Emplace and get pointer
}
newp->update(it->second);
}
}
return newp;
}
// Flush on update
void flush() { m_mapResolved.clear(); }
};
// Only public_flat_rw has the sensitity tree
class V3ConfigVarAttr {
public:
AstAttrType m_type; // Type of attribute
AstSenTree* m_sentreep; // Sensitivity tree for public_flat_rw
V3ConfigVarAttr(AstAttrType type, AstSenTree* sentreep)
: m_type(type)
, m_sentreep(sentreep) {}
};
// Overload vector with the required update function and to apply all entries
class V3ConfigVar : public std::vector<V3ConfigVarAttr> {
public:
// Update from other by copying all attributes
void update(const V3ConfigVar& node) {
reserve(size() + node.size());
insert(end(), node.begin(), node.end());
}
// Apply all attributes to the variable
void apply(AstVar* varp) {
for (const_iterator it = begin(); it != end(); ++it) {
AstNode* newp = new AstAttrOf(varp->fileline(), it->m_type);
varp->addAttrsp(newp);
if (it->m_type == AstAttrType::VAR_PUBLIC_FLAT_RW && it->m_sentreep) {
newp->addNext(new AstAlwaysPublic(varp->fileline(), it->m_sentreep, NULL));
}
}
}
};
typedef V3ConfigWildcardResolver<V3ConfigVar> V3ConfigVarResolver;
//######################################################################
// Function or task: Have variables and properties
class V3ConfigFTask {
V3ConfigVarResolver m_vars; // Variables in function/task
bool m_isolate; // Isolate function return
bool m_noinline; // Don't inline function/task
bool m_public; // Public function/task
public:
V3ConfigFTask()
: m_isolate(false)
, m_noinline(false)
, m_public(false) {}
void update(const V3ConfigFTask& f) {
// Don't overwrite true with false
if (f.m_isolate) m_isolate = true;
if (f.m_noinline) m_noinline = true;
if (f.m_public) m_public = true;
m_vars.update(f.m_vars);
}
V3ConfigVarResolver& vars() { return m_vars; }
void setIsolate(bool set) { m_isolate = set; }
void setNoInline(bool set) { m_noinline = set; }
void setPublic(bool set) { m_public = set; }
void apply(AstNodeFTask* ftaskp) {
if (m_noinline)
ftaskp->addStmtsp(new AstPragma(ftaskp->fileline(), AstPragmaType::NO_INLINE_TASK));
if (m_public)
ftaskp->addStmtsp(new AstPragma(ftaskp->fileline(), AstPragmaType::PUBLIC_TASK));
// Only functions can have isolate (return value)
if (VN_IS(ftaskp, Func)) ftaskp->attrIsolateAssign(m_isolate);
}
};
typedef V3ConfigWildcardResolver<V3ConfigFTask> V3ConfigFTaskResolver;
//######################################################################
// Modules have tasks, variables, named blocks and properties
class V3ConfigModule {
typedef vl_unordered_set<string> StringSet;
V3ConfigFTaskResolver m_tasks; // Functions/tasks in module
V3ConfigVarResolver m_vars; // Variables in module
StringSet m_coverageOffBlocks; // List of block names for coverage_off
bool m_inline; // Whether to force the inline
bool m_inlineValue; // The inline value (on/off)
bool m_public; // Public module
public:
V3ConfigModule()
: m_inline(false)
, m_inlineValue(false)
, m_public(false) {}
void update(const V3ConfigModule& m) {
m_tasks.update(m.m_tasks);
m_vars.update(m.m_vars);
for (StringSet::const_iterator it = m.m_coverageOffBlocks.begin();
it != m.m_coverageOffBlocks.end(); ++it) {
m_coverageOffBlocks.insert(*it);
}
if (!m_inline) {
m_inline = m.m_inline;
m_inlineValue = m.m_inlineValue;
}
if (!m_public) m_public = m.m_public;
}
V3ConfigFTaskResolver& ftasks() { return m_tasks; }
V3ConfigVarResolver& vars() { return m_vars; }
void addCoverageBlockOff(const string& name) { m_coverageOffBlocks.insert(name); }
void setInline(bool set) {
m_inline = true;
m_inlineValue = set;
}
void setPublic(bool set) { m_public = set; }
void apply(AstNodeModule* modp) {
if (m_inline) {
AstPragmaType type
= m_inlineValue ? AstPragmaType::INLINE_MODULE : AstPragmaType::NO_INLINE_MODULE;
AstNode* nodep = new AstPragma(modp->fileline(), type);
modp->addStmtp(nodep);
}
if (m_public) {
AstNode* nodep = new AstPragma(modp->fileline(), AstPragmaType::PUBLIC_MODULE);
modp->addStmtp(nodep);
}
}
void applyBlock(AstBegin* nodep) {
AstPragmaType pragma = AstPragmaType::COVERAGE_BLOCK_OFF;
if (!nodep->unnamed()) {
for (StringSet::const_iterator it = m_coverageOffBlocks.begin();
it != m_coverageOffBlocks.end(); ++it) {
if (VString::wildmatch(nodep->name(), *it)) {
nodep->addStmtsp(new AstPragma(nodep->fileline(), pragma));
}
}
}
}
};
typedef V3ConfigWildcardResolver<V3ConfigModule> V3ConfigModuleResolver;
//######################################################################
// Files have:
// - Line ignores (lint/coverage/tracing on/off)
// - Line attributes: Attributes attached to lines
// lint/coverage/tracing on/off
class V3ConfigIgnoresLine {
public:
int m_lineno; // Line number to make change at
V3ErrorCode m_code; // Error code
bool m_on; // True to enable message
V3ConfigIgnoresLine(V3ErrorCode code, int lineno, bool on)
: m_lineno(lineno)
, m_code(code)
, m_on(on) {}
~V3ConfigIgnoresLine() {}
inline bool operator<(const V3ConfigIgnoresLine& rh) const {
if (m_lineno < rh.m_lineno) return true;
if (m_lineno > rh.m_lineno) return false;
if (m_code < rh.m_code) return true;
if (m_code > rh.m_code) return false;
// Always turn "on" before "off" so that overlapping lines will end
// up finally with the error "off"
return (m_on>rh.m_on);
return (m_on > rh.m_on);
}
};
std::ostream& operator<<(std::ostream& os, V3ConfigLine rhs) {
return os<<rhs.m_lineno<<", "<<rhs.m_code<<", "<<rhs.m_on; }
std::ostream& operator<<(std::ostream& os, V3ConfigIgnoresLine rhs) {
return os << rhs.m_lineno << ", " << rhs.m_code << ", " << rhs.m_on;
}
class V3ConfigIgnores {
typedef std::multiset<V3ConfigLine> IgnLines; // list of {line,code,on}
typedef std::map<string,IgnLines> IgnFiles; // {filename} => list of {line,code,on}
// Some attributes are attached to entities of the occur on a fileline
// and multiple attributes can be attached to a line
typedef std::bitset<AstPragmaType::ENUM_SIZE> V3ConfigLineAttribute;
// MEMBERS
string m_lastFilename; // Last filename looked up
int m_lastLineno; // Last linenumber looked up
// File entity
class V3ConfigFile {
typedef std::map<int, V3ConfigLineAttribute> LineAttrMap; // Map line->bitset of attributes
typedef std::multiset<V3ConfigIgnoresLine> IgnLines; // list of {line,code,on}
typedef std::pair<V3ErrorCode, string> WaiverSetting; // Waive code if string matches
typedef std::vector<WaiverSetting> Waivers; // List of {code,wildcard string}
IgnLines::const_iterator m_lastIt; // Point with next linenumber > current line number
IgnLines::const_iterator m_lastEnd; // Point with end()
LineAttrMap m_lineAttrs; // Atributes to line mapping
IgnLines m_ignLines; // Ignore line settings
Waivers m_waivers; // Waive messages
IgnFiles m_ignWilds; // Ignores for each wildcarded filename
IgnFiles m_ignFiles; // Ignores for each non-wildcarded filename
struct {
int lineno; // Last line number
IgnLines::const_iterator it; // Point with next linenumber > current line number
} m_lastIgnore; // Last ignore line run
static V3ConfigIgnores s_singleton; // Singleton (not via local static, as that's slow)
V3ConfigIgnores() { m_lastLineno = -1; }
~V3ConfigIgnores() {}
// METHODS
inline IgnLines* findWilds(const string& wildname) {
IgnFiles::iterator it = m_ignWilds.find(wildname);
if (it != m_ignWilds.end()) {
return &(it->second);
} else {
m_ignWilds.insert(make_pair(wildname, IgnLines()));
it = m_ignWilds.find(wildname);
return &(it->second);
}
}
inline void absBuild(const string& filename) {
// Given a filename, find all wildcard matches against it and build
// hash with the specific filename. This avoids having to wildmatch
// more than once against any filename.
IgnFiles::iterator it = m_ignFiles.find(filename);
if (it == m_ignFiles.end()) {
// Haven't seen this filename before
m_ignFiles.insert(make_pair(filename, IgnLines()));
it = m_ignFiles.find(filename);
// Make new list for this file of all matches
for (IgnFiles::iterator fnit = m_ignWilds.begin(); fnit != m_ignWilds.end(); ++fnit) {
if (VString::wildmatch(filename.c_str(), fnit->first.c_str())) {
for (IgnLines::iterator lit = fnit->second.begin();
lit != fnit->second.end(); ++lit) {
it->second.insert(*lit);
}
}
}
}
m_lastIt = it->second.begin();
m_lastEnd = it->second.end();
// Match a given line and attribute to the map, line 0 is any
bool lineMatch(int lineno, AstPragmaType type) {
if (m_lineAttrs.find(0) != m_lineAttrs.end() && m_lineAttrs[0][type]) return true;
if (m_lineAttrs.find(lineno) == m_lineAttrs.end()) return false;
return m_lineAttrs[lineno][type];
}
public:
inline static V3ConfigIgnores& singleton() { return s_singleton; }
V3ConfigFile() {
m_lastIgnore.lineno = -1;
m_lastIgnore.it = m_ignLines.begin();
}
void update(const V3ConfigFile& file) {
// Copy in all Attributes
for (LineAttrMap::const_iterator it = file.m_lineAttrs.begin();
it != file.m_lineAttrs.end(); ++it) {
m_lineAttrs[it->first] |= it->second;
}
// Copy in all ignores
for (IgnLines::const_iterator it = file.m_ignLines.begin(); it != file.m_ignLines.end();
++it) {
m_ignLines.insert(*it);
}
// Update the iterator after the list has changed
m_lastIgnore.it = m_ignLines.begin();
m_waivers.reserve(m_waivers.size() + file.m_waivers.size());
m_waivers.insert(m_waivers.end(), file.m_waivers.begin(), file.m_waivers.end());
}
void addLineAttribute(int lineno, AstPragmaType attr) { m_lineAttrs[lineno].set(attr); }
void addIgnore(V3ErrorCode code, int lineno, bool on) {
m_ignLines.insert(V3ConfigIgnoresLine(code, lineno, on));
m_lastIgnore.it = m_ignLines.begin();
}
void addWaiver(V3ErrorCode code, const string& match) {
m_waivers.push_back(make_pair(code, match));
}
void addIgnore(V3ErrorCode code, const string& wildname, int lineno, bool on) {
// Insert
IgnLines* linesp = findWilds(wildname);
UINFO(9,"config addIgnore "<<wildname<<":"<<lineno<<", "<<code<<", "<<on<<endl);
linesp->insert(V3ConfigLine(code, lineno, on));
// Flush the match cache, due to a change in the rules.
m_ignFiles.clear();
m_lastFilename = " ";
void applyBlock(AstBegin* nodep) {
// Apply to block at this line
AstPragmaType pragma = AstPragmaType::COVERAGE_BLOCK_OFF;
if (lineMatch(nodep->fileline()->lineno(), pragma)) {
nodep->addStmtsp(new AstPragma(nodep->fileline(), pragma));
}
}
void applyCase(AstCase* nodep) {
// Apply to this case at this line
int lineno = nodep->fileline()->lineno();
if (lineMatch(lineno, AstPragmaType::FULL_CASE)) nodep->fullPragma(true);
if (lineMatch(lineno, AstPragmaType::PARALLEL_CASE)) nodep->parallelPragma(true);
}
inline void applyIgnores(FileLine* filelinep) {
// HOT routine, called each parsed token line
if (m_lastLineno != filelinep->lastLineno()
|| m_lastFilename != filelinep->filename()) {
//UINFO(9," ApplyIgnores for "<<filelinep->ascii()<<endl);
if (VL_UNLIKELY(m_lastFilename != filelinep->filename())) {
absBuild(filelinep->filename());
m_lastFilename = filelinep->filename();
}
// HOT routine, called each parsed token line of this filename
if (m_lastIgnore.lineno != filelinep->lineno()) {
// UINFO(9," ApplyIgnores for "<<filelinep->ascii()<<endl);
// Process all on/offs for lines up to and including the current line
int curlineno = filelinep->lastLineno();
for (; m_lastIt != m_lastEnd; ++m_lastIt) {
if (m_lastIt->m_lineno > curlineno) break;
//UINFO(9," Hit "<<*m_lastIt<<endl);
filelinep->warnOn(m_lastIt->m_code, m_lastIt->m_on);
for (; m_lastIgnore.it != m_ignLines.end(); ++m_lastIgnore.it) {
if (m_lastIgnore.it->m_lineno > curlineno) break;
// UINFO(9," Hit "<<*m_lastIt<<endl);
filelinep->warnOn(m_lastIgnore.it->m_code, m_lastIgnore.it->m_on);
}
if (0 && debug() >= 9) {
for (IgnLines::const_iterator it=m_lastIt; it != m_lastEnd; ++it) {
UINFO(9," NXT "<<*it<<endl);
for (IgnLines::const_iterator it = m_lastIgnore.it; it != m_ignLines.end(); ++it) {
UINFO(9, " NXT " << *it << endl);
}
}
m_lastLineno = filelinep->lastLineno();
m_lastIgnore.lineno = filelinep->lastLineno();
}
}
bool waive(V3ErrorCode code, const string& match) {
for (Waivers::const_iterator it = m_waivers.begin(); it != m_waivers.end(); ++it) {
if (((it->first == code) || (it->first == V3ErrorCode::I_LINT))
&& VString::wildmatch(match, it->second)) return true;
}
return false;
}
};
V3ConfigIgnores V3ConfigIgnores::s_singleton;
typedef V3ConfigWildcardResolver<V3ConfigFile> V3ConfigFileResolver;
//######################################################################
// Resolve modules and files in the design
class V3ConfigResolver {
V3ConfigModuleResolver m_modules; // Access to module names (with wildcards)
V3ConfigFileResolver m_files; // Access to file names (with wildcards)
static V3ConfigResolver s_singleton; // Singleton (not via local static, as that's slow)
V3ConfigResolver() {}
~V3ConfigResolver() {}
public:
inline static V3ConfigResolver& s() { return s_singleton; }
V3ConfigModuleResolver& modules() { return m_modules; }
V3ConfigFileResolver& files() { return m_files; }
};
V3ConfigResolver V3ConfigResolver::s_singleton;
//######################################################################
// V3Config
void V3Config::addCaseFull(const string& filename, int lineno) {
V3ConfigFile& file = V3ConfigResolver::s().files().at(filename);
file.addLineAttribute(lineno, AstPragmaType::FULL_CASE);
}
void V3Config::addCaseParallel(const string& filename, int lineno) {
V3ConfigFile& file = V3ConfigResolver::s().files().at(filename);
file.addLineAttribute(lineno, AstPragmaType::PARALLEL_CASE);
}
void V3Config::addCoverageBlockOff(const string& filename, int lineno) {
V3ConfigFile& file = V3ConfigResolver::s().files().at(filename);
file.addLineAttribute(lineno, AstPragmaType::COVERAGE_BLOCK_OFF);
}
void V3Config::addCoverageBlockOff(const string& module, const string& blockname) {
V3ConfigResolver::s().modules().at(module).addCoverageBlockOff(blockname);
}
void V3Config::addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max) {
if (filename=="*") {
FileLine::globalWarnOff(code,!on);
if (filename == "*") {
FileLine::globalWarnOff(code, !on);
} else {
V3ConfigIgnores::singleton().addIgnore(code, filename, min, on);
if (max) V3ConfigIgnores::singleton().addIgnore(code, filename, max, !on);
V3ConfigResolver::s().files().at(filename).addIgnore(code, min, on);
if (max) V3ConfigResolver::s().files().at(filename).addIgnore(code, max, !on);
V3ConfigResolver::s().files().flush();
}
}
void V3Config::applyIgnores(FileLine* filelinep) {
V3ConfigIgnores::singleton().applyIgnores(filelinep);
void V3Config::addInline(FileLine* fl, const string& module, const string& ftask, bool on) {
if (ftask.empty()) {
V3ConfigResolver::s().modules().at(module).setInline(on);
} else {
if (!on) {
fl->v3error("no_inline not supported for tasks" << endl);
} else {
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setNoInline(on);
}
}
}
void V3Config::addVarAttr(FileLine* fl, const string& module, const string& ftask,
const string& var, AstAttrType attr, AstSenTree* sensep) {
// Semantics: sensep only if public_flat_rw
if ((attr != AstAttrType::VAR_PUBLIC_FLAT_RW) && sensep) {
sensep->v3error("sensitivity not expected for attribute" << endl);
return;
}
// Semantics: Most of the attributes operate on signals
if (var.empty()) {
if (attr == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) {
if (ftask.empty()) {
fl->v3error("isolate_assignments only applies to signals or functions/tasks"
<< endl);
} else {
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setIsolate(true);
}
} else if (attr == AstAttrType::VAR_PUBLIC) {
if (ftask.empty()) {
// public module, this is the only exception from var here
V3ConfigResolver::s().modules().at(module).setPublic(true);
} else {
V3ConfigResolver::s().modules().at(module).ftasks().at(ftask).setPublic(true);
}
} else {
fl->v3error("missing -signal" << endl);
}
} else {
V3ConfigModule& mod = V3ConfigResolver::s().modules().at(module);
if (ftask.empty()) {
mod.vars().at(var).push_back(V3ConfigVarAttr(attr, sensep));
} else {
mod.ftasks().at(ftask).vars().at(var).push_back(V3ConfigVarAttr(attr, sensep));
}
}
}
void V3Config::addWaiver(V3ErrorCode code, const string& filename, const string& match) {
V3ConfigResolver::s().files().at(filename).addWaiver(code, match);
}
void V3Config::applyCase(AstCase* nodep) {
const string& filename = nodep->fileline()->filename();
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filename);
if (filep) filep->applyCase(nodep);
}
void V3Config::applyCoverageBlock(AstNodeModule* modulep, AstBegin* nodep) {
const string& filename = nodep->fileline()->filename();
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filename);
if (filep) filep->applyBlock(nodep);
const string& modname = modulep->name();
V3ConfigModule* modp = V3ConfigResolver::s().modules().resolve(modname);
if (modp) modp->applyBlock(nodep);
}
void V3Config::applyIgnores(FileLine* filelinep) {
const string& filename = filelinep->filename();
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filename);
if (filep) filep->applyIgnores(filelinep);
}
void V3Config::applyModule(AstNodeModule* modulep) {
const string& modname = modulep->name();
V3ConfigModule* modp = V3ConfigResolver::s().modules().resolve(modname);
if (modp) modp->apply(modulep);
}
void V3Config::applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp) {
const string& modname = modulep->name();
V3ConfigModule* modp = V3ConfigResolver::s().modules().resolve(modname);
if (!modp) return;
V3ConfigFTask* ftp = modp->ftasks().resolve(ftaskp->name());
if (ftp) ftp->apply(ftaskp);
}
void V3Config::applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp) {
V3ConfigVar* vp;
V3ConfigModule* modp = V3ConfigResolver::s().modules().resolve(modulep->name());
if (!modp) return;
if (ftaskp) {
V3ConfigFTask* ftp = modp->ftasks().resolve(ftaskp->name());
if (!ftp) return;
vp = ftp->vars().resolve(varp->name());
} else {
vp = modp->vars().resolve(varp->name());
}
if (vp) vp->apply(varp);
}
bool V3Config::waive(FileLine* filelinep, V3ErrorCode code, const string& message) {
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filelinep->filename());
if (!filep) return false;
return filep->waive(code, message);
}

View File

@ -26,13 +26,27 @@
#include "V3Error.h"
#include "V3FileLine.h"
#include "V3Ast.h"
//######################################################################
class V3Config {
public:
static void addCaseFull(const string& file, int lineno);
static void addCaseParallel(const string& file, int lineno);
static void addCoverageBlockOff(const string& file, int lineno);
static void addCoverageBlockOff(const string& module, const string& blockname);
static void addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max);
static void addWaiver(V3ErrorCode code, const string& filename, const string& msg);
static void addInline(FileLine* fl, const string& module, const string& ftask, bool on);
static void addVarAttr(FileLine* fl, const string& module, const string& ftask, const string& signal, AstAttrType type, AstSenTree* nodep);
static void applyCase(AstCase* nodep);
static void applyCoverageBlock(AstNodeModule* modulep, AstBegin* nodep);
static void applyIgnores(FileLine* filelinep);
static void applyModule(AstNodeModule* nodep);
static void applyFTask(AstNodeModule* modulep, AstNodeFTask* ftaskp);
static void applyVarAttr(AstNodeModule* modulep, AstNodeFTask* ftaskp, AstVar* varp);
static bool waive(FileLine* filelinep, V3ErrorCode code, const string& match);
};
#endif // Guard

View File

@ -46,10 +46,10 @@ class ConstVarMarkVisitor : public AstNVisitor {
// AstVar::user4p -> bool, Var marked, 0=not set yet
private:
// VISITORS
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (nodep->varp()) nodep->varp()->user4(1);
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -68,10 +68,10 @@ class ConstVarFindVisitor : public AstNVisitor {
bool m_found;
private:
// VISITORS
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (nodep->varp() && nodep->varp()->user4()) m_found = true;
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -212,7 +212,7 @@ private:
if (!operandsSame(ap, bp)) return false;
// Do it
cp->unlinkFrBack();
andp->unlinkFrBack()->deleteTree(); VL_DANGLING(andp); VL_DANGLING(notp);
VL_DO_DANGLING(andp->unlinkFrBack()->deleteTree(), andp); VL_DANGLING(notp);
// Replace whichever branch is now dangling
if (nodep->rhsp()) nodep->lhsp(cp);
else nodep->rhsp(cp);
@ -240,7 +240,7 @@ private:
newp->dtypeFrom(nodep);
newp->expr1p()->dtypeFrom(nodep); // As And might have been to change widths
newp->expr2p()->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
return true;
}
static bool operandShiftSame(const AstNode* nodep) {
@ -343,7 +343,7 @@ private:
&& nodep->lsbConst()==0
&& static_cast<int>(nodep->widthConst()) == extendp->lhsp()->width()
)) return false;
replaceWChild(nodep, extendp->lhsp()); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWChild(nodep, extendp->lhsp()), nodep);
return true;
}
bool operandSelBiLower(AstSel* nodep) {
@ -362,7 +362,7 @@ private:
bip->lhsp(new AstSel(nodep->fileline(), bilhsp, 0, nodep->widthConst()));
bip->rhsp(new AstSel(nodep->fileline(), birhsp, 0, nodep->widthConst()));
if (debug()>=9) bip->dumpTree(cout, "SEL(BI)-ou:");
replaceWChild(nodep, bip); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWChild(nodep, bip), nodep);
return true;
}
bool operandSelShiftLower(AstSel* nodep) {
@ -390,7 +390,7 @@ private:
newLsb, nodep->widthConst());
newp->dtypeFrom(nodep);
if (debug()>=9) newp->dumpTree(cout, "SEL(SH)-ou:");
nodep->replaceWith(newp); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->replaceWith(newp), nodep);
return true;
}
@ -409,14 +409,14 @@ private:
//
if (debug()>=9) nodep->dumpTree(cout, "BI(EXTEND)-in:");
smallerp->unlinkFrBack();
extendp->unlinkFrBack()->deleteTree(); // aka nodep->lhsp.
VL_DO_DANGLING(extendp->unlinkFrBack()->deleteTree(), extendp); // aka nodep->lhsp.
nodep->rhsp(smallerp);
constp->unlinkFrBack();
V3Number num (constp, subsize);
num.opAssign(constp->num());
nodep->lhsp(new AstConst(constp->fileline(), num));
constp->deleteTree(); VL_DANGLING(constp);
VL_DO_DANGLING(constp->deleteTree(), constp);
if (debug()>=9) nodep->dumpTree(cout, "BI(EXTEND)-ou:");
return true;
}
@ -622,11 +622,11 @@ private:
if (debug()>5) oldp->dumpTree(cout, " const_old: ");
if (debug()>5) newp->dumpTree(cout, " _new: ");
oldp->replaceWith(newp);
oldp->deleteTree(); VL_DANGLING(oldp);
VL_DO_DANGLING(oldp->deleteTree(), oldp);
}
void replaceNum(AstNode* nodep, uint32_t val) {
V3Number num (nodep, nodep->width(), val);
replaceNum(nodep, num); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
}
void replaceNumSigned(AstNodeBiop* nodep, uint32_t val) {
// We allow both sides to be constant, as one may have come from
@ -634,48 +634,48 @@ private:
if (m_warn && !(VN_IS(nodep->lhsp(), Const) && VN_IS(nodep->rhsp(), Const))) {
nodep->v3warn(UNSIGNED, "Comparison is constant due to unsigned arithmetic");
}
replaceNum(nodep, val); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, val), nodep);
}
void replaceNumLimited(AstNodeBiop* nodep, uint32_t val) {
// Avoids gcc warning about same
if (m_warn) nodep->v3warn(CMPCONST, "Comparison is constant due to limited range");
replaceNum(nodep, val); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, val), nodep);
}
void replaceZero(AstNode* nodep) {
replaceNum(nodep, 0); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, 0), nodep);
}
void replaceZeroChkPure(AstNode* nodep, AstNode* checkp) {
// For example, "0 * n" -> 0 if n has no side effects
// Else strength reduce it to 0 & n.
// If ever change the operation note AstAnd rule specially ignores this created pattern
if (isTPure(checkp)) {
replaceNum(nodep, 0); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, 0), nodep);
} else {
AstNode* newp = new AstAnd(nodep->fileline(),
new AstConst(nodep->fileline(), 0),
checkp->unlinkFrBack());
newp->dtypeFrom(nodep);
nodep->replaceWith(newp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
void replaceAllOnes(AstNode* nodep) {
V3Number ones (nodep, nodep->width(), 0);
ones.setMask(nodep->width());
replaceNum(nodep, ones); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, ones), nodep);
}
void replaceConst(AstNodeUniop* nodep) {
V3Number num (nodep, nodep->width());
nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num());
UINFO(4,"UNICONST -> "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
}
void replaceConst(AstNodeBiop* nodep) {
V3Number num (nodep, nodep->width());
nodep->numberOperate(num, VN_CAST(nodep->lhsp(), Const)->num(),
VN_CAST(nodep->rhsp(), Const)->num());
UINFO(4,"BICONST -> "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
}
void replaceConst(AstNodeTriop* nodep) {
V3Number num (nodep, nodep->width());
@ -683,7 +683,7 @@ private:
VN_CAST(nodep->rhsp(), Const)->num(),
VN_CAST(nodep->thsp(), Const)->num());
UINFO(4,"TRICONST -> "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
}
void replaceConstString(AstNode* oldp, const string& num) {
@ -693,7 +693,7 @@ private:
if (debug()>5) oldp->dumpTree(cout, " const_old: ");
if (debug()>5) newp->dumpTree(cout, " _new: ");
oldp->replaceWith(newp);
oldp->deleteTree(); VL_DANGLING(oldp);
VL_DO_DANGLING(oldp->deleteTree(), oldp);
}
//----------------------------------------
// Replacement functions.
@ -706,7 +706,7 @@ private:
// This may adversely affect the operation of the node being replaced.
childp->dtypeFrom(nodep);
nodep->replaceWith(childp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
//! Replace a ternary node with its RHS after iterating
@ -794,15 +794,15 @@ private:
lp->rhsp(nodep);
nodep->lhsp(lrp);
nodep->rhsp(rrp);
rp->deleteTree();
rlp->deleteTree();
VL_DO_DANGLING(rp->deleteTree(), rp);
VL_DO_DANGLING(rlp->deleteTree(), rlp);
} else if (operandsSame(lrp, rrp)) {
lp->lhsp(nodep);
lp->rhsp(rrp);
nodep->lhsp(llp);
nodep->rhsp(rlp);
rp->deleteTree();
lrp->deleteTree();
VL_DO_DANGLING(rp->deleteTree(), rp);
VL_DO_DANGLING(lrp->deleteTree(), lrp);
} else {
nodep->v3fatalSrc("replaceAndOr on something operandAndOrSame shouldn't have matched");
}
@ -822,8 +822,8 @@ private:
lp->rhsp(lrp);
nodep->lhsp(llp);
nodep->rhsp(rlp);
rp->deleteTree();
rrp->deleteTree();
VL_DO_DANGLING(rp->deleteTree(), rp);
VL_DO_DANGLING(rrp->deleteTree(), rrp);
//nodep->dumpTree(cout, " repShiftSame_new: ");
}
void replaceConcatSel(AstConcat* nodep) {
@ -842,9 +842,9 @@ private:
UINFO(5, "merged two adjacent sel "<<lselp <<" and "<<rselp<< " to one "<<newselp<<endl);
nodep->replaceWith(newselp);
lselp->deleteTree(); VL_DANGLING(lselp);
rselp->deleteTree(); VL_DANGLING(rselp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(lselp->deleteTree(), lselp);
VL_DO_DANGLING(rselp->deleteTree(), rselp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceConcatMerge(AstConcat* nodep) {
AstNodeBiop* lp = VN_CAST(nodep->lhsp(), NodeBiop);
@ -861,8 +861,8 @@ private:
lp->rhsp()->replaceWith(newrp);
lp->dtypeChgWidthSigned(newlp->width(), newlp->width(), AstNumeric::UNSIGNED);
UINFO(5, "merged "<< nodep <<endl);
rp->unlinkFrBack()->deleteTree(); VL_DANGLING(rp);
nodep->replaceWith(lp->unlinkFrBack()); nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(rp->unlinkFrBack()->deleteTree(), rp);
nodep->replaceWith(lp->unlinkFrBack()); VL_DO_DANGLING(nodep->deleteTree(), nodep);
iterate(lp->lhsp());
iterate(lp->rhsp());
} else nodep->v3fatalSrc("tried to merge two Concat which are not adjacent");
@ -875,7 +875,7 @@ private:
? static_cast<AstNode*>(new AstExtendS(nodep->fileline(), arg0p))
: static_cast<AstNode*>(new AstExtend (nodep->fileline(), arg0p)));
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replacePowShift(AstNodeBiop* nodep) { // Pow or PowS
UINFO(5,"POW(2,b)->SHIFTL(1,b) "<<nodep<<endl);
@ -885,7 +885,7 @@ private:
rhsp);
newp->dtypeFrom(nodep);
newp->lhsp()->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceMulShift(AstMul* nodep) { // Mul, but not MulS as not simple shift
UINFO(5,"MUL(2^n,b)->SHIFTL(b,n) "<<nodep<<endl);
@ -894,7 +894,7 @@ private:
AstShiftL* newp = new AstShiftL(nodep->fileline(),
opp, new AstConst(nodep->fileline(), amount));
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceDivShift(AstDiv* nodep) { // Mul, but not MulS as not simple shift
UINFO(5,"DIV(b,2^n)->SHIFTR(b,n) "<<nodep<<endl);
@ -903,7 +903,7 @@ private:
AstShiftR* newp = new AstShiftR(nodep->fileline(),
opp, new AstConst(nodep->fileline(), amount));
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceModAnd(AstModDiv* nodep) { // Mod, but not ModS as not simple shift
UINFO(5,"MOD(b,2^n)->AND(b,2^n-1) "<<nodep<<endl);
@ -914,7 +914,7 @@ private:
AstAnd* newp = new AstAnd(nodep->fileline(),
opp, new AstConst(nodep->fileline(), mask));
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceShiftOp(AstNodeBiop* nodep) {
UINFO(5,"SHIFT(AND(a,b),CONST)->AND(SHIFT(a,CONST),SHIFT(b,CONST)) "<<nodep<<endl);
@ -946,8 +946,8 @@ private:
int shift1 = VN_CAST(shift1p, Const)->toUInt();
int shift2 = VN_CAST(shift2p, Const)->toUInt();
int newshift = shift1+shift2;
shift1p->deleteTree(); VL_DANGLING(shift1p);
shift2p->deleteTree(); VL_DANGLING(shift2p);
VL_DO_DANGLING(shift1p->deleteTree(), shift1p);
VL_DO_DANGLING(shift2p->deleteTree(), shift2p);
nodep->lhsp(ap);
nodep->rhsp(new AstConst(nodep->fileline(), newshift));
iterate(nodep); // Further reduce, either node may have more reductions.
@ -958,8 +958,8 @@ private:
int shift2 = VN_CAST(shift2p, Const)->toUInt();
if (VN_IS(nodep, ShiftR)) shift2=-shift2;
int newshift = shift1+shift2;
shift1p->deleteTree(); VL_DANGLING(shift1p);
shift2p->deleteTree(); VL_DANGLING(shift2p);
VL_DO_DANGLING(shift1p->deleteTree(), shift1p);
VL_DO_DANGLING(shift2p->deleteTree(), shift2p);
AstNode* newp;
V3Number mask1 (nodep, nodep->width());
V3Number ones (nodep, nodep->width());
@ -987,11 +987,11 @@ private:
newp,
new AstConst(nodep->fileline(), mask));
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
//newp->dumpTree(cout, " repShiftShift_new: ");
iterate(newp); // Further reduce, either node may have more reductions.
}
lhsp->deleteTree(); VL_DANGLING(lhsp);
VL_DO_DANGLING(lhsp->deleteTree(), lhsp);
}
bool replaceAssignMultiSel(AstNodeAssign* nodep) {
@ -1033,8 +1033,9 @@ private:
new AstConcat(rhs1p->fileline(), rhs1p, rhs2p));
}
//pnewp->dumpTree(cout, "conew: ");
nodep->replaceWith(newp); nodep->deleteTree();
nextp->unlinkFrBack()->deleteTree();
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
VL_DO_DANGLING(nextp->unlinkFrBack()->deleteTree(), nextp);
return true;
}
@ -1062,7 +1063,7 @@ private:
nodep->v3error("Wire inputs its own output, creating circular logic (wire x=x)");
return false; // Don't delete the assign, or V3Gate will freak out
} else {
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return true;
}
}
@ -1156,8 +1157,8 @@ private:
if (debug()>=9 && newp) newp->dumpTreeAndNext(cout, " _new: ");
nodep->addNextHere(newp);
// Cleanup
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
conp->deleteTree(); VL_DANGLING(conp);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
VL_DO_DANGLING(conp->deleteTree(), conp);
// Further reduce, either node may have more reductions.
return true;
}
@ -1170,8 +1171,8 @@ private:
AstNode* streamp = VN_CAST(nodep->rhsp(), StreamR)->unlinkFrBack();
nodep->rhsp(srcp);
// Cleanup
sizep->deleteTree(); VL_DANGLING(sizep);
streamp->deleteTree(); VL_DANGLING(streamp);
VL_DO_DANGLING(sizep->deleteTree(), sizep);
VL_DO_DANGLING(streamp->deleteTree(), streamp);
// Further reduce, any of the nodes may have more reductions.
return true;
}
@ -1213,8 +1214,8 @@ private:
nodep->lhsp(dstp);
nodep->rhsp(srcp);
// Cleanup
sizep->deleteTree(); VL_DANGLING(sizep);
streamp->deleteTree(); VL_DANGLING(streamp);
VL_DO_DANGLING(sizep->deleteTree(), sizep);
VL_DO_DANGLING(streamp->deleteTree(), streamp);
// Further reduce, any of the nodes may have more reductions.
return true;
}
@ -1250,7 +1251,7 @@ private:
// widthMin no longer applicable if different C-expanded width
newp->dtypeSetLogicSized(nodep->width(), AstNumeric::UNSIGNED);
nodep->replaceWith(newp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
if (debug()>=9) newp->dumpTree(cout, " _new: ");
}
@ -1264,7 +1265,7 @@ private:
<<nodep->prettyTypeName()<<endl
<<errorp->warnOther()<<"... Location of non-constant "
<<errorp->prettyTypeName()<<": "<<simvis.whyNotMessage());
replaceZero(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceZero(nodep), nodep);
} else {
// Fetch the result
AstNode* valuep = simvis.fetchValueNull(nodep); // valuep is owned by Simulate
@ -1274,30 +1275,33 @@ private:
newp->dtypeFrom(nodep);
newp->fileline(nodep->fileline());
UINFO(4, "Simulate->"<<newp<<endl);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
//----------------------------------------
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Iterate modules backwards, in bottom-up order. That's faster
iterateChildrenBackwards(nodep);
}
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
iterateChildren(nodep);
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
// No ASSIGNW removals under funcs, we've long eliminated INITIALs
// (We should perhaps rename the assignw's to just assigns)
m_wremove = false;
iterateChildren(nodep);
m_wremove = true;
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
// No ASSIGNW removals under scope, we've long eliminated INITIALs
m_scopep = nodep;
m_wremove = false;
@ -1354,7 +1358,7 @@ private:
// If bp was a concat, then we have this exact same form again!
// Recurse rather then calling node->iterate to prevent 2^n recursion!
if (operandConcatMove(abConcp)) moveConcat(abConcp);
bcConcp->deleteTree(); VL_DANGLING(bcConcp);
VL_DO_DANGLING(bcConcp->deleteTree(), bcConcp);
} else {
AstConcat* abConcp = VN_CAST(nodep->lhsp(), Concat); abConcp->unlinkFrBack();
AstNode* ap = abConcp->lhsp()->unlinkFrBack();
@ -1365,21 +1369,21 @@ private:
nodep->lhsp(ap);
nodep->rhsp(bcConcp);
if (operandConcatMove(bcConcp)) moveConcat(bcConcp);
abConcp->deleteTree(); VL_DANGLING(abConcp);
VL_DO_DANGLING(abConcp->deleteTree(), abConcp);
}
}
// Special cases
virtual void visit(AstConst* nodep) {} // Already constant
virtual void visit(AstConst* nodep) VL_OVERRIDE {} // Already constant
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
if (m_params) {
iterateAndNextNull(nodep->paramsp());
} else {
iterateChildren(nodep);
}
}
virtual void visit(AstPin* nodep) {
virtual void visit(AstPin* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
@ -1397,7 +1401,7 @@ private:
rhsp->cloneTree(false)),
lhsp->cloneTree(false)));
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceSelSel(AstSel* nodep) {
@ -1414,8 +1418,8 @@ private:
newlsbp = new AstConst(lsb1p->fileline(),
VN_CAST(lsb1p, Const)->toUInt()
+ VN_CAST(lsb2p, Const)->toUInt());
lsb1p->deleteTree(); VL_DANGLING(lsb1p);
lsb2p->deleteTree(); VL_DANGLING(lsb2p);
VL_DO_DANGLING(lsb1p->deleteTree(), lsb1p);
VL_DO_DANGLING(lsb2p->deleteTree(), lsb2p);
} else {
// Width is important, we need the width of the fromp's
// expression, not the potentially smaller lsb1p's width
@ -1429,7 +1433,7 @@ private:
newlsbp,
widthp);
nodep->replaceWith(newp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceSelConcat(AstSel* nodep) {
@ -1469,7 +1473,7 @@ private:
conRhsp->width()-nodep->lsbConst()));
nodep->replaceWith(newp);
}
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
bool operandSelReplicate(AstSel* nodep) {
// SEL(REPLICATE(from,rep),lsb,width) => SEL(from,0,width) as long
@ -1489,7 +1493,7 @@ private:
new AstConst(lsbp->fileline(), lsbp->toUInt() % fromp->width()),
widthp);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
return true;
}
bool operandRepRep(AstReplicate* nodep) {
@ -1505,7 +1509,7 @@ private:
AstReplicate* newp = new AstReplicate(nodep->fileline(),
from2p, cnt1p->toUInt()*cnt2p->toUInt());
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
return true;
}
bool operandConcatSame(AstConcat* nodep) {
@ -1532,7 +1536,7 @@ private:
from1p->unlinkFrBack();
AstReplicate* newp = new AstReplicate(nodep->fileline(), from1p, cnt1+cnt2);
newp->dtypeFrom(nodep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
return true;
}
void replaceSelIntoBiop(AstSel* nodep) {
@ -1550,7 +1554,7 @@ private:
fromp->rhsp(new AstSel(nodep->fileline(),
birhsp, lsbp, widthp));
fromp->dtypeFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(fromp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
void replaceSelIntoUniop(AstSel* nodep) {
// SEL(NOT(a),1,bit) => NOT(SEL(a,bit))
@ -1564,17 +1568,17 @@ private:
fromp->lhsp(new AstSel(nodep->fileline(),
bilhsp, lsbp, widthp));
fromp->dtypeFrom(nodep);
nodep->replaceWith(fromp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(fromp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstAttrOf* nodep) {
virtual void visit(AstAttrOf* nodep) VL_OVERRIDE {
AstAttrOf* oldAttr = m_attrp;
m_attrp = nodep;
iterateChildren(nodep);
m_attrp = oldAttr;
}
virtual void visit(AstArraySel* nodep) {
virtual void visit(AstArraySel* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->bitp());
if (VN_IS(nodep->bitp(), Const)
&& VN_IS(nodep->fromp(), VarRef)
@ -1595,12 +1599,12 @@ private:
fromp->dtypeFrom(VN_CAST(fromp->dtypep()->skipRefp(),
NodeArrayDType)->subDTypep());
}
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
m_selp = NULL;
}
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
UASSERT_OBJ(nodep->varp(), nodep, "Not linked");
bool did = false;
@ -1621,7 +1625,7 @@ private:
if (operandConst(valuep)) {
const V3Number& num = VN_CAST(valuep, Const)->num();
//UINFO(2,"constVisit "<<cvtToHex(valuep)<<" "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
did = true;
}
else if (m_selp && VN_IS(valuep, InitArray)) {
@ -1631,7 +1635,7 @@ private:
if (VN_IS(itemp, Const)) {
const V3Number& num = VN_CAST(itemp, Const)->num();
//UINFO(2,"constVisit "<<cvtToHex(valuep)<<" "<<num<<endl);
replaceNum(nodep, num); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
did = true;
}
}
@ -1641,7 +1645,7 @@ private:
// This exception is fairly fragile, i.e. doesn't
// support arrays of arrays or other stuff
AstNode* newp = valuep->cloneTree(false);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
did = true;
}
}
@ -1651,7 +1655,7 @@ private:
<<nodep->varp()->prettyNameQ());
}
}
virtual void visit(AstEnumItemRef* nodep) {
virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
UASSERT_OBJ(nodep->itemp(), nodep, "Not linked");
bool did = false;
@ -1666,7 +1670,7 @@ private:
}
if (AstConst* valuep = VN_CAST(nodep->itemp()->valuep(), Const)) {
const V3Number& num = valuep->num();
replaceNum(nodep, num); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceNum(nodep, num), nodep);
did = true;
}
}
@ -1676,7 +1680,7 @@ private:
}
}
// virtual void visit(AstCvtPackString* nodep) {
// virtual void visit(AstCvtPackString* nodep) VL_OVERRIDE {
// Not constant propagated (for today) because AstNodeMath::isOpaque is set
// Someday if lower is constant, convert to quoted "string".
@ -1684,7 +1688,7 @@ private:
// Only one if it's not in a list
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
}
virtual void visit(AstSenItem* nodep) {
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_doNConst
&& (VN_IS(nodep->sensp(), Const)
@ -1694,13 +1698,13 @@ private:
if (nodep->isClocked()) { // A constant can never get a pos/negedge
if (onlySenItemInSenTree(nodep)) {
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} else {
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
} else { // Otherwise it may compute a result that needs to settle out
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Combo()));
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
} else if (m_doNConst && VN_IS(nodep->sensp(), Not)) {
// V3Gate may propagate NOTs into clocks... Just deal with it
@ -1716,7 +1720,7 @@ private:
AstNodeVarRef* senvarp = VN_CAST(lastSensp->unlinkFrBack(), NodeVarRef);
UASSERT_OBJ(senvarp, sensp, "Non-varref sensitivity variable");
sensp->replaceWith(senvarp);
sensp->deleteTree(); VL_DANGLING(sensp);
VL_DO_DANGLING(sensp->deleteTree(), sensp);
} else if (!m_doNConst // Deal with later when doNConst missing
&& (VN_IS(nodep->sensp(), EnumItemRef)
|| VN_IS(nodep->sensp(), Const))) {
@ -1726,22 +1730,22 @@ private:
"Null sensitivity variable");
}
}
virtual void visit(AstSenGate* nodep) {
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (AstConst* constp = VN_CAST(nodep->rhsp(), Const)) {
if (constp->isZero()) {
UINFO(4,"SENGATE(...,0)->NEVER"<<endl);
if (onlySenItemInSenTree(nodep)) {
nodep->replaceWith(new AstSenItem(nodep->fileline(), AstSenItem::Never()));
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
} else {
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
} else {
UINFO(4,"SENGATE(SENITEM,0)->ALWAYS SENITEM"<<endl);
AstNode* senitemp = nodep->sensesp()->unlinkFrBack();
nodep->replaceWith(senitemp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
}
@ -1778,7 +1782,7 @@ private:
}
};
virtual void visit(AstSenTree* nodep) {
virtual void visit(AstSenTree* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_doExpensive) {
//cout<<endl; nodep->dumpTree(cout, "ssin: ");
@ -1787,7 +1791,7 @@ private:
// SENTREE(... SENITEM(x), SENGATE(SENITEM(x),*) ...) => SENITEM(x)
// Do we need the SENITEM's to be identical? No because we're
// ORing between them; we just need to insure that the result is at
// ORing between them; we just need to ensure that the result is at
// least as frequently activating. So we simply
// SENGATE(SENITEM(x)) -> SENITEM(x), then let it collapse with the
// other SENITEM(x).
@ -1813,7 +1817,8 @@ private:
// Found, push this item up to the top
itemp->unlinkFrBack();
nodep->addSensesp(itemp);
gatep->unlinkFrBack()->deleteTree(); VL_DANGLING(gatep); VL_DANGLING(senp);
VL_DO_DANGLING(gatep->unlinkFrBack()->deleteTree(), gatep);
VL_DANGLING(senp);
}
}
}
@ -1874,7 +1879,8 @@ private:
&& ritemp->edgeType() == VEdgeType::ET_NEGEDGE)
litemp->edgeType(VEdgeType::ET_BOTHEDGE);
// Remove redundant node
ritemp->unlinkFrBack()->deleteTree(); VL_DANGLING(ritemp); VL_DANGLING(cmpp);
VL_DO_DANGLING(ritemp->unlinkFrBack()->deleteTree(), ritemp);
VL_DANGLING(cmpp);
// Try to collapse again
nextp = litemp;
}
@ -1887,17 +1893,17 @@ private:
//-----
// Zero elimination
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_doNConst && replaceNodeAssign(nodep)) return;
}
virtual void visit(AstAssignAlias* nodep) {
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
// Don't perform any optimizations, keep the alias around
}
virtual void visit(AstAssignVarScope* nodep) {
virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE {
// Don't perform any optimizations, the node won't be linked yet
}
virtual void visit(AstAssignW* nodep) {
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_doNConst && replaceNodeAssign(nodep)) return;
AstNodeVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); // Not VarXRef, as different refs may set different values to each hierarchy
@ -1917,14 +1923,14 @@ private:
new AstAssign(nodep->fileline(),
varrefp, exprp));
m_modp->addStmtp(newinitp);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
// Set the initial value right in the variable so we can constant propagate
AstNode* initvaluep = exprp->cloneTree(false);
varrefp->varp()->valuep(initvaluep);
}
}
virtual void visit(AstNodeIf* nodep) {
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_doNConst) {
if (const AstConst* constp = VN_CAST(nodep->condp(), Const)) {
@ -1942,13 +1948,13 @@ private:
} else {
nodep->unlinkFrBack();
}
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
// Empty block, remove it
// Note if we support more C++ then there might be side
// effects in the condition itself
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (!afterComment(nodep->ifsp())) {
UINFO(4,"IF({x}) NULL {...} => IF(NOT{x}}: "<<nodep<<endl);
@ -1970,7 +1976,7 @@ private:
AstIf* ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
ifp->branchPred(nodep->branchPred().invert());
nodep->replaceWith(ifp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
else if (ifSameAssign(nodep)) {
UINFO(4,"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})"<<endl);
@ -1983,7 +1989,7 @@ private:
ifp->rhsp(new AstCond(truep->fileline(),
condp, truep, falsep));
nodep->replaceWith(ifp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
else if (0 // Disabled, as vpm assertions are faster without due to short-circuiting
&& operandIfIf(nodep)) {
@ -1995,7 +2001,7 @@ private:
nodep->condp(new AstLogAnd(lowerIfp->fileline(),
condp, lowerCondp));
lowerIfp->replaceWith(lowerIfsp);
lowerIfp->deleteTree(); VL_DANGLING(lowerIfp);
VL_DO_DANGLING(lowerIfp->deleteTree(), lowerIfp);
}
else if (operandBoolShift(nodep->condp())) {
replaceBoolShift(nodep->condp());
@ -2003,7 +2009,7 @@ private:
}
}
virtual void visit(AstDisplay* nodep) {
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
// DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2))
iterateChildren(nodep);
if (stmtDisplayDisplay(nodep)) return;
@ -2045,10 +2051,10 @@ private:
if (!prevp->addNewline() && nodep->addNewline()) {
pformatp->text(pformatp->text()+"\n");
}
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return true;
}
virtual void visit(AstSFormatF* nodep) {
virtual void visit(AstSFormatF* nodep) VL_OVERRIDE {
// Substitute constants into displays. The main point of this is to
// simplify assertion methodologies which call functions with display's.
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
@ -2069,7 +2075,7 @@ private:
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && (isdigit(ch) || ch=='.')) {
} else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) {
fmt += ch;
} else if (inPct) {
inPct = false;
@ -2081,13 +2087,13 @@ private:
default: // Most operators, just move to next argument
if (argp) {
AstNode* nextp = argp->nextp();
if (argp && VN_IS(argp, Const)) { // Convert it
if (VN_IS(argp, Const)) { // Convert it
string out = VN_CAST(argp, Const)->num().displayed(nodep, fmt);
UINFO(9," DispConst: "<<fmt<<" -> "<<out
<<" for "<<argp<<endl);
// fmt = out w/ replace % with %% as it must be literal.
fmt = VString::quotePercent(out);
argp->unlinkFrBack()->deleteTree(); VL_DANGLING(argp);
VL_DO_DANGLING(argp->unlinkFrBack()->deleteTree(), argp);
}
argp = nextp;
}
@ -2107,21 +2113,21 @@ private:
&& nodep->name().find('%') == string::npos
&& !nodep->hidden()) {
// Just a simple constant string - the formatting is pointless
replaceConstString(nodep, nodep->name()); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceConstString(nodep, nodep->name()), nodep);
}
}
virtual void visit(AstFuncRef* nodep) {
virtual void visit(AstFuncRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_params) { // Only parameters force us to do constant function call propagation
replaceWithSimulation(nodep);
}
}
virtual void visit(AstArg* nodep) {
virtual void visit(AstArg* nodep) VL_OVERRIDE {
// replaceWithSimulation on the Arg's parent FuncRef replaces these
iterateChildren(nodep);
}
virtual void visit(AstWhile* nodep) {
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
bool oldHasJumpGo = m_hasJumpGo;
m_hasJumpGo = false;
{
@ -2134,7 +2140,7 @@ private:
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
if (nodep->precondsp()) nodep->replaceWith(nodep->precondsp());
else nodep->unlinkFrBack();
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
else if (nodep->condp()->isNeqZero()) {
if (!thisWhileHasJumpGo) {
@ -2147,27 +2153,27 @@ private:
}
}
}
virtual void visit(AstInitArray* nodep) {
virtual void visit(AstInitArray* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
virtual void visit(AstInitItem* nodep) {
virtual void visit(AstInitItem* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
// These are converted by V3Param. Don't constify as we don't want the
// from() VARREF to disappear, if any.
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
virtual void visit(AstNodePreSel* nodep) {}
virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE {}
// Ignored, can eliminate early
virtual void visit(AstSysIgnore* nodep) {
virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_doNConst) {
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
}
// Simplify
virtual void visit(AstBasicDType* nodep) {
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->cvtRangeConst();
}
@ -2175,7 +2181,7 @@ private:
//-----
// Jump elimination
virtual void visit(AstJumpGo* nodep) {
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
iterateChildren(nodep);
m_hasJumpGo = true;
if (m_doExpensive) {
@ -2185,7 +2191,7 @@ private:
if (AstJumpLabel* aboveLabelp = VN_CAST(nodep->abovep(), JumpLabel)) {
if (aboveLabelp == nodep->labelp()) {
UINFO(4, "JUMPGO => last remove "<<nodep<<endl);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
}
@ -2194,7 +2200,7 @@ private:
}
}
virtual void visit(AstJumpLabel* nodep) {
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
// Because JumpLabels disable many optimizations,
// remove JumpLabels that are not pointed to by any AstJumpGos
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
@ -2206,7 +2212,7 @@ private:
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
if (underp) nodep->replaceWith(underp);
else nodep->unlinkFrBack();
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
@ -2540,7 +2546,7 @@ private:
// Note we can't convert EqCase/NeqCase to Eq/Neq here because that would break 3'b1x1==3'b101
//-----
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
if (m_required) {
if (VN_IS(nodep, NodeDType) || VN_IS(nodep, Range)) {

View File

@ -54,8 +54,8 @@ private:
: m_comment(comment), m_varRefp(vp), m_chgRefp(cp) {}
~ToggleEnt() {}
void cleanup() {
m_varRefp->deleteTree(); m_varRefp = NULL;
m_chgRefp->deleteTree(); m_chgRefp = NULL;
VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = NULL);
VL_DO_CLEAR(m_chgRefp->deleteTree(), m_chgRefp = NULL);
}
};
@ -149,17 +149,21 @@ private:
+"_"+type;
}
// VISITORS - BOTH
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created
m_fileps.clear();
iterateChildren(nodep);
m_modp = NULL;
m_inModOff = true;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
bool origInModOff = m_inModOff;
{
m_modp = nodep;
m_inModOff = nodep->isTop(); // Ignore coverage on top module; it's a shell we created
m_fileps.clear();
iterateChildren(nodep);
}
m_modp = origModp;
m_inModOff = origInModOff;
}
// VISITORS - TOGGLE COVERAGE
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
bool oldtog = m_inToggleOff;
{
m_inToggleOff = true;
@ -167,7 +171,7 @@ private:
}
m_inToggleOff = oldtog;
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_modp && !m_inModOff && !m_inToggleOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageToggle()) {
@ -303,7 +307,7 @@ private:
}
// VISITORS - LINE COVERAGE
virtual void visit(AstIf* nodep) { // Note not AstNodeIf; other types don't get covered
virtual void visit(AstIf* nodep) VL_OVERRIDE { // Note not AstNodeIf; other types don't get covered
UINFO(4," IF: "<<nodep<<endl);
if (m_checkBlock) {
// An else-if. When we iterate the if, use "elsif" marking
@ -340,7 +344,7 @@ private:
m_checkBlock = true; // Reset as a child may have cleared it
}
}
virtual void visit(AstCaseItem* nodep) {
virtual void visit(AstCaseItem* nodep) VL_OVERRIDE {
UINFO(4," CASEI: "<<nodep<<endl);
if (m_checkBlock && !m_inModOff
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) {
@ -353,7 +357,7 @@ private:
m_checkBlock = true; // Reset as a child may have cleared it
}
}
virtual void visit(AstCover* nodep) {
virtual void visit(AstCover* nodep) VL_OVERRIDE {
UINFO(4," COVER: "<<nodep<<endl);
m_checkBlock = true; // Always do cover blocks, even if there's a $stop
iterateChildren(nodep);
@ -364,21 +368,21 @@ private:
}
m_checkBlock = true; // Reset as a child may have cleared it
}
virtual void visit(AstStop* nodep) {
virtual void visit(AstStop* nodep) VL_OVERRIDE {
UINFO(4," STOP: "<<nodep<<endl);
m_checkBlock = false;
}
virtual void visit(AstPragma* nodep) {
virtual void visit(AstPragma* nodep) VL_OVERRIDE {
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
// Skip all NEXT nodes under this block, and skip this if/case branch
UINFO(4," OFF: "<<nodep<<endl);
m_checkBlock = false;
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else {
if (m_checkBlock) iterateChildren(nodep);
}
}
virtual void visit(AstBegin* nodep) {
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
// Record the hierarchy of any named begins, so we can apply to user
// coverage points. This is because there may be cov points inside
// generate blocks; each point should get separate consideration.
@ -398,7 +402,7 @@ private:
}
// VISITORS - BOTH
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
if (m_checkBlock) {
iterateChildren(nodep);

View File

@ -92,7 +92,7 @@ private:
UINFO(8," new "<<removep->incp()->declp()<<endl);
// Mark the found node as a duplicate of the first node
// (Not vice-versa as we have the iterator for the found node)
removep->unlinkFrBack(); pushDeletep(removep); VL_DANGLING(removep);
removep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(removep), removep);
// Remove node from comparison so don't hit it again
hashed.erase(dupit);
++m_statToggleJoins;
@ -102,19 +102,19 @@ private:
}
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Find all Coverage's
iterateChildren(nodep);
// Simplify
detectDuplicates();
}
virtual void visit(AstCoverToggle* nodep) {
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
m_toggleps.push_back(nodep);
iterateChildren(nodep);
}
//--------------------
virtual void visit(AstNodeMath* nodep) {} // Accelerate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -57,13 +57,13 @@ private:
// NODE STATE
// ** Shared with DeadVisitor **
// VISITORS
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->modp()->user1Inc(-1);
}
//-----
virtual void visit(AstNodeMath* nodep) {} // Accelerate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -133,20 +133,23 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
if (!nodep->dead()) {
iterateChildren(nodep);
checkAll(nodep);
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
if (!nodep->dead()) {
iterateChildren(nodep);
checkAll(nodep);
}
}
m_modp = NULL;
m_modp = origModp;
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->scopep()) nodep->scopep()->user1Inc();
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->aboveScopep()) nodep->aboveScopep()->user1Inc();
@ -155,14 +158,14 @@ private:
m_scopesp.push_back(nodep);
}
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkAll(nodep);
m_cellsp.push_back(nodep);
nodep->modp()->user1Inc();
}
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->varScopep()) {
@ -177,7 +180,7 @@ private:
else nodep->packagep()->user1Inc();
}
}
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->packagep()) {
@ -185,7 +188,7 @@ private:
else nodep->packagep()->user1Inc();
}
}
virtual void visit(AstRefDType* nodep) {
virtual void visit(AstRefDType* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkDType(nodep);
checkAll(nodep);
@ -194,12 +197,12 @@ private:
else nodep->packagep()->user1Inc();
}
}
virtual void visit(AstNodeDType* nodep) {
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkDType(nodep);
checkAll(nodep);
}
virtual void visit(AstEnumItemRef* nodep) {
virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->packagep()) {
@ -208,20 +211,20 @@ private:
}
checkAll(nodep);
}
virtual void visit(AstModport* nodep) {
virtual void visit(AstModport* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_elimCells) {
if (!nodep->varsp()) {
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
return;
}
}
checkAll(nodep);
}
virtual void visit(AstTypedef* nodep) {
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_elimCells && !nodep->attrPublic()) {
pushDeletep(nodep->unlinkFrBack()); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
return;
}
checkAll(nodep);
@ -229,7 +232,7 @@ private:
// Normal modules may disappear, e.g. if they are parameterized then removed
if (nodep->attrPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc();
}
virtual void visit(AstVarScope* nodep) {
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->scopep()) nodep->scopep()->user1Inc();
@ -237,7 +240,7 @@ private:
m_vscsp.push_back(nodep);
}
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
iterateChildren(nodep);
checkAll(nodep);
if (nodep->isSigPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc();
@ -245,7 +248,7 @@ private:
m_varsp.push_back(nodep);
}
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
// See if simple assignments to variables may be eliminated because
// that variable is never used.
// Similar code in V3Life
@ -265,7 +268,7 @@ private:
}
//-----
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
if (nodep->isOutputter()) m_sideEffect = true;
iterateChildren(nodep);
checkAll(nodep);
@ -289,7 +292,7 @@ private:
if (!modp->dead()) { // If was dead didn't increment user1's
DeadModVisitor visitor(modp);
}
modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp);
VL_DO_DANGLING(modp->unlinkFrBack()->deleteTree(), modp);
retry = true;
}
}
@ -299,7 +302,7 @@ private:
return (!nodep->isSigPublic() // Can't elim publics!
&& !nodep->isIO()
&& ((nodep->isTemp() && !nodep->isTrace())
|| (nodep->isParam() && !nodep->isTrace())
|| (nodep->isParam() && !nodep->isTrace() && !v3Global.opt.xmlOnly())
|| m_elimUserVars)); // Post-Trace can kill most anything
}
@ -317,7 +320,7 @@ private:
if (scp->dtypep()) {
scp->dtypep()->user1Inc(-1);
}
scp->unlinkFrBack()->deleteTree(); VL_DANGLING(scp);
VL_DO_DANGLING(scp->unlinkFrBack()->deleteTree(), scp);
*it = NULL;
retry = true;
}
@ -330,7 +333,7 @@ private:
AstCell* cellp = *it;
if (cellp->user1() == 0 && !cellp->modp()->stmtsp()) {
cellp->modp()->user1Inc(-1);
cellp->unlinkFrBack()->deleteTree(); VL_DANGLING(cellp);
VL_DO_DANGLING(cellp->unlinkFrBack()->deleteTree(), cellp);
}
}
}
@ -347,11 +350,11 @@ private:
AstNodeAssign* assp = itr->second;
UINFO(4," Dead assign "<<assp<<endl);
assp->dtypep()->user1Inc(-1);
assp->unlinkFrBack()->deleteTree(); VL_DANGLING(assp);
VL_DO_DANGLING(assp->unlinkFrBack()->deleteTree(), assp);
}
if (vscp->scopep()) vscp->scopep()->user1Inc(-1);
vscp->dtypep()->user1Inc(-1);
vscp->unlinkFrBack()->deleteTree(); VL_DANGLING(vscp);
VL_DO_DANGLING(vscp->unlinkFrBack()->deleteTree(), vscp);
}
}
for (bool retry=true; retry; ) {
@ -365,7 +368,7 @@ private:
if (varp->dtypep()) {
varp->dtypep()->user1Inc(-1);
}
varp->unlinkFrBack()->deleteTree(); VL_DANGLING(varp);
VL_DO_DANGLING(varp->unlinkFrBack()->deleteTree(), varp);
*it = NULL;
retry = true;
}
@ -389,7 +392,7 @@ private:
if (!cont)
continue;
}
(*it)->unlinkFrBack()->deleteTree(); VL_DANGLING(*it);
VL_DO_DANGLING((*it)->unlinkFrBack()->deleteTree(), *it);
}
}
}

View File

@ -348,22 +348,22 @@ private:
}
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
//VV***** We reset all userp() on the netlist
m_modVarMap.clear();
iterateChildren(nodep);
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
UINFO(4," MOD "<<nodep<<endl);
AstNode::user3ClearTree();
iterateChildren(nodep);
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
m_cfuncp = nodep;
iterateChildren(nodep);
m_cfuncp = NULL;
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
m_activep = nodep;
bool oldinit = m_inInitial;
m_inInitial = nodep->hasInitial();
@ -371,7 +371,7 @@ private:
iterateChildren(nodep);
m_inInitial = oldinit;
}
virtual void visit(AstAssignDly* nodep) {
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
m_inDly = true;
m_nextDlyp = VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe NULL.
if (m_cfuncp) nodep->v3error("Unsupported: Delayed assignment inside public function/task");
@ -384,9 +384,9 @@ private:
if (newlhsp) {
nodep->lhsp(newlhsp);
} else {
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
lhsp->deleteTree(); VL_DANGLING(lhsp);
VL_DO_DANGLING(lhsp->deleteTree(), lhsp);
}
else {
iterateChildren(nodep);
@ -395,7 +395,7 @@ private:
m_nextDlyp = NULL;
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (!nodep->user2Inc()) { // Not done yet
if (m_inDly && nodep->lvalue()) {
UINFO(4,"AssignDlyVar: "<<nodep<<endl);
@ -432,7 +432,7 @@ private:
}
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), dlyvscp, true);
newrefp->user2(true); // No reason to do it again
nodep->replaceWith(newrefp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newrefp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
else if (!m_inDly && nodep->lvalue()) {
//UINFO(9,"NBA "<<nodep<<endl);
@ -444,10 +444,10 @@ private:
}
}
virtual void visit(AstNodeFor* nodep) {
virtual void visit(AstNodeFor* nodep) VL_OVERRIDE {
nodep->v3fatalSrc("For statements should have been converted to while statements in V3Begin");
}
virtual void visit(AstWhile* nodep) {
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
bool oldloop = m_inLoop;
m_inLoop = true;
iterateChildren(nodep);
@ -456,7 +456,7 @@ private:
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -82,14 +82,17 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep;
m_funcp = NULL;
iterateChildren(nodep);
m_modp = NULL;
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
m_funcp = NULL;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
m_funcp = nodep;
m_depth = 0;
m_maxdepth = 0;
@ -103,7 +106,7 @@ private:
iterateChildren(nodep);
m_stmtp = NULL;
}
virtual void visit(AstNodeStmt* nodep) {
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {
if (!nodep->isStatement()) {
iterateChildren(nodep);
} else {
@ -111,9 +114,9 @@ private:
}
}
// Operators
virtual void visit(AstNodeTermop* nodep) {
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {
}
virtual void visit(AstNodeMath* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
// We have some operator defines that use 2 parens, so += 2.
m_depth += 2;
if (m_depth>m_maxdepth) m_maxdepth = m_depth;
@ -135,24 +138,24 @@ private:
// (Here instead of new visitor after V3Descope just to avoid another visitor)
void needNonStaticFunc(AstNode* nodep) {
UASSERT_OBJ(m_funcp, nodep, "Non-static accessor not under a function");
if (m_funcp->isStatic().trueU()) {
if (m_funcp->isStatic().trueUnknown()) {
UINFO(5,"Mark non-public due to "<<nodep<<endl);
m_funcp->isStatic(false);
}
}
virtual void visit(AstUCFunc* nodep) {
virtual void visit(AstUCFunc* nodep) VL_OVERRIDE {
needNonStaticFunc(nodep);
iterateChildren(nodep);
}
virtual void visit(AstUCStmt* nodep) {
virtual void visit(AstUCStmt* nodep) VL_OVERRIDE {
needNonStaticFunc(nodep);
visitStmt(nodep);
}
//--------------------
// Default: Just iterate
virtual void visit(AstVar* nodep) {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -71,14 +71,17 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
UINFO(4," MOD "<<nodep<<endl);
m_modp = nodep;
m_deepNum = 0;
iterateChildren(nodep);
m_modp = NULL;
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
m_deepNum = 0;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
// We recurse into this.
int lastDepth = m_depth;
AstCFunc* lastFuncp = m_funcp;
@ -106,7 +109,7 @@ private:
}
m_depth--;
}
virtual void visit(AstNodeStmt* nodep) {
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {
if (!nodep->isStatement()) {
iterateChildren(nodep);
} else {
@ -114,11 +117,11 @@ private:
}
}
virtual void visit(AstNodeMath* nodep) {} // Accelerate
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {} // Accelerate
//--------------------
// Default: Just iterate
virtual void visit(AstVar* nodep) {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -44,18 +44,18 @@ private:
// NODE STATE
// Cleared entire netlist
// AstCFunc::user() // bool. Indicates processing completed
AstUser1InUse m_inuser1;
AstUser1InUse m_inuser1;
// TYPES
typedef std::multimap<string,AstCFunc*> FuncMmap;
typedef std::multimap<string, AstCFunc*> FuncMmap;
// STATE
AstNodeModule* m_modp; // Current module
AstScope* m_scopep; // Current scope
bool m_modSingleton; // m_modp is only instanced once
bool m_allowThis; // Allow function non-static
bool m_needThis; // Make function non-static
FuncMmap m_modFuncs; // Name of public functions added
AstNodeModule* m_modp; // Current module
AstScope* m_scopep; // Current scope
bool m_modSingleton; // m_modp is only instanced once
bool m_allowThis; // Allow function non-static
bool m_needThis; // Make function non-static
FuncMmap m_modFuncs; // Name of public functions added
// METHODS
VL_DEBUG_FUNC; // Declare debug()
@ -63,7 +63,7 @@ private:
static bool modIsSingleton(AstNodeModule* modp) {
// True iff there's exactly one instance of this module in the design.
int instances = 0;
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp=stmtp->nextp()) {
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
if (VN_IS(stmtp, Scope)) {
if (++instances > 1) { return false; }
}
@ -81,8 +81,7 @@ private:
// Sets 'hierThisr' true if the object is local to this scope
// (and could be made into a function-local later in V3Localize),
// false if the object is in another scope.
string descopedName(const AstScope* scopep, bool& hierThisr,
const AstVar* varp=NULL) {
string descopedName(const AstScope* scopep, bool& hierThisr, const AstVar* varp = NULL) {
UASSERT(scopep, "Var/Func not scoped");
hierThisr = (scopep == m_scopep);
@ -97,7 +96,6 @@ private:
//
// Static functions can't use this
if (!m_allowThis) relativeRefOk = false;
//
// Use absolute refs in top-scoped routines, keep them static.
// The DPI callback registration depends on representing top-level
@ -106,18 +104,15 @@ private:
//
// V3Combine wouldn't likely be able to combine top-level
// routines anyway, so there's no harm in keeping these static.
if (m_modp->isTop()) {
relativeRefOk = false;
}
UASSERT_OBJ(m_modp, scopep, "Scope not under module");
if (m_modp->isTop()) relativeRefOk = false;
//
// Use absolute refs if this scope is the only instance of the module.
// Saves a bit of overhead on passing the 'this' pointer, and there's no
// need to be nice to V3Combine when we have only a single instance.
// The risk that this prevents combining identical logic from differently-
// named but identical modules seems low.
if (m_modSingleton) {
relativeRefOk = false;
}
if (m_modSingleton) relativeRefOk = false;
if (varp && varp->isFuncLocal()) {
hierThisr = true;
@ -130,23 +125,21 @@ private:
// Reference to scope of cell directly under this module, can just "cell->"
string name = scopep->name();
string::size_type pos;
if ((pos = name.rfind('.')) != string::npos) {
name.erase(0, pos+1);
}
if ((pos = name.rfind('.')) != string::npos) name.erase(0, pos + 1);
m_needThis = true;
return name+"->";
return name + "->";
} else {
// Reference to something elsewhere, or relative references
// are disabled. Use global variable
UINFO(8," Descope "<<scopep<<endl);
UINFO(8," to "<<scopep->name()<<endl);
UINFO(8," under "<<m_scopep->name()<<endl);
UINFO(8, " Descope " << scopep << endl);
UINFO(8, " to " << scopep->name() << endl);
UINFO(8, " under " << m_scopep->name() << endl);
if (!scopep->aboveScopep()) { // Top
// We could also return "vlSymsp->TOPp->" here, but GCC would
// suspect aliases.
return "vlTOPp->";
} else {
return scopep->nameVlSym()+".";
return scopep->nameVlSym() + ".";
}
}
}
@ -155,64 +148,64 @@ private:
// We recorded all public functions in m_modFuncs.
// If for any given name only one function exists, we can use that function directly.
// If multiple functions exist, we need to select the appropriate scope.
for (FuncMmap::iterator it = m_modFuncs.begin(); it!=m_modFuncs.end(); ++it) {
for (FuncMmap::iterator it = m_modFuncs.begin(); it != m_modFuncs.end(); ++it) {
string name = it->first;
AstCFunc* topFuncp = it->second;
FuncMmap::iterator nextIt1 = it; ++nextIt1;
bool moreOfSame1 = (nextIt1!=m_modFuncs.end() && nextIt1->first == name);
FuncMmap::iterator nextIt1 = it;
++nextIt1;
bool moreOfSame1 = (nextIt1 != m_modFuncs.end() && nextIt1->first == name);
if (moreOfSame1) {
// Multiple functions under this name, need a wrapper function
UINFO(6," Wrapping "<<name<<" multifuncs\n");
UINFO(6, " Wrapping " << name << " multifuncs\n");
AstCFunc* newfuncp = topFuncp->cloneTree(false);
if (newfuncp->initsp()) newfuncp->initsp()->unlinkFrBackWithNext()->deleteTree();
if (newfuncp->stmtsp()) newfuncp->stmtsp()->unlinkFrBackWithNext()->deleteTree();
if (newfuncp->initsp()) newfuncp->initsp()->unlinkFrBackWithNext()->deleteTree();
if (newfuncp->stmtsp()) newfuncp->stmtsp()->unlinkFrBackWithNext()->deleteTree();
if (newfuncp->finalsp()) newfuncp->finalsp()->unlinkFrBackWithNext()->deleteTree();
newfuncp->name(name);
newfuncp->isStatic(false);
newfuncp->addInitsp(
new AstCStmt(newfuncp->fileline(),
EmitCBaseVisitor::symClassVar()+" = this->__VlSymsp;\n"));
newfuncp->addInitsp(new AstCStmt(newfuncp->fileline(),
EmitCBaseVisitor::symTopAssign()+"\n"));
EmitCBaseVisitor::symClassVar() + " = this->__VlSymsp;\n"));
newfuncp->addInitsp(
new AstCStmt(newfuncp->fileline(), EmitCBaseVisitor::symTopAssign() + "\n"));
topFuncp->addNextHere(newfuncp);
// In the body, call each function if it matches the given scope
for (FuncMmap::iterator eachIt = it;
eachIt != m_modFuncs.end() && eachIt->first==name; ++eachIt) {
eachIt != m_modFuncs.end() && eachIt->first == name; ++eachIt) {
it = eachIt;
AstCFunc* funcp = eachIt->second;
FuncMmap::iterator nextIt2 = eachIt; ++nextIt2;
bool moreOfSame = (nextIt2!=m_modFuncs.end() && nextIt2->first == name);
FuncMmap::iterator nextIt2 = eachIt;
++nextIt2;
bool moreOfSame = (nextIt2 != m_modFuncs.end() && nextIt2->first == name);
UASSERT_OBJ(funcp->scopep(), funcp, "Not scoped");
UINFO(6," Wrapping "<<name<<" "<<funcp<<endl);
UINFO(6," at "<<newfuncp->argTypes()<<" und "<<funcp->argTypes()<<endl);
UINFO(6, " Wrapping " << name << " " << funcp << endl);
UINFO(6, " at " << newfuncp->argTypes()
<< " und " << funcp->argTypes() << endl);
funcp->declPrivate(true);
AstNode* argsp = NULL;
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp=stmtp->nextp()) {
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) {
if (AstVar* portp = VN_CAST(stmtp, Var)) {
if (portp->isIO() && !portp->isFuncReturn()) {
AstNode* newp = new AstVarRef(portp->fileline(),
portp, portp->isWritable());
if (argsp) argsp = argsp->addNextNull(newp);
else argsp = newp;
AstNode* newp
= new AstVarRef(portp->fileline(), portp, portp->isWritable());
argsp = argsp ? argsp->addNextNull(newp) : newp;
}
}
}
AstNode* returnp = new AstCReturn(funcp->fileline(),
new AstCCall(funcp->fileline(),
funcp, argsp));
AstNode* returnp = new AstCReturn(
funcp->fileline(), new AstCCall(funcp->fileline(), funcp, argsp));
if (moreOfSame) {
AstIf* ifp = new AstIf(funcp->fileline(),
new AstEq(funcp->fileline(),
new AstCMath(funcp->fileline(),
"this", 64),
new AstCMath(funcp->fileline(),
string("&(")
+funcp->scopep()->nameVlSym()
+")", 64)),
returnp, NULL);
AstIf* ifp = new AstIf(
funcp->fileline(),
new AstEq(
funcp->fileline(), new AstCMath(funcp->fileline(), "this", 64),
new AstCMath(funcp->fileline(),
string("&(") + funcp->scopep()->nameVlSym() + ")",
64)),
returnp, NULL);
newfuncp->addStmtsp(ifp);
} else {
newfuncp->addStmtsp(returnp);
@ -220,68 +213,70 @@ private:
}
// Not really any way the user could do this, and we'd need
// to come up with some return value
//newfuncp->addStmtsp(new AstDisplay(newfuncp->fileline(),
// newfuncp->addStmtsp(new AstDisplay(newfuncp->fileline(),
// AstDisplayType::DT_WARNING,
// string("%%Error: ")+name+"() called with bad scope", NULL));
//newfuncp->addStmtsp(new AstStop(newfuncp->fileline()));
if (debug()>=9) newfuncp->dumpTree(cout, " newfunc: ");
// string("%%Error: ")+name+"() called with bad
// scope", NULL));
// newfuncp->addStmtsp(new AstStop(newfuncp->fileline()));
if (debug() >= 9) newfuncp->dumpTree(cout, " newfunc: ");
} else {
// Only a single function under this name, we can simply rename it
UINFO(6," Wrapping "<<name<<" just one "<<topFuncp<<endl);
UINFO(6, " Wrapping " << name << " just one " << topFuncp << endl);
topFuncp->name(name);
}
}
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
m_modFuncs.clear();
m_modSingleton = modIsSingleton(m_modp);
iterateChildren(nodep);
makePublicFuncWrappers();
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
m_modFuncs.clear();
m_modSingleton = modIsSingleton(m_modp);
iterateChildren(nodep);
makePublicFuncWrappers();
}
m_modp = origModp;
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
m_scopep = nodep;
iterateChildren(nodep);
m_scopep = NULL;
}
virtual void visit(AstVarScope* nodep) {
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {
// Delete the varscope when we're finished
nodep->unlinkFrBack();
pushDeletep(nodep);
}
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// Convert the hierch name
UASSERT_OBJ(m_scopep, nodep, "Node not under scope");
bool hierThis;
nodep->hiername(descopedName(nodep->varScopep()->scopep(), hierThis/*ref*/,
nodep->hiername(descopedName(nodep->varScopep()->scopep(), hierThis /*ref*/,
nodep->varScopep()->varp()));
nodep->hierThis(hierThis);
nodep->varScopep(NULL);
}
virtual void visit(AstCCall* nodep) {
//UINFO(9," "<<nodep<<endl);
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
// UINFO(9," "<<nodep<<endl);
iterateChildren(nodep);
// Convert the hierch name
UASSERT_OBJ(m_scopep, nodep, "Node not under scope");
UASSERT_OBJ(nodep->funcp()->scopep(), nodep, "CFunc not under scope");
bool hierThis;
nodep->hiername(descopedName(nodep->funcp()->scopep(), hierThis/*ref*/));
nodep->hiername(descopedName(nodep->funcp()->scopep(), hierThis /*ref*/));
// Can't do this, as we may have more calls later
// nodep->funcp()->scopep(NULL);
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
if (!nodep->user1()) {
m_needThis = false;
m_allowThis = nodep->isStatic().falseU(); // Non-static or unknown if static
m_allowThis = nodep->isStatic().falseUnknown(); // Non-static or unknown if static
iterateChildren(nodep);
nodep->user1(true);
if (m_needThis) {
nodep->isStatic(false);
}
if (m_needThis) nodep->isStatic(false);
// If it's under a scope, move it up to the top
if (m_scopep) {
nodep->unlinkFrBack();
@ -291,23 +286,22 @@ private:
// There may be multiple public functions by the same name;
// record for later correction or making of shells
m_modFuncs.insert(make_pair(nodep->name(), nodep));
nodep->name(m_scopep->nameDotless() +"__" + nodep->name());
nodep->name(m_scopep->nameDotless() + "__" + nodep->name());
}
}
}
}
virtual void visit(AstVar*) {}
virtual void visit(AstNode* nodep) {
iterateChildren(nodep);
}
virtual void visit(AstVar*) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
public:
// CONSTRUCTORS
explicit DescopeVisitor(AstNetlist* nodep)
: m_modp(NULL),
m_scopep(NULL),
m_modSingleton(false),
m_allowThis(false),
m_needThis(false) {
: m_modp(NULL)
, m_scopep(NULL)
, m_modSingleton(false)
, m_allowThis(false)
, m_needThis(false) {
iterate(nodep);
}
virtual ~DescopeVisitor() {}

File diff suppressed because it is too large Load Diff

View File

@ -56,11 +56,17 @@ public:
static string symClassVar() { return symClassName()+"* __restrict vlSymsp"; }
static string symTopAssign() {
return v3Global.opt.prefix()+"* __restrict vlTOPp VL_ATTR_UNUSED = vlSymsp->TOPp;"; }
static string modClassName(AstNodeModule* modp) { // Return name of current module being processed
if (modp->isTop()) {
static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp) {
if (nodep->isConstructor()) return prefixNameProtect(modp);
else if (nodep->isDestructor()) return string("~") + prefixNameProtect(modp);
else return nodep->nameProtect();
}
static string prefixNameProtect(const AstNode* nodep) { // C++ name with prefix
const AstNodeModule* modp = VN_CAST_CONST(nodep, NodeModule);
if (modp && modp->isTop()) {
return v3Global.opt.prefix();
} else {
return v3Global.opt.modPrefix()+"_"+protect(modp->name());
return v3Global.opt.modPrefix() + "_" + protect(nodep->name());
}
}
static string topClassName() { // Return name of top wrapper module
@ -108,7 +114,7 @@ private:
// MEMBERS
int m_count; // Number of statements
// VISITORS
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
m_count++;
iterateChildren(nodep);
}

View File

@ -40,47 +40,55 @@ class EmitCInlines : EmitCBaseVisitor {
void emitInt();
// VISITORS
virtual void visit(AstBasicDType* nodep) {
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE {
if (nodep->keyword() == AstBasicDTypeKwd::STRING) {
// Request #include <string> via verilated_heavy.h when we create symbol file
v3Global.needHeavy(true);
}
}
virtual void visit(AstAssocArrayDType* nodep) {
virtual void visit(AstAssocArrayDType* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstQueueDType* nodep) {
virtual void visit(AstQueueDType* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstValuePlusArgs* nodep) {
virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstAtoN* nodep) {
virtual void visit(AstValuePlusArgs* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstPutcN* nodep) {
virtual void visit(AstAtoN* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstGetcN* nodep) {
virtual void visit(AstPutcN* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstSubstrN* nodep) {
virtual void visit(AstGetcN* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstCompareNN* nodep) {
virtual void visit(AstGetcRefN* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstSubstrN* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
virtual void visit(AstCompareNN* nodep) VL_OVERRIDE {
v3Global.needHeavy(true);
iterateChildren(nodep);
}
// Default
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
//---------------------------------------

View File

@ -125,8 +125,8 @@ class CMakeEmitter {
*of << "\n### Sources...\n";
std::vector<string> classes_fast, classes_slow, support_fast, support_slow, global;
for (AstFile* nodep = v3Global.rootp()->filesp(); nodep;
nodep = VN_CAST(nodep->nextp(), File)) {
for (AstNodeFile* nodep = v3Global.rootp()->filesp(); nodep;
nodep = VN_CAST(nodep->nextp(), NodeFile)) {
AstCFile* cfilep = VN_CAST(nodep, CFile);
if (cfilep && cfilep->source()) {
if (cfilep->support()) {

View File

@ -110,7 +110,10 @@ class EmitCSyms : EmitCBaseVisitor {
void nameCheck(AstNode* nodep) {
// Prevent GCC compile time error; name check all things that reach C++ code
if (nodep->name() != "") {
if (nodep->name() != ""
&& !(VN_IS(nodep, CFunc)
&& (VN_CAST(nodep, CFunc)->isConstructor()
|| VN_CAST(nodep, CFunc)->isDestructor()))) {
string rsvd = m_words.isKeyword(nodep->name());
if (rsvd != "") {
// Generally V3Name should find all of these and throw SYMRSVDWORD.
@ -244,7 +247,7 @@ class EmitCSyms : EmitCBaseVisitor {
}
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Collect list of scopes
iterateChildren(nodep);
varsExpand();
@ -268,13 +271,16 @@ class EmitCSyms : EmitCBaseVisitor {
if (!m_dpiHdrOnly) emitDpiImp();
}
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
nameCheck(nodep);
m_modp = nodep;
iterateChildren(nodep);
m_modp = NULL;
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstCellInline* nodep) {
virtual void visit(AstCellInline* nodep) VL_OVERRIDE {
if (v3Global.opt.vpi()) {
string type = (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER"
: "SCOPE_MODULE";
@ -284,18 +290,19 @@ class EmitCSyms : EmitCBaseVisitor {
name_dedot, type)));
}
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
nameCheck(nodep);
m_scopes.push_back(make_pair(nodep, m_modp));
if (v3Global.opt.vpi() && !nodep->isTop()) {
string name_dedot = AstNode::dedotName(nodep->shortName());
m_vpiScopeCandidates.insert(make_pair(nodep->name(),
ScopeData(scopeSymString(nodep->name()),
nodep->name(), "SCOPE_MODULE")));
name_dedot, "SCOPE_MODULE")));
}
}
virtual void visit(AstScopeName* nodep) {
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
string name = nodep->scopeSymName();
//UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()<<" ss "<<name<<endl);
if (m_scopeNames.find(name) == m_scopeNames.end()) {
@ -315,7 +322,7 @@ class EmitCSyms : EmitCBaseVisitor {
}
}
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
nameCheck(nodep);
iterateChildren(nodep);
if (nodep->isSigUserRdPublic()
@ -323,13 +330,13 @@ class EmitCSyms : EmitCBaseVisitor {
m_modVars.push_back(make_pair(m_modp, nodep));
}
}
virtual void visit(AstCoverDecl* nodep) {
virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE {
// Assign numbers to all bins, so we know how big of an array to use
if (!nodep->dataDeclNullp()) { // else duplicate we don't need code for
nodep->binNum(m_coverBins++);
}
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
nameCheck(nodep);
if (nodep->dpiImport() || nodep->dpiExportWrapper()) {
m_dpis.push_back(nodep);
@ -339,9 +346,9 @@ class EmitCSyms : EmitCBaseVisitor {
m_funcp = NULL;
}
// NOPs
virtual void visit(AstConst*) {}
virtual void visit(AstConst*) VL_OVERRIDE {}
// Default
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
//---------------------------------------
@ -383,11 +390,10 @@ void EmitCSyms::emitSymHdr() {
puts("#include \"verilated.h\"\n");
}
// for
puts("\n// INCLUDE MODULE CLASSES\n");
for (AstNodeModule* nodep = v3Global.rootp()->modulesp();
nodep; nodep=VN_CAST(nodep->nextp(), NodeModule)) {
puts("#include \""+modClassName(nodep)+".h\"\n");
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep;
nodep = VN_CAST(nodep->nextp(), NodeModule)) {
puts("#include \"" + prefixNameProtect(nodep) + ".h\"\n");
}
if (v3Global.dpi()) {
@ -418,20 +424,23 @@ void EmitCSyms::emitSymHdr() {
puts("\n// SUBCELL STATE\n");
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
AstScope* scopep = it->first;
AstNodeModule* modp = it->second;
if (modp->isTop()) {
ofp()->printf("%-30s ", (modClassName(modp)+"*").c_str());
puts(protectIf(scopep->nameDotless()+"p", scopep->protect())+";\n");
}
else {
ofp()->printf("%-30s ", (modClassName(modp)+"").c_str());
puts(protectIf(scopep->nameDotless(), scopep->protect())+";\n");
ofp()->printf("%-30s ", (prefixNameProtect(modp) + "*").c_str());
puts(protectIf(scopep->nameDotless() + "p", scopep->protect()) + ";\n");
} else {
ofp()->printf("%-30s ", (prefixNameProtect(modp) + "").c_str());
puts(protectIf(scopep->nameDotless(), scopep->protect()) + ";\n");
}
}
if (m_coverBins) {
puts("\n// COVERAGE\n");
puts("uint32_t __Vcoverage["); puts(cvtToStr(m_coverBins)); puts("];\n");
puts(v3Global.opt.threads() ? "std::atomic<uint32_t>" : "uint32_t");
puts(" __Vcoverage[");
puts(cvtToStr(m_coverBins));
puts("];\n");
}
if (!m_scopeNames.empty()) { // Scope names
@ -471,7 +480,7 @@ void EmitCSyms::emitSymHdr() {
puts("void "+protect("__Vdeserialize")+"(VerilatedDeserialize& os);\n");
}
puts("\n");
puts("} VL_ATTR_ALIGNED(64);\n");
puts("} VL_ATTR_ALIGNED(VL_CACHE_LINE_BYTES);\n");
ofp()->putsEndGuard();
}
@ -480,8 +489,7 @@ void EmitCSyms::closeSplit() {
if (!m_ofp || m_ofp == m_ofpBase) return;
puts("}\n");
delete m_ofp;
m_ofp = NULL;
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
}
void EmitCSyms::checkSplit(bool usesVfinal) {
@ -522,9 +530,9 @@ void EmitCSyms::emitSymImpPreamble() {
// Includes
puts("#include \""+symClassName()+".h\"\n");
for (AstNodeModule* nodep = v3Global.rootp()->modulesp();
nodep; nodep=VN_CAST(nodep->nextp(), NodeModule)) {
puts("#include \""+modClassName(nodep)+".h\"\n");
for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); nodep;
nodep = VN_CAST(nodep->nextp(), NodeModule)) {
puts("#include \"" + prefixNameProtect(nodep) + ".h\"\n");
}
}
@ -580,13 +588,14 @@ void EmitCSyms::emitSymImp() {
}
puts(" , __Vm_didInit(false)\n");
puts(" // Setup submodule names\n");
char comma=',';
char comma = ',';
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
AstScope* scopep = it->first;
AstNodeModule* modp = it->second;
if (modp->isTop()) {
} else {
puts(string(" ")+comma+" "+protect(scopep->nameDotless()));
puts("(Verilated::catName(topp->name(),");
puts(string(" ") + comma + " " + protect(scopep->nameDotless()));
puts("(Verilated::catName(topp->name(), ");
// The "." is added by catName
putsQuoted(protectWordsIf(scopep->prettyName(), scopep->protect()));
puts("))\n");
@ -600,7 +609,8 @@ void EmitCSyms::emitSymImp() {
puts("TOPp = topp;\n");
puts("// Setup each module's pointers to their submodules\n");
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
AstScope* scopep = it->first;
AstNodeModule* modp = it->second;
if (!modp->isTop()) {
checkSplit(false);
string arrow = scopep->name();
@ -609,10 +619,9 @@ void EmitCSyms::emitSymImp() {
arrow.replace(pos, 1, "->");
}
if (arrow.substr(0, 5) == "TOP->") arrow.replace(0, 5, "TOPp->");
string arrowProt = protectWordsIf(arrow, scopep->protect());
ofp()->printf("%-30s ", arrowProt.c_str());
ofp()->puts(protectWordsIf(arrow, scopep->protect()));
puts(" = &");
puts(protectIf(scopep->nameDotless(), scopep->protect())+";\n");
puts(protectIf(scopep->nameDotless(), scopep->protect()) + ";\n");
++m_numStmts;
}
}
@ -620,7 +629,8 @@ void EmitCSyms::emitSymImp() {
puts("// Setup each module's pointer back to symbol table (for public functions)\n");
puts("TOPp->"+protect("__Vconfigure")+"(this, true);\n");
for (std::vector<ScopeModPair>::iterator it = m_scopes.begin(); it != m_scopes.end(); ++it) {
AstScope* scopep = it->first; AstNodeModule* modp = it->second;
AstScope* scopep = it->first;
AstNodeModule* modp = it->second;
if (!modp->isTop()) {
checkSplit(false);
// first is used by AstCoverDecl's call to __vlCoverInsert
@ -693,7 +703,7 @@ void EmitCSyms::emitSymImp() {
puts(protect("__Vscope_"+scopep->scopeSymName())+".exportInsert(__Vfinal, ");
putsQuoted(funcp->cname()); // Not protected - user asked for import/export
puts(", (void*)(&");
puts(modClassName(modp));
puts(prefixNameProtect(modp));
puts("::");
puts(funcp->nameProtect());
puts("));\n");
@ -775,7 +785,7 @@ void EmitCSyms::emitDpiHdr() {
puts("// DESCR" "IPTION: Verilator output: Prototypes for DPI import and export functions.\n");
puts("//\n");
puts("// Verilator includes this file in all generated .cpp files that use DPI functions.\n");
puts("// Manually include this file where DPI .c import functions are declared to insure\n");
puts("// Manually include this file where DPI .c import functions are declared to ensure\n");
puts("// the C functions match the expectations of the DPI imports.\n");
puts("\n");
puts("#include \"svdpi.h\"\n");

View File

@ -55,7 +55,7 @@ public:
of.puts("VM_THREADS = "); of.puts(cvtToStr(v3Global.opt.threads())); of.puts("\n");
of.puts("# Tracing output mode? 0/1 (from --trace)\n");
of.puts("VM_TRACE = "); of.puts(v3Global.opt.trace()?"1":"0"); of.puts("\n");
of.puts("# Tracing threadeds output mode? 0/1 (from --trace-fst-thread)\n");
of.puts("# Tracing threaded output mode? 0/1 (from --trace-fst-thread)\n");
of.puts("VM_TRACE_THREADED = "); of.puts(v3Global.opt.traceFormat().threaded()
?"1":"0"); of.puts("\n");
@ -101,8 +101,8 @@ public:
else if (support==2 && slow) {
}
else {
for (AstFile* nodep = v3Global.rootp()->filesp();
nodep; nodep = VN_CAST(nodep->nextp(), File)) {
for (AstNodeFile* nodep = v3Global.rootp()->filesp();
nodep; nodep = VN_CAST(nodep->nextp(), NodeFile)) {
AstCFile* cfilep = VN_CAST(nodep, CFile);
if (cfilep && cfilep->source()
&& cfilep->slow()==(slow!=0)
@ -189,7 +189,7 @@ public:
string cppfile = *it;
of.puts("\t"+V3Os::filenameNonExt(cppfile)+" \\\n");
string dir = V3Os::filenameDir(cppfile);
if (dirs.find(dir) == dirs.end()) dirs.insert(dir);
dirs.insert(dir);
}
of.puts("\n");

View File

@ -57,15 +57,15 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
virtual void visit(AstNodeModule* nodep) {
putfs(nodep, nodep->verilogKwd()+" "+modClassName(nodep)+";\n");
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n");
iterateChildren(nodep);
putqs(nodep, "end"+nodep->verilogKwd()+"\n");
putqs(nodep, "end" + nodep->verilogKwd() + "\n");
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
putfs(nodep, nodep->isFunction() ? "function":"task");
puts(" ");
puts(nodep->prettyName());
@ -75,7 +75,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
putqs(nodep, "end\n");
}
virtual void visit(AstBegin* nodep) {
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
if (nodep->unnamed()) {
putbs("begin\n");
} else {
@ -84,22 +84,22 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateChildren(nodep);
puts("end\n");
}
virtual void visit(AstGenerate* nodep) {
virtual void visit(AstGenerate* nodep) VL_OVERRIDE {
putfs(nodep, "generate\n");
iterateChildren(nodep);
putqs(nodep, "end\n");
}
virtual void visit(AstFinal* nodep) {
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
putfs(nodep, "final begin\n");
iterateChildren(nodep);
putqs(nodep, "end\n");
}
virtual void visit(AstInitial* nodep) {
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
putfs(nodep, "initial begin\n");
iterateChildren(nodep);
putqs(nodep, "end\n");
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
putfs(nodep, "always ");
if (m_sensesp) iterateAndNextNull(m_sensesp); // In active
else iterateAndNextNull(nodep->sensesp());
@ -107,7 +107,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateAndNextNull(nodep->bodysp());
putqs(nodep, "end\n");
}
virtual void visit(AstAlwaysPublic* nodep) {
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
putfs(nodep, "/*verilator public_flat_rw ");
if (m_sensesp) iterateAndNextNull(m_sensesp); // In active
else iterateAndNextNull(nodep->sensesp());
@ -115,37 +115,37 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateAndNextNull(nodep->bodysp());
putqs(nodep, "*/\n");
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->lhsp());
putfs(nodep, " "+nodep->verilogKwd()+" ");
iterateAndNextNull(nodep->rhsp());
if (!m_suppressSemi) puts(";\n");
}
virtual void visit(AstAssignDly* nodep) {
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->lhsp());
putfs(nodep, " <= ");
iterateAndNextNull(nodep->rhsp());
puts(";\n");
}
virtual void visit(AstAssignAlias* nodep) {
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
putbs("alias ");
iterateAndNextNull(nodep->lhsp());
putfs(nodep, " = ");
iterateAndNextNull(nodep->rhsp());
if (!m_suppressSemi) puts(";\n");
}
virtual void visit(AstAssignW* nodep) {
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
putfs(nodep, "assign ");
iterateAndNextNull(nodep->lhsp());
putbs(" = ");
iterateAndNextNull(nodep->rhsp());
if (!m_suppressSemi) puts(";\n");
}
virtual void visit(AstBreak* nodep) {
virtual void visit(AstBreak* nodep) VL_OVERRIDE {
putbs("break");
if (!m_suppressSemi) puts(";\n");
}
virtual void visit(AstSenTree* nodep) {
virtual void visit(AstSenTree* nodep) VL_OVERRIDE {
// AstSenItem is called for dumping in isolation by V3Order
putfs(nodep, "@(");
for (AstNode* expp=nodep->sensesp(); expp; expp = expp->nextp()) {
@ -154,16 +154,16 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
puts(")");
}
virtual void visit(AstSenGate* nodep) {
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->sensesp(), nodep->rhsp());
}
virtual void visit(AstSenItem* nodep) {
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
putfs(nodep, "");
puts(nodep->edgeType().verilogKwd());
if (nodep->sensp()) puts(" ");
iterateChildren(nodep);
}
virtual void visit(AstNodeCase* nodep) {
virtual void visit(AstNodeCase* nodep) VL_OVERRIDE {
putfs(nodep, "");
if (const AstCase* casep = VN_CAST(nodep, Case)) {
if (casep->priorityPragma()) puts("priority ");
@ -184,7 +184,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateAndNextNull(nodep->itemsp());
putqs(nodep, "endcase\n");
}
virtual void visit(AstCaseItem* nodep) {
virtual void visit(AstCaseItem* nodep) VL_OVERRIDE {
if (nodep->condsp()) {
iterateAndNextNull(nodep->condsp());
} else putbs("default");
@ -192,17 +192,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateAndNextNull(nodep->bodysp());
putqs(nodep, "end\n");
}
virtual void visit(AstComment* nodep) {
virtual void visit(AstComment* nodep) VL_OVERRIDE {
puts(string("// ")+nodep->name()+"\n");
iterateChildren(nodep);
}
virtual void visit(AstContinue* nodep) {
virtual void visit(AstContinue* nodep) VL_OVERRIDE {
putbs("continue");
if (!m_suppressSemi) puts(";\n");
}
virtual void visit(AstCoverDecl*) {} // N/A
virtual void visit(AstCoverInc*) {} // N/A
virtual void visit(AstCoverToggle*) {} // N/A
virtual void visit(AstCoverDecl*) VL_OVERRIDE {} // N/A
virtual void visit(AstCoverInc*) VL_OVERRIDE {} // N/A
virtual void visit(AstCoverToggle*) VL_OVERRIDE {} // N/A
void visitNodeDisplay(AstNode* nodep, AstNode* fileOrStrgp,
const string& text, AstNode* exprsp) {
@ -216,28 +216,28 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
puts(");\n");
}
virtual void visit(AstDisable* nodep) {
virtual void visit(AstDisable* nodep) VL_OVERRIDE {
putbs("disable "+nodep->name()+";\n");
}
virtual void visit(AstDisplay* nodep) {
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
}
virtual void visit(AstElabDisplay* nodep) {
virtual void visit(AstElabDisplay* nodep) VL_OVERRIDE {
visitNodeDisplay(nodep, NULL, nodep->fmtp()->text(), nodep->fmtp()->exprsp());
}
virtual void visit(AstFScanF* nodep) {
virtual void visit(AstFScanF* nodep) VL_OVERRIDE {
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
}
virtual void visit(AstSScanF* nodep) {
virtual void visit(AstSScanF* nodep) VL_OVERRIDE {
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
}
virtual void visit(AstSFormat* nodep) {
virtual void visit(AstSFormat* nodep) VL_OVERRIDE {
visitNodeDisplay(nodep, nodep->lhsp(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
}
virtual void visit(AstSFormatF* nodep) {
virtual void visit(AstSFormatF* nodep) VL_OVERRIDE {
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
}
virtual void visit(AstFOpen* nodep) {
virtual void visit(AstFOpen* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
putbs(" (");
if (nodep->filep()) iterateAndNextNull(nodep->filep());
@ -247,27 +247,27 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
if (nodep->modep()) iterateAndNextNull(nodep->modep());
puts(");\n");
}
virtual void visit(AstFClose* nodep) {
virtual void visit(AstFClose* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
putbs(" (");
if (nodep->filep()) iterateAndNextNull(nodep->filep());
puts(");\n");
}
virtual void visit(AstFFlush* nodep) {
virtual void visit(AstFFlush* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
putbs(" (");
if (nodep->filep()) iterateAndNextNull(nodep->filep());
puts(");\n");
}
virtual void visit(AstJumpGo* nodep) {
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
putbs("disable "+cvtToHex(nodep->labelp())+";\n");
}
virtual void visit(AstJumpLabel* nodep) {
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
putbs("begin : "+cvtToHex(nodep)+"\n");
if (nodep->stmtsp()) iterateAndNextNull(nodep->stmtsp());
puts("end\n");
}
virtual void visit(AstNodeReadWriteMem* nodep) {
virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
putbs(" (");
if (nodep->filenamep()) iterateAndNextNull(nodep->filenamep());
@ -277,17 +277,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
if (nodep->msbp()) { putbs(","); iterateAndNextNull(nodep->msbp()); }
puts(");\n");
}
virtual void visit(AstSysFuncAsTask* nodep) {
virtual void visit(AstSysFuncAsTask* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->lhsp());
puts(";\n");
}
virtual void visit(AstSysIgnore* nodep) {
virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
putbs(" (");
iterateAndNextNull(nodep->exprsp());
puts(");\n");
}
virtual void visit(AstNodeFor* nodep) {
virtual void visit(AstNodeFor* nodep) VL_OVERRIDE {
putfs(nodep, "for (");
m_suppressSemi = true;
iterateAndNextNull(nodep->initsp());
@ -300,14 +300,14 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateAndNextNull(nodep->bodysp());
putqs(nodep, "end\n");
}
virtual void visit(AstRepeat* nodep) {
virtual void visit(AstRepeat* nodep) VL_OVERRIDE {
putfs(nodep, "repeat (");
iterateAndNextNull(nodep->countp());
puts(") begin\n");
iterateAndNextNull(nodep->bodysp());
putfs(nodep, "end\n");
}
virtual void visit(AstWhile* nodep) {
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->precondsp());
putfs(nodep, "while (");
iterateAndNextNull(nodep->condp());
@ -317,7 +317,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop
putfs(nodep, "end\n");
}
virtual void visit(AstNodeIf* nodep) {
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
putfs(nodep, "");
if (const AstIf* ifp = VN_CAST(nodep, If)) {
if (ifp->priorityPragma()) puts("priority ");
@ -335,7 +335,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
putqs(nodep, "end\n");
}
virtual void visit(AstPast* nodep) {
virtual void visit(AstPast* nodep) VL_OVERRIDE {
putfs(nodep, "$past(");
iterateAndNextNull(nodep->exprp());
if (nodep->ticksp()) {
@ -344,49 +344,49 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
puts(")");
}
virtual void visit(AstReturn* nodep) {
virtual void visit(AstReturn* nodep) VL_OVERRIDE {
putfs(nodep, "return ");
iterateAndNextNull(nodep->lhsp());
puts(";\n");
}
virtual void visit(AstStop* nodep) {
virtual void visit(AstStop* nodep) VL_OVERRIDE {
putfs(nodep, "$stop;\n");
}
virtual void visit(AstFinish* nodep) {
virtual void visit(AstFinish* nodep) VL_OVERRIDE {
putfs(nodep, "$finish;\n");
}
virtual void visit(AstText* nodep) {
virtual void visit(AstNodeSimpleText* nodep) VL_OVERRIDE {
if (nodep->tracking() || m_trackText) {
puts(nodep->text());
} else {
putsNoTracking(nodep->text());
}
}
virtual void visit(AstTextBlock* nodep) {
visit(VN_CAST(nodep, Text));
virtual void visit(AstTextBlock* nodep) VL_OVERRIDE {
visit(VN_CAST(nodep, NodeSimpleText));
for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) {
iterate(childp);
if (nodep->commas() && childp->nextp()) puts(", ");
}
}
virtual void visit(AstScopeName* nodep) {
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
}
virtual void visit(AstCStmt* nodep) {
virtual void visit(AstCStmt* nodep) VL_OVERRIDE {
putfs(nodep, "$_CSTMT(");
iterateAndNextNull(nodep->bodysp());
puts(");\n");
}
virtual void visit(AstCMath* nodep) {
virtual void visit(AstCMath* nodep) VL_OVERRIDE {
putfs(nodep, "$_CMATH(");
iterateAndNextNull(nodep->bodysp());
puts(");\n");
}
virtual void visit(AstUCStmt* nodep) {
virtual void visit(AstUCStmt* nodep) VL_OVERRIDE {
putfs(nodep, "$c(");
iterateAndNextNull(nodep->bodysp());
puts(");\n");
}
virtual void visit(AstUCFunc* nodep) {
virtual void visit(AstUCFunc* nodep) VL_OVERRIDE {
putfs(nodep, "$c(");
iterateAndNextNull(nodep->bodysp());
puts(")");
@ -444,19 +444,19 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
}
virtual void visit(AstNodeTermop* nodep) {
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {
emitVerilogFormat(nodep, nodep->emitVerilog());
}
virtual void visit(AstNodeUniop* nodep) {
virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE {
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp());
}
virtual void visit(AstNodeBiop* nodep) {
virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE {
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp());
}
virtual void visit(AstNodeTriop* nodep) {
virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE {
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(), nodep->thsp());
}
virtual void visit(AstAttrOf* nodep) {
virtual void visit(AstAttrOf* nodep) VL_OVERRIDE {
putfs(nodep, "$_ATTROF(");
iterateAndNextNull(nodep->fromp());
if (nodep->dimp()) {
@ -465,7 +465,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
puts(")");
}
virtual void visit(AstInitArray* nodep) {
virtual void visit(AstInitArray* nodep) VL_OVERRIDE {
putfs(nodep, "`{");
int comma = 0;
const AstInitArray::KeyItemMap& mapr = nodep->map();
@ -479,13 +479,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
puts("}");
}
virtual void visit(AstNodeCond* nodep) {
virtual void visit(AstNodeCond* nodep) VL_OVERRIDE {
putbs("(");
iterateAndNextNull(nodep->condp()); putfs(nodep, " ? ");
iterateAndNextNull(nodep->expr1p()); putbs(" : ");
iterateAndNextNull(nodep->expr2p()); puts(")");
}
virtual void visit(AstRange* nodep) {
virtual void visit(AstRange* nodep) VL_OVERRIDE {
puts("[");
if (VN_IS(nodep->msbp(), Const) && VN_IS(nodep->lsbp(), Const)) {
// Looks nicer if we print [1:0] rather than [32'sh1:32sh0]
@ -496,7 +496,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateAndNextNull(nodep->rightp()); puts("]");
}
}
virtual void visit(AstSel* nodep) {
virtual void visit(AstSel* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->fromp()); puts("[");
if (VN_IS(nodep->lsbp(), Const)) {
if (nodep->widthp()->isOne()) {
@ -518,44 +518,44 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
}
puts("]");
}
virtual void visit(AstSliceSel* nodep) {
virtual void visit(AstSliceSel* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->fromp());
puts(cvtToStr(nodep->declRange()));
}
virtual void visit(AstTypedef* nodep) {
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
putfs(nodep, "typedef ");
iterateAndNextNull(nodep->dtypep()); puts(" ");
puts(nodep->prettyName());
puts(";\n");
}
virtual void visit(AstBasicDType* nodep) {
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE {
if (nodep->isSigned()) putfs(nodep, "signed ");
putfs(nodep, nodep->prettyName());
if (nodep->rangep()) { puts(" "); iterateAndNextNull(nodep->rangep()); puts(" "); }
else if (nodep->isRanged()) { puts(" ["); puts(cvtToStr(nodep->msb())); puts(":0] "); }
}
virtual void visit(AstConstDType* nodep) {
virtual void visit(AstConstDType* nodep) VL_OVERRIDE {
putfs(nodep, "const ");
iterate(nodep->subDTypep());
}
virtual void visit(AstNodeArrayDType* nodep) {
virtual void visit(AstNodeArrayDType* nodep) VL_OVERRIDE {
iterate(nodep->subDTypep());
iterateAndNextNull(nodep->rangep());
}
virtual void visit(AstNodeUOrStructDType* nodep) {
virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE {
puts(nodep->verilogKwd()+" ");
if (nodep->packed()) puts("packed ");
puts("\n");
iterateAndNextNull(nodep->membersp());
puts("}");
}
virtual void visit(AstMemberDType* nodep) {
virtual void visit(AstMemberDType* nodep) VL_OVERRIDE {
iterate(nodep->subDTypep());
puts(" ");
puts(nodep->name());
puts("}");
}
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
if (nodep->dotted()!="") {
putfs(nodep, nodep->dotted()); puts("."); puts(nodep->prettyName());
} else { putfs(nodep, nodep->prettyName()); }
@ -563,11 +563,11 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
iterateAndNextNull(nodep->pinsp());
puts(")");
}
virtual void visit(AstArg* nodep) {
virtual void visit(AstArg* nodep) VL_OVERRIDE {
iterateAndNextNull(nodep->exprp());
}
// Terminals
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (nodep->varScopep()) {
putfs(nodep, nodep->varScopep()->prettyName());
} else {
@ -575,43 +575,43 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
puts(nodep->varp()->prettyName());
}
}
virtual void visit(AstVarXRef* nodep) {
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
putfs(nodep, nodep->dotted());
puts(".");
puts(nodep->varp()->prettyName());
}
virtual void visit(AstConst* nodep) {
virtual void visit(AstConst* nodep) VL_OVERRIDE {
putfs(nodep, nodep->num().ascii(true, true));
}
// Just iterate
virtual void visit(AstTopScope* nodep) {
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
putfs(nodep, nodep->verilogKwd());
puts(" ");
iterate(nodep->dtypep()); puts(" ");
puts(nodep->prettyName());
if (!m_suppressVarSemi) puts(";\n"); else puts("\n");
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
m_sensesp = nodep->sensesp();
iterateAndNextNull(nodep->stmtsp());
m_sensesp = NULL;
}
virtual void visit(AstVarScope*) {}
virtual void visit(AstNodeText*) {}
virtual void visit(AstTraceDecl*) {}
virtual void visit(AstTraceInc*) {}
virtual void visit(AstVarScope*) VL_OVERRIDE {}
virtual void visit(AstNodeText*) VL_OVERRIDE {}
virtual void visit(AstTraceDecl*) VL_OVERRIDE {}
virtual void visit(AstTraceInc*) VL_OVERRIDE {}
// NOPs
virtual void visit(AstPragma*) {}
virtual void visit(AstCell*) {} // Handled outside the Visit class
virtual void visit(AstPragma*) VL_OVERRIDE {}
virtual void visit(AstCell*) VL_OVERRIDE {} // Handled outside the Visit class
// Default
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
puts(string("\n???? // ")+nodep->prettyTypeName()+"\n");
iterateChildren(nodep);
// Not v3fatalSrc so we keep processing
@ -757,12 +757,12 @@ void V3EmitV::emitv() {
EmitVFileVisitor visitor (v3Global.rootp(), &of);
} else {
// Process each module in turn
for (AstNodeModule* modp = v3Global.rootp()->modulesp();
modp; modp=VN_CAST(modp->nextp(), NodeModule)) {
V3OutVFile of (v3Global.opt.makeDir()
+"/"+EmitCBaseVisitor::modClassName(modp)+"__Vout.v");
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp;
modp = VN_CAST(modp->nextp(), NodeModule)) {
V3OutVFile of(v3Global.opt.makeDir() + "/" + EmitCBaseVisitor::prefixNameProtect(modp)
+ "__Vout.v");
of.putsHeader();
EmitVFileVisitor visitor (modp, &of);
EmitVFileVisitor visitor(modp, &of);
}
}
}
@ -779,8 +779,8 @@ void V3EmitV::verilogPrefixedTree(AstNode* nodep, std::ostream& os,
void V3EmitV::emitvFiles() {
UINFO(2,__FUNCTION__<<": "<<endl);
for (AstFile* filep = v3Global.rootp()->filesp(); filep;
filep = VN_CAST(filep->nextp(), File)) {
for (AstNodeFile* filep = v3Global.rootp()->filesp(); filep;
filep = VN_CAST(filep->nextp(), NodeFile)) {
AstVFile* vfilep = VN_CAST(filep, VFile);
if (vfilep && vfilep->tblockp()) {
V3OutVFile of(vfilep->name());

View File

@ -71,6 +71,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
void outputTag(AstNode* nodep, string tag) {
if (tag=="") tag = VString::downcase(nodep->typeName());
puts("<"+tag+" "+nodep->fileline()->xml());
puts(" "+nodep->fileline()->xmlDetailedLocation());
if (VN_IS(nodep, NodeDType)) { puts(" id="); outputId(nodep); }
if (nodep->name()!="") { puts(" name="); putsQuoted(nodep->prettyName()); }
if (nodep->tag()!="") { puts(" tag="); putsQuoted(nodep->tag()); }
@ -94,22 +95,22 @@ class EmitXmlFileVisitor : public AstNVisitor {
}
// VISITORS
virtual void visit(AstAssignW* nodep) {
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
outputTag(nodep, "contassign"); // IEEE: vpiContAssign
outputChildrenEnd(nodep, "contassign");
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
outputTag(nodep, "instance"); // IEEE: vpiInstance
puts(" defName="); putsQuoted(nodep->modName()); // IEEE vpiDefName
puts(" origName="); putsQuoted(nodep->origName());
outputChildrenEnd(nodep, "instance");
}
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
puts("<netlist>\n");
iterateChildren(nodep);
puts("</netlist>\n");
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
outputTag(nodep, "");
puts(" origName="); putsQuoted(nodep->origName());
if (nodep->level()==1 || nodep->level()==2) // ==2 because we don't add wrapper when in XML mode
@ -117,7 +118,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
if (nodep->modPublic()) puts(" public=\"true\"");
outputChildrenEnd(nodep, "");
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
AstVarType typ = nodep->varType();
string kw = nodep->verilogKwd();
string vt = nodep->dtypep()->name();
@ -131,18 +132,23 @@ class EmitXmlFileVisitor : public AstNVisitor {
}
puts(" origName="); putsQuoted(nodep->origName());
// Attributes
if (nodep->attrClocker()) puts(" clocker=\"true\"");
if (nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES)
puts(" clocker=\"true\"");
else if (nodep->attrClocker() == VVarAttrClocker::CLOCKER_NO)
puts(" clocker=\"false\"");
if (nodep->attrClockEn()) puts(" clock_enable=\"true\"");
if (nodep->attrIsolateAssign()) puts(" isolate_assignments=\"true\"");
if (nodep->isSigPublic()) puts(" public=\"true\"");
if (nodep->isSigUserRdPublic()) puts(" public_flat_rd=\"true\"");
if (nodep->isSigUserRWPublic()) puts(" public_flat_rw=\"true\"");
if (nodep->isGParam()) puts(" param=\"true\"");
else if (nodep->isParam()) puts(" localparam=\"true\"");
if (nodep->attrScBv()) puts(" sc_bv=\"true\"");
if (nodep->attrScClocked()) puts(" sc_clock=\"true\"");
if (nodep->attrSFormat()) puts(" sformat=\"true\"");
outputChildrenEnd(nodep, "");
}
virtual void visit(AstPin* nodep) {
virtual void visit(AstPin* nodep) VL_OVERRIDE {
// What we call a pin in verilator is a port in the IEEE spec.
outputTag(nodep, "port"); // IEEE: vpiPort
if (nodep->modVarp()->isIO()) {
@ -152,26 +158,26 @@ class EmitXmlFileVisitor : public AstNVisitor {
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
outputChildrenEnd(nodep, "port");
}
virtual void visit(AstSenItem* nodep) {
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
outputTag(nodep, "");
puts(" edgeType=\""+cvtToStr(nodep->edgeType().ascii())+"\""); // IEEE vpiTopModule
outputChildrenEnd(nodep, "");
}
virtual void visit(AstModportVarRef* nodep) {
virtual void visit(AstModportVarRef* nodep) VL_OVERRIDE {
// Dump direction for Modport references
string kw = nodep->direction().xmlKwd();
outputTag(nodep, "");
puts(" direction="); putsQuoted(kw);
outputChildrenEnd(nodep, "");
}
virtual void visit(AstVarXRef* nodep) {
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
outputTag(nodep, "");
puts(" dotted="); putsQuoted(nodep->dotted());
outputChildrenEnd(nodep, "");
}
// Data types
virtual void visit(AstBasicDType* nodep) {
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE {
outputTag(nodep, "basicdtype");
if (nodep->isRanged()) {
puts(" left=\""+cvtToStr(nodep->left())+"\"");
@ -179,30 +185,30 @@ class EmitXmlFileVisitor : public AstNVisitor {
}
puts("/>\n");
}
virtual void visit(AstIfaceRefDType* nodep) {
virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE {
string mpn;
outputTag(nodep, "");
if (nodep->isModport()) mpn = nodep->modportName();
puts(" modportname="); putsQuoted(mpn);
outputChildrenEnd(nodep, "");
}
virtual void visit(AstDisplay* nodep) {
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
outputTag(nodep, "");
puts(" displaytype="); putsQuoted(nodep->verilogKwd());
outputChildrenEnd(nodep, "");
}
virtual void visit(AstElabDisplay* nodep) {
virtual void visit(AstElabDisplay* nodep) VL_OVERRIDE {
outputTag(nodep, "");
puts(" displaytype="); putsQuoted(nodep->verilogKwd());
outputChildrenEnd(nodep, "");
}
virtual void visit(AstExtend* nodep) {
virtual void visit(AstExtend* nodep) VL_OVERRIDE {
outputTag(nodep, "");
puts(" width="); putsQuoted(cvtToStr(nodep->width()));
puts(" widthminv="); putsQuoted(cvtToStr(nodep->lhsp()->widthMinV()));
outputChildrenEnd(nodep, "");
}
virtual void visit(AstExtendS* nodep) {
virtual void visit(AstExtendS* nodep) VL_OVERRIDE {
outputTag(nodep, "");
puts(" width="); putsQuoted(cvtToStr(nodep->width()));
puts(" widthminv="); putsQuoted(cvtToStr(nodep->lhsp()->widthMinV()));
@ -210,7 +216,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
}
// Default
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
outputTag(nodep, "");
outputChildrenEnd(nodep, "");
}
@ -237,11 +243,11 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Children are iterated backwards to ensure correct compilation order
iterateChildrenBackwards(nodep);
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Only list modules and interfaces
// Assumes modules and interfaces list is already sorted level wise
if (!nodep->dead()
@ -251,7 +257,7 @@ private:
}
}
//-----
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// All modules are present at root so no need to iterate on children
}
@ -288,11 +294,12 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
if (nodep->level() >= 0
&& nodep->level() <=2 ) { // ==2 because we don't add wrapper when in XML mode
m_os<<"<cells>\n";
m_os<<"<cell "<<nodep->fileline()->xml()
<<" "<<nodep->fileline()->xmlDetailedLocation()
<<" name=\""<<nodep->name()<<"\""
<<" submodname=\""<<nodep->name()<<"\""
<<" hier=\""<<nodep->name()<<"\"";
@ -307,12 +314,13 @@ private:
m_os<<"</cells>\n";
}
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
if (nodep->modp()->dead()) {
return;
}
if (!m_hasChildren) m_os<<">\n";
m_os<<"<cell "<<nodep->fileline()->xml()
<<" "<<nodep->fileline()->xmlDetailedLocation()
<<" name=\""<<nodep->name()<<"\""
<<" submodname=\""<<nodep->modName()<<"\""
<<" hier=\""<<m_hier+nodep->name()<<"\"";
@ -329,7 +337,7 @@ private:
m_hasChildren = true;
}
//-----
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -205,11 +205,15 @@ public:
|| m_e==UNDRIVEN
|| m_e==UNUSED
|| m_e==VARHIDDEN ); }
};
inline bool operator==(V3ErrorCode lhs, V3ErrorCode rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(V3ErrorCode lhs, V3ErrorCode::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(V3ErrorCode::en lhs, V3ErrorCode rhs) { return (lhs == rhs.m_e); }
inline std::ostream& operator<<(std::ostream& os, V3ErrorCode rhs) { return os<<rhs.ascii(); }
};
inline bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const V3ErrorCode& lhs, V3ErrorCode::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(V3ErrorCode::en lhs, const V3ErrorCode& rhs) { return lhs == rhs.m_e; }
inline std::ostream& operator<<(std::ostream& os, const V3ErrorCode& rhs) {
return os << rhs.ascii();
}
//######################################################################
@ -291,8 +295,8 @@ inline void v3errorEndFatal(std::ostringstream& sstr) {
// Theses allow errors using << operators: v3error("foo"<<"bar");
// Careful, you can't put () around msg, as you would in most macro definitions
// Note the commas are the comma operator, not separating arguments. These are needed to insure
// evaluation order as otherwise we couldn't insure v3errorPrep is called first.
// Note the commas are the comma operator, not separating arguments. These are needed to ensure
// evaluation order as otherwise we couldn't ensure v3errorPrep is called first.
#define v3warnCode(code,msg) \
v3errorEnd((V3Error::v3errorPrep(code), (V3Error::v3errorStr()<<msg), V3Error::v3errorStr()));
#define v3warnCodeFatal(code,msg) \

View File

@ -80,7 +80,7 @@ private:
void replaceWithDelete(AstNode* nodep, AstNode* newp) {
newp->user1(1); // Already processed, don't need to re-iterate
nodep->replaceWith(newp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
AstNode* newWordAssign(AstNodeAssign* placep, int word, AstNode* lhsp, AstNode* rhsp) {
AstAssign* newp = new AstAssign(placep->fileline(),
@ -306,7 +306,7 @@ private:
}
// VISITORS
virtual void visit(AstExtend* nodep) {
virtual void visit(AstExtend* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
if (nodep->isWide()) {
@ -328,7 +328,7 @@ private:
"extending larger thing into smaller?");
lhsp->dtypeFrom(nodep); // Just mark it, else nop
}
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
}
bool expandWide(AstNodeAssign* nodep, AstExtend* rhsp) {
@ -343,7 +343,7 @@ private:
return true;
}
virtual void visit(AstSel* nodep) {
virtual void visit(AstSel* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
// Remember, Sel's may have non-integer rhs, so need to optimize for that!
@ -443,7 +443,7 @@ private:
if (midp) newp = new AstOr(nodep->fileline(), midp, newp);
if (hip) newp = new AstOr(nodep->fileline(), hip, newp);
newp->dtypeFrom(nodep);
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
else { // Long/Quad from Long/Quad
UINFO(8," SEL->SHIFT "<<nodep<<endl);
@ -461,7 +461,7 @@ private:
newp = new AstCCast(newp->fileline(), newp, nodep);
}
newp->dtypeFrom(nodep);
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
}
@ -553,8 +553,8 @@ private:
rhsp, lsb)));
}
}
rhsp->deleteTree(); VL_DANGLING(rhsp);
destp->deleteTree(); VL_DANGLING(destp);
VL_DO_DANGLING(rhsp->deleteTree(), rhsp);
VL_DO_DANGLING(destp->deleteTree(), destp);
} else {
UINFO(8," ASSIGNSEL(const,narrow) "<<nodep<<endl);
if (destp->isQuad() && !rhsp->isQuad()) {
@ -670,7 +670,7 @@ private:
}
}
virtual void visit(AstConcat* nodep) {
virtual void visit(AstConcat* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
if (nodep->isWide()) {
@ -693,7 +693,7 @@ private:
nodep->width()),
rhsp);
newp->dtypeFrom(nodep); // Unsigned
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
}
bool expandWide(AstNodeAssign* nodep, AstConcat* rhsp) {
@ -714,7 +714,7 @@ private:
return true;
}
virtual void visit(AstReplicate* nodep) {
virtual void visit(AstReplicate* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
if (nodep->isWide()) {
@ -746,10 +746,10 @@ private:
newp);
newp->dtypeFrom(nodep); // Unsigned
}
lhsp->deleteTree(); // Never used
VL_DO_DANGLING(lhsp->deleteTree(), lhsp); // Never used
}
newp->dtypeFrom(nodep); // Unsigned
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
}
bool expandWide(AstNodeAssign* nodep, AstReplicate* rhsp) {
@ -779,7 +779,7 @@ private:
return true;
}
virtual void visit(AstChangeXor* nodep) {
virtual void visit(AstChangeXor* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
UINFO(8," Wordize ChangeXor "<<nodep<<endl);
@ -791,7 +791,7 @@ private:
newAstWordSelClone(nodep->rhsp(), w));
newp = (newp==NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp));
}
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
void visitEqNeq(AstNodeBiop* nodep) {
@ -816,13 +816,13 @@ private:
new AstConst(nodep->fileline(), AstConst::SizedEData(), 0),
newp);
}
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
}
virtual void visit(AstEq* nodep) { visitEqNeq(nodep); }
virtual void visit(AstNeq* nodep) { visitEqNeq(nodep); }
virtual void visit(AstEq* nodep) VL_OVERRIDE { visitEqNeq(nodep); }
virtual void visit(AstNeq* nodep) VL_OVERRIDE { visitEqNeq(nodep); }
virtual void visit(AstRedOr* nodep) {
virtual void visit(AstRedOr* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
if (nodep->lhsp()->isWide()) {
@ -836,7 +836,7 @@ private:
newp = new AstNeq(nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::SizedEData(), 0),
newp);
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
} else {
UINFO(8," REDOR->EQ "<<nodep<<endl);
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
@ -844,10 +844,10 @@ private:
new AstConst(nodep->fileline(), AstConst::WidthedValue(),
longOrQuadWidth(nodep), 0),
lhsp);
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
}
virtual void visit(AstRedAnd* nodep) {
virtual void visit(AstRedAnd* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
if (nodep->lhsp()->isWide()) {
@ -870,17 +870,17 @@ private:
newp = new AstEq(nodep->fileline(),
new AstConst(nodep->fileline(), AstConst::SizedEData(),
~VL_MASK_E(0)), newp);
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
} else {
UINFO(8," REDAND->EQ "<<nodep<<endl);
AstNode* lhsp = nodep->lhsp()->unlinkFrBack();
AstNode* newp = new AstEq(nodep->fileline(),
new AstConst(nodep->fileline(), wordMask(lhsp)),
lhsp);
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
}
virtual void visit(AstRedXor* nodep) {
virtual void visit(AstRedXor* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
iterateChildren(nodep);
if (nodep->lhsp()->isWide()) {
@ -893,13 +893,13 @@ private:
}
newp = new AstRedXor(nodep->fileline(), newp);
UINFO(8," Wordize REDXORnew "<<newp<<endl);
replaceWithDelete(nodep, newp); VL_DANGLING(nodep);
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
}
// We don't reduce non-wide XORs, as its more efficient to use a temp register,
// which the inlined function does nicely.
}
virtual void visit(AstNodeStmt* nodep) {
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
if (!nodep->isStatement()) {
iterateChildren(nodep);
@ -909,7 +909,7 @@ private:
iterateChildren(nodep);
m_stmtp = NULL;
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
if (nodep->user1SetOnce()) return; // Process once
m_stmtp = nodep;
iterateChildren(nodep);
@ -948,15 +948,15 @@ private:
}
// Cleanup common code
if (did) {
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
m_stmtp = NULL;
}
//--------------------
// Default: Just iterate
virtual void visit(AstVar*) {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't hit varrefs under vars
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -594,7 +594,7 @@ protected:
// Just dispatch to the implementation
VInFilter::VInFilter(const string& command) { m_impp = new VInFilterImp(command); }
VInFilter::~VInFilter() { if (m_impp) delete m_impp; m_impp = NULL; }
VInFilter::~VInFilter() { if (m_impp) VL_DO_CLEAR(delete m_impp, m_impp = NULL); }
bool VInFilter::readWholefile(const string& filename, VInFilter::StrList& outl) {
if (!m_impp) v3fatalSrc("readWholefile on invalid filter");

View File

@ -120,6 +120,7 @@ void VFileContent::pushText(const string& text) {
string VFileContent::getLine(int lineno) const {
// Return error text rather than asserting so the user isn't left without a message
// cppcheck-suppress negativeContainerIndex
if (VL_UNCOVERABLE(lineno < 0 || lineno >= (int)m_lines.size())) {
if (debug() || v3Global.opt.debugCheck()) {
return ("%Error-internal-contents-bad-ct"+cvtToStr(m_id)
@ -158,6 +159,15 @@ FileLine::FileLine(FileLine::EmptySecret) {
}
}
const string FileLine::xmlDetailedLocation() const {
return "loc=\"" +
cvtToStr(filenameLetters()) + "," +
cvtToStr(firstLineno()) + "," +
cvtToStr(firstColumn()) + "," +
cvtToStr(lastLineno()) + "," +
cvtToStr(lastColumn()) + "\"";
}
string FileLine::lineDirectiveStrg(int enterExit) const {
char numbuf[20]; sprintf(numbuf, "%d", lastLineno());
char levelbuf[20]; sprintf(levelbuf, "%d", enterExit);
@ -341,7 +351,10 @@ void FileLine::v3errorEnd(std::ostringstream& str, const string& locationStr) {
if (!locationStr.empty()) {
lstr<<std::setw(ascii().length())<<" "<<": "<<locationStr;
}
if (warnIsOff(V3Error::errorCode())) V3Error::suppressThisWarning();
if (warnIsOff(V3Error::errorCode())
|| V3Config::waive(this, V3Error::errorCode(), str.str())) {
V3Error::suppressThisWarning();
}
else if (!V3Error::errorContexted()) nsstr<<warnContextPrimary();
V3Error::v3errorEnd(nsstr, lstr.str());
}

View File

@ -119,7 +119,7 @@ private:
return *defFilelinep;
}
public:
FileLine(const string& filename) {
explicit FileLine(const string& filename) {
m_lastLineno = m_firstLineno = 0;
m_lastColumn = m_firstColumn = 0;
m_filenameno = singleton().nameToNumber(filename);
@ -183,6 +183,7 @@ public:
const string filebasenameNoExt() const;
const string profileFuncname() const;
const string xml() const { return "fl=\""+filenameLetters()+cvtToStr(lastLineno())+"\""; }
const string xmlDetailedLocation() const;
string lineDirectiveStrg(int enterExit) const;
// Turn on/off warning messages on this line.
@ -239,7 +240,7 @@ public:
/// When building an error, additional location for additional references
/// Simplified information vs warnContextPrimary() to make dump clearer
string warnContextSecondary() const { return warnContext(true); }
bool operator==(FileLine rhs) const {
bool operator==(const FileLine& rhs) const {
return (m_firstLineno == rhs.m_firstLineno
&& m_firstColumn == rhs.m_firstColumn
&& m_lastLineno == rhs.m_lastLineno

View File

@ -207,7 +207,7 @@ private:
}
}
// VISITORS
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
++m_ops;
iterateChildren(nodep);
// We only allow a LHS ref for the var being set, and a RHS ref for
@ -235,7 +235,7 @@ private:
m_rhsVarRefs.push_back(nodep);
}
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
m_substTreep = nodep->rhsp();
if (!VN_IS(nodep->lhsp(), NodeVarRef)) {
clearSimple("ASSIGN(non-VARREF)");
@ -258,7 +258,7 @@ private:
}
//--------------------
// Default
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// *** Special iterator
if (!m_isSimple) return; // Fastpath
if (++m_ops > v3Global.opt.gateStmts()) {
@ -388,7 +388,7 @@ private:
void decomposeClkVectors();
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
iterateChildren(nodep);
//if (debug()>6) m_graph.dump();
if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre");
@ -419,20 +419,23 @@ private:
consumedMove();
replaceAssigns();
}
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
m_activeReducible = true;
iterateChildren(nodep);
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
m_activeReducible = true;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
UINFO(4," SCOPE "<<nodep<<endl);
m_scopep = nodep;
m_logicVertexp = NULL;
iterateChildren(nodep);
m_scopep = NULL;
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
// Create required blocks and add to module
UINFO(4," BLOCK "<<nodep<<endl);
m_activeReducible = !(nodep->hasClocked()); // Seq logic outputs aren't reducible
@ -443,16 +446,18 @@ private:
m_activep = NULL;
m_activeReducible = true;
}
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
if (m_scopep) {
UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block");
AstVarScope* varscp = nodep->varScopep();
UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp");
GateVarVertex* vvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl);
if (m_inSenItem) vvertexp->setIsClock();
// For SYNCASYNCNET
if (m_inSenItem) varscp->user2(true);
if (m_inSenItem) {
vvertexp->setIsClock();
// For SYNCASYNCNET
varscp->user2(true);
}
else if (m_activep && m_activep->hasClocked() && !nodep->lvalue()) {
if (varscp->user2()) {
if (!vvertexp->rstAsyncNodep()) vvertexp->rstAsyncNodep(nodep);
@ -469,19 +474,19 @@ private:
}
}
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
iterateNewStmt(nodep, (nodep->isJustOneBodyStmt()?NULL:"Multiple Stmts"), NULL);
}
virtual void visit(AstAlwaysPublic* nodep) {
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
bool lastslow = m_inSlow;
m_inSlow = true;
iterateNewStmt(nodep, "AlwaysPublic", NULL);
m_inSlow = lastslow;
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
iterateNewStmt(nodep, "User C Function", "User C Function");
}
virtual void visit(AstSenItem* nodep) {
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
// Note we look at only AstSenItems, not AstSenGate's
// The gating term of a AstSenGate is normal logic
m_inSenItem = true;
@ -492,33 +497,33 @@ private:
}
m_inSenItem = false;
}
virtual void visit(AstSenGate* nodep) {
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
// First handle the clock part will be handled in a minute by visit AstSenItem
// The logic gating term is dealt with as logic
iterateNewStmt(nodep, "Clock gater", "Clock gater");
}
virtual void visit(AstInitial* nodep) {
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
bool lastslow = m_inSlow;
m_inSlow = true;
iterateNewStmt(nodep, (nodep->isJustOneBodyStmt()?NULL:"Multiple Stmts"), NULL);
m_inSlow = lastslow;
}
virtual void visit(AstAssignAlias* nodep) {
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
iterateNewStmt(nodep, NULL, NULL);
}
virtual void visit(AstAssignW* nodep) {
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
iterateNewStmt(nodep, NULL, NULL);
}
virtual void visit(AstCoverToggle* nodep) {
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
iterateNewStmt(nodep, "CoverToggle", "CoverToggle");
}
virtual void visit(AstTraceInc* nodep) {
virtual void visit(AstTraceInc* nodep) VL_OVERRIDE {
bool lastslow = m_inSlow;
m_inSlow = true;
iterateNewStmt(nodep, "Tracing", "Tracing");
m_inSlow = lastslow;
}
virtual void visit(AstConcat* nodep) {
virtual void visit(AstConcat* nodep) VL_OVERRIDE {
UASSERT_OBJ(!(VN_IS(nodep->backp(), NodeAssign)
&& VN_CAST(nodep->backp(), NodeAssign)->lhsp()==nodep),
nodep, "Concat on LHS of assignment; V3Const should have deleted it");
@ -527,7 +532,7 @@ private:
//--------------------
// Default
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (nodep->isOutputter() && m_logicVertexp) m_logicVertexp->setConsumed("outputter");
}
@ -666,7 +671,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
varvertexp->propagateAttrClocksFrom(vvertexp);
}
// Remove the edge
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
++m_statRefs;
edgep = vvertexp->outBeginp();
}
@ -674,7 +679,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
if (removedAllUsages) {
// Remove input links
while (V3GraphEdge* edgep = vvertexp->inBeginp()) {
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
}
// Clone tree so we remember it for tracing, and keep the pointer
// to the "ALWAYS" part of the tree as part of this statement
@ -709,7 +714,7 @@ bool GateVisitor::elimLogicOkOutputs(GateLogicVertex* consumeVertexp,
for (GateVarRefList::const_iterator it = rhsVarRefs.begin();
it != rhsVarRefs.end(); ++it) {
AstVarScope* vscp = (*it)->varScopep();
if (varscopes.find(vscp) == varscopes.end()) varscopes.insert(vscp);
varscopes.insert(vscp);
}
for (V3GraphEdge* edgep = consumeVertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
GateVarVertex* consVVertexp = dynamic_cast<GateVarVertex*>(edgep->top());
@ -731,25 +736,25 @@ void GateVisitor::replaceAssigns() {
if (vscp->valuep() && !VN_IS(vscp->valuep(), NodeMath)) {
//if (debug()>9) vscp->dumpTree(cout, "-vscPre: ");
while (AstNode* delp = VN_CAST(vscp->valuep(), Comment)) {
delp->unlinkFrBack()->deleteTree(); VL_DANGLING(delp);
VL_DO_DANGLING(delp->unlinkFrBack()->deleteTree(), delp);
}
if (AstInitial* delp = VN_CAST(vscp->valuep(), Initial)) {
AstNode* bodyp = delp->bodysp();
bodyp->unlinkFrBackWithNext();
delp->replaceWith(bodyp);
delp->deleteTree(); VL_DANGLING(delp);
VL_DO_DANGLING(delp->deleteTree(), delp);
}
if (AstAlways* delp = VN_CAST(vscp->valuep(), Always)) {
AstNode* bodyp = delp->bodysp();
bodyp->unlinkFrBackWithNext();
delp->replaceWith(bodyp);
delp->deleteTree(); VL_DANGLING(delp);
VL_DO_DANGLING(delp->deleteTree(), delp);
}
if (AstNodeAssign* delp = VN_CAST(vscp->valuep(), NodeAssign)) {
AstNode* rhsp = delp->rhsp();
rhsp->unlinkFrBack();
delp->replaceWith(rhsp);
delp->deleteTree(); VL_DANGLING(delp);
VL_DO_DANGLING(delp->deleteTree(), delp);
}
//if (debug()>9) {vscp->dumpTree(cout, "-vscDone: "); cout<<endl;}
if (!VN_IS(vscp->valuep(), NodeMath)
@ -805,7 +810,7 @@ void GateVisitor::consumedMove() {
// with "tracing-on" sensitivity
UINFO(8," Remove unconsumed "<<nodep<<endl);
nodep->unlinkFrBack();
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
}
@ -860,7 +865,7 @@ private:
void hashReplace(AstNode* oldp, AstNode* newp);
// VISITORS
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
if (nodep->varScopep() == m_elimVarScp) {
// Substitute in the new tree
// It's possible we substitute into something that will be reduced more later,
@ -884,10 +889,10 @@ private:
if (AstNodeVarRef* varrefp = VN_CAST(substp, NodeVarRef)) varrefp->lvalue(false);
hashReplace(nodep, substp);
nodep->replaceWith(substp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -1066,7 +1071,7 @@ private:
bool m_dedupable; // Determined the assign to be dedupable
// VISITORS
virtual void visit(AstNodeAssign* assignp) {
virtual void visit(AstNodeAssign* assignp) VL_OVERRIDE {
if (m_dedupable) {
// I think we could safely dedupe an always block with multiple
// non-blocking statements, but erring on side of caution here
@ -1077,7 +1082,7 @@ private:
}
}
}
virtual void visit(AstAlways* alwaysp) {
virtual void visit(AstAlways* alwaysp) VL_OVERRIDE {
if (m_dedupable) {
if (!m_always) {
m_always = true;
@ -1091,7 +1096,7 @@ private:
// always @(...)
// if (...)
// foo = ...; // or foo <= ...;
virtual void visit(AstNodeIf* ifp) {
virtual void visit(AstNodeIf* ifp) VL_OVERRIDE {
if (m_dedupable) {
if (m_always && !m_ifCondp && !ifp->elsesp()) { //we're under an always, this is the first IF, and there's no else
m_ifCondp = ifp->condp();
@ -1102,10 +1107,10 @@ private:
}
}
virtual void visit(AstComment*) {} // NOP
virtual void visit(AstComment*) VL_OVERRIDE {} // NOP
//--------------------
// Default
virtual void visit(AstNode*) {
virtual void visit(AstNode*) VL_OVERRIDE {
m_dedupable = false;
}
@ -1207,7 +1212,7 @@ private:
dupVvertexp->propagateAttrClocksFrom(vvertexp);
// Remove inputs links
while (V3GraphEdge* inedgep = vvertexp->inBeginp()) {
inedgep->unlinkDelete(); VL_DANGLING(inedgep);
VL_DO_DANGLING(inedgep->unlinkDelete(), inedgep);
}
// replaceAssigns() does the deleteTree on lvertexNodep in a later step
AstNode* lvertexNodep = lvertexp->nodep();
@ -1338,19 +1343,19 @@ private:
UINFO(5, "assemble to new sel: "<<newselp<<endl);
// replace preSel with newSel
preselp->replaceWith(newselp);
preselp->deleteTree(); VL_DANGLING(preselp);
VL_DO_DANGLING(preselp->deleteTree(), preselp);
// create new rhs for pre assignment
AstNode* newrhsp = new AstConcat(
m_assignp->rhsp()->fileline(), m_assignp->rhsp()->cloneTree(false),
assignp->rhsp()->cloneTree(false));
AstNode* oldrhsp = m_assignp->rhsp();
oldrhsp->replaceWith(newrhsp);
oldrhsp->deleteTree(); VL_DANGLING(oldrhsp);
VL_DO_DANGLING(oldrhsp->deleteTree(), oldrhsp);
m_assignp->dtypeChgWidthSigned(m_assignp->width()+assignp->width(),
m_assignp->width()+assignp->width(),
AstNumeric::SIGNED);
// don't need to delete, will be handled
//assignp->unlinkFrBack(); assignp->deleteTree(); VL_DANGLING(assignp);
//assignp->unlinkFrBack(); VL_DO_DANGLING(assignp->deleteTree(), assignp);
// update the graph
{
@ -1362,11 +1367,11 @@ private:
GateEitherVertex* fromvp
= dynamic_cast<GateEitherVertex*>(oedgep->fromp());
new V3GraphEdge(m_graphp, fromvp, m_logicvp, 1);
oedgep->unlinkDelete(); VL_DANGLING(oedgep);
VL_DO_DANGLING(oedgep->unlinkDelete(), oedgep);
}
}
// delete all outedges to lvertexp, only one
oldedgep->unlinkDelete(); VL_DANGLING(oldedgep);
VL_DO_DANGLING(oldedgep->unlinkDelete(), oldedgep);
}
++m_numMergedAssigns;
} else {
@ -1425,7 +1430,7 @@ private:
bool m_found; // Offset found
// VISITORS
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
UINFO(9,"CLK DECOMP Concat search var (off = "<<m_offset<<") - "<<nodep<<endl);
if (nodep->varScopep() == m_vscp && !nodep->user2() && !m_found) {
// A concatenation may use the same var multiple times
@ -1437,14 +1442,14 @@ private:
}
m_offset += nodep->dtypep()->width();
}
virtual void visit(AstConcat* nodep) {
virtual void visit(AstConcat* nodep) VL_OVERRIDE {
UINFO(9,"CLK DECOMP Concat search (off = "<<m_offset<<") - "<<nodep<<endl);
iterate(nodep->rhsp());
iterate(nodep->lhsp());
}
//--------------------
// Default
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -1556,7 +1561,7 @@ private:
AstNode* rhsp = assignp->rhsp();
rhsp->replaceWith(new AstVarRef(rhsp->fileline(), m_clk_vsp, false));
for (V3GraphEdge* edgep = lvertexp->inBeginp(); edgep; ) {
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
}
new V3GraphEdge(m_graphp, m_clk_vvertexp, lvertexp, 1);
m_total_decomposed_clk_vectors++;
@ -1617,19 +1622,19 @@ void GateVisitor::decomposeClkVectors() {
class GateDeassignVisitor : public GateBaseVisitor {
private:
// VISITORS
virtual void visit(AstVarScope* nodep) {
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {
if (AstNodeAssign* assp = VN_CAST(nodep->valuep(), NodeAssign)) {
UINFO(5," Removeassign "<<assp<<endl);
AstNode* valuep = assp->rhsp();
valuep->unlinkFrBack();
assp->replaceWith(valuep);
assp->deleteTree(); VL_DANGLING(assp);
VL_DO_DANGLING(assp->deleteTree(), assp);
}
}
// Speedups
virtual void visit(AstVar* nodep) {}
virtual void visit(AstActive* nodep) {}
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {}
virtual void visit(AstActive* nodep) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}

View File

@ -83,7 +83,7 @@ private:
}
// VISITORS
virtual void visit(AstTopScope* nodep) {
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
AstNode::user2ClearTree(); // user2p() used on entire tree
AstScope* scopep = nodep->scopep();
@ -93,7 +93,7 @@ private:
iterateChildren(nodep);
}
//----
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
// Consumption/generation of a variable,
AstVarScope* vscp = nodep->varScopep();
UASSERT_OBJ(vscp, nodep, "Scope not assigned");
@ -105,23 +105,23 @@ private:
AstVarScope* newvscp = genInpClk(vscp);
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->lvalue());
nodep->replaceWith(newrefp);
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
m_activep = nodep;
UASSERT_OBJ(nodep->sensesp(), nodep, "Unlinked");
iterateChildren(nodep->sensesp()); // iterateAndNext?
m_activep = NULL;
iterateChildren(nodep);
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
//-----
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -152,7 +152,7 @@ private:
AstNodeModule* m_topModp; // Top module
// VISITORS
virtual void visit(AstTopScope* nodep) {
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
AstNode::user1ClearTree(); // user1p() used on entire tree
iterateChildren(nodep);
{
@ -161,14 +161,14 @@ private:
GenClkRenameVisitor visitor (nodep, m_topModp);
}
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Only track the top scopes, not lower level functions
if (nodep->isTop()) {
m_topModp = nodep;
iterateChildren(nodep);
}
}
virtual void visit(AstCCall* nodep) {
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (!nodep->funcp()->entryPoint()) {
// Enter the function and trace it
@ -176,7 +176,7 @@ private:
iterate(nodep->funcp());
}
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
if (!m_tracingCall && !nodep->entryPoint()) {
// Only consider logic within a CFunc when looking
// at the call to it, and not when scanning whatever
@ -188,7 +188,7 @@ private:
}
//----
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
// Consumption/generation of a variable,
AstVarScope* vscp = nodep->varScopep();
UASSERT_OBJ(vscp, nodep, "Scope not assigned");
@ -203,13 +203,13 @@ private:
vscp->circular(true);
}
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
//UINFO(8,"ASS "<<nodep<<endl);
m_assignp = nodep;
iterateChildren(nodep);
m_assignp = NULL;
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
UINFO(8,"ACTIVE "<<nodep<<endl);
m_activep = nodep;
UASSERT_OBJ(nodep->sensesp(), nodep, "Unlinked");
@ -219,8 +219,8 @@ private:
}
//-----
virtual void visit(AstVar*) {} // Don't want varrefs under it
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't want varrefs under it
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

86
src/V3Global.cpp Normal file
View File

@ -0,0 +1,86 @@
// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Common implemenetations
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2004-2020 by Wilson Snyder. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
//
// Verilator is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//*************************************************************************
#include "config_build.h"
#include "verilatedos.h"
#include "V3Global.h"
#include "V3Ast.h"
#include "V3File.h"
#include "V3LinkCells.h"
#include "V3Parse.h"
#include "V3ParseSym.h"
#include "V3Stats.h"
//######################################################################
// V3 Class -- top level
AstNetlist* V3Global::makeNetlist() {
AstNetlist* newp = new AstNetlist();
newp->addTypeTablep(new AstTypeTable(newp->fileline()));
return newp;
}
void V3Global::checkTree() { rootp()->checkTree(); }
void V3Global::clear() {
if (m_rootp) VL_DO_CLEAR(m_rootp->deleteTree(), m_rootp = NULL);
}
void V3Global::readFiles() {
// NODE STATE
// AstNode::user4p() // VSymEnt* Package and typedef symbol names
AstUser4InUse inuser4;
VInFilter filter(v3Global.opt.pipeFilter());
V3ParseSym parseSyms(v3Global.rootp()); // Symbol table must be common across all parsing
V3Parse parser(v3Global.rootp(), &filter, &parseSyms);
// Read top module
const V3StringList& vFiles = v3Global.opt.vFiles();
for (V3StringList::const_iterator it = vFiles.begin(); it != vFiles.end(); ++it) {
string filename = *it;
parser.parseFile(new FileLine(FileLine::commandLineFilename()), filename, false,
"Cannot find file containing module: ");
}
// Read libraries
// To be compatible with other simulators,
// this needs to be done after the top file is read
const V3StringSet& libraryFiles = v3Global.opt.libraryFiles();
for (V3StringSet::const_iterator it = libraryFiles.begin(); it != libraryFiles.end(); ++it) {
string filename = *it;
parser.parseFile(new FileLine(FileLine::commandLineFilename()), filename, true,
"Cannot find file containing library module: ");
}
// v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree"));
V3Error::abortIfErrors();
if (!v3Global.opt.preprocOnly()) {
// Resolve all modules cells refer to
V3LinkCells::link(v3Global.rootp(), &filter, &parseSyms);
}
}
void V3Global::dumpCheckGlobalTree(const string& stagename, int newNumber, bool doDump) {
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename(stagename + ".tree", newNumber),
false, doDump);
if (v3Global.opt.stats()) V3Stats::statsStage(stagename);
}

View File

@ -55,10 +55,16 @@ public:
inline VWidthMinUsage(en _e) : m_e(_e) {}
explicit inline VWidthMinUsage(int _e) : m_e(static_cast<en>(_e)) {}
operator en() const { return m_e; }
};
inline bool operator==(VWidthMinUsage lhs, VWidthMinUsage rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(VWidthMinUsage lhs, VWidthMinUsage::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(VWidthMinUsage::en lhs, VWidthMinUsage rhs) { return (lhs == rhs.m_e); }
};
inline bool operator==(const VWidthMinUsage& lhs, const VWidthMinUsage& rhs) {
return lhs.m_e == rhs.m_e;
}
inline bool operator==(const VWidthMinUsage& lhs, VWidthMinUsage::en rhs) {
return lhs.m_e == rhs;
}
inline bool operator==(VWidthMinUsage::en lhs, const VWidthMinUsage& rhs) {
return lhs == rhs.m_e;
}
//######################################################################
// V3Global - The top level class for the entire program

View File

@ -224,7 +224,7 @@ void V3Graph::clear() {
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; /*BELOW*/) {
V3GraphEdge* nextp = edgep->outNextp();
delete edgep;
VL_DO_DANGLING(delete edgep, edgep);
edgep = nextp;
}
vertexp->outUnlink();
@ -232,7 +232,7 @@ void V3Graph::clear() {
// Delete the old vertices
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; /*BELOW*/) {
V3GraphVertex* nextp = vertexp->verticesNextp();
delete vertexp;
VL_DO_DANGLING(delete vertexp, vertexp);
vertexp = nextp;
}
verticesUnlink();

View File

@ -65,15 +65,15 @@ public:
const char* ascii() const {
static const char* const names[] = { "FORWARD", "REVERSE" };
return names[m_e];
};
}
// METHODS unique to this class
GraphWay invert() const { return m_e == FORWARD ? REVERSE : FORWARD; }
bool forward() const { return m_e == FORWARD; }
bool reverse() const { return m_e != FORWARD; }
};
inline bool operator==(GraphWay lhs, GraphWay rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(GraphWay lhs, GraphWay::en rhs) { return (lhs.m_e == rhs); }
inline bool operator==(GraphWay::en lhs, GraphWay rhs) { return (lhs == rhs.m_e); }
inline bool operator==(const GraphWay& lhs, const GraphWay& rhs) { return lhs.m_e == rhs.m_e; }
inline bool operator==(const GraphWay& lhs, GraphWay::en rhs) { return lhs.m_e == rhs; }
inline bool operator==(GraphWay::en lhs, const GraphWay& rhs) { return lhs == rhs.m_e; }
//============================================================================
@ -104,6 +104,7 @@ public:
// METHODS
void clear(); // Empty it of all vertices/edges, as if making a new object
void clearColors();
bool empty() const { return m_vertices.empty(); }
V3GraphVertex* verticesBeginp() const { return m_vertices.begin(); }
@ -270,7 +271,7 @@ class V3GraphEdge {
// Wires/variables aren't edges. Edges have only a single to/from vertex
public:
// ENUMS
enum Cuttable { NOT_CUTABLE = false, CUTABLE = true }; // For passing to V3GraphEdge
enum Cutable { NOT_CUTABLE = false, CUTABLE = true }; // For passing to V3GraphEdge
protected:
friend class V3Graph; friend class V3GraphVertex;
friend class GraphAcyc; friend class GraphAcycEdge;

View File

@ -275,7 +275,7 @@ void GraphAcyc::deleteMarked() {
nextp = vertexp->verticesNextp();
GraphAcycVertex* avertexp = static_cast<GraphAcycVertex*>(vertexp);
if (avertexp->isDelete()) {
avertexp->unlinkDelete(&m_breakGraph); VL_DANGLING(avertexp);
VL_DO_DANGLING(avertexp->unlinkDelete(&m_breakGraph), avertexp);
}
}
}
@ -291,13 +291,13 @@ void GraphAcyc::simplifyNone(GraphAcycVertex* avertexp) {
while (V3GraphEdge* edgep = avertexp->outBeginp()) {
V3GraphVertex* otherVertexp = edgep->top();
//UINFO(9," out "<<otherVertexp<<endl);
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
workPush(otherVertexp);
}
while (V3GraphEdge* edgep = avertexp->inBeginp()) {
V3GraphVertex* otherVertexp = edgep->fromp();
//UINFO(9," in "<<otherVertexp<<endl);
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
workPush(otherVertexp);
}
}
@ -328,8 +328,8 @@ void GraphAcyc::simplifyOne(GraphAcycVertex* avertexp) {
// cppcheck-suppress leakReturnValNotUsed
edgeFromEdge(templateEdgep, inVertexp, outVertexp);
// Remove old edge
inEdgep->unlinkDelete(); VL_DANGLING(inEdgep);
outEdgep->unlinkDelete(); VL_DANGLING(outEdgep); VL_DANGLING(templateEdgep);
VL_DO_DANGLING(inEdgep->unlinkDelete(), inEdgep);
VL_DO_DANGLING(outEdgep->unlinkDelete(), outEdgep); VL_DANGLING(templateEdgep);
workPush(inVertexp);
workPush(outVertexp);
}
@ -363,10 +363,10 @@ void GraphAcyc::simplifyOut(GraphAcycVertex* avertexp) {
// cppcheck-suppress leakReturnValNotUsed
edgeFromEdge(inEdgep, inVertexp, outVertexp);
// Remove old edge
inEdgep->unlinkDelete(); VL_DANGLING(inEdgep);
VL_DO_DANGLING(inEdgep->unlinkDelete(), inEdgep);
workPush(inVertexp);
}
outEdgep->unlinkDelete(); VL_DANGLING(outEdgep);
VL_DO_DANGLING(outEdgep->unlinkDelete(), outEdgep);
workPush(outVertexp);
}
}
@ -389,18 +389,18 @@ void GraphAcyc::simplifyDup(GraphAcycVertex* avertexp) {
// !cutable duplicates prev !cutable: we can ignore it, redundant
// cutable duplicates prev !cutable: know it's not a relevant loop, ignore it
UINFO(8," DelDupEdge "<<avertexp<<" -> "<<edgep->top()<<endl);
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
} else if (!edgep->cutable()) {
// !cutable duplicates prev cutable: delete the earlier cutable
UINFO(8," DelDupPrev "<<avertexp<<" -> "<<prevEdgep->top()<<endl);
prevEdgep->unlinkDelete(); VL_DANGLING(prevEdgep);
VL_DO_DANGLING(prevEdgep->unlinkDelete(), prevEdgep);
outVertexp->userp(edgep);
} else {
// cutable duplicates prev cutable: combine weights
UINFO(8," DelDupComb "<<avertexp<<" -> "<<edgep->top()<<endl);
prevEdgep->weight(prevEdgep->weight() + edgep->weight());
addOrigEdgep(prevEdgep, edgep);
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
}
workPush(outVertexp);
workPush(avertexp);
@ -418,7 +418,7 @@ void GraphAcyc::cutBasic(GraphAcycVertex* avertexp) {
nextp = edgep->outNextp();
if (edgep->cutable() && edgep->top()==avertexp) {
cutOrigEdge(edgep, " Cut Basic");
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
workPush(avertexp);
}
}
@ -439,7 +439,7 @@ void GraphAcyc::cutBackward(GraphAcycVertex* avertexp) {
nextp = edgep->outNextp();
if (edgep->cutable() && edgep->top()->user()) {
cutOrigEdge(edgep, " Cut A->B->A");
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
workPush(avertexp);
}
}
@ -506,7 +506,7 @@ void GraphAcyc::placeTryEdge(V3GraphEdge* edgep) {
// Adding this edge would cause a loop, kill it
edgep->cutable(true); // So graph still looks pretty
cutOrigEdge(edgep, " Cut loop");
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
// Back out the ranks we calculated
while (GraphAcycVertex* vertexp = workBeginp()) {
workPop();

View File

@ -110,10 +110,10 @@ private:
}
if (saveOld) {
if (m_sumWeights) prevEdgep->weight(prevEdgep->weight() + edgep->weight());
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
} else {
if (m_sumWeights) edgep->weight(prevEdgep->weight() + edgep->weight());
prevEdgep->unlinkDelete(); VL_DANGLING(prevEdgep);
VL_DO_DANGLING(prevEdgep->unlinkDelete(), prevEdgep);
outVertexp->userp(edgep);
}
}
@ -150,9 +150,7 @@ public:
V3GraphEdge* deletep = NULL;
for (V3GraphEdge* edgep = vxp->outBeginp();
edgep; edgep = edgep->outNextp()) {
if (deletep) {
deletep->unlinkDelete(); deletep = NULL;
}
if (deletep) VL_DO_CLEAR(deletep->unlinkDelete(), deletep = NULL);
// It should be safe to modify the graph, despite using
// the GraphPathChecker, as none of the modifications will
// change what can be reached from what, nor should they
@ -162,7 +160,7 @@ public:
}
}
if (deletep) {
deletep->unlinkDelete(); VL_DANGLING(deletep);
VL_DO_DANGLING(deletep->unlinkDelete(), deletep);
}
}
}

View File

@ -354,7 +354,7 @@ private:
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
nextp = vertexp->verticesNextp();
if (nfaState(vertexp)) {
vertexp->unlinkDelete(m_graphp); VL_DANGLING(vertexp);
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
}
}
@ -409,7 +409,7 @@ private:
if (vvertexp->accepting()) {
for (V3GraphEdge* nextp,*edgep = vertexp->outBeginp(); edgep; edgep=nextp) {
nextp = edgep->outNextp();
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
}
}
}
@ -445,7 +445,7 @@ private:
for (V3GraphVertex* nextp,*vertexp = m_graphp->verticesBeginp(); vertexp; vertexp=nextp) {
nextp = vertexp->verticesNextp();
if (!vertexp->user()) {
vertexp->unlinkDelete(m_graphp); VL_DANGLING(vertexp);
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
}
}
}
@ -487,7 +487,7 @@ private:
}
}
// Transitions to this state removed by the unlink function
vertexp->unlinkDelete(m_graphp); VL_DANGLING(vertexp);
VL_DO_DANGLING(vertexp->unlinkDelete(m_graphp), vertexp);
}
}
}
@ -566,7 +566,7 @@ private:
DfaVertex* tovertexp = static_cast<DfaVertex*>(edgep->top());
if (tovertexp->accepting()) {
new DfaEdge(graphp(), vvertexp, m_tempNewerReject, vedgep);
edgep->unlinkDelete(); VL_DANGLING(edgep);
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
}
// NOT of all values goes to accept
@ -595,10 +595,11 @@ public:
add_complement_edges();
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_preswap");
m_tempNewerReject->unlinkDelete(graphp()); m_tempNewerReject = NULL;
VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = NULL);
if (debug()>=6) m_graphp->dumpDotFilePrefixed("comp_out");
}
~DfaGraphComplement() {}
VL_UNCOPYABLE(DfaGraphComplement);
};
void DfaGraph::dfaComplement() {

View File

@ -89,7 +89,7 @@ class DfaVertex : public V3GraphVertex {
bool m_accepting; // Accepting state?
public:
// CONSTRUCTORS
DfaVertex(DfaGraph* graphp, bool start=false, bool accepting=false)
explicit DfaVertex(DfaGraph* graphp, bool start=false, bool accepting=false)
: V3GraphVertex(graphp)
, m_start(start), m_accepting(accepting) {}
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)

View File

@ -73,7 +73,7 @@ GraphPathChecker::~GraphPathChecker() {
for (V3GraphVertex* vxp = m_graphp->verticesBeginp();
vxp; vxp = vxp->verticesNextp()) {
GraphPCNode* nodep = static_cast<GraphPCNode*>(vxp->userp());
delete nodep; VL_DANGLING(nodep);
VL_DO_DANGLING(delete nodep, nodep);
vxp->userp(NULL);
}
}

View File

@ -42,8 +42,8 @@ class GraphPathChecker : GraphAlg<const V3Graph> {
public:
// CONSTRUCTORS
GraphPathChecker(const V3Graph* graphp,
V3EdgeFuncP edgeFuncp = V3GraphEdge::followAlwaysTrue);
explicit GraphPathChecker(const V3Graph* graphp,
V3EdgeFuncP edgeFuncp = V3GraphEdge::followAlwaysTrue);
~GraphPathChecker();
// METHODS

View File

@ -95,9 +95,9 @@ private:
public:
// CONSTRUCTORS
GraphStream(const V3Graph* graphp,
GraphWay way = GraphWay::FORWARD,
const T_Compare& lessThan = T_Compare())
explicit GraphStream(const V3Graph* graphp,
GraphWay way = GraphWay::FORWARD,
const T_Compare& lessThan = T_Compare())
// NOTE: Perhaps REVERSE way should also reverse the sense of the
// lessThan function? For now the only usage of REVERSE is not
// sensitive to its lessThan at all, so it doesn't matter.

View File

@ -88,10 +88,10 @@ private:
//--------------------
// Default: Just iterate
virtual void visit(AstVar*) {}
virtual void visit(AstTypedef*) {}
virtual void visit(AstParamTypeDType*) {}
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar*) VL_OVERRIDE {}
virtual void visit(AstTypedef*) VL_OVERRIDE {}
virtual void visit(AstParamTypeDType*) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
nodeHashIterate(nodep);
}

View File

@ -100,7 +100,8 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
UASSERT_OBJ(!m_modp, nodep, "Unsupported: Recursive modules");
m_modp = nodep;
m_allMods.push_back(nodep);
m_modp->user2(CIL_MAYBE);
@ -115,12 +116,12 @@ private:
iterateChildren(nodep);
m_modp = NULL;
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
nodep->modp()->user3Inc(); // Inc refs
m_instances[m_modp][nodep->modp()]++;
iterateChildren(nodep);
}
virtual void visit(AstPragma* nodep) {
virtual void visit(AstPragma* nodep) VL_OVERRIDE {
if (nodep->pragType() == AstPragmaType::INLINE_MODULE) {
//UINFO(0,"PRAG MARK "<<m_modp<<endl);
if (!m_modp) {
@ -129,39 +130,41 @@ private:
|| m_modp->user2() == CIL_NOTSOFT) {
m_modp->user2(CIL_USER);
}
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); // Remove so don't propagate to upper cell...
// Remove so don't propagate to upper cell...
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else if (nodep->pragType() == AstPragmaType::NO_INLINE_MODULE) {
if (!m_modp) {
nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE
} else {
cantInline("Pragma NO_INLINE_MODULE", false);
}
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); // Remove so don't propagate to upper cell...
// Remove so don't propagate to upper cell...
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else {
iterateChildren(nodep);
}
}
virtual void visit(AstVarXRef* nodep) {
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
// Cleanup link until V3LinkDot can correct it
nodep->varp(NULL);
}
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
// Cleanup link until V3LinkDot can correct it
if (!nodep->packagep()) nodep->taskp(NULL);
iterateChildren(nodep);
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
iterateChildren(nodep);
m_modp->user4Inc(); // statement count
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
// Don't count assignments, as they'll likely flatten out
// Still need to iterate though to nullify VarXRefs
int oldcnt = m_modp->user4();
iterateChildren(nodep);
m_modp->user4(oldcnt);
}
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Build user2, user3, and user4 for all modules.
// Also build m_allMods and m_instances.
iterateChildren(nodep);
@ -175,10 +178,10 @@ private:
// update user4 (statement count) to reflect that:
int statements = modp->user4();
LocalInstanceMap& localsr = m_instances[modp];
for (LocalInstanceMap::iterator it = localsr.begin(); it != localsr.end(); ++it) {
AstNodeModule* childp = it->first;
for (LocalInstanceMap::iterator iti = localsr.begin(); iti != localsr.end(); ++iti) {
AstNodeModule* childp = iti->first;
if (childp->user1()) { // inlining child
statements += (childp->user4() * it->second);
statements += (childp->user4() * iti->second);
}
}
modp->user4(statements);
@ -204,7 +207,7 @@ private:
}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_modp) {
m_modp->user4Inc(); // Inc statement count
@ -240,13 +243,13 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
nodep->user4p(nodep->clonep());
}
// Accelerate
virtual void visit(AstNodeStmt* nodep) {}
virtual void visit(AstNodeMath* nodep) {}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {}
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
@ -278,7 +281,7 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstCellInline* nodep) {
virtual void visit(AstCellInline* nodep) VL_OVERRIDE {
// Inlined cell under the inline cell, need to move to avoid conflicts
nodep->unlinkFrBack();
m_modp->addInlinesp(nodep);
@ -289,17 +292,17 @@ private:
// Do CellInlines under this, but don't move them
iterateChildren(nodep);
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
// Cell under the inline cell, need to rename to avoid conflicts
string name = m_cellp->name() + "__DOT__" + nodep->name();
nodep->name(name);
iterateChildren(nodep);
}
virtual void visit(AstModule* nodep) {
virtual void visit(AstModule* nodep) VL_OVERRIDE {
m_renamedInterfaces.clear();
iterateChildren(nodep);
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
if (nodep->user2p()) {
// Make an assignment, so we'll trace it properly
// user2p is either a const or a var.
@ -383,17 +386,17 @@ private:
if (debug()>=9 && nodep->valuep()) { nodep->valuep()->dumpTree(cout, "varchangei:"); }
iterateChildren(nodep);
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
// Function under the inline cell, need to rename to avoid conflicts
nodep->name(m_cellp->name() + "__DOT__" + nodep->name());
iterateChildren(nodep);
}
virtual void visit(AstTypedef* nodep) {
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
// Typedef under the inline cell, need to rename to avoid conflicts
nodep->name(m_cellp->name() + "__DOT__" + nodep->name());
iterateChildren(nodep);
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (nodep->varp()->user2p() // It's being converted to an alias.
&& !nodep->varp()->user3()
&& !VN_IS(nodep->backp(), AssignAlias)) { // Don't constant propagate aliases (we just made)
@ -401,7 +404,7 @@ private:
AstVarRef* exprvarrefp = VN_CAST(nodep->varp()->user2p(), VarRef);
if (exprconstp) {
nodep->replaceWith(exprconstp->cloneTree(true));
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
return;
}
else if (exprvarrefp) {
@ -414,7 +417,7 @@ private:
nodep->name(nodep->varp()->name());
iterateChildren(nodep);
}
virtual void visit(AstVarXRef* nodep) {
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
// Track what scope it was originally under so V3LinkDot can resolve it
string newdots = VString::dot(m_cellp->name(), ".", nodep->inlinedDots());
nodep->inlinedDots(newdots);
@ -433,7 +436,7 @@ private:
}
iterateChildren(nodep);
}
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
// Track what scope it was originally under so V3LinkDot can resolve it
string newdots = VString::dot(m_cellp->name(), ".", nodep->inlinedDots());
nodep->inlinedDots(newdots);
@ -445,9 +448,9 @@ private:
}
// Not needed, as V3LinkDot doesn't care about typedefs
//virtual void visit(AstRefDType* nodep) {}
//virtual void visit(AstRefDType* nodep) VL_OVERRIDE {}
virtual void visit(AstScopeName* nodep) {
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
// If there's a %m in the display text, we add a special node that will contain the name()
// Similar code in V3Begin
// To keep correct visual order, must add before other Text's
@ -461,12 +464,12 @@ private:
if (afterp) nodep->scopeEntrp(afterp);
iterateChildren(nodep);
}
virtual void visit(AstCoverDecl* nodep) {
virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE {
// Fix path in coverage statements
nodep->hier(VString::dot(m_cellp->prettyName(), ".", nodep->hier()));
iterateChildren(nodep);
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
@ -510,11 +513,11 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Iterate modules backwards, in bottom-up order. Required!
iterateChildrenBackwards(nodep);
}
virtual void visit(AstIfaceRefDType* nodep) {
virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE {
if (nodep->user5()) {
// The cell has been removed so let's make sure we don't leave a reference to it
// This dtype may still be in use by the AstAssignVarScope created earlier
@ -522,11 +525,15 @@ private:
nodep->cellp(NULL);
}
}
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
iterateChildren(nodep);
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
if (nodep->modp()->user1()) { // Marked with inline request
UINFO(5," Inline CELL "<<nodep<<endl);
UINFO(5," To MOD "<<m_modp<<endl);
@ -597,17 +604,17 @@ private:
if (stmtsp) stmtsp->unlinkFrBackWithNext();
if (stmtsp) m_modp->addStmtp(stmtsp);
// Remove the cell
newmodp->deleteTree(); VL_DANGLING(newmodp); // Clear any leftover ports, etc
VL_DO_DANGLING(newmodp->deleteTree(), newmodp); // Clear any leftover ports, etc
nodep->unlinkFrBack();
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
if (debug()>=9) { m_modp->dumpTree(cout, "donemod:"); }
}
}
//--------------------
virtual void visit(AstNodeMath* nodep) {} // Accelerate
virtual void visit(AstNodeStmt* nodep) {} // Accelerate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
@ -638,17 +645,17 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
virtual void visit(AstModule* nodep) {
virtual void visit(AstModule* nodep) VL_OVERRIDE {
if (nodep->isTop()) {
iterateChildren(nodep);
}
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
string oldScope = m_scope;
if (m_scope.empty()) {
m_scope = nodep->name();
@ -684,7 +691,7 @@ private:
m_scope = oldScope;
}
virtual void visit(AstAssignVarScope* nodep) {
virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE {
// Reference
AstVarRef* reflp = VN_CAST(nodep->lhsp(), VarRef);
// What the reference refers to
@ -710,9 +717,9 @@ private:
}
//--------------------
virtual void visit(AstNodeMath*) {} // Accelerate
virtual void visit(AstNodeStmt*) {} // Accelerate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
@ -746,7 +753,7 @@ void V3Inline::inlineAll(AstNetlist* nodep) {
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp; modp=nextmodp) {
nextmodp = VN_CAST(modp->nextp(), NodeModule);
if (modp->user1()) { // Was inlined
modp->unlinkFrBack()->deleteTree(); VL_DANGLING(modp);
VL_DO_DANGLING(modp->unlinkFrBack()->deleteTree(), modp);
}
}
{

View File

@ -54,7 +54,7 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
UINFO(4," CELL "<<nodep<<endl);
m_cellp = nodep;
//VV***** We reset user1p() on each cell!!!
@ -62,7 +62,7 @@ private:
iterateChildren(nodep);
m_cellp = NULL;
}
virtual void visit(AstPin* nodep) {
virtual void visit(AstPin* nodep) VL_OVERRIDE {
// PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input)
// or ASSIGNW(expr,VARXREF(p)) (if sub's output)
UINFO(4," PIN "<<nodep<<endl);
@ -113,10 +113,10 @@ private:
}
// We're done with the pin
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
virtual void visit(AstUdpTable* nodep) {
virtual void visit(AstUdpTable* nodep) VL_OVERRIDE {
if (!v3Global.opt.bboxUnsup()) {
// If we support primitives, update V3Undriven to remove special case
nodep->v3error("Unsupported: Verilog 1995 UDP Tables. Use --bbox-unsup to ignore tables.");
@ -124,13 +124,13 @@ private:
}
// Save some time
virtual void visit(AstNodeMath*) {}
virtual void visit(AstNodeAssign*) {}
virtual void visit(AstAlways*) {}
virtual void visit(AstNodeMath*) VL_OVERRIDE {}
virtual void visit(AstNodeAssign*) VL_OVERRIDE {}
virtual void visit(AstAlways*) VL_OVERRIDE {}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -155,7 +155,7 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
if (VN_IS(nodep->dtypep(), IfaceRefDType)) {
UINFO(8," dm-1-VAR "<<nodep<<endl);
insert(nodep);
@ -163,9 +163,9 @@ private:
iterateChildren(nodep);
}
// Save some time
virtual void visit(AstNodeMath*) {}
virtual void visit(AstNodeMath*) VL_OVERRIDE {}
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -213,7 +213,7 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
if (VN_IS(nodep->dtypep(), UnpackArrayDType)
&& VN_IS(VN_CAST(nodep->dtypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) {
UINFO(8," dv-vec-VAR "<<nodep<<endl);
@ -246,7 +246,7 @@ private:
iterateChildren(nodep);
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
UINFO(4," CELL "<<nodep<<endl);
// Find submodule vars
UASSERT_OBJ(nodep->modp(), nodep, "Unlinked");
@ -303,16 +303,17 @@ private:
// Done. Delete original
m_cellRangep = NULL;
if (isIface) {
ifaceVarp->unlinkFrBack(); pushDeletep(ifaceVarp); VL_DANGLING(ifaceVarp);
ifaceVarp->unlinkFrBack();
VL_DO_DANGLING(pushDeletep(ifaceVarp), ifaceVarp);
}
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else {
m_cellRangep = NULL;
iterateChildren(nodep);
}
}
virtual void visit(AstPin* nodep) {
virtual void visit(AstPin* nodep) VL_OVERRIDE {
// Any non-direct pins need reconnection with a part-select
if (!nodep->exprp()) return; // No-connect
if (m_cellRangep) {
@ -379,7 +380,7 @@ private:
newp->dtypep(nodep->modVarp()->dtypep());
newp->packagep(varrefp->packagep());
arrselp->addNextHere(newp);
arrselp->unlinkFrBack()->deleteTree();
VL_DO_DANGLING(arrselp->unlinkFrBack()->deleteTree(), arrselp);
}
} else {
AstVar* pinVarp = nodep->modVarp();
@ -446,10 +447,10 @@ private:
}
// Save some time
virtual void visit(AstNodeMath*) {}
virtual void visit(AstNodeMath*) VL_OVERRIDE {}
//--------------------
// Default: Just iterate
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -124,7 +124,7 @@ private:
}
// VISITORS
virtual void visit(AstNodeSel* nodep) {
virtual void visit(AstNodeSel* nodep) VL_OVERRIDE {
// This covers both AstArraySel and AstWordSel
//
// If some vector is a bazillion dwords long, and we're selecting 1
@ -135,7 +135,7 @@ private:
VisitBase vb(this, nodep);
iterateAndNextNull(nodep->bitp());
}
virtual void visit(AstSel* nodep) {
virtual void visit(AstSel* nodep) VL_OVERRIDE {
// Similar to AstNodeSel above, a small select into a large vector
// is not expensive. Count the cost of the AstSel itself (scales with
// its width) and the cost of the lsbp() and widthp() nodes, but not
@ -144,13 +144,13 @@ private:
iterateAndNextNull(nodep->lsbp());
iterateAndNextNull(nodep->widthp());
}
virtual void visit(AstSliceSel* nodep) {
virtual void visit(AstSliceSel* nodep) VL_OVERRIDE {
nodep->v3fatalSrc("AstSliceSel unhandled");
}
virtual void visit(AstMemberSel* nodep) {
virtual void visit(AstMemberSel* nodep) VL_OVERRIDE {
nodep->v3fatalSrc("AstMemberSel unhandled");
}
virtual void visit(AstConcat* nodep) {
virtual void visit(AstConcat* nodep) VL_OVERRIDE {
// Nop.
//
// Ignore concat. The problem with counting concat is that when we
@ -170,7 +170,7 @@ private:
// the widths of the operands (ignored here).
markCost(nodep);
}
virtual void visit(AstNodeIf* nodep) {
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
VisitBase vb(this, nodep);
iterateAndNextNull(nodep->condp());
uint32_t savedCount = m_instrCount;
@ -195,7 +195,7 @@ private:
if (nodep->ifsp()) nodep->ifsp()->user4(0); // Don't dump it
}
}
virtual void visit(AstNodeCond* nodep) {
virtual void visit(AstNodeCond* nodep) VL_OVERRIDE {
// Just like if/else above, the ternary operator only evaluates
// one of the two expressions, so only count the max.
VisitBase vb(this, nodep);
@ -220,7 +220,7 @@ private:
if (nodep->expr2p()) nodep->expr2p()->user4(0); // Don't dump it
}
}
virtual void visit(AstActive* nodep) {
virtual void visit(AstActive* nodep) VL_OVERRIDE {
// You'd think that the OrderLogicVertex's would be disjoint trees
// of stuff in the AST, but it isn't so: V3Order makes an
// OrderLogicVertex for each ACTIVE, and then also makes an
@ -236,14 +236,14 @@ private:
markCost(nodep);
UASSERT_OBJ(nodep == m_startNodep, nodep, "Multiple actives, or not start node");
}
virtual void visit(AstCCall* nodep) {
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
VisitBase vb(this, nodep);
iterateChildren(nodep);
m_tracingCall = true;
iterate(nodep->funcp());
UASSERT_OBJ(!m_tracingCall, nodep, "visit(AstCFunc) should have cleared m_tracingCall.");
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
// Don't count a CFunc other than by tracing a call or counting it
// from the root
UASSERT_OBJ(m_tracingCall || nodep == m_startNodep, nodep,
@ -257,7 +257,7 @@ private:
}
m_inCFunc = saved_inCFunc;
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
VisitBase vb(this, nodep);
iterateChildren(nodep);
}
@ -289,7 +289,7 @@ public:
private:
// METHODS
string indent() { return string(m_depth, ':')+" "; }
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
++m_depth;
if (unsigned costPlus1 = nodep->user4()) {
*m_osp <<" "<<indent()

View File

@ -59,7 +59,7 @@ public:
"1800-2017"
};
return names[m_e];
};
}
static V3LangCode mostRecent() { return V3LangCode(L1800_2017); }
bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009
|| m_e == L1800_2012 || m_e == L1800_2017; }

View File

@ -158,7 +158,7 @@ public:
// above our current iteration point.
if (debug()>4) oldassp->dumpTree(cout, " REMOVE/SAMEBLK ");
entp->complexAssign();
m_statep->pushUnlinkDeletep(oldassp); VL_DANGLING(oldassp);
VL_DO_DANGLING(m_statep->pushUnlinkDeletep(oldassp), oldassp);
++m_statep->m_statAssnDel;
}
}
@ -195,7 +195,7 @@ public:
// We'll later constant propagate
UINFO(4," replaceconst: "<<varrefp<<endl);
varrefp->replaceWith(constp->cloneTree(false));
varrefp->deleteTree(); VL_DANGLING(varrefp);
VL_DO_DANGLING(varrefp->deleteTree(), varrefp);
++m_statep->m_statAssnCon;
return; // **DONE, no longer a var reference**
}
@ -296,7 +296,7 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
// Consumption/generation of a variable,
// it's used so can't elim assignment before this use.
UASSERT_OBJ(nodep->varScopep(), nodep, "NULL");
@ -307,10 +307,10 @@ private:
m_sideEffect = true; // $sscanf etc may have RHS vars that are lvalues
m_lifep->complexAssign(vscp);
} else {
m_lifep->varUsageReplace(vscp, nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(m_lifep->varUsageReplace(vscp, nodep), nodep);
}
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
// Collect any used variables first, as lhs may also be on rhs
// Similar code in V3Dead
vluint64_t lastEdit = AstNode::editCountGbl(); // When it was last edited
@ -330,13 +330,13 @@ private:
iterateAndNextNull(nodep->lhsp());
}
}
virtual void visit(AstAssignDly* nodep) {
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
// Don't treat as normal assign; V3Life doesn't understand time sense
iterateChildren(nodep);
}
//---- Track control flow changes
virtual void visit(AstNodeIf* nodep) {
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
UINFO(4," IF "<<nodep<<endl);
// Condition is part of PREVIOUS block
iterateAndNextNull(nodep->condp());
@ -358,11 +358,11 @@ private:
// For the next assignments, clear any variables that were read or written in the block
ifLifep->lifeToAbove();
elseLifep->lifeToAbove();
delete ifLifep;
delete elseLifep;
VL_DO_DANGLING(delete ifLifep, ifLifep);
VL_DO_DANGLING(delete elseLifep, elseLifep);
}
virtual void visit(AstWhile* nodep) {
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
// While's are a problem, as we don't allow loops in the graph. We
// may go around the cond/body multiple times. Thus a
// lifelication just in the body is ok, but we can't delete an
@ -388,10 +388,10 @@ private:
// For the next assignments, clear any variables that were read or written in the block
condLifep->lifeToAbove();
bodyLifep->lifeToAbove();
delete condLifep;
delete bodyLifep;
VL_DO_DANGLING(delete condLifep, condLifep);
VL_DO_DANGLING(delete bodyLifep, bodyLifep);
}
virtual void visit(AstJumpLabel* nodep) {
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
// As with While's we can't predict if a JumpGo will kill us or not
// It's worse though as an IF(..., JUMPGO) may change the control flow.
// Just don't optimize blocks with labels; they're rare - so far.
@ -408,9 +408,9 @@ private:
UINFO(4," joinjump"<<endl);
// For the next assignments, clear any variables that were read or written in the block
bodyLifep->lifeToAbove();
delete bodyLifep;
VL_DO_DANGLING(delete bodyLifep, bodyLifep);
}
virtual void visit(AstCCall* nodep) {
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
//UINFO(4," CCALL "<<nodep<<endl);
iterateChildren(nodep);
// Enter the function and trace it
@ -419,8 +419,8 @@ private:
iterate(nodep->funcp());
}
}
virtual void visit(AstCFunc* nodep) {
//UINFO(4," CCALL "<<nodep<<endl);
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
//UINFO(4," CFUNC "<<nodep<<endl);
if (!m_tracingCall && !nodep->entryPoint()) return;
m_tracingCall = false;
if (nodep->dpiImport() && !nodep->pure()) {
@ -428,17 +428,17 @@ private:
}
iterateChildren(nodep);
}
virtual void visit(AstUCFunc* nodep) {
virtual void visit(AstUCFunc* nodep) VL_OVERRIDE {
m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment
iterateChildren(nodep);
}
virtual void visit(AstCMath* nodep) {
virtual void visit(AstCMath* nodep) VL_OVERRIDE {
m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment
iterateChildren(nodep);
}
virtual void visit(AstVar*) {} // Don't want varrefs under it
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't want varrefs under it
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
@ -453,11 +453,11 @@ public:
{
m_lifep = new LifeBlock(NULL, m_statep);
iterate(nodep);
if (m_lifep) { delete m_lifep; m_lifep = NULL; }
if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = NULL);
}
}
virtual ~LifeVisitor() {
if (m_lifep) { delete m_lifep; m_lifep = NULL; }
if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = NULL);
}
VL_UNCOPYABLE(LifeVisitor);
};
@ -472,28 +472,28 @@ private:
LifeState* m_statep; // Current state
// VISITORS
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
if (nodep->entryPoint()) {
// Usage model 1: Simulate all C code, doing lifetime analysis
LifeVisitor visitor (nodep, m_statep);
}
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
// Usage model 2: Cleanup basic blocks
LifeVisitor visitor (nodep, m_statep);
}
virtual void visit(AstInitial* nodep) {
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
// Usage model 2: Cleanup basic blocks
LifeVisitor visitor (nodep, m_statep);
}
virtual void visit(AstFinal* nodep) {
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
// Usage model 2: Cleanup basic blocks
LifeVisitor visitor (nodep, m_statep);
}
virtual void visit(AstVar*) {} // Accelerate
virtual void visit(AstNodeStmt*) {} // Accelerate
virtual void visit(AstNodeMath*) {} // Accelerate
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -58,21 +58,21 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITORS
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
AstVarScope* vscp = nodep->varScopep();
UASSERT_OBJ(vscp, nodep, "Scope not assigned");
if (AstVarScope* newvscp = reinterpret_cast<AstVarScope*>(vscp->user4p())) {
UINFO(9, " Replace "<<nodep<<" to "<<newvscp<<endl);
AstVarRef* newrefp = new AstVarRef(nodep->fileline(), newvscp, nodep->lvalue());
nodep->replaceWith(newrefp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Only track the top scopes, not lower level functions
if (nodep->isTop()) iterateChildren(nodep);
}
virtual void visit(AstCCall* nodep) {
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (!nodep->funcp()->entryPoint()) {
// Enter the function and trace it
@ -80,18 +80,18 @@ private:
iterate(nodep->funcp());
}
}
virtual void visit(AstExecGraph* nodep) {
virtual void visit(AstExecGraph* nodep) VL_OVERRIDE {
// Can just iterate across the MTask bodies in any order. Order
// isn't important for LifePostElimVisitor's simple substitution.
iterateChildren(nodep);
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
if (!m_tracingCall && !nodep->entryPoint()) return;
m_tracingCall = false;
iterateChildren(nodep);
}
virtual void visit(AstVar*) {} // Don't want varrefs under it
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't want varrefs under it
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -253,13 +253,13 @@ private:
// Delete and mark so LifePostElimVisitor will get it
UINFO(4," DELETE "<<app->nodep<<endl);
dlyVarp->user4p(origVarp);
app->nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(app->nodep);
VL_DO_DANGLING(app->nodep->unlinkFrBack()->deleteTree(), app->nodep);
++m_statAssnDel;
}
}
// VISITORS
virtual void visit(AstTopScope* nodep) {
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
AstNode::user4ClearTree(); // user4p() used on entire tree
// First, build maps of every location (mtask and sequence
@ -284,7 +284,7 @@ private:
// Replace any node4p varscopes with the new scope
LifePostElimVisitor visitor (nodep);
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
// Consumption/generation of a variable,
AstVarScope* vscp = nodep->varScopep();
UASSERT_OBJ(vscp, nodep, "Scope not assigned");
@ -296,14 +296,14 @@ private:
m_reads[vscp].insert(loc);
}
}
virtual void visit(AstAssignPre* nodep) {
virtual void visit(AstAssignPre* nodep) VL_OVERRIDE {
// Do not record varrefs within assign pre.
//
// The pre-assignment into the dly var should not count as its
// first write; we only want to consider reads and writes that
// would still happen if the dly var were eliminated.
}
virtual void visit(AstAssignPost* nodep) {
virtual void visit(AstAssignPost* nodep) VL_OVERRIDE {
// Don't record ASSIGNPOST in the read/write maps, record them in a
// separate map
if (AstVarRef* rhsp = VN_CAST(nodep->rhsp(), VarRef)) {
@ -315,11 +315,11 @@ private:
m_assignposts[dlyVarp] = LifePostLocation(loc, nodep);
}
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Only track the top scopes, not lower level functions
if (nodep->isTop()) iterateChildren(nodep);
}
virtual void visit(AstCCall* nodep) {
virtual void visit(AstCCall* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (!nodep->funcp()->entryPoint()) {
// Enter the function and trace it
@ -327,7 +327,7 @@ private:
iterate(nodep->funcp());
}
}
virtual void visit(AstExecGraph* nodep) {
virtual void visit(AstExecGraph* nodep) VL_OVERRIDE {
// Treat the ExecGraph like a call to each mtask body
m_mtasksGraphp = nodep->depGraphp();
for (V3GraphVertex* mtaskVxp = m_mtasksGraphp->verticesBeginp();
@ -339,14 +339,14 @@ private:
}
m_execMTaskp = NULL;
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
if (!m_tracingCall && !nodep->entryPoint()) return;
m_tracingCall = false;
iterateChildren(nodep);
}
//-----
virtual void visit(AstVar*) {} // Don't want varrefs under it
virtual void visit(AstNode* nodep) {
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't want varrefs under it
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -158,7 +158,7 @@ private:
}
// VISITs
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
AstNode::user1ClearTree();
readModNames();
iterateChildren(nodep);
@ -190,45 +190,49 @@ private:
v3error("Specified --top-module '"<<v3Global.opt.topModule()<<"' was not found in design.");
}
}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Module: Pick up modnames, so we can resolve cells later
m_modp = nodep;
UINFO(2,"Link Module: "<<nodep<<endl);
if (nodep->fileline()->filebasenameNoExt() != nodep->prettyName()
&& !v3Global.opt.isLibraryFile(nodep->fileline()->filename())
&& !nodep->recursiveClone()
&& !nodep->internal()) {
// We only complain once per file, otherwise library-like files
// have a huge mess of warnings
if (m_declfnWarned.find(nodep->fileline()->filename()) == m_declfnWarned.end()) {
m_declfnWarned.insert(nodep->fileline()->filename());
nodep->v3warn(DECLFILENAME, "Filename '"<<nodep->fileline()->filebasenameNoExt()
<<"' does not match "<<nodep->typeName()
<<" name: "<<nodep->prettyNameQ());
AstNodeModule* oldModp = m_modp;
{
m_modp = nodep;
UINFO(2, "Link Module: " << nodep << endl);
if (nodep->fileline()->filebasenameNoExt() != nodep->prettyName()
&& !v3Global.opt.isLibraryFile(nodep->fileline()->filename())
&& !nodep->recursiveClone() && !nodep->internal()) {
// We only complain once per file, otherwise library-like files
// have a huge mess of warnings
if (m_declfnWarned.find(nodep->fileline()->filename()) == m_declfnWarned.end()) {
m_declfnWarned.insert(nodep->fileline()->filename());
nodep->v3warn(DECLFILENAME, "Filename '"
<< nodep->fileline()->filebasenameNoExt()
<< "' does not match " << nodep->typeName()
<< " name: " << nodep->prettyNameQ());
}
}
if (VN_IS(nodep, Iface) || VN_IS(nodep, Package)) {
nodep->inLibrary(true); // Interfaces can't be at top, unless asked
}
bool topMatch = (v3Global.opt.topModule() == nodep->prettyName());
if (topMatch) {
m_topVertexp = vertex(nodep);
UINFO(2, "Link --top-module: " << nodep << endl);
nodep->inLibrary(false); // Safer to make sure it doesn't disappear
}
if (v3Global.opt.topModule() == "" ? nodep->inLibrary() // Library cells are lower
: !topMatch) { // Any non-specified module is lower
// Put under a fake vertex so that the graph ranking won't indicate
// this is a top level module
if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph);
new V3GraphEdge(&m_graph, m_libVertexp, vertex(nodep), 1, false);
}
// Note AstBind also has iteration on cells
iterateChildren(nodep);
nodep->checkTree();
}
if (VN_IS(nodep, Iface) || VN_IS(nodep, Package)) nodep->inLibrary(true); // Interfaces can't be at top, unless asked
bool topMatch = (v3Global.opt.topModule()==nodep->prettyName());
if (topMatch) {
m_topVertexp = vertex(nodep);
UINFO(2,"Link --top-module: "<<nodep<<endl);
nodep->inLibrary(false); // Safer to make sure it doesn't disappear
}
if (v3Global.opt.topModule()==""
? nodep->inLibrary() // Library cells are lower
: !topMatch) { // Any non-specified module is lower
// Put under a fake vertex so that the graph ranking won't indicate
// this is a top level module
if (!m_libVertexp) m_libVertexp = new LibraryVertex(&m_graph);
new V3GraphEdge(&m_graph, m_libVertexp, vertex(nodep), 1, false);
}
// Note AstBind also has iteration on cells
iterateChildren(nodep);
nodep->checkTree();
m_modp = NULL;
m_modp = oldModp;
}
virtual void visit(AstIfaceRefDType* nodep) {
virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE {
// Cell: Resolve its filename. If necessary, parse it.
UINFO(4,"Link IfaceRef: "<<nodep<<endl);
// Use findIdUpward instead of findIdFlat; it doesn't matter for now
@ -247,14 +251,14 @@ private:
// Note cannot do modport resolution here; modports are allowed underneath generates
}
virtual void visit(AstPackageImport* nodep) {
virtual void visit(AstPackageImport* nodep) VL_OVERRIDE {
// Package Import: We need to do the package before the use of a package
iterateChildren(nodep);
UASSERT_OBJ(nodep->packagep(), nodep, "Unlinked package"); // Parser should set packagep
new V3GraphEdge(&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false);
}
virtual void visit(AstBind* nodep) {
virtual void visit(AstBind* nodep) VL_OVERRIDE {
// Bind: Has cells underneath that need to be put into the new
// module, and cells which need resolution
// TODO this doesn't allow bind to dotted hier names, that would require
@ -276,7 +280,7 @@ private:
pushDeletep(nodep->unlinkFrBack());
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
// Cell: Resolve its filename. If necessary, parse it.
// Execute only once. Complication is that cloning may result in
// user1 being set (for pre-clone) so check if user1() matches the
@ -354,7 +358,7 @@ private:
if (pinStar) pinp->v3error("Duplicate .* in a cell");
pinStar = true;
// Done with this fake pin
pinp->unlinkFrBack()->deleteTree(); VL_DANGLING(pinp);
VL_DO_DANGLING(pinp->unlinkFrBack()->deleteTree(), pinp);
}
}
// Convert unnamed pins to pin number based assignments
@ -381,9 +385,7 @@ private:
<<pinp->prettyNameQ());
}
}
if (ports.find(pinp->name()) == ports.end()) {
ports.insert(pinp->name());
}
ports.insert(pinp->name());
}
// We search ports, rather than in/out declarations as they aren't resolved yet,
// and it's easier to do it now than in V3LinkDot when we'd need to repeat steps.
@ -448,8 +450,8 @@ private:
// Accelerate the recursion
// Must do statements to support Generates, math though...
virtual void visit(AstNodeMath* nodep) {}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}
@ -470,7 +472,7 @@ private:
<<foundp->warnContextSecondary());
}
nodep->unlinkFrBack();
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (!foundp) {
m_mods.rootp()->insert(nodep->name(), new VSymEnt(&m_mods, nodep));
}

View File

@ -400,7 +400,7 @@ public:
VSymEnt* getScopeSym(AstScope* nodep) {
NameScopeSymMap::iterator it = m_nameScopeSymMap.find(nodep->name());
UASSERT_OBJ(it != m_nameScopeSymMap.end(), nodep,
"Scope never assigned a symbol entry?");
"Scope never assigned a symbol entry '" << nodep->name() << "'");
return it->second;
}
void implicitOkAdd(AstNodeModule* nodep, const string& varname) {
@ -726,7 +726,7 @@ class LinkDotFindVisitor : public AstNVisitor {
}
// VISITs
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Process $unit or other packages
// Not needed - dotted references not allowed from inside packages
//for (AstNodeModule* nodep = v3Global.rootp()->modulesp();
@ -758,8 +758,8 @@ class LinkDotFindVisitor : public AstNVisitor {
m_curSymp = m_modSymp = NULL;
}
}
virtual void visit(AstTypeTable* nodep) {}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstTypeTable* nodep) VL_OVERRIDE {}
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Called on top module from Netlist, other modules from the cell creating them,
// and packages
UINFO(8," "<<nodep<<endl);
@ -821,12 +821,12 @@ class LinkDotFindVisitor : public AstNVisitor {
// Prep for next
m_packagep = NULL;
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
UASSERT_OBJ(m_statep->forScopeCreation(), nodep,
"Scopes should only exist right after V3Scope");
// Ignored. Processed in next step
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
UINFO(5," CELL under "<<m_scope<<" is "<<nodep<<endl);
// Process XREFs/etc inside pins
if (nodep->recursive() && m_inRecursion) return;
@ -867,7 +867,7 @@ class LinkDotFindVisitor : public AstNVisitor {
m_paramNum = oldParamNum;
m_inRecursion = oldRecursion;
}
virtual void visit(AstCellInline* nodep) {
virtual void visit(AstCellInline* nodep) VL_OVERRIDE {
UINFO(5," CELLINLINE under "<<m_scope<<" is "<<nodep<<endl);
VSymEnt* aboveSymp = m_curSymp;
// If baz__DOT__foo__DOT__bar, we need to find baz__DOT__foo and add bar to it.
@ -887,11 +887,11 @@ class LinkDotFindVisitor : public AstNVisitor {
m_statep->insertInline(aboveSymp, m_modSymp, nodep, nodep->name());
}
}
virtual void visit(AstDefParam* nodep) {
virtual void visit(AstDefParam* nodep) VL_OVERRIDE {
nodep->user1p(m_curSymp);
iterateChildren(nodep);
}
virtual void visit(AstGenerate* nodep) {
virtual void visit(AstGenerate* nodep) VL_OVERRIDE {
// Begin: ... blocks often replicate under genif/genfor, so simply
// suppress duplicate checks. See t_gen_forif.v for an example.
bool lastInGen = m_inGenerate;
@ -901,7 +901,7 @@ class LinkDotFindVisitor : public AstNVisitor {
}
m_inGenerate = lastInGen;
}
virtual void visit(AstBegin* nodep) {
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
UINFO(5," "<<nodep<<endl);
// Rename "genblk"s to include a number
if (m_statep->forPrimary() && !nodep->user4SetOnce()) {
@ -943,7 +943,7 @@ class LinkDotFindVisitor : public AstNVisitor {
m_beginp = oldbegin;
m_beginNum = oldNum;
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
// NodeTask: Remember its name for later resolution
UINFO(5," "<<nodep<<endl);
UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Function/Task not under module?");
@ -979,13 +979,13 @@ class LinkDotFindVisitor : public AstNVisitor {
}
m_curSymp = oldCurSymp;
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
// Var: Remember its name for later resolution
UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?");
iterateChildren(nodep);
if (m_ftaskp && nodep->isParam()) {
nodep->v3error("Unsupported: Parameters in functions."); // Big3 unsupported too
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
if (!m_statep->forScopeCreation()) {
@ -1020,7 +1020,8 @@ class LinkDotFindVisitor : public AstNVisitor {
nodep->v3error("Duplicate declaration of signal: "
<<nodep->prettyNameQ()<<endl
<<(ansiWarn
? nodep->warnMore()+"... note: ANSI ports must have type declared with the I/O (IEEE 2017 23.2.2.2)\n"
? nodep->warnMore() + "... note: ANSI ports must have"
" type declared with the I/O (IEEE 1800-2017 23.2.2.2)\n"
: "")
<<nodep->warnContextPrimary()<<endl
<<findvarp->warnOther()<<"... Location of original declaration"<<endl
@ -1038,12 +1039,12 @@ class LinkDotFindVisitor : public AstNVisitor {
AstNodeDType* newdtypep = nodep->subDTypep();
UASSERT_OBJ(newdtypep && nodep->childDTypep(), findvarp,
"No child type?");
bdtypep->unlinkFrBack()->deleteTree();
VL_DO_DANGLING(bdtypep->unlinkFrBack()->deleteTree(), bdtypep);
newdtypep->unlinkFrBack();
findvarp->childDTypep(newdtypep);
}
}
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
} else {
// User can disable the message at either point
if (!(m_ftaskp && m_ftaskp->dpiImport())
@ -1075,7 +1076,7 @@ class LinkDotFindVisitor : public AstNVisitor {
newp->valuep(valuep);
UINFO(9," replace parameter "<<nodep<<endl);
UINFO(9," with "<<newp<<endl);
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep);
nodep = newp;
}
}
@ -1097,22 +1098,21 @@ class LinkDotFindVisitor : public AstNVisitor {
}
}
}
virtual void visit(AstTypedef* nodep) {
// Remember its name for later resolution
UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module?");
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit");
iterateChildren(nodep);
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
}
virtual void visit(AstParamTypeDType* nodep) {
UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module?");
virtual void visit(AstParamTypeDType* nodep) VL_OVERRIDE {
UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit");
iterateChildren(nodep);
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
// For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist
UASSERT_OBJ(!m_statep->forScopeCreation(), nodep, "No CFuncs expected in tree yet");
}
virtual void visit(AstEnumItem* nodep) {
virtual void visit(AstEnumItem* nodep) VL_OVERRIDE {
// EnumItem: Remember its name for later resolution
iterateChildren(nodep);
// Find under either a task or the module's vars
@ -1150,7 +1150,7 @@ class LinkDotFindVisitor : public AstNVisitor {
m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep);
}
}
virtual void visit(AstPackageImport* nodep) {
virtual void visit(AstPackageImport* nodep) VL_OVERRIDE {
UINFO(4," Link: "<<nodep<<endl);
VSymEnt* srcp = m_statep->getNodeSym(nodep->packagep());
if (nodep->name()=="*") {
@ -1168,7 +1168,7 @@ class LinkDotFindVisitor : public AstNVisitor {
UINFO(9," Link Done: "<<nodep<<endl);
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstPackageExport* nodep) {
virtual void visit(AstPackageExport* nodep) VL_OVERRIDE {
UINFO(9," Link: "<<nodep<<endl);
VSymEnt* srcp = m_statep->getNodeSym(nodep->packagep());
if (nodep->name()!="*") {
@ -1182,13 +1182,13 @@ class LinkDotFindVisitor : public AstNVisitor {
UINFO(9," Link Done: "<<nodep<<endl);
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstPackageExportStarStar* nodep) {
virtual void visit(AstPackageExportStarStar* nodep) VL_OVERRIDE {
UINFO(4," Link: "<<nodep<<endl);
m_curSymp->exportStarStar(m_statep->symsp());
// No longer needed, but can't delete until any multi-instantiated modules are expanded
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}
@ -1253,8 +1253,8 @@ private:
}
// VISITs
virtual void visit(AstTypeTable* nodep) {}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstTypeTable* nodep) VL_OVERRIDE {}
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
UINFO(5," "<<nodep<<endl);
if (nodep->dead() || !nodep->user4()) {
UINFO(4,"Mark dead module "<<nodep<<endl);
@ -1271,7 +1271,7 @@ private:
m_modp = NULL;
}
}
virtual void visit(AstPin* nodep) {
virtual void visit(AstPin* nodep) VL_OVERRIDE {
// Pin: Link to submodule's port
// Deal with implicit definitions - do before Resolve visitor as may
// be referenced above declaration
@ -1280,7 +1280,7 @@ private:
pinImplicitExprRecurse(nodep->exprp());
}
}
virtual void visit(AstDefParam* nodep) {
virtual void visit(AstDefParam* nodep) VL_OVERRIDE {
iterateChildren(nodep);
nodep->v3warn(DEFPARAM, "Suggest replace defparam assignment with Verilog 2001 #(."
<<nodep->prettyName()<<"(...etc...))");
@ -1299,10 +1299,10 @@ private:
nodep->name(),
exprp);
cellp->addParamsp(pinp);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
}
virtual void visit(AstPort* nodep) {
virtual void visit(AstPort* nodep) VL_OVERRIDE {
// Port: Stash the pin number
// Need to set pin numbers after varnames are created
// But before we do the final resolution based on names
@ -1327,16 +1327,16 @@ private:
symp->exported(false);
}
// Ports not needed any more
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
virtual void visit(AstAssignW* nodep) {
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
// Deal with implicit definitions
// We used to nodep->allowImplicit() here, but it turns out
// normal "assigns" can also make implicit wires. Yuk.
pinImplicitExprRecurse(nodep->lhsp());
iterateChildren(nodep);
}
virtual void visit(AstAssignAlias* nodep) {
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
// tran gates need implicit creation
// As VarRefs don't exist in forPrimary, sanity check
UASSERT_OBJ(!m_statep->forPrimary(), nodep, "Assign aliases unexpected pre-dot");
@ -1348,13 +1348,13 @@ private:
}
iterateChildren(nodep);
}
virtual void visit(AstImplicit* nodep) {
virtual void visit(AstImplicit* nodep) VL_OVERRIDE {
// Unsupported gates need implicit creation
pinImplicitExprRecurse(nodep);
// We're done with implicit gates
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}
@ -1384,11 +1384,11 @@ class LinkDotScopeVisitor : public AstNVisitor {
int debug() { return LinkDotState::debug(); }
// VISITs
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Recurse..., backward as must do packages before using packages
iterateChildrenBackwards(nodep);
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
UINFO(8," SCOPE "<<nodep<<endl);
UASSERT_OBJ(m_statep->forScopeCreation(), nodep,
"Scopes should only exist right after V3Scope");
@ -1400,7 +1400,7 @@ class LinkDotScopeVisitor : public AstNVisitor {
m_modSymp = NULL;
m_scopep = NULL;
}
virtual void visit(AstVarScope* nodep) {
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {
if (!nodep->varp()->isFuncLocal()) {
VSymEnt* varSymp = m_statep->insertSym(m_modSymp, nodep->varp()->name(), nodep, NULL);
if (nodep->varp()->isIfaceRef()
@ -1434,12 +1434,12 @@ class LinkDotScopeVisitor : public AstNVisitor {
}
}
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
VSymEnt* symp = m_statep->insertBlock(m_modSymp, nodep->name(), nodep, NULL);
symp->fallbackp(m_modSymp);
// No recursion, we don't want to pick up variables
}
virtual void visit(AstAssignAlias* nodep) {
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
// Track aliases created by V3Inline; if we get a VARXREF(aliased_from)
// we'll need to replace it with a VARXREF(aliased_to)
if (debug()>=9) nodep->dumpTree(cout, "- alias: ");
@ -1449,7 +1449,7 @@ class LinkDotScopeVisitor : public AstNVisitor {
fromVscp->user2p(toVscp);
iterateChildren(nodep);
}
virtual void visit(AstAssignVarScope* nodep) {
virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE {
UINFO(5,"ASSIGNVARSCOPE "<<nodep<<endl);
if (debug()>=9) nodep->dumpTree(cout, "- avs: ");
VSymEnt* rhsSymp;
@ -1497,14 +1497,14 @@ class LinkDotScopeVisitor : public AstNVisitor {
// or maybe an alias of an alias
m_statep->insertScopeAlias(LinkDotState::SAMN_IFTOP, lhsSymp, rhsSymp);
// We have stored the link, we don't need these any more
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
// For speed, don't recurse things that can't have scope
// Note we allow AstNodeStmt's as generates may be under them
virtual void visit(AstCell*) {}
virtual void visit(AstVar*) {}
virtual void visit(AstNodeMath*) {}
virtual void visit(AstNode* nodep) {
virtual void visit(AstCell*) VL_OVERRIDE {}
virtual void visit(AstVar*) VL_OVERRIDE {}
virtual void visit(AstNodeMath*) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}
@ -1534,7 +1534,7 @@ class LinkDotIfaceVisitor : public AstNVisitor {
int debug() { return LinkDotState::debug(); }
// VISITs
virtual void visit(AstModport* nodep) {
virtual void visit(AstModport* nodep) VL_OVERRIDE {
// Modport: Remember its name for later resolution
UINFO(5," fiv: "<<nodep<<endl);
VSymEnt* oldCurSymp = m_curSymp;
@ -1546,7 +1546,7 @@ class LinkDotIfaceVisitor : public AstNVisitor {
}
m_curSymp = oldCurSymp;
}
virtual void visit(AstModportFTaskRef* nodep) {
virtual void visit(AstModportFTaskRef* nodep) VL_OVERRIDE {
UINFO(5," fif: "<<nodep<<endl);
iterateChildren(nodep);
if (nodep->isExport()) nodep->v3error("Unsupported: modport export");
@ -1565,10 +1565,10 @@ class LinkDotIfaceVisitor : public AstNVisitor {
if (m_statep->forScopeCreation()) {
// Done with AstModportFTaskRef.
// Delete to prevent problems if we dead-delete pointed to ftask
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
virtual void visit(AstModportVarRef* nodep) {
virtual void visit(AstModportVarRef* nodep) VL_OVERRIDE {
UINFO(5," fiv: "<<nodep<<endl);
iterateChildren(nodep);
VSymEnt* symp = m_curSymp->findIdFallback(nodep->name());
@ -1589,10 +1589,10 @@ class LinkDotIfaceVisitor : public AstNVisitor {
if (m_statep->forScopeCreation()) {
// Done with AstModportVarRef.
// Delete to prevent problems if we dead-delete pointed to variable
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}
@ -1769,12 +1769,12 @@ private:
}
// VISITs
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Recurse..., backward as must do packages before using packages
iterateChildrenBackwards(nodep);
}
virtual void visit(AstTypeTable* nodep) {}
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstTypeTable* nodep) VL_OVERRIDE {}
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
if (nodep->dead()) return;
checkNoDot(nodep);
UINFO(8," "<<nodep<<endl);
@ -1787,7 +1787,7 @@ private:
m_modp = NULL;
m_ds.m_dotSymp = m_curSymp = m_modSymp = NULL;
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
UINFO(8," "<<nodep<<endl);
VSymEnt* oldModSymp = m_modSymp;
VSymEnt* oldCurSymp = m_curSymp;
@ -1798,13 +1798,13 @@ private:
m_modSymp = oldModSymp;
m_curSymp = oldCurSymp;
}
virtual void visit(AstCellInline* nodep) {
virtual void visit(AstCellInline* nodep) VL_OVERRIDE {
checkNoDot(nodep);
if (m_statep->forScopeCreation() && !v3Global.opt.vpi()) {
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
// Cell: Recurse inside or cleanup not founds
checkNoDot(nodep);
m_cellp = nodep;
@ -1833,7 +1833,7 @@ private:
// Parent module inherits child's publicity
// This is done bottom up in the LinkBotupVisitor stage
}
virtual void visit(AstPin* nodep) {
virtual void visit(AstPin* nodep) VL_OVERRIDE {
// Pin: Link to submodule's port
checkNoDot(nodep);
iterateChildren(nodep);
@ -1844,7 +1844,7 @@ private:
if (!foundp) {
if (nodep->name() == "__paramNumber1" && VN_IS(m_cellp->modp(), Primitive)) {
// Primitive parameter is really a delay we can just ignore
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
string suggest
@ -1875,7 +1875,7 @@ private:
}
// Early return() above when deleted
}
virtual void visit(AstDot* nodep) {
virtual void visit(AstDot* nodep) VL_OVERRIDE {
// Legal under a DOT: AstDot, AstParseRef, AstPackageRef, AstNodeSel
// also a DOT can be part of an expression, but only above plus
// AstFTaskRef are legal children
@ -1923,7 +1923,7 @@ private:
}
if (debug()>=9) newp->dumpTree("-dot-out: ");
nodep->replaceWith(newp);
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else { // Dot midpoint
AstNode* newp = nodep->rhsp()->unlinkFrBack();
if (m_ds.m_unresolved) {
@ -1932,7 +1932,7 @@ private:
newp = crp;
}
nodep->replaceWith(newp);
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
if (start) {
@ -1941,7 +1941,7 @@ private:
m_ds.m_dotp = lastStates.m_dotp;
}
}
virtual void visit(AstParseRef* nodep) {
virtual void visit(AstParseRef* nodep) VL_OVERRIDE {
if (nodep->user3SetOnce()) return;
UINFO(9," linkPARSEREF "<<m_ds.ascii()<<" n="<<nodep<<endl);
// m_curSymp is symbol table of outer expression
@ -1963,7 +1963,7 @@ private:
VFlagChildDType(), nodep->name());
if (m_ds.m_dotErr) nodep->unlinkFrBack(); // Avoid circular node loop on errors
else nodep->replaceWith(newp);
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
else {
//
@ -2042,7 +2042,7 @@ private:
UINFO(9," cell -> iface varref "<<foundp->nodep()<<endl);
AstNode* newp = new AstVarRef(ifaceRefVarp->fileline(),
ifaceRefVarp, false);
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep);
} else if (VN_IS(cellp->modp(), NotFoundModule)) {
cellp->modNameFileline()->v3error("Cannot find file containing interface: "
<<cellp->modp()->prettyNameQ());
@ -2060,7 +2060,7 @@ private:
m_ds.m_dotPos = DP_SCOPE;
ok = true;
AstNode* newp = new AstVarRef(nodep->fileline(), varp, false);
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
else if (allowVar) {
AstNode* newp;
@ -2070,11 +2070,21 @@ private:
refp->varp(varp);
m_ds.m_dotText = "";
if (m_ds.m_unresolved && m_ds.m_unlinkedScope) {
newp = new AstUnlinkedRef(nodep->fileline(), VN_CAST(refp, VarXRef),
refp->name(),
m_ds.m_unlinkedScope->unlinkFrBack());
m_ds.m_unlinkedScope = NULL;
m_ds.m_unresolved = false;
string dotted = refp->dotted();
size_t pos = dotted.find("__BRA__??__KET__");
// Arrays of interfaces all have the same parameters
if (pos != string::npos && varp->isParam()
&& VN_IS(m_ds.m_unlinkedScope, CellArrayRef)) {
refp->dotted(dotted.substr(0, pos));
newp = refp;
} else {
newp = new AstUnlinkedRef(nodep->fileline(),
VN_CAST(refp, VarXRef),
refp->name(),
m_ds.m_unlinkedScope->unlinkFrBack());
m_ds.m_unlinkedScope = NULL;
m_ds.m_unresolved = false;
}
} else {
newp = refp;
}
@ -2084,7 +2094,7 @@ private:
newp = refp;
}
UINFO(9," new "<<newp<<endl);
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep);
m_ds.m_dotPos = DP_MEMBER;
ok = true;
}
@ -2117,14 +2127,14 @@ private:
AstVar* varp = makeIfaceModportVar(nodep->fileline(),
cellp, ifacep, modportp);
AstVarRef* refp = new AstVarRef(varp->fileline(), varp, false);
nodep->replaceWith(refp); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->replaceWith(refp); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
else if (AstEnumItem* valuep = VN_CAST(foundp->nodep(), EnumItem)) {
if (allowVar) {
AstNode* newp = new AstEnumItemRef(nodep->fileline(),
valuep, foundp->packagep());
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep);
ok = true;
m_ds.m_dotText = "";
}
@ -2166,7 +2176,7 @@ private:
// Create if implicit, and also if error (so only complain once)
AstVarRef* newp = new AstVarRef(nodep->fileline(), nodep->name(), false);
nodep->replaceWith(newp);
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
createImplicitVar(m_curSymp, newp, m_modp, m_modSymp, err);
}
}
@ -2175,7 +2185,7 @@ private:
m_ds = lastStates;
}
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
// VarRef: Resolve its reference
// ParseRefs are used the first pass (forPrimary) so we shouldn't get can't find
// errors here now that we have a VarRef.
@ -2194,7 +2204,7 @@ private:
}
}
}
virtual void visit(AstVarXRef* nodep) {
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
// VarRef: Resolve its reference
// We always link even if varp() is set, because the module we choose may change
// due to creating new modules, flattening, etc.
@ -2237,11 +2247,10 @@ private:
AstVarRef* newrefp = new AstVarRef(nodep->fileline(),
nodep->varp(), nodep->lvalue());
nodep->replaceWith(newrefp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
} else {
string baddot;
VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot);
AstVarScope* vscp = foundp ? VN_CAST(foundp->nodep(), VarScope) : NULL;
if (!vscp) {
@ -2262,17 +2271,17 @@ private:
UINFO(7," Resolved "<<nodep<<endl); // Also prints taskp
AstVarRef* newvscp = new AstVarRef(nodep->fileline(), vscp, nodep->lvalue());
nodep->replaceWith(newvscp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
UINFO(9," new "<<newvscp<<endl); // Also prints taskp
}
}
}
}
virtual void visit(AstEnumItemRef* nodep) {
virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE {
// EnumItemRef may be under a dot. Should already be resolved.
iterateChildren(nodep);
}
virtual void visit(AstMethodCall* nodep) {
virtual void visit(AstMethodCall* nodep) VL_OVERRIDE {
// Created here so should already be resolved.
DotStates lastStates = m_ds;
{
@ -2281,7 +2290,7 @@ private:
}
m_ds = lastStates;
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
checkNoDot(nodep);
iterateChildren(nodep);
if (m_statep->forPrimary() && nodep->isIO() && !m_ftaskp && !nodep->user4()) {
@ -2289,7 +2298,7 @@ private:
<<nodep->prettyNameQ());
}
}
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
if (nodep->user3SetOnce()) return;
UINFO(8," "<<nodep<<endl);
if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) {
@ -2323,7 +2332,7 @@ private:
AstNode* newp = new AstMethodCall(nodep->fileline(), varEtcp,
VFlagChildDType(), nodep->name(), argsp);
nodep->replaceWith(newp);
pushDeletep(nodep); VL_DANGLING(nodep);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
} else {
checkNoDot(nodep);
@ -2403,7 +2412,7 @@ private:
}
m_ds = lastStates;
}
virtual void visit(AstSelBit* nodep) {
virtual void visit(AstSelBit* nodep) VL_OVERRIDE {
if (nodep->user3SetOnce()) return;
iterateAndNextNull(nodep->lhsp());
if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart}
@ -2425,10 +2434,10 @@ private:
AstNode* exprp = nodep->bitp()->unlinkFrBack();
AstCellArrayRef* newp
= new AstCellArrayRef(nodep->fileline(), nodep->fromp()->name(), exprp);
nodep->replaceWith(newp); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
virtual void visit(AstNodePreSel* nodep) {
virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE {
// Excludes simple AstSelBit, see above
if (nodep->user3SetOnce()) return;
if (m_ds.m_dotPos == DP_SCOPE) { // Already under dot, so this is {modulepart} DOT {modulepart}
@ -2446,11 +2455,11 @@ private:
}
m_ds = lastStates;
}
virtual void visit(AstMemberSel* nodep) {
virtual void visit(AstMemberSel* nodep) VL_OVERRIDE {
// checkNoDot not appropriate, can be under a dot
iterateChildren(nodep);
}
virtual void visit(AstBegin* nodep) {
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
UINFO(5," "<<nodep<<endl);
checkNoDot(nodep);
VSymEnt* oldCurSymp = m_curSymp;
@ -2462,7 +2471,7 @@ private:
m_ds.m_dotSymp = m_curSymp = oldCurSymp;
UINFO(5," cur=se"<<cvtToHex(m_curSymp)<<endl);
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
UINFO(5," "<<nodep<<endl);
checkNoDot(nodep);
VSymEnt* oldCurSymp = m_curSymp;
@ -2474,7 +2483,7 @@ private:
m_ds.m_dotSymp = m_curSymp = oldCurSymp;
m_ftaskp = NULL;
}
virtual void visit(AstRefDType* nodep) {
virtual void visit(AstRefDType* nodep) VL_OVERRIDE {
// Resolve its reference
if (nodep->user3SetOnce()) return;
if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) {
@ -2488,7 +2497,8 @@ private:
} else {
checkNoDot(nodep);
}
if (!nodep->defp()) {
if (nodep->typeofp()) { // Really is a typeof not a reference
} else if (!nodep->defp()) {
VSymEnt* foundp;
if (nodep->packagep()) {
foundp = m_statep->getNodeSym(nodep->packagep())->findIdFlat(nodep->name());
@ -2510,7 +2520,7 @@ private:
}
iterateChildren(nodep);
}
virtual void visit(AstDpiExport* nodep) {
virtual void visit(AstDpiExport* nodep) VL_OVERRIDE {
// AstDpiExport: Make sure the function referenced exists, then dump it
iterateChildren(nodep);
checkNoDot(nodep);
@ -2525,37 +2535,37 @@ private:
taskp->dpiExport(true);
if (nodep->cname()!="") taskp->cname(nodep->cname());
}
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
virtual void visit(AstPackageImport* nodep) {
virtual void visit(AstPackageImport* nodep) VL_OVERRIDE {
// No longer needed
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
virtual void visit(AstPackageExport* nodep) {
virtual void visit(AstPackageExport* nodep) VL_OVERRIDE {
// No longer needed
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
virtual void visit(AstPackageExportStarStar* nodep) {
virtual void visit(AstPackageExportStarStar* nodep) VL_OVERRIDE {
// No longer needed
checkNoDot(nodep);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
virtual void visit(AstCellRef* nodep) {
virtual void visit(AstCellRef* nodep) VL_OVERRIDE {
UINFO(5," AstCellRef: "<<nodep<<" "<<m_ds.ascii()<<endl);
iterateChildren(nodep);
}
virtual void visit(AstCellArrayRef* nodep) {
virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE {
UINFO(5," AstCellArrayRef: "<<nodep<<" "<<m_ds.ascii()<<endl);
// Expression already iterated
}
virtual void visit(AstUnlinkedRef* nodep) {
virtual void visit(AstUnlinkedRef* nodep) VL_OVERRIDE {
UINFO(5," AstCellArrayRef: "<<nodep<<" "<<m_ds.ascii()<<endl);
// No need to iterate, if we have a UnlinkedVarXRef, we're already done
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
checkNoDot(nodep);
iterateChildren(nodep);

View File

@ -49,7 +49,7 @@ private:
AstNodeFTask* m_ftaskp; // Current function/task
AstWhile* m_loopp; // Current loop
bool m_loopInc; // In loop increment
int m_repeatNum; // Repeat counter
int m_modRepeatNum; // Repeat counter
BeginStack m_beginStack; // All begin blocks above current node
// METHODS
@ -107,30 +107,35 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
if (nodep->dead()) return;
m_modp = nodep;
m_repeatNum = 0;
iterateChildren(nodep);
m_modp = NULL;
AstNodeModule* origModp = m_modp;
int origRepeatNum = m_modRepeatNum;
{
m_modp = nodep;
m_modRepeatNum = 0;
iterateChildren(nodep);
}
m_modp = origModp;
m_modRepeatNum = origRepeatNum;
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
m_ftaskp = nodep;
iterateChildren(nodep);
m_ftaskp = NULL;
}
virtual void visit(AstBegin* nodep) {
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
UINFO(8," "<<nodep<<endl);
m_beginStack.push_back(nodep);
iterateChildren(nodep);
m_beginStack.pop_back();
}
virtual void visit(AstRepeat* nodep) {
virtual void visit(AstRepeat* nodep) VL_OVERRIDE {
// So later optimizations don't need to deal with them,
// REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- }
// Note var can be signed or unsigned based on original number.
AstNode* countp = nodep->countp()->unlinkFrBackWithNext();
string name = string("__Vrepeat")+cvtToStr(m_repeatNum++);
string name = string("__Vrepeat")+cvtToStr(m_modRepeatNum++);
// Spec says value is integral, if negative is ignored
AstVar* varp = new AstVar(nodep->fileline(), AstVarType::BLOCKTEMP, name,
nodep->findSigned32DType());
@ -156,9 +161,9 @@ private:
initsp = initsp->addNext(newp);
newp = initsp;
nodep->replaceWith(newp);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstWhile* nodep) {
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
// Don't need to track AstRepeat/AstFor as they have already been converted
AstWhile* lastLoopp = m_loopp;
bool lastInc = m_loopInc;
@ -172,7 +177,7 @@ private:
m_loopInc = lastInc;
m_loopp = lastLoopp;
}
virtual void visit(AstReturn* nodep) {
virtual void visit(AstReturn* nodep) VL_OVERRIDE {
iterateChildren(nodep);
AstFunc* funcp = VN_CAST(m_ftaskp, Func);
if (!m_ftaskp) {
@ -193,9 +198,9 @@ private:
AstJumpLabel* labelp = findAddLabel(m_ftaskp, false);
nodep->addPrev(new AstJumpGo(nodep->fileline(), labelp));
}
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
virtual void visit(AstBreak* nodep) {
virtual void visit(AstBreak* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (!m_loopp) { nodep->v3error("break isn't underneath a loop"); }
else {
@ -203,9 +208,9 @@ private:
AstJumpLabel* labelp = findAddLabel(m_loopp, false);
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
}
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
virtual void visit(AstContinue* nodep) {
virtual void visit(AstContinue* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (!m_loopp) { nodep->v3error("continue isn't underneath a loop"); }
else {
@ -214,9 +219,9 @@ private:
AstJumpLabel* labelp = findAddLabel(m_loopp, true);
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
}
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
virtual void visit(AstDisable* nodep) {
virtual void visit(AstDisable* nodep) VL_OVERRIDE {
UINFO(8," DISABLE "<<nodep<<endl);
iterateChildren(nodep);
AstBegin* beginp = NULL;
@ -236,15 +241,15 @@ private:
AstJumpLabel* labelp = findAddLabel(beginp, false);
nodep->addNextHere(new AstJumpGo(nodep->fileline(), labelp));
}
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
//if (debug()>=9) { UINFO(0,"\n"); beginp->dumpTree(cout, " labelo: "); }
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true);
}
virtual void visit(AstConst* nodep) {}
virtual void visit(AstNode* nodep) {
virtual void visit(AstConst* nodep) VL_OVERRIDE {}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -254,7 +259,7 @@ public:
m_ftaskp = NULL;
m_loopp = NULL;
m_loopInc = false;
m_repeatNum = 0;
m_modRepeatNum = 0;
iterate(nodep);
}
virtual ~LinkJumpVisitor() {}

View File

@ -50,7 +50,7 @@ private:
// VISITs
// Result handing
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
// VarRef: LValue its reference
if (m_setRefLvalue) {
nodep->lvalue(true);
@ -66,7 +66,7 @@ private:
}
// Nodes that start propagating down lvalues
virtual void visit(AstPin* nodep) {
virtual void visit(AstPin* nodep) VL_OVERRIDE {
if (nodep->modVarp() && nodep->modVarp()->isWritable()) {
// When the varref's were created, we didn't know the I/O state
// Now that we do, and it's from a output, we know it's a lvalue
@ -77,7 +77,7 @@ private:
iterateChildren(nodep);
}
}
virtual void visit(AstNodeAssign* nodep) {
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -87,7 +87,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFOpen* nodep) {
virtual void visit(AstFOpen* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -98,7 +98,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFClose* nodep) {
virtual void visit(AstFClose* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -106,7 +106,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFFlush* nodep) {
virtual void visit(AstFFlush* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -114,7 +114,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFGetC* nodep) {
virtual void visit(AstFGetC* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -122,7 +122,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFGetS* nodep) {
virtual void visit(AstFGetS* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -131,7 +131,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFRead* nodep) {
virtual void visit(AstFRead* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -140,7 +140,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFScanF* nodep) {
virtual void visit(AstFScanF* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -149,7 +149,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstFUngetC* nodep) {
virtual void visit(AstFUngetC* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -157,7 +157,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstSScanF* nodep) {
virtual void visit(AstSScanF* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -165,13 +165,13 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstSysIgnore* nodep) {
virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE {
// Can't know if lvalue or not; presume so as stricter
bool last_setRefLvalue = m_setRefLvalue;
iterateChildren(nodep);
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstReadMem* nodep) {
virtual void visit(AstReadMem* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -183,7 +183,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstValuePlusArgs* nodep) {
virtual void visit(AstValuePlusArgs* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = false;
@ -193,7 +193,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstSFormat* nodep) {
virtual void visit(AstSFormat* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
m_setRefLvalue = true;
@ -205,7 +205,7 @@ private:
}
// Nodes that change LValue state
virtual void visit(AstSel* nodep) {
virtual void visit(AstSel* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{
iterateAndNextNull(nodep->lhsp());
@ -216,7 +216,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstNodeSel* nodep) {
virtual void visit(AstNodeSel* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{ // Only set lvalues on the from
iterateAndNextNull(nodep->lhsp());
@ -225,7 +225,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstCellArrayRef* nodep) {
virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{ // selp is not an lvalue
m_setRefLvalue = false;
@ -233,7 +233,7 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstNodePreSel* nodep) {
virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE {
bool last_setRefLvalue = m_setRefLvalue;
{ // Only set lvalues on the from
iterateAndNextNull(nodep->lhsp());
@ -243,12 +243,12 @@ private:
}
m_setRefLvalue = last_setRefLvalue;
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
m_ftaskp = nodep;
iterateChildren(nodep);
m_ftaskp = NULL;
}
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
AstNode* pinp = nodep->pinsp();
AstNodeFTask* taskp = nodep->taskp();
// We'll deal with mismatching pins later
@ -270,7 +270,7 @@ private:
}
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}

View File

@ -28,6 +28,7 @@
#include "V3Global.h"
#include "V3LinkParse.h"
#include "V3Ast.h"
#include "V3Config.h"
#include <algorithm>
#include <cstdarg>
@ -105,7 +106,9 @@ private:
}
// VISITs
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
V3Config::applyFTask(m_modp, nodep);
if (!nodep->user1SetOnce()) { // Process only once.
cleanFileline(nodep);
m_ftaskp = nodep;
@ -113,7 +116,7 @@ private:
m_ftaskp = NULL;
}
}
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
if (!nodep->user1SetOnce()) { // Process only once.
cleanFileline(nodep);
UINFO(5," "<<nodep<<endl);
@ -123,22 +126,22 @@ private:
m_valueModp = upperValueModp;
}
}
virtual void visit(AstNodeDType* nodep) {
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
visitIterateNodeDType(nodep);
}
virtual void visit(AstEnumDType* nodep) {
virtual void visit(AstEnumDType* nodep) VL_OVERRIDE {
if (nodep->name() == "") {
nodep->name(nameFromTypedef(nodep)); // Might still remain ""
}
visitIterateNodeDType(nodep);
}
virtual void visit(AstNodeUOrStructDType* nodep) {
virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE {
if (nodep->name() == "") {
nodep->name(nameFromTypedef(nodep)); // Might still remain ""
}
visitIterateNodeDType(nodep);
}
virtual void visit(AstEnumItem* nodep) {
virtual void visit(AstEnumItem* nodep) VL_OVERRIDE {
// Expand ranges
cleanFileline(nodep);
iterateChildren(nodep);
@ -166,11 +169,11 @@ private:
else addp = newp;
}
nodep->replaceWith(addp);
nodep->deleteTree();
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
cleanFileline(nodep);
if (VN_IS(nodep->subDTypep(), ParseTypeDType)) {
// It's a parameter type. Use a different node type for this.
@ -184,11 +187,14 @@ private:
AstNode* newp = new AstParamTypeDType(nodep->fileline(),
nodep->varType(), nodep->name(),
VFlagChildDType(), dtypep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
return;
}
// Maybe this variable has a signal attribute
V3Config::applyVarAttr(m_modp, m_ftaskp, nodep);
if (v3Global.opt.publicFlatRW()) {
switch (nodep->varType()) {
case AstVarType::VAR:
@ -249,74 +255,74 @@ private:
}
}
virtual void visit(AstAttrOf* nodep) {
virtual void visit(AstAttrOf* nodep) VL_OVERRIDE {
cleanFileline(nodep);
iterateChildren(nodep);
if (nodep->attrType() == AstAttrType::DT_PUBLIC) {
AstTypedef* typep = VN_CAST(nodep->backp(), Typedef);
UASSERT_OBJ(typep, nodep, "Attribute not attached to typedef");
typep->attrPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
nodep->v3warn(DEPRECATED, "sc_clock is deprecated and will be removed");
m_varp->attrScClocked(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCK_ENABLE) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->attrClockEn(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->sigUserRWPublic(true); m_varp->sigModPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->sigUserRWPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RD) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->sigUserRdPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RW) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->sigUserRWPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->attrIsolateAssign(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_SFORMAT) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->attrSFormat(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_SC_BV) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->attrScBv(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCKER) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->attrClocker(VVarAttrClocker::CLOCKER_YES);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_NO_CLOCKER) {
UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable");
m_varp->attrClocker(VVarAttrClocker::CLOCKER_NO);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
}
virtual void visit(AstAlwaysPublic* nodep) {
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
// AlwaysPublic was attached under a var, but it's a statement that should be
// at the same level as the var
cleanFileline(nodep);
@ -331,7 +337,7 @@ private:
}
}
virtual void visit(AstDefImplicitDType* nodep) {
virtual void visit(AstDefImplicitDType* nodep) VL_OVERRIDE {
cleanFileline(nodep);
UINFO(8," DEFIMPLICIT "<<nodep<<endl);
// Must remember what names we've already created, and combine duplicates
@ -357,7 +363,7 @@ private:
if (VN_IS(backp, Typedef)) { // A typedef doesn't need us to make yet another level of typedefing
// For typedefs just remove the AstRefDType level of abstraction
nodep->replaceWith(dtypep);
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
return;
} else {
defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL,
@ -367,17 +373,17 @@ private:
}
}
nodep->replaceWith(new AstRefDType(nodep->fileline(), defp->name()));
nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstTypedefFwd* nodep) {
virtual void visit(AstTypedefFwd* nodep) VL_OVERRIDE {
// We only needed the forward declaration in order to parse correctly.
// We won't even check it was ever really defined, as it might have been in a header
// file referring to a module we never needed
nodep->unlinkFrBack()->deleteTree();
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
}
virtual void visit(AstForeach* nodep) {
virtual void visit(AstForeach* nodep) VL_OVERRIDE {
// FOREACH(array,loopvars,body)
// -> BEGIN(declare vars, loopa=lowest; WHILE(loopa<=highest, ... body))
//nodep->dumpTree(cout, "-foreach-old:");
@ -433,19 +439,24 @@ private:
dimension--;
}
//newp->dumpTree(cout, "-foreach-new:");
firstVarsp->deleteTree(); VL_DANGLING(firstVarsp);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
VL_DO_DANGLING(firstVarsp->deleteTree(), firstVarsp);
nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep);
}
virtual void visit(AstNodeModule* nodep) {
// Module: Create sim table for entire module and iterate
cleanFileline(nodep);
//
m_modp = nodep;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
V3Config::applyModule(nodep);
AstNodeModule* origModp = m_modp;
{
// Module: Create sim table for entire module and iterate
cleanFileline(nodep);
//
m_modp = nodep;
m_valueModp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
m_valueModp = nodep;
iterateChildren(nodep);
m_modp = NULL;
m_valueModp = NULL;
}
void visitIterateNoValueMod(AstNode* nodep) {
// Iterate a node which shouldn't have any local variables moved to an Initial
@ -456,25 +467,36 @@ private:
iterateChildren(nodep);
m_valueModp = upperValueModp;
}
virtual void visit(AstInitial* nodep) {
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
visitIterateNoValueMod(nodep);
}
virtual void visit(AstFinal* nodep) {
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
visitIterateNoValueMod(nodep);
}
virtual void visit(AstAlways* nodep) {
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
m_inAlways = true;
visitIterateNoValueMod(nodep);
m_inAlways = false;
}
virtual void visit(AstCover* nodep) {
virtual void visit(AstCover* nodep) VL_OVERRIDE {
visitIterateNoValueMod(nodep);
}
virtual void visit(AstRestrict* nodep) {
virtual void visit(AstRestrict* nodep) VL_OVERRIDE {
visitIterateNoValueMod(nodep);
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
V3Config::applyCoverageBlock(m_modp, nodep);
cleanFileline(nodep);
iterateChildren(nodep);
}
virtual void visit(AstCase* nodep) VL_OVERRIDE {
V3Config::applyCase(nodep);
cleanFileline(nodep);
iterateChildren(nodep);
}
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
cleanFileline(nodep);
iterateChildren(nodep);

View File

@ -49,12 +49,12 @@ private:
// NODE STATE
// Entire netlist:
// AstCaseItem::user2() // bool Moved default caseitems
AstUser2InUse m_inuser2;
AstUser2InUse m_inuser2;
// STATE
// Below state needs to be preserved between each module call.
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Function or task we're inside
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Function or task we're inside
AstNodeCoverOrAssert* m_assertp; // Current assertion
int m_senitemCvtNum; // Temporary signal counter
@ -65,31 +65,36 @@ private:
// TODO: Most of these visitors are here for historical reasons.
// TODO: ExpectDecriptor can move to data type resolution, and the rest
// TODO: could move to V3LinkParse to get them out of the way of elaboration
virtual void visit(AstNodeModule* nodep) {
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
// Module: Create sim table for entire module and iterate
UINFO(8,"MODULE "<<nodep<<endl);
if (nodep->dead()) return;
m_modp = nodep;
m_senitemCvtNum = 0;
iterateChildren(nodep);
m_modp = NULL;
AstNodeModule* origModp = m_modp;
int origSenitemCvtNum = m_senitemCvtNum;
{
m_modp = nodep;
m_senitemCvtNum = 0;
iterateChildren(nodep);
}
m_modp = origModp;
m_senitemCvtNum = origSenitemCvtNum;
}
virtual void visit(AstInitial* nodep) {
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// Initial assignments under function/tasks can just be simple
// assignments without the initial
if (m_ftaskp) {
nodep->replaceWith(nodep->bodysp()->unlinkFrBackWithNext()); VL_DANGLING(nodep);
VL_DO_DANGLING(nodep->replaceWith(nodep->bodysp()->unlinkFrBackWithNext()), nodep);
}
}
virtual void visit(AstNodeCoverOrAssert* nodep) {
virtual void visit(AstNodeCoverOrAssert* nodep) VL_OVERRIDE {
if (m_assertp) nodep->v3error("Assert not allowed under another assert");
m_assertp = nodep;
iterateChildren(nodep);
m_assertp = NULL;
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (m_ftaskp) nodep->funcLocal(true);
if (nodep->isSigModPublic()) {
@ -98,7 +103,7 @@ private:
}
}
virtual void visit(AstNodeVarRef* nodep) {
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
// VarRef: Resolve its reference
if (nodep->varp()) {
nodep->varp()->usedParam(true);
@ -106,7 +111,7 @@ private:
iterateChildren(nodep);
}
virtual void visit(AstNodeFTask* nodep) {
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
// NodeTask: Remember its name for later resolution
// Remember the existing symbol table scope
m_ftaskp = nodep;
@ -116,14 +121,14 @@ private:
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
}
}
virtual void visit(AstNodeFTaskRef* nodep) {
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
iterateChildren(nodep);
if (nodep->taskp() && (nodep->taskp()->dpiContext() || nodep->taskp()->dpiExport())) {
nodep->scopeNamep(new AstScopeName(nodep->fileline()));
}
}
virtual void visit(AstSenItem* nodep) {
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
// Remove bit selects, and bark if it's not a simple variable
iterateChildren(nodep);
if (nodep->isClocked()) {
@ -167,18 +172,18 @@ private:
did = 0;
if (AstNodeSel* selp = VN_CAST(nodep->sensp(), NodeSel)) {
AstNode* fromp = selp->fromp()->unlinkFrBack();
selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp);
selp->replaceWith(fromp); VL_DO_DANGLING(selp->deleteTree(), selp);
did = 1;
}
// NodeSel doesn't include AstSel....
if (AstSel* selp = VN_CAST(nodep->sensp(), Sel)) {
AstNode* fromp = selp->fromp()->unlinkFrBack();
selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp);
selp->replaceWith(fromp); VL_DO_DANGLING(selp->deleteTree(), selp);
did = 1;
}
if (AstNodePreSel* selp = VN_CAST(nodep->sensp(), NodePreSel)) {
AstNode* fromp = selp->lhsp()->unlinkFrBack();
selp->replaceWith(fromp); selp->deleteTree(); VL_DANGLING(selp);
selp->replaceWith(fromp); VL_DO_DANGLING(selp->deleteTree(), selp);
did = 1;
}
}
@ -190,11 +195,11 @@ private:
nodep->v3error("Unsupported: Complex statement in sensitivity list");
}
}
virtual void visit(AstSenGate* nodep) {
virtual void visit(AstSenGate* nodep) VL_OVERRIDE {
nodep->v3fatalSrc("SenGates shouldn't be in tree yet");
}
virtual void visit(AstNodePreSel* nodep) {
virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE {
if (!nodep->attrp()) {
iterateChildren(nodep);
// Constification may change the fromp() to a constant, which will lose the
@ -226,7 +231,7 @@ private:
}
}
virtual void visit(AstCaseItem* nodep) {
virtual void visit(AstCaseItem* nodep) VL_OVERRIDE {
// Move default caseItems to the bottom of the list
// That saves us from having to search each case list twice, for non-defaults and defaults
iterateChildren(nodep);
@ -238,21 +243,21 @@ private:
}
}
virtual void visit(AstPragma* nodep) {
virtual void visit(AstPragma* nodep) VL_OVERRIDE {
if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) {
UASSERT_OBJ(m_modp, nodep, "PUBLIC_MODULE not under a module");
m_modp->modPublic(true);
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
else if (nodep->pragType() == AstPragmaType::PUBLIC_TASK) {
UASSERT_OBJ(m_ftaskp, nodep, "PUBLIC_TASK not under a task");
m_ftaskp->taskPublic(true);
m_modp->modPublic(true); // Need to get to the task...
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
else if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
if (!v3Global.opt.coverageLine()) { // No need for block statements; may optimize better without
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
else {
@ -270,7 +275,7 @@ private:
if (!inPct && ch=='%') {
inPct = true;
fmt = ch;
} else if (inPct && (isdigit(ch) || ch=='.')) {
} else if (inPct && (isdigit(ch) || ch=='.' || ch=='-')) {
fmt += ch;
} else if (inPct) {
inPct = false;
@ -343,7 +348,7 @@ private:
}
newFormat.append(str);
AstNode *nextp = argp->nextp();
argp->unlinkFrBack(); pushDeletep(argp); VL_DANGLING(argp);
argp->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(argp), argp);
argp = nextp;
} else {
newFormat.append("%?"); // V3Width to figure it out
@ -359,31 +364,31 @@ private:
if (filep && filep->varp()) filep->varp()->attrFileDescr(true);
}
virtual void visit(AstFOpen* nodep) {
virtual void visit(AstFOpen* nodep) VL_OVERRIDE {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
}
virtual void visit(AstFClose* nodep) {
virtual void visit(AstFClose* nodep) VL_OVERRIDE {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
}
virtual void visit(AstFEof* nodep) {
virtual void visit(AstFEof* nodep) VL_OVERRIDE {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
}
virtual void visit(AstFRead* nodep) {
virtual void visit(AstFRead* nodep) VL_OVERRIDE {
iterateChildren(nodep);
expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef));
}
virtual void visit(AstFScanF* nodep) {
virtual void visit(AstFScanF* nodep) VL_OVERRIDE {
iterateChildren(nodep);
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
}
virtual void visit(AstSScanF* nodep) {
virtual void visit(AstSScanF* nodep) VL_OVERRIDE {
iterateChildren(nodep);
expectFormat(nodep, nodep->text(), nodep->exprsp(), true);
}
virtual void visit(AstSFormatF* nodep) {
virtual void visit(AstSFormatF* nodep) VL_OVERRIDE {
iterateChildren(nodep);
// Cleanup old-school displays without format arguments
if (!nodep->hasFormat()) {
@ -392,7 +397,7 @@ private:
&& VN_CAST(nodep->exprsp(), Const)->num().isFromString()) {
AstConst* fmtp = VN_CAST(nodep->exprsp()->unlinkFrBack(), Const);
nodep->text(fmtp->num().toString());
pushDeletep(fmtp); VL_DANGLING(fmtp);
VL_DO_DANGLING(pushDeletep(fmtp), fmtp);
}
nodep->hasFormat(true);
}
@ -405,7 +410,7 @@ private:
}
}
virtual void visit(AstUdpTable* nodep) {
virtual void visit(AstUdpTable* nodep) VL_OVERRIDE {
UINFO(5,"UDPTABLE "<<nodep<<endl);
if (!v3Global.opt.bboxUnsup()) {
// We don't warn until V3Inst, so that UDPs that are in libraries and
@ -432,27 +437,27 @@ private:
}
}
}
nodep->unlinkFrBack(); pushDeletep(nodep); VL_DANGLING(nodep);
nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
virtual void visit(AstScCtor* nodep) {
virtual void visit(AstScCtor* nodep) VL_OVERRIDE {
// Constructor info means the module must remain public
m_modp->modPublic(true);
iterateChildren(nodep);
}
virtual void visit(AstScDtor* nodep) {
virtual void visit(AstScDtor* nodep) VL_OVERRIDE {
// Destructor info means the module must remain public
m_modp->modPublic(true);
iterateChildren(nodep);
}
virtual void visit(AstScInt* nodep) {
virtual void visit(AstScInt* nodep) VL_OVERRIDE {
// Special class info means the module must remain public
m_modp->modPublic(true);
iterateChildren(nodep);
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}
@ -484,24 +489,27 @@ private:
VL_DEBUG_FUNC; // Declare debug()
// VISITs
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
// Iterate modules backwards, in bottom-up order.
iterateChildrenBackwards(nodep);
}
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
iterateChildren(nodep);
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
// Parent module inherits child's publicity
if (nodep->modp()->modPublic()) m_modp->modPublic(true);
//** No iteration for speed
}
virtual void visit(AstNodeMath* nodep) {
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
// Speedup
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
// Default: Just iterate
iterateChildren(nodep);
}

View File

@ -77,14 +77,14 @@ private:
// See above
// METHODS
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
VarFlags flags (nodep->varp());
if (flags.m_done) {
nodep->hiername(""); // Remove this->
nodep->hierThis(true);
}
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:
@ -151,11 +151,11 @@ private:
}
// VISITORS
virtual void visit(AstNetlist* nodep) {
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
iterateChildren(nodep);
moveVars();
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
UINFO(4," CFUNC "<<nodep<<endl);
m_cfuncp = nodep;
searchFuncStmts(nodep->argsp());
@ -186,7 +186,7 @@ private:
}
}
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
if (!nodep->isSigPublic()
&& !nodep->isPrimaryIO()
&& !m_cfuncp) { // Not already inside a function
@ -195,7 +195,7 @@ private:
}
// No iterate; Don't want varrefs under it
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (!VarFlags(nodep->varp()).m_notOpt) {
if (!m_cfuncp) { // Not in function, can't optimize
clearOptimizable(nodep->varp(), "BVnofunc");
@ -224,7 +224,7 @@ private:
}
// No iterate; Don't want varrefs under it
}
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -59,6 +59,7 @@ private:
if (addPvt) {
string newname = string("__PVT__")+nodep->name();
nodep->name(newname);
nodep->editCountInc();
} else {
string rsvd = m_words.isKeyword(nodep->name());
if (rsvd != "") {
@ -66,6 +67,7 @@ private:
+": "<<nodep->prettyNameQ());
string newname = string("__SYM__")+nodep->name();
nodep->name(newname);
nodep->editCountInc();
}
}
nodep->user1(1);
@ -73,50 +75,53 @@ private:
}
// VISITORS
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
iterateChildren(nodep);
m_modp = NULL;
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
AstNodeModule* origModp = m_modp;
{
m_modp = nodep;
iterateChildren(nodep);
}
m_modp = origModp;
}
// Add __PVT__ to names of local signals
virtual void visit(AstVar* nodep) {
virtual void visit(AstVar* nodep) VL_OVERRIDE {
// Don't iterate... Don't need temps for RANGES under the Var.
rename(nodep, (!m_modp->isTop()
&& !nodep->isSigPublic()
&& !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers
&& !nodep->isTemp())); // Don't bother to rename internal signals
}
virtual void visit(AstCFunc* nodep) {
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
if (!nodep->user1()) {
iterateChildren(nodep);
rename(nodep, false);
}
}
virtual void visit(AstVarRef* nodep) {
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
if (nodep->varp()) {
iterate(nodep->varp());
nodep->name(nodep->varp()->name());
}
}
virtual void visit(AstCell* nodep) {
virtual void visit(AstCell* nodep) VL_OVERRIDE {
if (!nodep->user1()) {
rename(nodep, !nodep->modp()->modPublic());
iterateChildren(nodep);
}
}
virtual void visit(AstMemberDType* nodep) {
virtual void visit(AstMemberDType* nodep) VL_OVERRIDE {
if (!nodep->user1()) {
rename(nodep, false);
iterateChildren(nodep);
}
}
virtual void visit(AstMemberSel* nodep) {
virtual void visit(AstMemberSel* nodep) VL_OVERRIDE {
if (!nodep->user1()) {
rename(nodep, false);
iterateChildren(nodep);
}
}
virtual void visit(AstScope* nodep) {
virtual void visit(AstScope* nodep) VL_OVERRIDE {
if (!nodep->user1SetOnce()) {
if (nodep->aboveScopep()) iterate(nodep->aboveScopep());
if (nodep->aboveCellp()) iterate(nodep->aboveCellp());
@ -129,7 +134,7 @@ private:
}
//--------------------
virtual void visit(AstNode* nodep) {
virtual void visit(AstNode* nodep) VL_OVERRIDE {
iterateChildren(nodep);
}
public:

View File

@ -32,7 +32,6 @@
#include <iomanip>
#define MAX_SPRINTF_DOUBLE_SIZE 100 // Maximum characters with a sprintf %e/%f/%g (probably < 30)
#define MAX_WIDTH 5*1024 // Maximum width before error
// Number operations build output in-place so can't call e.g. foo.opX(foo)
#define NUM_ASSERT_OP_ARGS1(arg1) \
@ -125,10 +124,11 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl)
value_startp = cp;
if (atoi(widthn.c_str())) {
if (atoi(widthn.c_str()) < 0 || atoi(widthn.c_str()) > MAX_WIDTH) {
if (atoi(widthn.c_str()) < 0 || atoi(widthn.c_str()) > v3Global.opt.maxNumWidth()) {
// atoi might convert large number to negative, so can't tell which
v3error("Unsupported: Width of number exceeds implementation limit: "<<sourcep);
width(MAX_WIDTH, true);
v3error("Unsupported: Width of number exceeds implementation limit: "
<< sourcep << " (IEEE 1800-2017 6.9.1)");
width(v3Global.opt.maxNumWidth(), true);
} else {
width(atoi(widthn.c_str()), true);
}
@ -198,7 +198,7 @@ void V3Number::V3NumberCreate(AstNode* nodep, const char* sourcep, FileLine* fl)
<<std::endl
<<((!m_sized && !warned++)
? (V3Error::warnMore()+"... As that number was unsized"
+" ('d...) it is limited to 32 bits (IEEE 2017 5.7.1)\n"
+" ('d...) it is limited to 32 bits (IEEE 1800-2017 5.7.1)\n"
+ V3Error::warnMore()+"... Suggest adding a size to it.")
: ""));
while (*(cp+1)) cp++; // Skip ahead so don't get multiple warnings
@ -497,10 +497,10 @@ bool V3Number::displayedFmtLegal(char format) {
}
}
string V3Number::displayPad(size_t fmtsize, char pad, const string& in) {
string prefix;
if (in.length() < fmtsize) prefix = string(fmtsize - in.length(), pad);
return prefix + in;
string V3Number::displayPad(size_t fmtsize, char pad, bool left, const string& in) {
string padding;
if (in.length() < fmtsize) padding = string(fmtsize - in.length(), pad);
return left ? (in + padding) : (padding + in);
}
string V3Number::displayed(AstNode* nodep, const string& vformat) const {
@ -512,6 +512,11 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
UASSERT(pos != vformat.end() && pos[0]=='%',
"$display-like function with non format argument "<<*this);
++pos;
bool left = false;
if (pos[0] == '-') {
left = true;
++pos;
}
string fmtsize;
for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0]=='.'); ++pos) {
fmtsize += pos[0];
@ -574,7 +579,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
}
}
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, ' ', str);
str = displayPad(fmtsizen, ' ', left, str);
return str;
}
case '~': // Signed decimal
@ -604,7 +609,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
bool zeropad = fmtsize.length()>0 && fmtsize[0]=='0';
// fmtsize might have changed since we parsed the %fmtsize
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, (zeropad ? '0' : ' '), str);
str = displayPad(fmtsizen, (zeropad ? '0' : ' '), left, str);
return str;
}
case 'e':
@ -651,7 +656,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const {
}
case '@': { // Packed string
size_t fmtsizen = static_cast<size_t>(atoi(fmtsize.c_str()));
str = displayPad(fmtsizen, ' ', toString());
str = displayPad(fmtsizen, ' ', left, toString());
return str;
}
default:
@ -1535,8 +1540,8 @@ V3Number& V3Number::opShiftRS(const V3Number& lhs, const V3Number& rhs, uint32_t
if (rhs.isFourState()) return setAllBitsX();
setZero();
for (int bit=32; bit<rhs.width(); bit++) {
for (int bit=0; bit<this->width(); bit++) {
setBit(bit, lhs.bitIs(lbits-1)); // 0/1/X/Z
for (int sbit = 0; sbit < this->width(); sbit++) {
setBit(sbit, lhs.bitIs(lbits - 1)); // 0/1/X/Z
}
if (rhs.bitIs1(lbits-1)) setAllBits1(); // -1 else 0
return *this; // shift of over 2^32 must be -1/0

View File

@ -151,7 +151,7 @@ public:
V3Number(VerilogStringLiteral, AstNode* nodep, const string& str);
class String {};
V3Number(String, AstNode* nodep, const string& value) { init(nodep, 0); setString(value); }
V3Number(const V3Number* nump, int width = 1) {
explicit V3Number(const V3Number* nump, int width = 1) {
init(NULL, width);
m_fileline = nump->fileline();
}
@ -175,7 +175,7 @@ private:
for (int i=0; i<words(); i++) m_value[i] = m_valueX[i] = 0;
}
void setNames(AstNode* nodep);
static string displayPad(size_t fmtsize, char pad, const string& in);
static string displayPad(size_t fmtsize, char pad, bool left, const string& in);
string displayed(FileLine* fl, const string& vformat) const;
string displayed(const string& vformat) const {
return displayed(m_fileline, vformat);

View File

@ -182,9 +182,7 @@ void V3Options::checkParameters() {
}
void V3Options::addCppFile(const string& filename) {
if (m_cppFiles.find(filename) == m_cppFiles.end()) {
m_cppFiles.insert(filename);
}
m_cppFiles.insert(filename);
}
void V3Options::addCFlags(const string& filename) {
m_cFlags.push_back(filename);
@ -193,9 +191,7 @@ void V3Options::addLdLibs(const string& filename) {
m_ldLibs.push_back(filename);
}
void V3Options::addFuture(const string& flag) {
if (m_futures.find(flag) == m_futures.end()) {
m_futures.insert(flag);
}
m_futures.insert(flag);
}
bool V3Options::isFuture(const string& flag) const {
return m_futures.find(flag) != m_futures.end();
@ -204,25 +200,19 @@ bool V3Options::isLibraryFile(const string& filename) const {
return m_libraryFiles.find(filename) != m_libraryFiles.end();
}
void V3Options::addLibraryFile(const string& filename) {
if (m_libraryFiles.find(filename) == m_libraryFiles.end()) {
m_libraryFiles.insert(filename);
}
m_libraryFiles.insert(filename);
}
bool V3Options::isClocker(const string& signame) const {
return m_clockers.find(signame) != m_clockers.end();
}
void V3Options::addClocker(const string& signame) {
if (m_clockers.find(signame) == m_clockers.end()) {
m_clockers.insert(signame);
}
m_clockers.insert(signame);
}
bool V3Options::isNoClocker(const string& signame) const {
return m_noClockers.find(signame) != m_noClockers.end();
}
void V3Options::addNoClocker(const string& signame) {
if (m_noClockers.find(signame) == m_noClockers.end()) {
m_noClockers.insert(signame);
}
m_noClockers.insert(signame);
}
void V3Options::addVFile(const string& filename) {
// We use a list for v files, because it's legal to have includes
@ -374,7 +364,12 @@ string V3Options::filePath(FileLine* fl, const string& modname, const string& la
void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) {
static bool shown_notfound_msg = false;
if (!shown_notfound_msg) {
if (modname.find("__Vhsh") != string::npos) {
std::cerr << V3Error::warnMore() << "... Unsupported: Name is longer than 127 characters;"
<< " automatic file lookup not supported.\n";
std::cerr << V3Error::warnMore() << "... Suggest putting filename with this module/package"
<< " onto command line instead.\n";
} else 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);
@ -943,6 +938,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
fl->v3fatal("Unknown --make system specified: '"<<argv[i]<<"'");
}
}
else if (!strcmp(sw, "-max-num-width")) {
shift;
m_maxNumWidth = atoi(argv[i]);
}
else if (!strcmp(sw, "-no-l2name")) { // Historical and undocumented
m_l2Name = "";
}
@ -1513,6 +1512,7 @@ V3Options::V3Options() {
m_gateStmts = 100;
m_ifDepth = 0;
m_inlineMult = 2000;
m_maxNumWidth = 65536;
m_moduleRecursion = 100;
m_outputSplit = 0;
m_outputSplitCFuncs = 0;
@ -1548,7 +1548,7 @@ V3Options::V3Options() {
}
V3Options::~V3Options() {
delete m_impp; m_impp = NULL;
VL_DO_CLEAR(delete m_impp, m_impp = NULL);
}
void V3Options::setDebugMode(int level) {

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