Merge from master for release.
This commit is contained in:
commit
39eea781bc
|
|
@ -104,7 +104,7 @@ SpacesInContainerLiterals: true
|
|||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp03
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
|
|
|
|||
|
|
@ -35,8 +35,9 @@ before_install:
|
|||
- clang++ -E -dM -c -x c++ /dev/null | sort
|
||||
|
||||
# Install all dependencies
|
||||
# We run twice to attempt on failure to recover from temp network problems
|
||||
install:
|
||||
- ./ci/travis-install.bash
|
||||
- ./ci/travis-install.bash || ./ci/travis-install.bash
|
||||
|
||||
before_script:
|
||||
# ccache maintenance
|
||||
|
|
|
|||
30
Changes
30
Changes
|
|
@ -2,6 +2,32 @@ Revision history for Verilator
|
|||
|
||||
The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
* Verilator 4.100 2020-09-07
|
||||
|
||||
** C++11 or newer compilers are now required.
|
||||
|
||||
** SystemC 2.3.0 or newer (SYSTEMC_VERSION >= 20111121) is now required.
|
||||
|
||||
** Support hierarchical Verilation (#2206). [Yutetsu TAKATSUKASA]
|
||||
|
||||
**** Support (with limitations) class extern, class extends, virtual class.
|
||||
|
||||
**** Support $urandom, $urandom_range without stability.
|
||||
|
||||
**** Fix false DECLFILENAME on black-boxed modules (#2430). [Philipp Wagner]
|
||||
|
||||
**** Fix naming of "id : begin" blocks.
|
||||
|
||||
**** Fix class constructor error on assignments to const.
|
||||
|
||||
**** Fix splitting eval functions with --output-split-cfuncs (#2368). [Geza Lore]
|
||||
|
||||
**** Fix queues as class members (#2525). [nanduraj1]
|
||||
|
||||
**** Add support for assume property. [Peter Monsson]
|
||||
|
||||
|
||||
* Verilator 4.040 2020-08-15
|
||||
|
||||
** Version 4.040 is planned to be the final version that will
|
||||
|
|
@ -31,6 +57,10 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
|||
|
||||
**** Fix SystemC net names (#2500). [Edgar E. Iglesias]
|
||||
|
||||
**** Fix build with Bison 3.7 and newer (#2505). [Rupert Swarbrick]
|
||||
|
||||
**** Fix slice of unpacked array (#2506) (#2507). [Yutetsu TAKATSUKASA]
|
||||
|
||||
|
||||
* Verilator 4.038 2020-07-11
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ datarootdir = @datarootdir@
|
|||
CFG_WITH_CCWARN = @CFG_WITH_CCWARN@
|
||||
CFG_WITH_DEFENV = @CFG_WITH_DEFENV@
|
||||
CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
|
||||
CFG_WITH_THREADED = @CFG_WITH_THREADED@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
|
@ -438,7 +437,7 @@ CPPCHECK_INC = -I$(srcdir)/include -I$(srcdir)/src/obj_dbg -I$(srcdir)/src
|
|||
|
||||
cppcheck: $(CPPCHECK_DEP)
|
||||
%.cppcheck: %.cpp
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 $(CPPCHECK_INC) $<
|
||||
$(CPPCHECK) $(CPPCHECK_FLAGS) -DVL_DEBUG=1 -DVL_CPPCHECK=1 -DVL_THREADED=1 $(CPPCHECK_INC) $<
|
||||
|
||||
CLANGTIDY = clang-tidy
|
||||
CLANGTIDY_FLAGS = -config=''
|
||||
|
|
@ -546,9 +545,6 @@ dist-file-list:
|
|||
@echo $(wildcard $(DISTFILES))
|
||||
@echo "end-dist-file-list:"; # Scripts look for this
|
||||
|
||||
print-cfg-with-threaded:
|
||||
@echo $(CFG_WITH_THREADED)
|
||||
|
||||
######################################################################
|
||||
# Distributions
|
||||
|
||||
|
|
|
|||
175
bin/verilator
175
bin/verilator
|
|
@ -327,6 +327,7 @@ arguments.
|
|||
--generate-key Create random key for --protect-key
|
||||
--getenv <var> Get environment variable with defaults
|
||||
--help Display this help
|
||||
--hierarchical Enable hierarchical Verilation
|
||||
-I<dir> Directory to search for includes
|
||||
-j <jobs> Parallelism for --build
|
||||
--gate-stmts <value> Tune gate optimizer depth
|
||||
|
|
@ -951,6 +952,12 @@ immediately. This can be useful in makefiles. See also -V, and the various
|
|||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=item --hierarchical
|
||||
|
||||
Enable hierarchical Verilation otherwise /*verilator hier_block*/ metacomment
|
||||
is ignored.
|
||||
See L</"HIERARCHICAL VERILATION">.
|
||||
|
||||
=item -II<dir>
|
||||
|
||||
See -y.
|
||||
|
|
@ -2010,7 +2017,7 @@ This is an example similar to the above, but using SystemC.
|
|||
#include "Vour.h"
|
||||
int sc_main(int argc, char** argv) {
|
||||
Verilated::commandArgs(argc, argv);
|
||||
sc_clock clk ("clk", 10, 0.5, 3, true);
|
||||
sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
|
||||
Vour* top;
|
||||
top = new Vour("top");
|
||||
top->clk(clk);
|
||||
|
|
@ -2208,10 +2215,13 @@ For --make gmake, it creates:
|
|||
|
||||
{prefix}.mk // Make include file for compiling
|
||||
{prefix}_classes.mk // Make include file with class names
|
||||
{prefix}_hier.mk // Make file for hierarchy blocks
|
||||
{prefix}_hierMkArgs.f // Arguments for hierarchical Verilation.
|
||||
|
||||
For --make cmake, it creates:
|
||||
|
||||
{prefix}.cmake // CMake include script for compiling
|
||||
{prefix}_hierCMakeArgs.f // Arguments for hierarchical Verilation.
|
||||
|
||||
For -cc and -sc mode, it also creates:
|
||||
|
||||
|
|
@ -2223,6 +2233,13 @@ For -cc and -sc mode, it also creates:
|
|||
{prefix}{each_verilog_module}.h // Lower level internal header files
|
||||
{prefix}{each_verilog_module}{__n}.cpp // Additional lower C++ files (--output-split)
|
||||
|
||||
For --hierarchy mode, it creates:
|
||||
{prefix}__hierVer.d // Make dependencies of the top module in the
|
||||
hierarchical Verilation
|
||||
{prefix}__hier.dir/ // Directory to store .dot, .vpp, .tree of the
|
||||
top module in the hierarchical Verilation
|
||||
V{hier_block}/ // Directory to Verilate each hierarchy block
|
||||
|
||||
In certain debug and other modes, it also creates:
|
||||
|
||||
{prefix}.xml // XML tree information (--xml)
|
||||
|
|
@ -2830,6 +2847,71 @@ here, use DIRECTORY or PREFIX.
|
|||
|
||||
=back
|
||||
|
||||
=head1 HIERARCHICAL VERILATION
|
||||
|
||||
Large designs may take long (e.g. 10+ minutes) and huge memory (e.g. 100+GB)
|
||||
to Verilate. One workaround is hierarchical Verilation, it is to Verilate
|
||||
each moderate size of building blocks and finally combine the building blocks.
|
||||
The building block will be called "hierarchy block" later.
|
||||
|
||||
The current hierarchical Verilation is based on protect-lib. Each hierarchy
|
||||
block is Verilated to protect-lib. User modules of the hierarchy blocks will see
|
||||
a tiny wrapper generated by protect-lib instead of the actual design.
|
||||
|
||||
=head2 Usage
|
||||
|
||||
All user need to do is mark moderate size of module as hierarchy block and pass
|
||||
--hierarchical option to verilator command.
|
||||
There are two ways to mark a module:
|
||||
|
||||
a) Write /* verilator hier_block */ metacomment in HDL code
|
||||
See L</"LANGUAGE EXTENSIONS"> for more detail.
|
||||
b) add hier_block line in the configuration file.
|
||||
See C<hier_block> in L</"CONFIGURATION FILES"> for example.
|
||||
|
||||
You don't have to take care of hierarchical blocks when compiling
|
||||
Verilated C++ code. You can compile as usual.
|
||||
make -C obj_dir -f Vtop_module_name.mk
|
||||
|
||||
See also "Overlapping Verilation and compilation" to get executable quickly.
|
||||
|
||||
=head2 Limitations
|
||||
|
||||
Because hierarchy blocks are Verilated to protect-lib, they have some
|
||||
limitations such as:
|
||||
|
||||
The block cannot be accessed using dot (.) from upper module.
|
||||
Signals in the block cannot be traced.
|
||||
Modport cannot be used at the hirarchical block boundary.
|
||||
|
||||
On the other hand, the following usage is supported.
|
||||
|
||||
- Nested hierarchy block. A hierarchy block may instantiate other
|
||||
hierarchy blocks.
|
||||
- Parameterized hierarchy block. Parameters of a hierarchy block can be
|
||||
overridden using #(.param_name(value)) construct.
|
||||
|
||||
The simulation speed may not be as fast as flat Verilation, in which
|
||||
all modules are globally scheduled.
|
||||
|
||||
=head2 Overlapping Verilation and compilation
|
||||
|
||||
Verilator needs to run N + 2 times in hierarchical Verilation, where N is
|
||||
the number of hierarchy blocks.
|
||||
1 of 2 is for the top module which refers wrappers of all other hierarchy
|
||||
blocks.
|
||||
The other 1 of 2 is the initial run that searches modules marked with
|
||||
/*verilator hier_block*/ metacomment and creates a plan and write in
|
||||
(prefix)_hier.mk.
|
||||
This initial run internally invokes other N + 1 runs, so you don't have
|
||||
to care about these N + 1 times of run.
|
||||
|
||||
If -j <jobs> option is specified, Verilation for hierarchy blocks
|
||||
runs in parallel.
|
||||
|
||||
If --build option is also specified, C++ compilation also runs as soon as
|
||||
a hierarchy block is Verilated. C++ compilation and Verilation for
|
||||
other hierarchy blocks run simultaneously.
|
||||
|
||||
=head1 MULTITHREADING
|
||||
|
||||
|
|
@ -3049,6 +3131,12 @@ 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 hier_block -module "<modulename>"
|
||||
|
||||
Specifies that the module is a unit of hierarchical Verilation.
|
||||
Note that the setting is ignored unless --hierachical option is specified.
|
||||
See L</"HIERARCHICAL VERILATION"> for more information.
|
||||
|
||||
=item inline -module "<modulename>"
|
||||
|
||||
Specifies the module may be inlined into any modules that use this module.
|
||||
|
|
@ -3397,6 +3485,17 @@ Specifies that following lines of code should have coverage re-enabled (if
|
|||
appropriate --coverage flags are passed) after being disabled earlier with
|
||||
/*verilator coverage_off*/.
|
||||
|
||||
=item /*verilator hier_block*/
|
||||
|
||||
Specifies that the module is a unit of hierarchical Verilation.
|
||||
This metacomment must be between
|
||||
"module module_name(...);" and "endmodule".
|
||||
The module will not be inlined nor uniquified for each instance in
|
||||
hierarchical Verilation.
|
||||
Note that the metacomment is ignored unless --hierachical option is specified.
|
||||
|
||||
See L</"HIERARCHICAL VERILATION"> for more information.
|
||||
|
||||
=item /*verilator inline_module*/
|
||||
|
||||
Specifies the module the comment appears in may be inlined into any modules
|
||||
|
|
@ -3591,10 +3690,11 @@ for more information.
|
|||
|
||||
=item /*verilator sc_clock*/
|
||||
|
||||
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.
|
||||
Deprecated and ignored. Previously 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 and is ignored.
|
||||
|
||||
=item /*verilator sc_bv*/
|
||||
|
||||
|
|
@ -3994,11 +4094,12 @@ All specify blocks and timing checks are ignored.
|
|||
Monitor and strobe are not supported, convert to always_comb $display or
|
||||
similar.
|
||||
|
||||
=item $random
|
||||
=item $random, $urandom, $urandom_range
|
||||
|
||||
$random does not support the optional argument to set the seed. Use the
|
||||
srand function in C to accomplish this, and note there is only one random
|
||||
number generator (not one per module).
|
||||
$random and $urandom do not support the optional argument to set the seed.
|
||||
Use +verilator+seed argument to set the seed. There is one random seed per
|
||||
C thread, not per module for $random, nor per object for random stability
|
||||
of $urandom/$urandom_range.
|
||||
|
||||
=item $readmemb, $readmemh
|
||||
|
||||
|
|
@ -4099,17 +4200,7 @@ default as a code style warning.
|
|||
=item BLKANDNBLK
|
||||
|
||||
BLKANDNBLK is an error that a variable comes from a mix of blocking and
|
||||
non-blocking assignments. Generally, this is caused by a register driven
|
||||
by both combo logic and a flop:
|
||||
|
||||
always @ (posedge clk) foo[0] <= ...
|
||||
always @* foo[1] = ...
|
||||
|
||||
Simply use a different register for the flop:
|
||||
|
||||
always @ (posedge clk) foo_flopped[0] <= ...
|
||||
always @* foo[0] = foo_flopped[0];
|
||||
always @* foo[1] = ...
|
||||
non-blocking assignments.
|
||||
|
||||
This is not illegal in SystemVerilog, but a violation of good coding
|
||||
practice. Verilator reports this as an error, because ignoring this warning
|
||||
|
|
@ -4120,6 +4211,24 @@ BLKANDNBLK" metacomment or the -Wno-BLKANDNBLK option) when one of the
|
|||
assignments is inside a public task, or when the blocking and non-blocking
|
||||
assignments have non-overlapping bits and structure members.
|
||||
|
||||
Generally, this is caused by a register driven by both combo logic and a
|
||||
flop:
|
||||
|
||||
logic [1:0] foo;
|
||||
always @ (posedge clk) foo[0] <= ...
|
||||
always @* foo[1] = ...
|
||||
|
||||
Simply use a different register for the flop:
|
||||
|
||||
logic [1:0] foo;
|
||||
always @ (posedge clk) foo_flopped[0] <= ...
|
||||
always @* foo[0] = foo_flopped[0];
|
||||
always @* foo[1] = ...
|
||||
|
||||
Or, this may also avoid the error:
|
||||
|
||||
logic [1:0] foo /*verilator split_var*/;
|
||||
|
||||
=item BLKSEQ
|
||||
|
||||
This indicates that a blocking assignment (=) is used in a sequential
|
||||
|
|
@ -4348,6 +4457,10 @@ Deprecated and no longer used as a warning. Used to indicate that the
|
|||
specified signal was is generated inside the model, and also being used as
|
||||
a clock.
|
||||
|
||||
=item HIERBLOCK
|
||||
|
||||
Warns that the top module is marked as a hierarchy block
|
||||
by hier_block metacomment, which is not legal. This setting on the top module will be ignored.
|
||||
=item IFDEPTH
|
||||
|
||||
Warns that if/if else statements have exceeded the depth specified with
|
||||
|
|
@ -4542,6 +4655,12 @@ signal.
|
|||
Disabled by default as this is a code style warning; it will simulate
|
||||
correctly.
|
||||
|
||||
=item PKGNODECL
|
||||
|
||||
Error that a package/class appears to have been referenced that has not yet
|
||||
been declared. According to IEEE 1800-2017 26.3 all packages must be
|
||||
declared before being used.
|
||||
|
||||
=item PROCASSWIRE
|
||||
|
||||
Error that a procedural assignment is setting a wire. According to IEEE, a
|
||||
|
|
@ -4932,19 +5051,11 @@ The following deprecated items are scheduled for future removal:
|
|||
|
||||
=over 4
|
||||
|
||||
=item Pre-C++11 compiler support
|
||||
=item C++11 compiler support
|
||||
|
||||
Verilator supports pre-C++11 compilers for non-threaded models when
|
||||
configured with --enable-prec11/--enable-prec11-final. 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.2 and earlier support
|
||||
|
||||
Support for SystemC versions 2.2 and earlier including the related sc_clock
|
||||
variable attribute will be removed no sooner than September 2020. The
|
||||
supported versions will be SystemC 2.3.0 (SYSTEMC_VERSION 20111121) and
|
||||
later (presently 2.3.0, 2.3.1, 2.3.2, 2.3.3).
|
||||
Verilator currently requires C++11 or newer compilers. Verilator will
|
||||
require C++14 or newer compilers for both compiling Verilator and compiling
|
||||
Verilated models no sooner than January 2022.
|
||||
|
||||
=item Configuration File -msg
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ if [ "$TRAVIS_BUILD_STAGE_NAME" = "build" ]; then
|
|||
if [ "$COVERAGE" != 1 ]; then
|
||||
autoconf
|
||||
./configure --enable-longtests --enable-ccwarn
|
||||
"$MAKE" -j "$NPROC"
|
||||
"$MAKE" -j "$NPROC" -k
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
file bin/verilator_bin
|
||||
file bin/verilator_bin_dbg
|
||||
|
|
@ -72,7 +72,7 @@ elif [ "$TRAVIS_BUILD_STAGE_NAME" = "test" ]; then
|
|||
# it as data rather than a Mach-O). Unclear if this is an OS X issue or
|
||||
# one for Travis. Remove the file and re-link...
|
||||
rm bin/verilator_bin_dbg
|
||||
"$MAKE" -j "$NPROC"
|
||||
"$MAKE" -j "$NPROC" -k
|
||||
elif [ "$TRAVIS_OS_NAME" = "freebsd" ]; then
|
||||
export VERILATOR_TEST_NO_GDB=1 # Disable for now, ideally should run
|
||||
export VERILATOR_TEST_NO_GPROF=1 # gprof is a bit different on FreeBSD, disable
|
||||
|
|
|
|||
65
configure.ac
65
configure.ac
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[4.040 2020-08-15],
|
||||
AC_INIT([Verilator],[4.100 2020-09-07],
|
||||
[https://verilator.org],
|
||||
[verilator],[https://verilator.org])
|
||||
# When releasing, also update header of Changes file
|
||||
|
|
@ -113,22 +113,6 @@ AC_ARG_ENABLE([longtests],
|
|||
AC_SUBST(CFG_WITH_LONGTESTS)
|
||||
AC_MSG_RESULT($CFG_WITH_LONGTESTS)
|
||||
|
||||
# CFG_WITH_PREC11
|
||||
AC_MSG_CHECKING(whether allow pre-C++11)
|
||||
AC_ARG_ENABLE([prec11-final],
|
||||
[AS_HELP_STRING([--enable-prec11-final],
|
||||
[enable pre-C++11 compilers for Verilator binary
|
||||
and Verilated makefiles])],
|
||||
[case "${enableval}" in
|
||||
yes) CFG_WITH_PREC11=yes ;;
|
||||
no) CFG_WITH_PREC11=no ;;
|
||||
*) AC_MSG_ERROR([bad value ${enableval} for --enable-prec11-final]) ;;
|
||||
esac],
|
||||
[CFG_WITH_PREC11=no;]
|
||||
)
|
||||
AC_SUBST(CFG_WITH_PREC11)
|
||||
AC_MSG_RESULT($CFG_WITH_PREC11)
|
||||
|
||||
# Compiler flags (ensure they are not empty to avoid configure defaults)
|
||||
CFLAGS+=" "
|
||||
CPPFLAGS+=" "
|
||||
|
|
@ -410,12 +394,17 @@ _MY_LDLIBS_CHECK_IFELSE(
|
|||
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"
|
||||
CXXFLAGS="$CXXFLAGS $CFG_CXXFLAGS_STD_NEWEST $CFG_CXXFLAGS_NO_UNUSED"
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([#include <thread>], [[ ]])],
|
||||
# Need C++11 at least
|
||||
#Alternative: AX_CXX_COMPILE_STDCXX([11])
|
||||
AC_DEFUN([_MY_CXX_CHECK_CXX_VER],
|
||||
[# _MY_CXX_CHECK_CXX_VER(flag) -- Check if compiler runs C++11
|
||||
# Set $_my_result
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([#include <thread>
|
||||
#if (__cplusplus < 201103L)
|
||||
# error "Too old"
|
||||
#endif
|
||||
], [[ ]])],
|
||||
[_my_result=yes
|
||||
if test -s conftest.err; then
|
||||
if grep -e "$1" conftest.err >/dev/null; then
|
||||
|
|
@ -423,24 +412,24 @@ AC_LINK_IFELSE(
|
|||
fi
|
||||
fi],
|
||||
[_my_result=no])
|
||||
CFG_WITH_THREADED=$_my_result
|
||||
AC_SUBST(CFG_WITH_THREADED)
|
||||
AC_MSG_RESULT($CFG_WITH_THREADED)
|
||||
CXXFLAGS="$ACO_SAVE_CXXFLAGS"
|
||||
])
|
||||
|
||||
# Check compiler flag
|
||||
if test "$CFG_WITH_THREADED" = "no" ; then
|
||||
if test "$CFG_WITH_PREC11" = "no" ; then
|
||||
AC_MSG_NOTICE([[]])
|
||||
AC_MSG_ERROR([[the $CXX compiler appears to not support C++11.
|
||||
AC_MSG_CHECKING(whether $CXX supports C++11)
|
||||
_MY_CXX_CHECK_CXX_VER()
|
||||
AC_MSG_RESULT($_my_result)
|
||||
if test "$_my_result" = "no" ; then
|
||||
CXXFLAGS="$CXXFLAGS $CFG_CXXFLAGS_STD_NEWEST"
|
||||
CFG_CXX_FLAGS_CMAKE="$CFG_CXX_FLAGS_CMAKE $CFG_CXXFLAGS_STD_NEWEST"
|
||||
AC_MSG_CHECKING(whether $CXX supports C++11 with $CFG_CXXFLAGS_STD_NEWEST)
|
||||
_MY_CXX_CHECK_CXX_VER()
|
||||
AC_MSG_RESULT($_my_result)
|
||||
fi
|
||||
if test "$_my_result" = "no" ; then
|
||||
AC_MSG_NOTICE([[]])
|
||||
AC_MSG_ERROR([[the $CXX compiler appears to not support C++11.
|
||||
|
||||
Verilator will require a C++11 or newer compiler for all releases starting
|
||||
September 2020. Please investigate a C++11 build environment now so you
|
||||
will be ready. Until then you may rerun configure with the
|
||||
--enable-prec11-final argument to enable reduced functionality with such
|
||||
older compilers. Thanks.]])
|
||||
Verilator requires a C++11 or newer compiler.]])
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
# Checks for library functions.
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ Pieter Kapsenberg
|
|||
Piotr Binkowski
|
||||
Qingyao Sun
|
||||
Richard Myers
|
||||
Rupert Swarbrick
|
||||
Sean Cross
|
||||
Sebastien Van Cauwenberghe
|
||||
Sergi Granell
|
||||
|
|
|
|||
|
|
@ -69,12 +69,12 @@ Linux distribution, see instead <<Install From a Package Manager>>.
|
|||
|
||||
=== OS Requirements
|
||||
|
||||
Verilator is developed and has primary testing on Ubuntu. Versions have
|
||||
also built on Redhat Linux, Apple OS-X, HPUX and Solaris. It should run
|
||||
with minor porting on any GNU/Linux-ish platform. Verilator also works on
|
||||
Windows under Cygwin, and Windows under MinGW (gcc -mno-cygwin). Verilated
|
||||
output (not Verilator itself) compiles under all the options above, plus
|
||||
MSVC++.
|
||||
Verilator is developed and has primary testing on Ubuntu, with additional
|
||||
testing on FreeBSD and Apple OS-X. Versions have also built on Redhat
|
||||
Linux, HPUX and Solaris. It should run with minor porting on any
|
||||
GNU/Linux-ish platform. Verilator also works on Windows under Cygwin, and
|
||||
Windows under MinGW (gcc -mno-cygwin). Verilated output (not Verilator
|
||||
itself) compiles under all the options above, plus MSVC++.
|
||||
|
||||
=== Install Prerequisites
|
||||
|
||||
|
|
|
|||
|
|
@ -387,10 +387,8 @@ changed; if clear, checking those signals for changes may be skipped.
|
|||
|
||||
=== Compiler Version and C++11
|
||||
|
||||
Verilator supports GCC 4.4.7 and newer. GCC 4.4.7 does not support C++11,
|
||||
therefore C++11 is generally not required. Exceptions may be made to
|
||||
require C++11 for features that are only practical with C++11,
|
||||
e.g. threads.
|
||||
Verilator requires C++11. Verilator does not require any newer versions,
|
||||
but is maintained to build successfully with C++14/C++17/C++20.
|
||||
|
||||
=== Indentation and Naming Style
|
||||
|
||||
|
|
|
|||
|
|
@ -29,19 +29,11 @@ int sc_main(int argc, char* argv[]) {
|
|||
Vtop* top = new Vtop("top");
|
||||
|
||||
// Initialize SC model
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_start(1, SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
|
||||
// Simulate until $finish
|
||||
while (!Verilated::gotFinish()) {
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_start(1, SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Final model cleanup
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ int main(int argc, char** argv, char** env) {
|
|||
|
||||
#if VM_TRACE
|
||||
// When tracing, the contents of the secret module will not be seen
|
||||
VerilatedVcdC* tfp = NULL;
|
||||
VerilatedVcdC* tfp = nullptr;
|
||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||
Verilated::traceEverOn(true);
|
||||
|
|
@ -62,13 +62,13 @@ int main(int argc, char** argv, char** env) {
|
|||
#if VM_TRACE
|
||||
if (tfp) {
|
||||
tfp->close();
|
||||
tfp = NULL;
|
||||
tfp = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Destroy model
|
||||
delete top;
|
||||
top = NULL;
|
||||
top = nullptr;
|
||||
|
||||
// Fin
|
||||
exit(0);
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ int main(int argc, char** argv, char** env) {
|
|||
|
||||
// Destroy model
|
||||
delete top;
|
||||
top = NULL;
|
||||
top = nullptr;
|
||||
|
||||
// Fin
|
||||
exit(0);
|
||||
|
|
|
|||
|
|
@ -44,21 +44,9 @@ int sc_main(int argc, char* argv[]) {
|
|||
// General logfile
|
||||
ios::sync_with_stdio();
|
||||
|
||||
// Defaults time
|
||||
#if (SYSTEMC_VERSION > 20011000)
|
||||
#else
|
||||
sc_time dut(1.0, sc_ns);
|
||||
sc_set_default_time_unit(dut);
|
||||
#endif
|
||||
|
||||
// Define clocks
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
|
||||
sc_clock fastclk("fastclk", 2, SC_NS, 0.5, 2, SC_NS, true);
|
||||
#else
|
||||
sc_clock clk("clk", 10, 0.5, 3, true);
|
||||
sc_clock fastclk("fastclk", 2, 0.5, 2, true);
|
||||
#endif
|
||||
|
||||
// Define interconnect
|
||||
sc_signal<bool> reset_l;
|
||||
|
|
@ -89,16 +77,12 @@ int sc_main(int argc, char* argv[]) {
|
|||
|
||||
// You must do one evaluation before enabling waves, in order to allow
|
||||
// SystemC to interconnect everything for testing.
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_start(1, SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
|
||||
#if VM_TRACE
|
||||
// If verilator was invoked with --trace argument,
|
||||
// and if at run time passed the +trace argument, turn on tracing
|
||||
VerilatedVcdSc* tfp = NULL;
|
||||
VerilatedVcdSc* tfp = nullptr;
|
||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||
|
|
@ -125,11 +109,7 @@ int sc_main(int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
// Simulate 1ns
|
||||
#if (SYSTEMC_VERSION >= 20070314)
|
||||
sc_start(1, SC_NS);
|
||||
#else
|
||||
sc_start(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Final model cleanup
|
||||
|
|
@ -139,7 +119,7 @@ int sc_main(int argc, char* argv[]) {
|
|||
#if VM_TRACE
|
||||
if (tfp) {
|
||||
tfp->close();
|
||||
tfp = NULL;
|
||||
tfp = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -151,7 +131,7 @@ int sc_main(int argc, char* argv[]) {
|
|||
|
||||
// Destroy model
|
||||
delete top;
|
||||
top = NULL;
|
||||
top = nullptr;
|
||||
|
||||
// Fin
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@
|
|||
#endif
|
||||
// clang-format on
|
||||
|
||||
#define VL_VALUE_STRING_MAX_WIDTH 8192 ///< Max static char array for VL_VALUE_STRING
|
||||
/// Max static char array for VL_VALUE_STRING
|
||||
constexpr unsigned VL_VALUE_STRING_MAX_WIDTH = 8192;
|
||||
|
||||
//===========================================================================
|
||||
// Static sanity checks (when get C++11 can use static_assert)
|
||||
|
|
@ -69,7 +70,12 @@ VL_THREAD_LOCAL Verilated::ThreadLocal Verilated::t_s;
|
|||
|
||||
Verilated::CommandArgValues Verilated::s_args;
|
||||
|
||||
VerilatedImp VerilatedImp::s_s;
|
||||
VerilatedImp::VerilatedImpU VerilatedImp::s_s;
|
||||
|
||||
struct VerilatedImpInitializer {
|
||||
VerilatedImpInitializer() { VerilatedImp::setup(); }
|
||||
~VerilatedImpInitializer() { VerilatedImp::teardown(); }
|
||||
} g_VerilatedImpInitializer;
|
||||
|
||||
//===========================================================================
|
||||
// User definable functions
|
||||
|
|
@ -176,7 +182,7 @@ void VL_FATAL_MT(const char* filename, int linenum, const char* hier, const char
|
|||
std::string _vl_string_vprintf(const char* formatp, va_list ap) VL_MT_SAFE {
|
||||
va_list aq;
|
||||
va_copy(aq, ap);
|
||||
int len = VL_VSNPRINTF(NULL, 0, formatp, aq);
|
||||
int len = VL_VSNPRINTF(nullptr, 0, formatp, aq);
|
||||
va_end(aq);
|
||||
if (VL_UNLIKELY(len < 1)) return "";
|
||||
|
||||
|
|
@ -255,19 +261,17 @@ Verilated::Serialized::Serialized() {
|
|||
}
|
||||
|
||||
Verilated::NonSerialized::NonSerialized() {
|
||||
s_profThreadsStart = 1;
|
||||
s_profThreadsWindow = 2;
|
||||
s_profThreadsFilenamep = strdup("profile_threads.dat");
|
||||
}
|
||||
Verilated::NonSerialized::~NonSerialized() {
|
||||
if (s_profThreadsFilenamep) {
|
||||
VL_DO_CLEAR(free(const_cast<char*>(s_profThreadsFilenamep)),
|
||||
s_profThreadsFilenamep = NULL);
|
||||
s_profThreadsFilenamep = nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Verilated::serialized2Size() VL_PURE { return sizeof(VerilatedImp::s_s.m_ser); }
|
||||
void* Verilated::serialized2Ptr() VL_MT_UNSAFE { return &VerilatedImp::s_s.m_ser; }
|
||||
size_t Verilated::serialized2Size() VL_PURE { return sizeof(VerilatedImp::s_s.v.m_ser); }
|
||||
void* Verilated::serialized2Ptr() VL_MT_UNSAFE { return &VerilatedImp::s_s.v.m_ser; }
|
||||
|
||||
//===========================================================================
|
||||
// Random -- Mostly called at init time, so not inline.
|
||||
|
|
@ -316,8 +320,6 @@ vluint64_t vl_rand64() VL_MT_SAFE {
|
|||
return result;
|
||||
}
|
||||
|
||||
IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); }
|
||||
QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); }
|
||||
// VL_RANDOM_W currently unused as $random always 32 bits, left for backwards compatibility
|
||||
// LCOV_EXCL_START
|
||||
WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||
|
|
@ -687,7 +689,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
|||
// Note also assumes variables < 64 are not wide, this assumption is
|
||||
// sometimes not true in low-level routines written here in verilated.cpp
|
||||
static VL_THREAD_LOCAL char tmp[VL_VALUE_STRING_MAX_WIDTH];
|
||||
const char* pctp = NULL; // Most recent %##.##g format
|
||||
const char* pctp = nullptr; // Most recent %##.##g format
|
||||
bool inPct = false;
|
||||
bool widthSet = false;
|
||||
bool left = false;
|
||||
|
|
@ -766,8 +768,8 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
|||
if (!widthSet) width = VerilatedImp::timeFormatWidth();
|
||||
output += _vl_vsformat_time(tmp, d, left, width);
|
||||
} else {
|
||||
std::string fmt(pctp, pos - pctp + 1);
|
||||
sprintf(tmp, fmt.c_str(), d);
|
||||
std::string fmts(pctp, pos - pctp + 1);
|
||||
sprintf(tmp, fmts.c_str(), d);
|
||||
output += tmp;
|
||||
}
|
||||
break;
|
||||
|
|
@ -777,7 +779,7 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
|||
const int lbits = va_arg(ap, int);
|
||||
QData ld = 0;
|
||||
WData qlwp[VL_WQ_WORDS_E];
|
||||
WDataInP lwp = NULL;
|
||||
WDataInP lwp = nullptr;
|
||||
if (lbits <= VL_QUADSIZE) {
|
||||
ld = _VL_VA_ARG_Q(ap, lbits);
|
||||
VL_SET_WQ(qlwp, ld);
|
||||
|
|
@ -947,7 +949,7 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, WDataInP fromp,
|
|||
} else {
|
||||
if (floc < 0) return EOF;
|
||||
floc = floc & ~7; // Align to closest character
|
||||
if (fromp == NULL) {
|
||||
if (fromp == nullptr) {
|
||||
return fstr[fstr.length() - 1 - (floc >> 3)];
|
||||
} else {
|
||||
return VL_BITRSHIFT_W(fromp, floc) & 0xff;
|
||||
|
|
@ -969,7 +971,7 @@ static inline void _vl_vsss_read_str(FILE* fp, int& floc, WDataInP fromp, const
|
|||
while (true) {
|
||||
int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
if (c == EOF || isspace(c)) break;
|
||||
if (acceptp && NULL == strchr(acceptp, c)) break; // String - allow anything
|
||||
if (acceptp && nullptr == strchr(acceptp, c)) break; // String - allow anything
|
||||
if (acceptp) c = tolower(c); // Non-strings we'll simplify
|
||||
*cp++ = c;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
|
|
@ -984,7 +986,7 @@ static inline char* _vl_vsss_read_bin(FILE* fp, int& floc, WDataInP fromp, const
|
|||
// whitespace). In the fp case, except descriptor to have been opened in binary mode.
|
||||
while (n-- > 0) {
|
||||
const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
if (c == EOF) return NULL;
|
||||
if (c == EOF) return nullptr;
|
||||
if (!inhibit) *beginp++ = c;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
}
|
||||
|
|
@ -1088,7 +1090,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||
}
|
||||
case 's': {
|
||||
_vl_vsss_skipspace(fp, floc, fromp, fstr);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, NULL);
|
||||
_vl_vsss_read_str(fp, floc, fromp, fstr, tmp, nullptr);
|
||||
if (!tmp[0]) goto done;
|
||||
int lpos = (static_cast<int>(strlen(tmp))) - 1;
|
||||
int lsb = 0;
|
||||
|
|
@ -1118,7 +1120,7 @@ IData _vl_vsscanf(FILE* fp, // If a fscanf
|
|||
double r;
|
||||
vlsint64_t ld;
|
||||
} u;
|
||||
u.r = strtod(tmp, NULL);
|
||||
u.r = strtod(tmp, nullptr);
|
||||
VL_SET_WQ(owp, u.ld);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1409,7 +1411,7 @@ IData VL_FSCANF_IX(IData fpi, const char* formatp, ...) VL_MT_SAFE {
|
|||
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
IData got = _vl_vsscanf(fp, 0, NULL, "", formatp, ap);
|
||||
IData got = _vl_vsscanf(fp, 0, nullptr, "", formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
|
|
@ -1420,7 +1422,7 @@ IData VL_SSCANF_IIX(int lbits, IData ld, const char* formatp, ...) VL_MT_SAFE {
|
|||
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
IData got = _vl_vsscanf(NULL, lbits, fnw, "", formatp, ap);
|
||||
IData got = _vl_vsscanf(nullptr, lbits, fnw, "", formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
|
|
@ -1430,21 +1432,21 @@ IData VL_SSCANF_IQX(int lbits, QData ld, const char* formatp, ...) VL_MT_SAFE {
|
|||
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
IData got = _vl_vsscanf(NULL, lbits, fnw, "", formatp, ap);
|
||||
IData got = _vl_vsscanf(nullptr, lbits, fnw, "", formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
IData VL_SSCANF_IWX(int lbits, WDataInP lwp, const char* formatp, ...) VL_MT_SAFE {
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
IData got = _vl_vsscanf(NULL, lbits, lwp, "", formatp, ap);
|
||||
IData got = _vl_vsscanf(nullptr, lbits, lwp, "", formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_SAFE {
|
||||
va_list ap;
|
||||
va_start(ap, formatp);
|
||||
IData got = _vl_vsscanf(NULL, ld.length() * 8, NULL, ld, formatp, ap);
|
||||
IData got = _vl_vsscanf(nullptr, ld.length() * 8, nullptr, ld, formatp, ap);
|
||||
va_end(ap);
|
||||
return got;
|
||||
}
|
||||
|
|
@ -1621,7 +1623,7 @@ IData VL_VALUEPLUSARGS_INN(int, const std::string& ld, std::string& rdr) VL_MT_S
|
|||
const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE {
|
||||
const std::string& match = VerilatedImp::argPlusMatch(prefixp);
|
||||
static VL_THREAD_LOCAL char outstr[VL_VALUE_STRING_MAX_WIDTH];
|
||||
if (match.empty()) return NULL;
|
||||
if (match.empty()) return nullptr;
|
||||
outstr[0] = '\0';
|
||||
strncat(outstr, match.c_str() + strlen(prefixp) + 1, // +1 to skip the "+"
|
||||
VL_VALUE_STRING_MAX_WIDTH - 1);
|
||||
|
|
@ -1641,12 +1643,12 @@ std::string VL_TO_STRING_W(int words, WDataInP obj) {
|
|||
|
||||
std::string VL_TOLOWER_NN(const std::string& ld) VL_MT_SAFE {
|
||||
std::string out = ld;
|
||||
for (std::string::iterator it = out.begin(); it != out.end(); ++it) *it = tolower(*it);
|
||||
for (auto& cr : out) cr = tolower(cr);
|
||||
return out;
|
||||
}
|
||||
std::string VL_TOUPPER_NN(const std::string& ld) VL_MT_SAFE {
|
||||
std::string out = ld;
|
||||
for (std::string::iterator it = out.begin(); it != out.end(); ++it) *it = toupper(*it);
|
||||
for (auto& cr : out) cr = toupper(cr);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
@ -1701,7 +1703,7 @@ IData VL_ATOI_N(const std::string& str, int base) VL_PURE {
|
|||
str_mod.erase(std::remove(str_mod.begin(), str_mod.end(), '_'), str_mod.end());
|
||||
|
||||
errno = 0;
|
||||
long v = std::strtol(str_mod.c_str(), NULL, base);
|
||||
auto v = std::strtol(str_mod.c_str(), nullptr, base);
|
||||
if (errno != 0) v = 0;
|
||||
return static_cast<IData>(v);
|
||||
}
|
||||
|
|
@ -1759,24 +1761,24 @@ static const char* formatBinary(int nBits, vluint32_t bits) {
|
|||
}
|
||||
|
||||
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_hex{hex}
|
||||
, m_bits{bits}
|
||||
, m_filename(filename) // Need () or GCC 4.8 false warning
|
||||
, 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
|
||||
// cppcheck-suppress resourceLeak // m_fp is nullptr - bug in cppcheck
|
||||
return;
|
||||
}
|
||||
}
|
||||
VlReadMem::~VlReadMem() {
|
||||
if (m_fp) {
|
||||
fclose(m_fp);
|
||||
m_fp = NULL;
|
||||
m_fp = nullptr;
|
||||
}
|
||||
}
|
||||
bool VlReadMem::get(QData& addrr, std::string& valuer) {
|
||||
|
|
@ -1864,8 +1866,8 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
|
|||
QData shift = m_hex ? 4ULL : 1ULL;
|
||||
bool innum = false;
|
||||
// Shift value in
|
||||
for (std::string::const_iterator it = rhs.begin(); it != rhs.end(); ++it) {
|
||||
char c = tolower(*it);
|
||||
for (const auto& i : rhs) {
|
||||
char c = tolower(i);
|
||||
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);
|
||||
|
|
@ -1895,9 +1897,9 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
|
|||
}
|
||||
|
||||
VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end)
|
||||
: m_hex(hex)
|
||||
, m_bits(bits)
|
||||
, m_addr(0) {
|
||||
: m_hex{hex}
|
||||
, m_bits{bits}
|
||||
, m_addr{0} {
|
||||
if (VL_UNLIKELY(start > end)) {
|
||||
VL_FATAL_MT(filename.c_str(), 0, "", "$writemem invalid address range");
|
||||
return;
|
||||
|
|
@ -1906,14 +1908,14 @@ VlWriteMem::VlWriteMem(bool hex, int bits, const std::string& filename, QData st
|
|||
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
|
||||
// cppcheck-suppress resourceLeak // m_fp is nullptr - bug in cppcheck
|
||||
return;
|
||||
}
|
||||
}
|
||||
VlWriteMem::~VlWriteMem() {
|
||||
if (m_fp) {
|
||||
fclose(m_fp);
|
||||
m_fp = NULL;
|
||||
m_fp = nullptr;
|
||||
}
|
||||
}
|
||||
void VlWriteMem::print(QData addr, bool addrstamp, const void* valuep) {
|
||||
|
|
@ -2174,17 +2176,7 @@ void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix,
|
|||
//===========================================================================
|
||||
// Verilated:: Methods
|
||||
|
||||
Verilated::ThreadLocal::ThreadLocal()
|
||||
:
|
||||
#ifdef VL_THREADED
|
||||
t_mtaskId(0)
|
||||
, t_endOfEvalReqd(0)
|
||||
,
|
||||
#endif
|
||||
t_dpiScopep(NULL)
|
||||
, t_dpiFilename(0)
|
||||
, t_dpiLineno(0) {
|
||||
}
|
||||
Verilated::ThreadLocal::ThreadLocal() {}
|
||||
Verilated::ThreadLocal::~ThreadLocal() {}
|
||||
|
||||
void Verilated::debug(int level) VL_MT_SAFE {
|
||||
|
|
@ -2291,7 +2283,7 @@ void Verilated::profThreadsFilenamep(const char* flagp) VL_MT_SAFE {
|
|||
const char* Verilated::catName(const char* n1, const char* n2, const char* delimiter) VL_MT_SAFE {
|
||||
// Returns new'ed data
|
||||
// Used by symbol table creation to make module names
|
||||
static VL_THREAD_LOCAL char* strp = NULL;
|
||||
static VL_THREAD_LOCAL char* strp = nullptr;
|
||||
static VL_THREAD_LOCAL size_t len = 0;
|
||||
size_t newlen = strlen(n1) + strlen(n2) + strlen(delimiter) + 1;
|
||||
if (!strp || newlen > len) {
|
||||
|
|
@ -2310,7 +2302,7 @@ const char* Verilated::catName(const char* n1, const char* n2, const char* delim
|
|||
|
||||
// Keeping these out of class Verilated to avoid having to include <list>
|
||||
// in verilated.h (for compilation speed)
|
||||
typedef std::list<std::pair<Verilated::VoidPCb, void*> > VoidPCbList;
|
||||
typedef std::list<std::pair<Verilated::VoidPCb, void*>> VoidPCbList;
|
||||
static VoidPCbList g_flushCbs;
|
||||
static VoidPCbList g_exitCbs;
|
||||
|
||||
|
|
@ -2324,7 +2316,7 @@ static void removeCb(Verilated::VoidPCb cb, void* datap, VoidPCbList& cbs) {
|
|||
cbs.remove(pair);
|
||||
}
|
||||
static void runCallbacks(VoidPCbList& cbs) VL_MT_SAFE {
|
||||
for (VoidPCbList::iterator it = cbs.begin(); it != cbs.end(); ++it) { it->first(it->second); }
|
||||
for (const auto& i : cbs) i.first(i.second);
|
||||
}
|
||||
|
||||
void Verilated::addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE {
|
||||
|
|
@ -2435,31 +2427,60 @@ void Verilated::endOfEvalGuts(VerilatedEvalMsgQueue* evalMsgQp) VL_MT_SAFE {
|
|||
}
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
// VerilatedImp:: Constructors
|
||||
|
||||
// verilated.o may exist both in protect-lib and main module.
|
||||
// Both the main module and the protec-lib refer the same instance of
|
||||
// static variables such as Verilated or VerilatedImplData.
|
||||
// This is important to share the state such as Verilated::gotFinish.
|
||||
// But the sharing may cause double-free error when shutting down because destructors
|
||||
// are called twice.
|
||||
// 1st time:From protec-lib shared object on the way of unloading after exitting main()
|
||||
// 2nd time:From main executable.
|
||||
//
|
||||
// To avoid the trouble, all member variables are enclosed in VerilatedImpU union.
|
||||
// ctor nor dtor of members are not called automatically.
|
||||
// VerilatedImp::setup() and teardown() guarantees to initialize/destruct just once.
|
||||
|
||||
void VerilatedImp::setup() {
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
new (&VerilatedImp::s_s) VerilatedImpData();
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
void VerilatedImp::teardown() {
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
VerilatedImp::s_s.~VerilatedImpU();
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// VerilatedImp:: Methods
|
||||
|
||||
std::string VerilatedImp::timeFormatSuffix() VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_sergMutex);
|
||||
return s_s.m_serg.m_timeFormatSuffix;
|
||||
const VerilatedLockGuard lock(s_s.v.m_sergMutex);
|
||||
return s_s.v.m_serg.m_timeFormatSuffix;
|
||||
}
|
||||
void VerilatedImp::timeFormatSuffix(const std::string& value) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_sergMutex);
|
||||
s_s.m_serg.m_timeFormatSuffix = value;
|
||||
const VerilatedLockGuard lock(s_s.v.m_sergMutex);
|
||||
s_s.v.m_serg.m_timeFormatSuffix = value;
|
||||
}
|
||||
void VerilatedImp::timeFormatUnits(int value) VL_MT_SAFE { s_s.m_ser.m_timeFormatUnits = value; }
|
||||
void VerilatedImp::timeFormatUnits(int value) VL_MT_SAFE { s_s.v.m_ser.m_timeFormatUnits = value; }
|
||||
void VerilatedImp::timeFormatPrecision(int value) VL_MT_SAFE {
|
||||
s_s.m_ser.m_timeFormatPrecision = value;
|
||||
s_s.v.m_ser.m_timeFormatPrecision = value;
|
||||
}
|
||||
void VerilatedImp::timeFormatWidth(int value) VL_MT_SAFE { s_s.m_ser.m_timeFormatWidth = value; }
|
||||
void VerilatedImp::timeFormatWidth(int value) VL_MT_SAFE { s_s.v.m_ser.m_timeFormatWidth = value; }
|
||||
|
||||
void VerilatedImp::internalsDump() VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_argMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_argMutex);
|
||||
VL_PRINTF_MT("internalsDump:\n");
|
||||
versionDump();
|
||||
VL_PRINTF_MT(" Argv:");
|
||||
for (ArgVec::const_iterator it = s_s.m_argVec.begin(); it != s_s.m_argVec.end(); ++it) {
|
||||
VL_PRINTF_MT(" %s", it->c_str());
|
||||
}
|
||||
for (const auto& i : s_s.v.m_argVec) VL_PRINTF_MT(" %s", i.c_str());
|
||||
VL_PRINTF_MT("\n");
|
||||
scopesDump();
|
||||
exportsDump();
|
||||
|
|
@ -2469,22 +2490,22 @@ void VerilatedImp::versionDump() VL_MT_SAFE {
|
|||
VL_PRINTF_MT(" Version: %s %s\n", Verilated::productName(), Verilated::productVersion());
|
||||
}
|
||||
|
||||
void VerilatedImp::commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
|
||||
const VerilatedLockGuard lock(s_s.m_argMutex);
|
||||
s_s.m_argVec.clear(); // Always clear
|
||||
void VerilatedImp::commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.v.m_argMutex) {
|
||||
const VerilatedLockGuard lock(s_s.v.m_argMutex);
|
||||
s_s.v.m_argVec.clear(); // Always clear
|
||||
commandArgsAddGuts(argc, argv);
|
||||
}
|
||||
void VerilatedImp::commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex) {
|
||||
const VerilatedLockGuard lock(s_s.m_argMutex);
|
||||
void VerilatedImp::commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.v.m_argMutex) {
|
||||
const VerilatedLockGuard lock(s_s.v.m_argMutex);
|
||||
commandArgsAddGuts(argc, argv);
|
||||
}
|
||||
void VerilatedImp::commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex) {
|
||||
if (!s_s.m_argVecLoaded) s_s.m_argVec.clear();
|
||||
void VerilatedImp::commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.v.m_argMutex) {
|
||||
if (!s_s.v.m_argVecLoaded) s_s.v.m_argVec.clear();
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
s_s.m_argVec.push_back(argv[i]);
|
||||
s_s.v.m_argVec.push_back(argv[i]);
|
||||
commandArgVl(argv[i]);
|
||||
}
|
||||
s_s.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||
s_s.v.m_argVecLoaded = true; // Can't just test later for empty vector, no arguments is ok
|
||||
}
|
||||
void VerilatedImp::commandArgVl(const std::string& arg) {
|
||||
if (0 == strncmp(arg.c_str(), "+verilator+", strlen("+verilator+"))) {
|
||||
|
|
@ -2554,12 +2575,12 @@ VerilatedSyms::~VerilatedSyms() {
|
|||
// VerilatedModule:: Methods
|
||||
|
||||
VerilatedModule::VerilatedModule(const char* namep)
|
||||
: m_namep(strdup(namep)) {}
|
||||
: m_namep{strdup(namep)} {}
|
||||
|
||||
VerilatedModule::~VerilatedModule() {
|
||||
// Memory cleanup - not called during normal operation
|
||||
// NOLINTNEXTLINE(google-readability-casting)
|
||||
if (m_namep) VL_DO_CLEAR(free((void*)(m_namep)), m_namep = NULL);
|
||||
if (m_namep) VL_DO_CLEAR(free((void*)(m_namep)), m_namep = nullptr);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
|
@ -2587,8 +2608,8 @@ size_t VerilatedVarProps::totalSize() const {
|
|||
}
|
||||
|
||||
void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const {
|
||||
if (VL_UNLIKELY(dim <= 0 || dim > udims())) return NULL;
|
||||
if (VL_UNLIKELY(indx < low(dim) || indx > high(dim))) return NULL;
|
||||
if (VL_UNLIKELY(dim <= 0 || dim > udims())) return nullptr;
|
||||
if (VL_UNLIKELY(indx < low(dim) || indx > high(dim))) return nullptr;
|
||||
int indxAdj = indx - low(dim);
|
||||
vluint8_t* bytep = reinterpret_cast<vluint8_t*>(datap);
|
||||
// If on index 1 of a 2 index array, then each index 1 is index2sz*entsz
|
||||
|
|
@ -2601,23 +2622,14 @@ void* VerilatedVarProps::datapAdjustIndex(void* datap, int dim, int indx) const
|
|||
//======================================================================
|
||||
// VerilatedScope:: Methods
|
||||
|
||||
VerilatedScope::VerilatedScope() {
|
||||
m_callbacksp = NULL;
|
||||
m_namep = NULL;
|
||||
m_identifierp = NULL;
|
||||
m_funcnumMax = 0;
|
||||
m_symsp = NULL;
|
||||
m_varsp = NULL;
|
||||
m_timeunit = 0;
|
||||
m_type = SCOPE_OTHER;
|
||||
}
|
||||
VerilatedScope::VerilatedScope() {}
|
||||
|
||||
VerilatedScope::~VerilatedScope() {
|
||||
// Memory cleanup - not called during normal operation
|
||||
VerilatedImp::scopeErase(this);
|
||||
if (m_namep) VL_DO_CLEAR(delete[] m_namep, m_namep = NULL);
|
||||
if (m_callbacksp) VL_DO_CLEAR(delete[] m_callbacksp, m_callbacksp = NULL);
|
||||
if (m_varsp) VL_DO_CLEAR(delete m_varsp, m_varsp = NULL);
|
||||
if (m_namep) VL_DO_CLEAR(delete[] m_namep, m_namep = nullptr);
|
||||
if (m_callbacksp) VL_DO_CLEAR(delete[] m_callbacksp, m_callbacksp = nullptr);
|
||||
if (m_varsp) VL_DO_CLEAR(delete m_varsp, m_varsp = nullptr);
|
||||
m_funcnumMax = 0; // Force callback table to empty
|
||||
}
|
||||
|
||||
|
|
@ -2696,10 +2708,10 @@ void VerilatedScope::varInsert(int finalize, const char* namep, void* datap, boo
|
|||
// cppcheck-suppress unusedFunction // Used by applications
|
||||
VerilatedVar* VerilatedScope::varFind(const char* namep) const VL_MT_SAFE_POSTINIT {
|
||||
if (VL_LIKELY(m_varsp)) {
|
||||
VerilatedVarNameMap::iterator it = m_varsp->find(namep);
|
||||
const auto it = m_varsp->find(namep);
|
||||
if (VL_LIKELY(it != m_varsp->end())) return &(it->second);
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
|
||||
|
|
@ -2708,7 +2720,7 @@ void* VerilatedScope::exportFindNullError(int funcnum) VL_MT_SAFE {
|
|||
+ "' 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;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* VerilatedScope::exportFindError(int funcnum) const {
|
||||
|
|
@ -2717,7 +2729,7 @@ void* VerilatedScope::exportFindError(int funcnum) const {
|
|||
+ "' but this DPI export function exists only in other scopes, not scope '"
|
||||
+ name() + "'");
|
||||
VL_FATAL_MT("unknown", 0, "", msg.c_str());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VerilatedScope::scopeDump() const {
|
||||
|
|
@ -2729,9 +2741,7 @@ void VerilatedScope::scopeDump() const {
|
|||
}
|
||||
}
|
||||
if (VerilatedVarNameMap* varsp = this->varsp()) {
|
||||
for (VerilatedVarNameMap::const_iterator it = varsp->begin(); it != varsp->end(); ++it) {
|
||||
VL_PRINTF_MT(" VAR %p: %s\n", &(it->second), it->first);
|
||||
}
|
||||
for (const auto& i : *varsp) VL_PRINTF_MT(" VAR %p: %s\n", &(i.second), i.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
// Version check
|
||||
#if defined(SYSTEMC_VERSION) && (SYSTEMC_VERSION < 20111121)
|
||||
# warning "Verilator soon requires SystemC 2.3.*; see manual for deprecated other versions."
|
||||
# warning "Verilator requires SystemC 2.3.* or newer."
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ class VerilatedVcdSc;
|
|||
class VerilatedFst;
|
||||
class VerilatedFstC;
|
||||
|
||||
enum VerilatedVarType {
|
||||
enum VerilatedVarType : vluint8_t {
|
||||
VLVT_UNKNOWN = 0,
|
||||
VLVT_PTR, // Pointer to something
|
||||
VLVT_UINT8, // AKA CData
|
||||
|
|
@ -163,7 +163,7 @@ private:
|
|||
|
||||
public:
|
||||
explicit VerilatedLockGuard(VerilatedMutex& mutexr) VL_ACQUIRE(mutexr)
|
||||
: m_mutexr(mutexr) {
|
||||
: m_mutexr(mutexr) { // Need () or GCC 4.8 false warning
|
||||
m_mutexr.lock();
|
||||
}
|
||||
~VerilatedLockGuard() VL_RELEASE() { m_mutexr.unlock(); }
|
||||
|
|
@ -203,7 +203,7 @@ public:
|
|||
/// The constructor establishes the thread id for all later calls.
|
||||
/// If necessary, a different class could be made that inits it otherwise.
|
||||
VerilatedAssertOneThread()
|
||||
: m_threadid(VL_THREAD_ID()) {}
|
||||
: m_threadid{VL_THREAD_ID()} {}
|
||||
~VerilatedAssertOneThread() { check(); }
|
||||
// METHODS
|
||||
/// Check that the current thread ID is the same as the construction thread ID
|
||||
|
|
@ -313,21 +313,21 @@ public: // But for internal use only
|
|||
|
||||
class VerilatedScope {
|
||||
public:
|
||||
typedef enum {
|
||||
typedef enum : vluint8_t {
|
||||
SCOPE_MODULE,
|
||||
SCOPE_OTHER
|
||||
} Type; // Type of a scope, currently module is only interesting
|
||||
private:
|
||||
// Fastpath:
|
||||
VerilatedSyms* m_symsp; ///< Symbol table
|
||||
void** m_callbacksp; ///< Callback table pointer (Fastpath)
|
||||
int m_funcnumMax; ///< Maxium function number stored (Fastpath)
|
||||
VerilatedSyms* m_symsp = nullptr; ///< Symbol table
|
||||
void** m_callbacksp = nullptr; ///< Callback table pointer (Fastpath)
|
||||
int m_funcnumMax = 0; ///< Maxium function number stored (Fastpath)
|
||||
// 4 bytes padding (on -m64), for rent.
|
||||
VerilatedVarNameMap* m_varsp; ///< Variable map
|
||||
const char* m_namep; ///< Scope name (Slowpath)
|
||||
const char* m_identifierp; ///< Identifier of scope (with escapes removed)
|
||||
vlsint8_t m_timeunit; ///< Timeunit in negative power-of-10
|
||||
Type m_type; ///< Type of the scope
|
||||
VerilatedVarNameMap* m_varsp = nullptr; ///< Variable map
|
||||
const char* m_namep = nullptr; ///< Scope name (Slowpath)
|
||||
const char* m_identifierp = nullptr; ///< Identifier of scope (with escapes removed)
|
||||
vlsint8_t m_timeunit = 0; ///< Timeunit in negative power-of-10
|
||||
Type m_type = SCOPE_OTHER; ///< Type of the scope
|
||||
|
||||
public: // But internals only - called from VerilatedModule's
|
||||
VerilatedScope();
|
||||
|
|
@ -393,8 +393,8 @@ class Verilated {
|
|||
static struct NonSerialized { // Non-serialized information
|
||||
// These are reloaded from on command-line settings, so do not need to persist
|
||||
// Fast path
|
||||
vluint64_t s_profThreadsStart; ///< +prof+threads starting time
|
||||
vluint32_t s_profThreadsWindow; ///< +prof+threads window size
|
||||
vluint64_t s_profThreadsStart = 1; ///< +prof+threads starting time
|
||||
vluint32_t s_profThreadsWindow = 2; ///< +prof+threads window size
|
||||
// Slow path
|
||||
const char* s_profThreadsFilenamep; ///< +prof+threads filename
|
||||
NonSerialized();
|
||||
|
|
@ -405,23 +405,22 @@ class Verilated {
|
|||
// assumption is that the restore is allowed to pass different arguments
|
||||
static struct CommandArgValues {
|
||||
VerilatedMutex m_argMutex; ///< Mutex for s_args members, when VL_THREADED
|
||||
int argc;
|
||||
const char** argv;
|
||||
CommandArgValues()
|
||||
: argc(0)
|
||||
, argv(NULL) {}
|
||||
int argc = 0;
|
||||
const char** argv = nullptr;
|
||||
CommandArgValues() {}
|
||||
~CommandArgValues() {}
|
||||
} s_args;
|
||||
|
||||
// Not covered by mutex, as per-thread
|
||||
static VL_THREAD_LOCAL struct ThreadLocal {
|
||||
#ifdef VL_THREADED
|
||||
vluint32_t t_mtaskId; ///< Current mtask# executing on this thread
|
||||
vluint32_t t_endOfEvalReqd; ///< Messages may be pending, thread needs endOf-eval calls
|
||||
vluint32_t t_mtaskId = 0; ///< Current mtask# executing on this thread
|
||||
vluint32_t t_endOfEvalReqd
|
||||
= 0; ///< Messages may be pending, thread needs endOf-eval calls
|
||||
#endif
|
||||
const VerilatedScope* t_dpiScopep; ///< DPI context scope
|
||||
const char* t_dpiFilename; ///< DPI context filename
|
||||
int t_dpiLineno; ///< DPI context line number
|
||||
const VerilatedScope* t_dpiScopep = nullptr; ///< DPI context scope
|
||||
const char* t_dpiFilename = nullptr; ///< DPI context filename
|
||||
int t_dpiLineno = 0; ///< DPI context line number
|
||||
|
||||
ThreadLocal();
|
||||
~ThreadLocal();
|
||||
|
|
@ -561,8 +560,8 @@ public:
|
|||
t_s.t_dpiFilename = filenamep;
|
||||
t_s.t_dpiLineno = lineno;
|
||||
}
|
||||
static void dpiClearContext() VL_MT_SAFE { t_s.t_dpiScopep = NULL; }
|
||||
static bool dpiInContext() VL_MT_SAFE { return t_s.t_dpiScopep != NULL; }
|
||||
static void dpiClearContext() VL_MT_SAFE { t_s.t_dpiScopep = nullptr; }
|
||||
static bool dpiInContext() VL_MT_SAFE { return t_s.t_dpiScopep != nullptr; }
|
||||
static const char* dpiFilenamep() VL_MT_SAFE { return t_s.t_dpiFilename; }
|
||||
static int dpiLineno() VL_MT_SAFE { return t_s.t_dpiLineno; }
|
||||
static int exportFuncNum(const char* namep) VL_MT_SAFE;
|
||||
|
|
@ -644,9 +643,19 @@ extern void VL_PRINTF_MT(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
|||
/// Print a debug message from internals with standard prefix, with printf style format
|
||||
extern void VL_DBG_MSGF(const char* formatp, ...) VL_ATTR_PRINTF(1) VL_MT_SAFE;
|
||||
|
||||
extern IData VL_RANDOM_I(int obits); ///< Randomize a signal
|
||||
extern QData VL_RANDOM_Q(int obits); ///< Randomize a signal
|
||||
extern vluint64_t vl_rand64() VL_MT_SAFE;
|
||||
inline IData VL_RANDOM_I(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_I(obits); }
|
||||
inline QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); }
|
||||
extern WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp); ///< Randomize a signal
|
||||
inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) {
|
||||
vluint64_t rnd = vl_rand64();
|
||||
if (VL_LIKELY(hi > lo)) {
|
||||
// Modulus isn't very fast but it's common that hi-low is power-of-two
|
||||
return (rnd % (hi - lo)) + lo;
|
||||
} else {
|
||||
return (rnd % (lo - hi)) + hi;
|
||||
}
|
||||
}
|
||||
|
||||
/// Init time only, so slow is fine
|
||||
extern IData VL_RAND_RESET_I(int obits); ///< Random reset a signal
|
||||
|
|
@ -837,13 +846,8 @@ extern int VL_TIME_STR_CONVERT(const char* strp) VL_PURE;
|
|||
|
||||
/// Return current simulation time
|
||||
#if defined(SYSTEMC_VERSION)
|
||||
# if SYSTEMC_VERSION > 20011000
|
||||
// Already defined: extern sc_time sc_time_stamp();
|
||||
inline vluint64_t vl_time_stamp64() { return sc_time_stamp().value(); }
|
||||
# else // Before SystemC changed to integral time representation
|
||||
// Already defined: extern double sc_time_stamp();
|
||||
inline vluint64_t vl_time_stamp64() { return static_cast<vluint64_t>(sc_time_stamp()); }
|
||||
# endif
|
||||
#else // Non-SystemC
|
||||
# ifdef VL_TIME_STAMP64
|
||||
extern vluint64_t vl_time_stamp64();
|
||||
|
|
|
|||
|
|
@ -200,9 +200,29 @@ else
|
|||
VK_OBJS += $(VK_FAST_OBJS) $(VK_SLOW_OBJS)
|
||||
endif
|
||||
|
||||
$(VM_PREFIX)__ALL.a: $(VK_OBJS)
|
||||
$(AR) -cr $@ $^
|
||||
$(RANLIB) $@
|
||||
# When archiving just objects (.o), single $(AR) run is enough.
|
||||
# When merging objects (.o) and archives (.a), the following steps are taken.
|
||||
# 1. Extract object files from .a
|
||||
# 2. Create a new archive from extracted .o and given .o
|
||||
%.a:
|
||||
@echo "Archive $(AR) -cr $@ $^"
|
||||
@if test $(words $(filter %.a,$^)) -eq 0; then \
|
||||
$(AR) -cr $@ $^; \
|
||||
$(RANLIB) $@; \
|
||||
else \
|
||||
$(RM) -rf $*__tmpdir; \
|
||||
for archive in $(filter %.a,$^); do \
|
||||
mkdir -p $*__tmpdir/$$(basename $${archive}); \
|
||||
cd $*__tmpdir/$$(basename $${archive}); \
|
||||
$(AR) -x ../../$${archive}; \
|
||||
cd ../..; \
|
||||
done; \
|
||||
$(AR) -cr $@ $(filter %.o,$^) $*__tmpdir/*/*.o; \
|
||||
$(RM) -rf $*__tmpdir; \
|
||||
fi
|
||||
|
||||
$(VM_PREFIX)__ALL.a: $(VK_OBJS) $(VM_HIER_LIBS)
|
||||
|
||||
|
||||
######################################################################
|
||||
### Compile rules
|
||||
|
|
|
|||
|
|
@ -70,15 +70,15 @@ private:
|
|||
public:
|
||||
// METHODS
|
||||
// cppcheck-suppress truncLongCastReturn
|
||||
virtual vluint64_t count() const VL_OVERRIDE { return *m_countp; }
|
||||
virtual void zero() const VL_OVERRIDE { *m_countp = 0; }
|
||||
virtual vluint64_t count() const override { return *m_countp; }
|
||||
virtual void zero() const override { *m_countp = 0; }
|
||||
// CONSTRUCTORS
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
explicit VerilatedCoverItemSpec(T* countp)
|
||||
: m_countp(countp) {
|
||||
: m_countp{countp} {
|
||||
*m_countp = 0;
|
||||
}
|
||||
virtual ~VerilatedCoverItemSpec() VL_OVERRIDE {}
|
||||
virtual ~VerilatedCoverItemSpec() override {}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -100,16 +100,12 @@ private:
|
|||
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
|
||||
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
|
||||
|
||||
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex); ///< Item about to insert
|
||||
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex); ///< Filename about to insert
|
||||
int m_insertLineno VL_GUARDED_BY(m_mutex); ///< Line number about to insert
|
||||
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex) = nullptr; ///< Item about to insert
|
||||
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex) = nullptr; ///< Filename about to insert
|
||||
int m_insertLineno VL_GUARDED_BY(m_mutex) = 0; ///< Line number about to insert
|
||||
|
||||
// CONSTRUCTORS
|
||||
VerilatedCovImp() {
|
||||
m_insertp = NULL;
|
||||
m_insertFilenamep = NULL;
|
||||
m_insertLineno = 0;
|
||||
}
|
||||
VerilatedCovImp() {}
|
||||
VL_UNCOPYABLE(VerilatedCovImp);
|
||||
|
||||
public:
|
||||
|
|
@ -123,7 +119,7 @@ private:
|
|||
// PRIVATE METHODS
|
||||
int valueIndex(const std::string& value) VL_REQUIRES(m_mutex) {
|
||||
static int nextIndex = KEY_UNDEF + 1;
|
||||
ValueIndexMap::iterator iter = m_valueIndexes.find(value);
|
||||
const auto iter = m_valueIndexes.find(value);
|
||||
if (iter != m_valueIndexes.end()) return iter->second;
|
||||
nextIndex++;
|
||||
assert(nextIndex > 0); // Didn't rollover
|
||||
|
|
@ -235,10 +231,7 @@ private:
|
|||
#undef SELF_CHECK
|
||||
}
|
||||
void clearGuts() VL_REQUIRES(m_mutex) {
|
||||
for (ItemList::const_iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
VL_DO_DANGLING(delete itemp, itemp);
|
||||
}
|
||||
for (const auto& itemp : m_items) VL_DO_DANGLING(delete itemp, itemp);
|
||||
m_items.clear();
|
||||
m_indexValues.clear();
|
||||
m_valueIndexes.clear();
|
||||
|
|
@ -256,8 +249,7 @@ public:
|
|||
const VerilatedLockGuard lock(m_mutex);
|
||||
if (matchp && matchp[0]) {
|
||||
ItemList newlist;
|
||||
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
for (const auto& itemp : m_items) {
|
||||
if (!itemMatchesString(itemp, matchp)) {
|
||||
VL_DO_DANGLING(delete itemp, itemp);
|
||||
} else {
|
||||
|
|
@ -270,9 +262,7 @@ public:
|
|||
void zero() VL_EXCLUDES(m_mutex) {
|
||||
Verilated::quiesce();
|
||||
const VerilatedLockGuard lock(m_mutex);
|
||||
for (ItemList::const_iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||
(*it)->zero();
|
||||
}
|
||||
for (const auto& itemp : m_items) itemp->zero();
|
||||
}
|
||||
|
||||
// We assume there's always call to i/f/p in that order
|
||||
|
|
@ -340,7 +330,7 @@ public:
|
|||
}
|
||||
m_items.push_back(m_insertp);
|
||||
// Prepare for next
|
||||
m_insertp = NULL;
|
||||
m_insertp = nullptr;
|
||||
}
|
||||
|
||||
void write(const char* filename) VL_EXCLUDES(m_mutex) {
|
||||
|
|
@ -360,10 +350,9 @@ public:
|
|||
os << "# SystemC::Coverage-3\n";
|
||||
|
||||
// Build list of events; totalize if collapsing hierarchy
|
||||
typedef std::map<std::string, std::pair<std::string, vluint64_t> > EventMap;
|
||||
typedef std::map<std::string, std::pair<std::string, vluint64_t>> EventMap;
|
||||
EventMap eventCounts;
|
||||
for (ItemList::iterator it = m_items.begin(); it != m_items.end(); ++it) {
|
||||
VerilatedCovImpItem* itemp = *(it);
|
||||
for (const auto& itemp : m_items) {
|
||||
std::string name;
|
||||
std::string hier;
|
||||
bool per_instance = false;
|
||||
|
|
@ -394,7 +383,7 @@ public:
|
|||
// inefficient)
|
||||
|
||||
// Find or insert the named event
|
||||
EventMap::iterator cit = eventCounts.find(name);
|
||||
const auto cit = eventCounts.find(name);
|
||||
if (cit != eventCounts.end()) {
|
||||
const std::string& oldhier = cit->second.first;
|
||||
cit->second.second += itemp->count();
|
||||
|
|
@ -405,11 +394,11 @@ public:
|
|||
}
|
||||
|
||||
// Output body
|
||||
for (EventMap::const_iterator it = eventCounts.begin(); it != eventCounts.end(); ++it) {
|
||||
for (const auto& i : eventCounts) {
|
||||
os << "C '" << std::dec;
|
||||
os << it->first;
|
||||
if (!it->second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, it->second.first);
|
||||
os << "' " << it->second.second;
|
||||
os << i.first;
|
||||
if (!i.second.first.empty()) os << keyValueFormatter(VL_CIK_HIER, i.second.first);
|
||||
os << "' " << i.second.second;
|
||||
os << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
@ -445,15 +434,15 @@ void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8)
|
|||
A(21), A(22), A(23), A(24), A(25), A(26), A(27), A(28),
|
||||
A(29)) VL_MT_SAFE {
|
||||
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
|
||||
= {NULL, NULL, NULL, // filename,lineno,page
|
||||
key0, key1, key2, key3, key4, key5, key6, key7, key8, key9,
|
||||
key10, key11, key12, key13, key14, key15, key16, key17, key18, key19,
|
||||
key20, key21, key22, key23, key24, key25, key26, key27, key28, key29};
|
||||
= {nullptr, nullptr, nullptr, // filename,lineno,page
|
||||
key0, key1, key2, key3, key4, key5, key6, key7, key8, key9,
|
||||
key10, key11, key12, key13, key14, key15, key16, key17, key18, key19,
|
||||
key20, key21, key22, key23, key24, key25, key26, key27, key28, key29};
|
||||
const char* valps[VerilatedCovImpBase::MAX_KEYS]
|
||||
= {NULL, NULL, NULL, // filename,lineno,page
|
||||
valp0, valp1, valp2, valp3, valp4, valp5, valp6, valp7, valp8, valp9,
|
||||
valp10, valp11, valp12, valp13, valp14, valp15, valp16, valp17, valp18, valp19,
|
||||
valp20, valp21, valp22, valp23, valp24, valp25, valp26, valp27, valp28, valp29};
|
||||
= {nullptr, nullptr, nullptr, // filename,lineno,page
|
||||
valp0, valp1, valp2, valp3, valp4, valp5, valp6, valp7, valp8, valp9,
|
||||
valp10, valp11, valp12, valp13, valp14, valp15, valp16, valp17, valp18, valp19,
|
||||
valp20, valp21, valp22, valp23, valp24, valp25, valp26, valp27, valp28, valp29};
|
||||
VerilatedCovImp::imp().insertp(keyps, valps);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
// there's not much more gain in having a version for each number of args.
|
||||
#define K(n) const char* key##n
|
||||
#define A(n) const char *key##n, const char *valp##n // Argument list
|
||||
#define D(n) const char *key##n = NULL, const char *valp##n = NULL // Argument list
|
||||
#define D(n) const char *key##n = nullptr, const char *valp##n = nullptr // Argument list
|
||||
static void _insertp(D(0), D(1), D(2), D(3), D(4), D(5), D(6), D(7), D(8), D(9));
|
||||
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), D(11),
|
||||
D(12), D(13), D(14), D(15), D(16), D(17), D(18), D(19));
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int w
|
|||
static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) {
|
||||
if (VL_UNLIKELY(!h)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"%%Error: DPI svOpenArrayHandle function called with NULL handle");
|
||||
"%%Error: DPI svOpenArrayHandle function called with nullptr handle");
|
||||
}
|
||||
const VerilatedDpiOpenVar* varp = reinterpret_cast<const VerilatedDpiOpenVar*>(h);
|
||||
if (VL_UNLIKELY(!varp->magicOk())) {
|
||||
|
|
@ -202,10 +202,10 @@ int svIncrement(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h
|
|||
int svSize(const svOpenArrayHandle h, int d) { return _vl_openhandle_varp(h)->elements(d); }
|
||||
int svDimensions(const svOpenArrayHandle h) { return _vl_openhandle_varp(h)->udims(); }
|
||||
|
||||
/// Return pointer to open array data, or NULL if not in IEEE standard C layout
|
||||
/// Return pointer to open array data, or nullptr if not in IEEE standard C layout
|
||||
void* svGetArrayPtr(const svOpenArrayHandle h) {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
|
||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return nullptr;
|
||||
return varp->datap();
|
||||
}
|
||||
/// Return size of open array, or 0 if not in IEEE standard C layout
|
||||
|
|
@ -226,7 +226,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
|||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
|
||||
" %d dimensional array using %d dimensional function.\n",
|
||||
varp->udims(), nargs);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
if (nargs >= 1) {
|
||||
datap = varp->datapAdjustIndex(datap, 1, indx1);
|
||||
|
|
@ -234,7 +234,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
|||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 "
|
||||
"out of bounds; %d outside [%d:%d].\n",
|
||||
indx1, varp->left(1), varp->right(1));
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (nargs >= 2) {
|
||||
|
|
@ -243,7 +243,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
|||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 "
|
||||
"out of bounds; %d outside [%d:%d].\n",
|
||||
indx2, varp->left(2), varp->right(2));
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (nargs >= 3) {
|
||||
|
|
@ -252,7 +252,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
|
|||
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 "
|
||||
"out of bounds; %d outside [%d:%d].\n",
|
||||
indx1, varp->left(3), varp->right(3));
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return datap;
|
||||
|
|
@ -268,11 +268,11 @@ static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) {
|
|||
return indx - varp->low(0);
|
||||
}
|
||||
|
||||
/// Return pointer to simulator open array element, or NULL if outside range
|
||||
/// Return pointer to simulator open array element, or nullptr if outside range
|
||||
static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2,
|
||||
int indx3) VL_MT_SAFE {
|
||||
const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(h);
|
||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return NULL;
|
||||
if (VL_UNLIKELY(!varp->isDpiStdLayout())) return nullptr;
|
||||
void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3);
|
||||
return datap;
|
||||
}
|
||||
|
|
@ -794,7 +794,7 @@ void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int
|
|||
svScope svGetScope() {
|
||||
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
|
||||
_VL_SVDPI_CONTEXT_WARN();
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
// NOLINTNEXTLINE(google-readability-casting)
|
||||
return (svScope)(Verilated::dpiScope());
|
||||
|
|
|
|||
|
|
@ -58,14 +58,12 @@
|
|||
// VerilatedFst
|
||||
|
||||
VerilatedFst::VerilatedFst(void* fst)
|
||||
: m_fst(fst)
|
||||
, m_symbolp(NULL)
|
||||
, m_strbuf(NULL) {}
|
||||
: m_fst{fst} {}
|
||||
|
||||
VerilatedFst::~VerilatedFst() {
|
||||
if (m_fst) fstWriterClose(m_fst);
|
||||
if (m_symbolp) VL_DO_CLEAR(delete[] m_symbolp, m_symbolp = NULL);
|
||||
if (m_strbuf) VL_DO_CLEAR(delete[] m_strbuf, m_strbuf = NULL);
|
||||
if (m_symbolp) VL_DO_CLEAR(delete[] m_symbolp, m_symbolp = nullptr);
|
||||
if (m_strbuf) VL_DO_CLEAR(delete[] m_strbuf, m_strbuf = nullptr);
|
||||
}
|
||||
|
||||
void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
|
||||
|
|
@ -82,7 +80,7 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
|
|||
VerilatedTrace<VerilatedFst>::traceInit();
|
||||
|
||||
// Clear the scope stack
|
||||
std::list<std::string>::iterator it = m_curScope.begin();
|
||||
auto it = m_curScope.begin();
|
||||
while (it != m_curScope.end()) {
|
||||
fstWriterSetUpscope(m_fst);
|
||||
it = m_curScope.erase(it);
|
||||
|
|
@ -91,10 +89,7 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
|
|||
// convert m_code2symbol into an array for fast lookup
|
||||
if (!m_symbolp) {
|
||||
m_symbolp = new fstHandle[nextCode()];
|
||||
for (Code2SymbolType::iterator it = m_code2symbol.begin(); it != m_code2symbol.end();
|
||||
++it) {
|
||||
m_symbolp[it->first] = it->second;
|
||||
}
|
||||
for (const auto& i : m_code2symbol) m_symbolp[i.first] = i.second;
|
||||
}
|
||||
m_code2symbol.clear();
|
||||
|
||||
|
|
@ -106,7 +101,7 @@ void VerilatedFst::close() {
|
|||
m_assertOne.check();
|
||||
VerilatedTrace<VerilatedFst>::close();
|
||||
fstWriterClose(m_fst);
|
||||
m_fst = NULL;
|
||||
m_fst = nullptr;
|
||||
}
|
||||
|
||||
void VerilatedFst::flush() {
|
||||
|
|
@ -142,8 +137,8 @@ void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstV
|
|||
tokens.insert(tokens.begin(), moduleName()); // Add current module to the hierarchy
|
||||
|
||||
// Find point where current and new scope diverge
|
||||
std::list<std::string>::iterator cur_it = m_curScope.begin();
|
||||
std::list<std::string>::iterator new_it = tokens.begin();
|
||||
auto cur_it = m_curScope.begin();
|
||||
auto new_it = tokens.begin();
|
||||
while (cur_it != m_curScope.end() && new_it != tokens.end()) {
|
||||
if (*cur_it != *new_it) break;
|
||||
++cur_it;
|
||||
|
|
@ -158,7 +153,7 @@ void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstV
|
|||
|
||||
// Follow the hierarchy of the new variable from the common scope point
|
||||
while (new_it != tokens.end()) {
|
||||
fstWriterSetScope(m_fst, FST_ST_VCD_SCOPE, new_it->c_str(), NULL);
|
||||
fstWriterSetScope(m_fst, FST_ST_VCD_SCOPE, new_it->c_str(), nullptr);
|
||||
m_curScope.push_back(*new_it);
|
||||
new_it = tokens.erase(new_it);
|
||||
}
|
||||
|
|
@ -173,7 +168,7 @@ void VerilatedFst::declare(vluint32_t code, const char* name, int dtypenum, fstV
|
|||
fstWriterEmitEnumTableRef(m_fst, enumNum);
|
||||
}
|
||||
|
||||
Code2SymbolType::const_iterator it = m_code2symbol.find(code);
|
||||
const auto it = vlstd::as_const(m_code2symbol).find(code);
|
||||
if (it == m_code2symbol.end()) { // New
|
||||
m_code2symbol[code]
|
||||
= fstWriterCreateVar(m_fst, vartype, vardir, bits, name_str.c_str(), 0);
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ private:
|
|||
Code2SymbolType m_code2symbol;
|
||||
Local2FstDtype m_local2fstdtype;
|
||||
std::list<std::string> m_curScope;
|
||||
fstHandle* m_symbolp; ///< same as m_code2symbol, but as an array
|
||||
char* m_strbuf; ///< String buffer long enough to hold maxBits() chars
|
||||
fstHandle* m_symbolp = nullptr; ///< same as m_code2symbol, but as an array
|
||||
char* m_strbuf = nullptr; ///< String buffer long enough to hold maxBits() chars
|
||||
|
||||
// CONSTRUCTORS
|
||||
VL_UNCOPYABLE(VerilatedFst);
|
||||
|
|
@ -63,11 +63,11 @@ protected:
|
|||
// Implementation of VerilatedTrace interface
|
||||
|
||||
// Implementations of protected virtual methods for VerilatedTrace
|
||||
void emitTimeChange(vluint64_t timeui) VL_OVERRIDE;
|
||||
virtual void emitTimeChange(vluint64_t timeui) override;
|
||||
|
||||
// Hooks called from VerilatedTrace
|
||||
bool preFullDump() VL_OVERRIDE { return isOpen(); }
|
||||
bool preChangeDump() VL_OVERRIDE { return isOpen(); }
|
||||
virtual bool preFullDump() override { return isOpen(); }
|
||||
virtual bool preChangeDump() override { return isOpen(); }
|
||||
|
||||
// Implementations of duck-typed methods for VerilatedTrace. These are
|
||||
// called from only one place (namely full*) so always inline them.
|
||||
|
|
@ -83,7 +83,7 @@ public:
|
|||
//=========================================================================
|
||||
// External interface to client code
|
||||
|
||||
explicit VerilatedFst(void* fst = NULL);
|
||||
explicit VerilatedFst(void* fst = nullptr);
|
||||
~VerilatedFst();
|
||||
|
||||
/// Open the file; call isOpen() to see if errors
|
||||
|
|
@ -93,7 +93,7 @@ public:
|
|||
/// Flush any remaining data to this file
|
||||
void flush() VL_MT_UNSAFE;
|
||||
/// Is file open?
|
||||
bool isOpen() const { return m_fst != NULL; }
|
||||
bool isOpen() const { return m_fst != nullptr; }
|
||||
|
||||
//=========================================================================
|
||||
// Internal interface to Verilator generated code
|
||||
|
|
@ -135,8 +135,8 @@ class VerilatedFstC {
|
|||
VL_UNCOPYABLE(VerilatedFstC);
|
||||
|
||||
public:
|
||||
explicit VerilatedFstC(void* filep = NULL)
|
||||
: m_sptrace(filep) {}
|
||||
explicit VerilatedFstC(void* filep = nullptr)
|
||||
: m_sptrace{filep} {}
|
||||
~VerilatedFstC() { close(); }
|
||||
/// Routines can only be called from one thread; allow next call from different thread
|
||||
void changeThread() { spTrace()->changeThread(); }
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class VlReadMem {
|
|||
public:
|
||||
VlReadMem(bool hex, int bits, const std::string& filename, QData start, QData end);
|
||||
~VlReadMem();
|
||||
bool isOpen() const { return m_fp != NULL; }
|
||||
bool isOpen() const { return m_fp != nullptr; }
|
||||
int linenum() const { return m_linenum; }
|
||||
bool get(QData& addrr, std::string& valuer);
|
||||
void setData(void* valuep, const std::string& rhs);
|
||||
|
|
@ -69,15 +69,14 @@ class VlWriteMem {
|
|||
public:
|
||||
VlWriteMem(bool hex, int bits, const std::string& filename, QData start, QData end);
|
||||
~VlWriteMem();
|
||||
bool isOpen() const { return m_fp != NULL; }
|
||||
bool isOpen() const { return m_fp != nullptr; }
|
||||
void print(QData addr, bool addrstamp, const void* valuep);
|
||||
};
|
||||
|
||||
//===================================================================
|
||||
// Verilog array container
|
||||
// Similar to std::array<WData, N>, but:
|
||||
// 1. Doesn't require C++11
|
||||
// 2. Lighter weight, only methods needed by Verilator, to help compile time.
|
||||
// Similar to std::array<WData, N>, but lighter weight, only methods needed
|
||||
// by Verilator, to help compile time.
|
||||
//
|
||||
// This is only used when we need an upper-level container and so can't
|
||||
// simply use a C style array (which is just a pointer).
|
||||
|
|
@ -146,21 +145,21 @@ public:
|
|||
int exists(const T_Key& index) const { return m_map.find(index) != m_map.end(); }
|
||||
// Return first element. Verilog: function int first(ref index);
|
||||
int first(T_Key& indexr) const {
|
||||
typename Map::const_iterator it = m_map.begin();
|
||||
const auto it = m_map.cbegin();
|
||||
if (it == m_map.end()) return 0;
|
||||
indexr = it->first;
|
||||
return 1;
|
||||
}
|
||||
// Return last element. Verilog: function int last(ref index)
|
||||
int last(T_Key& indexr) const {
|
||||
typename Map::const_reverse_iterator it = m_map.rbegin();
|
||||
const auto it = m_map.crbegin();
|
||||
if (it == m_map.rend()) return 0;
|
||||
indexr = it->first;
|
||||
return 1;
|
||||
}
|
||||
// Return next element. Verilog: function int next(ref index)
|
||||
int next(T_Key& indexr) const {
|
||||
typename Map::const_iterator it = m_map.find(indexr);
|
||||
auto it = m_map.find(indexr);
|
||||
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
||||
++it;
|
||||
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
||||
|
|
@ -169,7 +168,7 @@ public:
|
|||
}
|
||||
// Return prev element. Verilog: function int prev(ref index)
|
||||
int prev(T_Key& indexr) const {
|
||||
typename Map::const_iterator it = m_map.find(indexr);
|
||||
auto it = m_map.find(indexr);
|
||||
if (VL_UNLIKELY(it == m_map.end())) return 0;
|
||||
if (VL_UNLIKELY(it == m_map.begin())) return 0;
|
||||
--it;
|
||||
|
|
@ -180,7 +179,7 @@ public:
|
|||
// Can't just overload operator[] or provide a "at" reference to set,
|
||||
// because we need to be able to insert only when the value is set
|
||||
T_Value& at(const T_Key& index) {
|
||||
typename Map::iterator it = m_map.find(index);
|
||||
const auto it = m_map.find(index);
|
||||
if (it == m_map.end()) {
|
||||
std::pair<typename Map::iterator, bool> pit
|
||||
= m_map.insert(std::make_pair(index, m_defaultValue));
|
||||
|
|
@ -190,7 +189,7 @@ public:
|
|||
}
|
||||
// Accessing. Verilog: v = assoc[index]
|
||||
const T_Value& at(const T_Key& index) const {
|
||||
typename Map::iterator it = m_map.find(index);
|
||||
const auto it = m_map.find(index);
|
||||
if (it == m_map.end()) {
|
||||
return m_defaultValue;
|
||||
} else {
|
||||
|
|
@ -205,8 +204,8 @@ public:
|
|||
std::string to_string() const {
|
||||
std::string out = "'{";
|
||||
std::string comma;
|
||||
for (typename Map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
out += comma + VL_TO_STRING(it->first) + ":" + VL_TO_STRING(it->second);
|
||||
for (const auto& i : m_map) {
|
||||
out += comma + VL_TO_STRING(i.first) + ":" + VL_TO_STRING(i.second);
|
||||
comma = ", ";
|
||||
}
|
||||
// Default not printed - maybe random init data
|
||||
|
|
@ -240,10 +239,9 @@ 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));
|
||||
for (const auto& i : obj) {
|
||||
QData addr = i.first;
|
||||
if (addr >= start && addr <= end) wmem.print(addr, true, &(i.second));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -362,8 +360,8 @@ public:
|
|||
std::string to_string() const {
|
||||
std::string out = "'{";
|
||||
std::string comma;
|
||||
for (typename Deque::const_iterator it = m_deque.begin(); it != m_deque.end(); ++it) {
|
||||
out += comma + VL_TO_STRING(*it);
|
||||
for (const auto& i : m_deque) {
|
||||
out += comma + VL_TO_STRING(i);
|
||||
comma = ", ";
|
||||
}
|
||||
return out + "} ";
|
||||
|
|
@ -380,13 +378,7 @@ template <class T_Value> std::string VL_TO_STRING(const VlQueue<T_Value>& obj) {
|
|||
// be protected by other means
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || (__cplusplus >= 201103L)
|
||||
# define VlClassRef std::shared_ptr
|
||||
#else
|
||||
# define VlClassRef VlClassRef__SystemVerilog_class_support_requires_a_C11_or_newer_compiler
|
||||
#endif
|
||||
// clang-format on
|
||||
#define VlClassRef std::shared_ptr
|
||||
|
||||
template <class T> // T typically of type VlClassRef<x>
|
||||
inline T VL_NULL_CHECK(T t, const char* filename, int linenum) {
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedMsg(const std::function<void()>& cb)
|
||||
: m_mtaskId(Verilated::mtaskId())
|
||||
, m_cb(cb) {}
|
||||
: m_mtaskId{Verilated::mtaskId()}
|
||||
, m_cb{cb} {}
|
||||
~VerilatedMsg() {}
|
||||
// METHODS
|
||||
vluint32_t mtaskId() const { return m_mtaskId; }
|
||||
|
|
@ -84,7 +84,7 @@ class VerilatedEvalMsgQueue {
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedEvalMsgQueue()
|
||||
: m_depth(0) {
|
||||
: m_depth{0} {
|
||||
assert(atomic_is_lock_free(&m_depth));
|
||||
}
|
||||
~VerilatedEvalMsgQueue() {}
|
||||
|
|
@ -112,7 +112,7 @@ public:
|
|||
// Unfortunately to release the lock we need to copy the message
|
||||
// (Or have the message be a pointer, but then new/delete cost on each message)
|
||||
// We assume messages are small, so copy
|
||||
auto it = m_queue.begin();
|
||||
const auto it = m_queue.begin();
|
||||
const VerilatedMsg msg = *(it);
|
||||
m_queue.erase(it);
|
||||
m_mutex.unlock();
|
||||
|
|
@ -172,12 +172,11 @@ public:
|
|||
// FILE* list constructed from a file-descriptor
|
||||
class VerilatedFpList {
|
||||
FILE* m_fp[31];
|
||||
std::size_t m_sz;
|
||||
std::size_t m_sz = 0;
|
||||
|
||||
public:
|
||||
typedef FILE* const* const_iterator;
|
||||
explicit VerilatedFpList()
|
||||
: m_sz(0) {}
|
||||
explicit VerilatedFpList() {}
|
||||
const_iterator begin() const { return m_fp; }
|
||||
const_iterator end() const { return m_fp + m_sz; }
|
||||
std::size_t size() const { return m_sz; }
|
||||
|
|
@ -190,10 +189,11 @@ public:
|
|||
//======================================================================
|
||||
// VerilatedImp
|
||||
|
||||
class VerilatedImp {
|
||||
class VerilatedImpData {
|
||||
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||
protected:
|
||||
friend class Verilated;
|
||||
friend class VerilatedImp;
|
||||
|
||||
// TYPES
|
||||
typedef std::vector<std::string> ArgVec;
|
||||
|
|
@ -201,17 +201,13 @@ protected:
|
|||
typedef std::map<const char*, int, VerilatedCStrCmp> ExportNameMap;
|
||||
|
||||
// MEMBERS
|
||||
static VerilatedImp s_s; ///< Static Singleton; One and only static this
|
||||
|
||||
struct Serialized { // All these members serialized/deserialized
|
||||
int m_timeFormatUnits; // $timeformat units
|
||||
int m_timeFormatPrecision; // $timeformat number of decimal places
|
||||
int m_timeFormatWidth; // $timeformat character width
|
||||
int m_timeFormatUnits = UNITS_NONE; // $timeformat units
|
||||
int m_timeFormatPrecision = 0; // $timeformat number of decimal places
|
||||
int m_timeFormatWidth = 20; // $timeformat character width
|
||||
enum { UNITS_NONE = 99 }; // Default based on precision
|
||||
Serialized()
|
||||
: m_timeFormatUnits(UNITS_NONE)
|
||||
, m_timeFormatPrecision(0)
|
||||
, m_timeFormatWidth(20) {}
|
||||
Serialized() {}
|
||||
~Serialized() {}
|
||||
} m_ser;
|
||||
|
||||
|
|
@ -252,19 +248,37 @@ protected:
|
|||
// List of free descriptors in the MCT region [4, 32)
|
||||
std::vector<IData> m_fdFreeMct VL_GUARDED_BY(m_fdMutex);
|
||||
|
||||
// CONSTRUCTORS
|
||||
VerilatedImpData()
|
||||
: m_argVecLoaded{false}
|
||||
, m_exportNext{0} {
|
||||
|
||||
m_fdps.resize(31);
|
||||
std::fill(m_fdps.begin(), m_fdps.end(), (FILE*)0);
|
||||
m_fdFreeMct.resize(30);
|
||||
for (std::size_t i = 0, id = 1; i < m_fdFreeMct.size(); ++i, ++id) { m_fdFreeMct[i] = id; }
|
||||
}
|
||||
};
|
||||
|
||||
class VerilatedImp {
|
||||
// Whole class is internal use only - Global information shared between verilated*.cpp files.
|
||||
protected:
|
||||
friend class Verilated;
|
||||
|
||||
// MEMBERS
|
||||
union VerilatedImpU { ///< Enclose in an union to call ctor/dtor manually
|
||||
VerilatedImpData v;
|
||||
VerilatedImpU() {}
|
||||
~VerilatedImpU() {}
|
||||
};
|
||||
static VerilatedImpU s_s; ///< Static Singleton; One and only static this
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// CONSTRUCTORS
|
||||
VerilatedImp()
|
||||
: m_argVecLoaded(false)
|
||||
, m_exportNext(0) {
|
||||
s_s.m_fdps.resize(31);
|
||||
std::fill(s_s.m_fdps.begin(), s_s.m_fdps.end(), (FILE*)0);
|
||||
s_s.m_fdFreeMct.resize(30);
|
||||
for (std::size_t i = 0, id = 1; i < s_s.m_fdFreeMct.size(); ++i, ++id) {
|
||||
s_s.m_fdFreeMct[i] = id;
|
||||
}
|
||||
}
|
||||
VerilatedImp() {}
|
||||
~VerilatedImp() {}
|
||||
static void setup();
|
||||
static void teardown();
|
||||
|
||||
private:
|
||||
VL_UNCOPYABLE(VerilatedImp);
|
||||
|
|
@ -276,28 +290,28 @@ public:
|
|||
|
||||
// METHODS - arguments
|
||||
public:
|
||||
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex);
|
||||
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.m_argMutex);
|
||||
static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.m_argMutex) {
|
||||
const VerilatedLockGuard lock(s_s.m_argMutex);
|
||||
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.v.m_argMutex);
|
||||
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.v.m_argMutex);
|
||||
static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.v.m_argMutex) {
|
||||
const VerilatedLockGuard lock(s_s.v.m_argMutex);
|
||||
// Note prefixp does not include the leading "+"
|
||||
size_t len = strlen(prefixp);
|
||||
if (VL_UNLIKELY(!s_s.m_argVecLoaded)) {
|
||||
s_s.m_argVecLoaded = true; // Complain only once
|
||||
if (VL_UNLIKELY(!s_s.v.m_argVecLoaded)) {
|
||||
s_s.v.m_argVecLoaded = true; // Complain only once
|
||||
VL_FATAL_MT("unknown", 0, "",
|
||||
"%Error: Verilog called $test$plusargs or $value$plusargs without"
|
||||
" testbench C first calling Verilated::commandArgs(argc,argv).");
|
||||
}
|
||||
for (ArgVec::const_iterator it = s_s.m_argVec.begin(); it != s_s.m_argVec.end(); ++it) {
|
||||
if ((*it)[0] == '+') {
|
||||
if (0 == strncmp(prefixp, it->c_str() + 1, len)) return *it;
|
||||
for (const auto& i : s_s.v.m_argVec) {
|
||||
if (i[0] == '+') {
|
||||
if (0 == strncmp(prefixp, i.c_str() + 1, len)) return i;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.m_argMutex);
|
||||
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.v.m_argMutex);
|
||||
static void commandArgVl(const std::string& arg);
|
||||
static bool commandArgVlValue(const std::string& arg, const std::string& prefix,
|
||||
std::string& valuer);
|
||||
|
|
@ -308,18 +322,18 @@ public:
|
|||
// There's often many more scopes than userdata's and thus having a ~48byte
|
||||
// per map overhead * N scopes would take much more space and cache thrashing.
|
||||
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_userMapMutex);
|
||||
UserMap::iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
|
||||
if (it != s_s.m_userMap.end()) {
|
||||
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
|
||||
const auto it = s_s.v.m_userMap.find(std::make_pair(scopep, userKey));
|
||||
if (it != s_s.v.m_userMap.end()) {
|
||||
it->second = userData;
|
||||
} else {
|
||||
s_s.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData));
|
||||
s_s.v.m_userMap.insert(it, std::make_pair(std::make_pair(scopep, userKey), userData));
|
||||
}
|
||||
}
|
||||
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_userMapMutex);
|
||||
UserMap::const_iterator it = s_s.m_userMap.find(std::make_pair(scopep, userKey));
|
||||
if (VL_UNLIKELY(it == s_s.m_userMap.end())) return NULL;
|
||||
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
|
||||
const auto& it = vlstd::as_const(s_s.v.m_userMap).find(std::make_pair(scopep, userKey));
|
||||
if (VL_UNLIKELY(it == s_s.v.m_userMap.end())) return nullptr;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
|
@ -327,25 +341,26 @@ private:
|
|||
/// Symbol table destruction cleans up the entries for each scope.
|
||||
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope on destruction, so we simply iterate.
|
||||
const VerilatedLockGuard lock(s_s.m_userMapMutex);
|
||||
for (UserMap::iterator it = s_s.m_userMap.begin(); it != s_s.m_userMap.end();) {
|
||||
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
|
||||
for (auto it = s_s.v.m_userMap.begin(); it != s_s.v.m_userMap.end();) {
|
||||
if (it->first.first == scopep) {
|
||||
s_s.m_userMap.erase(it++);
|
||||
s_s.v.m_userMap.erase(it++);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void userDump() VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_userMapMutex); // Avoid it changing in middle of dump
|
||||
const VerilatedLockGuard lock(
|
||||
s_s.v.m_userMapMutex); // Avoid it changing in middle of dump
|
||||
bool first = true;
|
||||
for (UserMap::const_iterator it = s_s.m_userMap.begin(); it != s_s.m_userMap.end(); ++it) {
|
||||
for (const auto& i : s_s.v.m_userMap) {
|
||||
if (first) {
|
||||
VL_PRINTF_MT(" userDump:\n");
|
||||
first = false;
|
||||
}
|
||||
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", it->first.first,
|
||||
it->first.second, it->second);
|
||||
VL_PRINTF_MT(" DPI_USER_DATA scope %p key %p: %p\n", i.first.first, i.first.second,
|
||||
i.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -353,51 +368,50 @@ public: // But only for verilated*.cpp
|
|||
// METHODS - scope name
|
||||
static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope at construction
|
||||
const VerilatedLockGuard lock(s_s.m_nameMutex);
|
||||
VerilatedScopeNameMap::iterator it = s_s.m_nameMap.find(scopep->name());
|
||||
if (it == s_s.m_nameMap.end()) {
|
||||
s_s.m_nameMap.insert(it, std::make_pair(scopep->name(), scopep));
|
||||
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||
const auto it = s_s.v.m_nameMap.find(scopep->name());
|
||||
if (it == s_s.v.m_nameMap.end()) {
|
||||
s_s.v.m_nameMap.insert(it, std::make_pair(scopep->name(), scopep));
|
||||
}
|
||||
}
|
||||
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_nameMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||
// If too slow, can assume this is only VL_MT_SAFE_POSINIT
|
||||
VerilatedScopeNameMap::const_iterator it = s_s.m_nameMap.find(namep);
|
||||
if (VL_UNLIKELY(it == s_s.m_nameMap.end())) return NULL;
|
||||
const auto& it = s_s.v.m_nameMap.find(namep);
|
||||
if (VL_UNLIKELY(it == s_s.v.m_nameMap.end())) return nullptr;
|
||||
return it->second;
|
||||
}
|
||||
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
|
||||
// Slow ok - called once/scope at destruction
|
||||
const VerilatedLockGuard lock(s_s.m_nameMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||
userEraseScope(scopep);
|
||||
VerilatedScopeNameMap::iterator it = s_s.m_nameMap.find(scopep->name());
|
||||
if (it != s_s.m_nameMap.end()) s_s.m_nameMap.erase(it);
|
||||
const auto it = s_s.v.m_nameMap.find(scopep->name());
|
||||
if (it != s_s.v.m_nameMap.end()) s_s.v.m_nameMap.erase(it);
|
||||
}
|
||||
static void scopesDump() VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_nameMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
|
||||
VL_PRINTF_MT(" scopesDump:\n");
|
||||
for (VerilatedScopeNameMap::const_iterator it = s_s.m_nameMap.begin();
|
||||
it != s_s.m_nameMap.end(); ++it) {
|
||||
const VerilatedScope* scopep = it->second;
|
||||
for (const auto& i : s_s.v.m_nameMap) {
|
||||
const VerilatedScope* scopep = i.second;
|
||||
scopep->scopeDump();
|
||||
}
|
||||
VL_PRINTF_MT("\n");
|
||||
}
|
||||
static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE_POSTINIT {
|
||||
// Thread save only assuming this is called only after model construction completed
|
||||
return &s_s.m_nameMap;
|
||||
return &s_s.v.m_nameMap;
|
||||
}
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
// METHODS - hierarchy
|
||||
static void hierarchyAdd(const VerilatedScope* fromp, const VerilatedScope* top) VL_MT_SAFE {
|
||||
// Slow ok - called at construction for VPI accessible elements
|
||||
const VerilatedLockGuard lock(s_s.m_hierMapMutex);
|
||||
s_s.m_hierMap[fromp].push_back(top);
|
||||
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
|
||||
s_s.v.m_hierMap[fromp].push_back(top);
|
||||
}
|
||||
static const VerilatedHierarchyMap* hierarchyMap() VL_MT_SAFE_POSTINIT {
|
||||
// Thread save only assuming this is called only after model construction completed
|
||||
return &s_s.m_hierMap;
|
||||
return &s_s.v.m_hierMap;
|
||||
}
|
||||
|
||||
public: // But only for verilated*.cpp
|
||||
|
|
@ -411,19 +425,19 @@ public: // But only for verilated*.cpp
|
|||
// miss at the cost of a multiply, and all lookups move to slowpath.
|
||||
static int exportInsert(const char* namep) VL_MT_SAFE {
|
||||
// Slow ok - called once/function at creation
|
||||
const VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
ExportNameMap::iterator it = s_s.m_exportMap.find(namep);
|
||||
if (it == s_s.m_exportMap.end()) {
|
||||
s_s.m_exportMap.insert(it, std::make_pair(namep, s_s.m_exportNext++));
|
||||
return s_s.m_exportNext++;
|
||||
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||
const auto it = s_s.v.m_exportMap.find(namep);
|
||||
if (it == s_s.v.m_exportMap.end()) {
|
||||
s_s.v.m_exportMap.insert(it, std::make_pair(namep, s_s.v.m_exportNext++));
|
||||
return s_s.v.m_exportNext++;
|
||||
} else {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
static int exportFind(const char* namep) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
ExportNameMap::const_iterator it = s_s.m_exportMap.find(namep);
|
||||
if (VL_LIKELY(it != s_s.m_exportMap.end())) return it->second;
|
||||
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||
const auto& it = s_s.v.m_exportMap.find(namep);
|
||||
if (VL_LIKELY(it != s_s.v.m_exportMap.end())) return it->second;
|
||||
std::string msg = (std::string("%Error: Testbench C called ") + namep
|
||||
+ " but no such DPI export function name exists in ANY model");
|
||||
VL_FATAL_MT("unknown", 0, "", msg.c_str());
|
||||
|
|
@ -431,23 +445,21 @@ public: // But only for verilated*.cpp
|
|||
}
|
||||
static const char* exportName(int funcnum) VL_MT_SAFE {
|
||||
// Slowpath; find name for given export; errors only so no map to reverse-map it
|
||||
const VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
for (ExportNameMap::const_iterator it = s_s.m_exportMap.begin();
|
||||
it != s_s.m_exportMap.end(); ++it) {
|
||||
if (it->second == funcnum) return it->first;
|
||||
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||
for (const auto& i : s_s.v.m_exportMap) {
|
||||
if (i.second == funcnum) return i.first;
|
||||
}
|
||||
return "*UNKNOWN*";
|
||||
}
|
||||
static void exportsDump() VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_exportMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
|
||||
bool first = true;
|
||||
for (ExportNameMap::const_iterator it = s_s.m_exportMap.begin();
|
||||
it != s_s.m_exportMap.end(); ++it) {
|
||||
for (const auto& i : s_s.v.m_exportMap) {
|
||||
if (first) {
|
||||
VL_PRINTF_MT(" exportDump:\n");
|
||||
first = false;
|
||||
}
|
||||
VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", it->second, it->first);
|
||||
VL_PRINTF_MT(" DPI_EXPORT_NAME %05d: %s\n", i.second, i.first);
|
||||
}
|
||||
}
|
||||
// We don't free up m_exportMap until the end, because we can't be sure
|
||||
|
|
@ -458,13 +470,13 @@ public: // But only for verilated*.cpp
|
|||
static std::string timeFormatSuffix() VL_MT_SAFE;
|
||||
static void timeFormatSuffix(const std::string& value) VL_MT_SAFE;
|
||||
static int timeFormatUnits() VL_MT_SAFE {
|
||||
if (s_s.m_ser.m_timeFormatUnits == Serialized::UNITS_NONE) {
|
||||
if (s_s.v.m_ser.m_timeFormatUnits == VerilatedImpData::Serialized::UNITS_NONE) {
|
||||
return Verilated::timeprecision();
|
||||
}
|
||||
return s_s.m_ser.m_timeFormatUnits;
|
||||
return s_s.v.m_ser.m_timeFormatUnits;
|
||||
}
|
||||
static int timeFormatPrecision() VL_MT_SAFE { return s_s.m_ser.m_timeFormatPrecision; }
|
||||
static int timeFormatWidth() VL_MT_SAFE { return s_s.m_ser.m_timeFormatWidth; }
|
||||
static int timeFormatPrecision() VL_MT_SAFE { return s_s.v.m_ser.m_timeFormatPrecision; }
|
||||
static int timeFormatWidth() VL_MT_SAFE { return s_s.v.m_ser.m_timeFormatWidth; }
|
||||
static void timeFormatUnits(int value) VL_MT_SAFE;
|
||||
static void timeFormatPrecision(int value) VL_MT_SAFE;
|
||||
static void timeFormatWidth(int value) VL_MT_SAFE;
|
||||
|
|
@ -472,93 +484,91 @@ public: // But only for verilated*.cpp
|
|||
public: // But only for verilated*.cpp
|
||||
// METHODS - file IO
|
||||
static IData fdNewMcd(const char* filenamep) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
if (s_s.m_fdFreeMct.empty()) return 0;
|
||||
IData idx = s_s.m_fdFreeMct.back();
|
||||
s_s.m_fdFreeMct.pop_back();
|
||||
s_s.m_fdps[idx] = fopen(filenamep, "w");
|
||||
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return 0;
|
||||
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||
if (s_s.v.m_fdFreeMct.empty()) return 0;
|
||||
IData idx = s_s.v.m_fdFreeMct.back();
|
||||
s_s.v.m_fdFreeMct.pop_back();
|
||||
s_s.v.m_fdps[idx] = fopen(filenamep, "w");
|
||||
if (VL_UNLIKELY(!s_s.v.m_fdps[idx])) return 0;
|
||||
return (1 << idx);
|
||||
}
|
||||
static IData fdNew(const char* filenamep, const char* modep) VL_MT_SAFE {
|
||||
FILE* fp = fopen(filenamep, modep);
|
||||
if (VL_UNLIKELY(!fp)) return 0;
|
||||
// Bit 31 indicates it's a descriptor not a MCD
|
||||
const VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
if (s_s.m_fdFree.empty()) {
|
||||
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||
if (s_s.v.m_fdFree.empty()) {
|
||||
// Need to create more space in m_fdps and m_fdFree
|
||||
const std::size_t start = std::max<std::size_t>(31UL + 1UL + 3UL, s_s.m_fdps.size());
|
||||
const std::size_t start = std::max<std::size_t>(31UL + 1UL + 3UL, s_s.v.m_fdps.size());
|
||||
const std::size_t excess = 10;
|
||||
s_s.m_fdps.resize(start + excess);
|
||||
std::fill(s_s.m_fdps.begin() + start, s_s.m_fdps.end(), (FILE*)0);
|
||||
s_s.m_fdFree.resize(excess);
|
||||
for (std::size_t i = 0, id = start; i < s_s.m_fdFree.size(); ++i, ++id) {
|
||||
s_s.m_fdFree[i] = id;
|
||||
s_s.v.m_fdps.resize(start + excess);
|
||||
std::fill(s_s.v.m_fdps.begin() + start, s_s.v.m_fdps.end(), (FILE*)0);
|
||||
s_s.v.m_fdFree.resize(excess);
|
||||
for (std::size_t i = 0, id = start; i < s_s.v.m_fdFree.size(); ++i, ++id) {
|
||||
s_s.v.m_fdFree[i] = id;
|
||||
}
|
||||
}
|
||||
IData idx = s_s.m_fdFree.back();
|
||||
s_s.m_fdFree.pop_back();
|
||||
s_s.m_fdps[idx] = fp;
|
||||
IData idx = s_s.v.m_fdFree.back();
|
||||
s_s.v.m_fdFree.pop_back();
|
||||
s_s.v.m_fdps[idx] = fp;
|
||||
return (idx | (1UL << 31)); // bit 31 indicates not MCD
|
||||
}
|
||||
static void fdFlush(IData fdi) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||
for (VerilatedFpList::const_iterator it = fdlist.begin(); it != fdlist.end(); ++it) {
|
||||
fflush(*it);
|
||||
}
|
||||
for (const auto& i : fdlist) fflush(i);
|
||||
}
|
||||
static IData fdSeek(IData fdi, IData offset, IData origin) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
|
||||
return static_cast<IData>(
|
||||
fseek(*fdlist.begin(), static_cast<long>(offset), static_cast<int>(origin)));
|
||||
}
|
||||
static IData fdTell(IData fdi) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
|
||||
return static_cast<IData>(ftell(*fdlist.begin()));
|
||||
}
|
||||
static void fdWrite(IData fdi, const std::string& output) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||
for (VerilatedFpList::const_iterator it = fdlist.begin(); it != fdlist.end(); ++it) {
|
||||
if (VL_UNLIKELY(!*it)) continue;
|
||||
fwrite(output.c_str(), 1, output.size(), *it);
|
||||
for (const auto& i : fdlist) {
|
||||
if (VL_UNLIKELY(!i)) continue;
|
||||
(void)fwrite(output.c_str(), 1, output.size(), i);
|
||||
}
|
||||
}
|
||||
static void fdClose(IData fdi) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||
if ((fdi & (1 << 31)) != 0) {
|
||||
// Non-MCD case
|
||||
IData idx = VL_MASK_I(31) & fdi;
|
||||
if (VL_UNLIKELY(idx >= s_s.m_fdps.size())) return;
|
||||
if (VL_UNLIKELY(!s_s.m_fdps[idx])) return; // Already free
|
||||
fclose(s_s.m_fdps[idx]);
|
||||
s_s.m_fdps[idx] = (FILE*)0;
|
||||
s_s.m_fdFree.push_back(idx);
|
||||
if (VL_UNLIKELY(idx >= s_s.v.m_fdps.size())) return;
|
||||
if (VL_UNLIKELY(!s_s.v.m_fdps[idx])) return; // Already free
|
||||
fclose(s_s.v.m_fdps[idx]);
|
||||
s_s.v.m_fdps[idx] = (FILE*)0;
|
||||
s_s.v.m_fdFree.push_back(idx);
|
||||
} else {
|
||||
// MCD case
|
||||
for (int i = 0; (fdi != 0) && (i < 31); i++, fdi >>= 1) {
|
||||
if (fdi & VL_MASK_I(1)) {
|
||||
fclose(s_s.m_fdps[i]);
|
||||
s_s.m_fdps[i] = NULL;
|
||||
s_s.m_fdFreeMct.push_back(i);
|
||||
fclose(s_s.v.m_fdps[i]);
|
||||
s_s.v.m_fdps[i] = nullptr;
|
||||
s_s.v.m_fdFreeMct.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock(s_s.m_fdMutex);
|
||||
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
|
||||
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return NULL;
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return nullptr;
|
||||
return *fdlist.begin();
|
||||
}
|
||||
|
||||
private:
|
||||
static inline VerilatedFpList fdToFpList(IData fdi) VL_REQUIRES(s_s.m_fdMutex) {
|
||||
static inline VerilatedFpList fdToFpList(IData fdi) VL_REQUIRES(s_s.v.m_fdMutex) {
|
||||
VerilatedFpList fp;
|
||||
if ((fdi & (1 << 31)) != 0) {
|
||||
// Non-MCD case
|
||||
|
|
@ -568,13 +578,13 @@ private:
|
|||
case 1: fp.push_back(stdout); break;
|
||||
case 2: fp.push_back(stderr); break;
|
||||
default:
|
||||
if (VL_LIKELY(idx < s_s.m_fdps.size())) fp.push_back(s_s.m_fdps[idx]);
|
||||
if (VL_LIKELY(idx < s_s.v.m_fdps.size())) fp.push_back(s_s.v.m_fdps[idx]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// MCD Case
|
||||
for (int i = 0; (fdi != 0) && (i < fp.capacity()); ++i, fdi >>= 1) {
|
||||
if (fdi & VL_MASK_I(1)) fp.push_back(s_s.m_fdps[i]);
|
||||
if (fdi & VL_MASK_I(1)) fp.push_back(s_s.v.m_fdps[i]);
|
||||
}
|
||||
}
|
||||
return fp;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ protected:
|
|||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
bool m_isOpen = false; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
|
|
@ -49,13 +49,12 @@ protected:
|
|||
|
||||
public:
|
||||
VerilatedSerialize() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t[bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
}
|
||||
virtual ~VerilatedSerialize() {
|
||||
close();
|
||||
if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = NULL);
|
||||
if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = nullptr);
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
|
|
@ -94,8 +93,8 @@ protected:
|
|||
// For speed, keep m_cp as the first member of this structure
|
||||
vluint8_t* m_cp; ///< Current pointer into m_bufp buffer
|
||||
vluint8_t* m_bufp; ///< Output buffer
|
||||
vluint8_t* m_endp; ///< Last valid byte in m_bufp buffer
|
||||
bool m_isOpen; ///< True indicates open file/stream
|
||||
vluint8_t* m_endp = nullptr; ///< Last valid byte in m_bufp buffer
|
||||
bool m_isOpen = false; ///< True indicates open file/stream
|
||||
std::string m_filename; ///< Filename, for error messages
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
|
|
@ -111,14 +110,12 @@ protected:
|
|||
|
||||
public:
|
||||
VerilatedDeserialize() {
|
||||
m_isOpen = false;
|
||||
m_bufp = new vluint8_t[bufferSize()];
|
||||
m_cp = m_bufp;
|
||||
m_endp = NULL;
|
||||
}
|
||||
virtual ~VerilatedDeserialize() {
|
||||
close();
|
||||
if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = NULL);
|
||||
if (m_bufp) VL_DO_CLEAR(delete[] m_bufp, m_bufp = nullptr);
|
||||
}
|
||||
// METHODS
|
||||
bool isOpen() const { return m_isOpen; }
|
||||
|
|
@ -159,19 +156,18 @@ private:
|
|||
|
||||
class VerilatedSave : public VerilatedSerialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
int m_fd = -1; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedSave()
|
||||
: m_fd(-1) {}
|
||||
virtual ~VerilatedSave() VL_OVERRIDE { close(); }
|
||||
VerilatedSave() {}
|
||||
virtual ~VerilatedSave() override { close(); }
|
||||
// METHODS
|
||||
/// Open the file; call isOpen() to see if errors
|
||||
void open(const char* filenamep) VL_MT_UNSAFE_ONE;
|
||||
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
|
||||
virtual void close() VL_OVERRIDE VL_MT_UNSAFE_ONE;
|
||||
virtual void flush() VL_OVERRIDE VL_MT_UNSAFE_ONE;
|
||||
virtual void close() override VL_MT_UNSAFE_ONE;
|
||||
virtual void flush() override VL_MT_UNSAFE_ONE;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -180,21 +176,20 @@ public:
|
|||
|
||||
class VerilatedRestore : public VerilatedDeserialize {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
int m_fd = -1; ///< File descriptor we're writing to
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedRestore()
|
||||
: m_fd(-1) {}
|
||||
virtual ~VerilatedRestore() VL_OVERRIDE { close(); }
|
||||
VerilatedRestore() {}
|
||||
virtual ~VerilatedRestore() override { close(); }
|
||||
|
||||
// METHODS
|
||||
/// Open the file; call isOpen() to see if errors
|
||||
void open(const char* filenamep) VL_MT_UNSAFE_ONE;
|
||||
void open(const std::string& filename) VL_MT_UNSAFE_ONE { open(filename.c_str()); }
|
||||
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;
|
||||
virtual void close() override VL_MT_UNSAFE_ONE;
|
||||
virtual void flush() override VL_MT_UNSAFE_ONE {}
|
||||
virtual void fill() override VL_MT_UNSAFE_ONE;
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -257,10 +252,9 @@ VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Val
|
|||
os << rhs.atDefault();
|
||||
vluint32_t len = rhs.size();
|
||||
os << len;
|
||||
for (typename VlAssocArray<T_Key, T_Value>::const_iterator it = rhs.begin(); it != rhs.end();
|
||||
++it) {
|
||||
T_Key index = it->first; // Copy to get around const_iterator
|
||||
T_Value value = it->second;
|
||||
for (const auto& i : rhs) {
|
||||
T_Key index = i.first; // Copy to get around const_iterator
|
||||
T_Value value = i.second;
|
||||
os << index << value;
|
||||
}
|
||||
return os;
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ protected:
|
|||
friend class VerilatedVarProps;
|
||||
friend class VerilatedScope;
|
||||
VerilatedRange()
|
||||
: m_left(0)
|
||||
, m_right(0) {}
|
||||
: m_left{0}
|
||||
, m_right{0} {}
|
||||
VerilatedRange(int left, int right)
|
||||
: m_left(left)
|
||||
, m_right(right) {}
|
||||
: m_left{left}
|
||||
, m_right{right} {}
|
||||
void init(int left, int right) {
|
||||
m_left = left;
|
||||
m_right = right;
|
||||
|
|
@ -92,48 +92,48 @@ class VerilatedVarProps {
|
|||
protected:
|
||||
friend class VerilatedScope;
|
||||
VerilatedVarProps(VerilatedVarType vltype, VerilatedVarFlags vlflags, int pdims, int udims)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(vlflags)
|
||||
, m_pdims(pdims)
|
||||
, m_udims(udims) {
|
||||
initUnpacked(NULL);
|
||||
: m_magic{MAGIC}
|
||||
, m_vltype{vltype}
|
||||
, m_vlflags{vlflags}
|
||||
, m_pdims{pdims}
|
||||
, m_udims{udims} {
|
||||
initUnpacked(nullptr);
|
||||
}
|
||||
|
||||
public:
|
||||
class Unpacked {};
|
||||
// Without packed
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(0)
|
||||
, m_udims(0) {}
|
||||
: m_magic{MAGIC}
|
||||
, m_vltype{vltype}
|
||||
, m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning
|
||||
, m_pdims{0}
|
||||
, m_udims{0} {}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Unpacked, int udims, const int* ulims)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(0)
|
||||
, m_udims(udims) {
|
||||
: m_magic{MAGIC}
|
||||
, m_vltype{vltype}
|
||||
, m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning
|
||||
, m_pdims{0}
|
||||
, m_udims{udims} {
|
||||
initUnpacked(ulims);
|
||||
}
|
||||
// With packed
|
||||
class Packed {};
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(1)
|
||||
, m_udims(0)
|
||||
, m_packed(pl, pr) {}
|
||||
: m_magic{MAGIC}
|
||||
, m_vltype{vltype}
|
||||
, m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning
|
||||
, m_pdims{1}
|
||||
, m_udims{0}
|
||||
, m_packed{pl, pr} {}
|
||||
VerilatedVarProps(VerilatedVarType vltype, int vlflags, Packed, int pl, int pr, Unpacked,
|
||||
int udims, const int* ulims)
|
||||
: m_magic(MAGIC)
|
||||
, m_vltype(vltype)
|
||||
, m_vlflags(VerilatedVarFlags(vlflags))
|
||||
, m_pdims(1)
|
||||
, m_udims(udims)
|
||||
, m_packed(pl, pr) {
|
||||
: m_magic{MAGIC}
|
||||
, m_vltype{vltype}
|
||||
, m_vlflags(VerilatedVarFlags(vlflags)) // Need () or GCC 4.8 false warning
|
||||
, m_pdims{1}
|
||||
, m_udims{udims}
|
||||
, m_packed{pl, pr} {
|
||||
initUnpacked(ulims);
|
||||
}
|
||||
|
||||
|
|
@ -196,11 +196,11 @@ class VerilatedDpiOpenVar {
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, void* datap)
|
||||
: m_propsp(propsp)
|
||||
, m_datap(datap) {}
|
||||
: m_propsp{propsp}
|
||||
, m_datap{datap} {}
|
||||
VerilatedDpiOpenVar(const VerilatedVarProps* propsp, const void* datap)
|
||||
: m_propsp(propsp)
|
||||
, m_datap(const_cast<void*>(datap)) {}
|
||||
: m_propsp{propsp}
|
||||
, m_datap{const_cast<void*>(datap)} {}
|
||||
~VerilatedDpiOpenVar() {}
|
||||
// METHODS
|
||||
void* datap() const { return m_datap; }
|
||||
|
|
@ -237,10 +237,10 @@ protected:
|
|||
// CONSTRUCTORS
|
||||
VerilatedVar(const char* namep, void* datap, VerilatedVarType vltype,
|
||||
VerilatedVarFlags vlflags, int dims, bool isParam)
|
||||
: VerilatedVarProps(vltype, vlflags, (dims > 0 ? 1 : 0), ((dims > 1) ? dims - 1 : 0))
|
||||
, m_datap(datap)
|
||||
, m_namep(namep)
|
||||
, m_isParam(isParam) {}
|
||||
: VerilatedVarProps{vltype, vlflags, (dims > 0 ? 1 : 0), ((dims > 1) ? dims - 1 : 0)}
|
||||
, m_datap{datap}
|
||||
, m_namep{namep}
|
||||
, m_isParam{isParam} {}
|
||||
|
||||
public:
|
||||
~VerilatedVar() {}
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@
|
|||
|
||||
std::atomic<vluint64_t> VlMTaskVertex::s_yields;
|
||||
|
||||
VL_THREAD_LOCAL VlThreadPool::ProfileTrace* VlThreadPool::t_profilep = NULL;
|
||||
VL_THREAD_LOCAL VlThreadPool::ProfileTrace* VlThreadPool::t_profilep = nullptr;
|
||||
|
||||
//=============================================================================
|
||||
// VlMTaskVertex
|
||||
|
||||
VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
|
||||
: m_upstreamDepsDone(0)
|
||||
, m_upstreamDepCount(upstreamDepCount) {
|
||||
: m_upstreamDepsDone{0}
|
||||
, m_upstreamDepCount{upstreamDepCount} {
|
||||
assert(atomic_is_lock_free(&m_upstreamDepsDone));
|
||||
}
|
||||
|
||||
|
|
@ -36,13 +36,11 @@ VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
|
|||
// VlWorkerThread
|
||||
|
||||
VlWorkerThread::VlWorkerThread(VlThreadPool* poolp, bool profiling)
|
||||
: m_waiting(false)
|
||||
, m_ready_size(0)
|
||||
, m_poolp(poolp)
|
||||
, m_profiling(profiling)
|
||||
, m_exiting(false)
|
||||
// Must init this last -- after setting up fields that it might read:
|
||||
, m_cthread(startWorker, this) {}
|
||||
: m_waiting{false}
|
||||
, m_poolp{poolp}
|
||||
, m_profiling{profiling} // Must init this last -- after setting up fields that it might read:
|
||||
, m_exiting{false}
|
||||
, m_cthread{startWorker, this} {}
|
||||
|
||||
VlWorkerThread::~VlWorkerThread() {
|
||||
m_exiting.store(true, std::memory_order_release);
|
||||
|
|
@ -55,7 +53,7 @@ void VlWorkerThread::workerLoop() {
|
|||
if (VL_UNLIKELY(m_profiling)) m_poolp->setupProfilingClientThread();
|
||||
|
||||
ExecRec work;
|
||||
work.m_fnp = NULL;
|
||||
work.m_fnp = nullptr;
|
||||
|
||||
while (true) {
|
||||
if (VL_LIKELY(!work.m_fnp)) dequeWork(&work);
|
||||
|
|
@ -65,7 +63,7 @@ void VlWorkerThread::workerLoop() {
|
|||
|
||||
if (VL_LIKELY(work.m_fnp)) {
|
||||
work.m_fnp(work.m_evenCycle, work.m_sym);
|
||||
work.m_fnp = NULL;
|
||||
work.m_fnp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +76,7 @@ void VlWorkerThread::startWorker(VlWorkerThread* workerp) { workerp->workerLoop(
|
|||
// VlThreadPool
|
||||
|
||||
VlThreadPool::VlThreadPool(int nThreads, bool profiling)
|
||||
: m_profiling(profiling) {
|
||||
: m_profiling{profiling} {
|
||||
// --threads N passes nThreads=N-1, as the "main" threads counts as 1
|
||||
unsigned cpus = std::thread::hardware_concurrency();
|
||||
if (cpus < nThreads + 1) {
|
||||
|
|
@ -110,7 +108,7 @@ VlThreadPool::~VlThreadPool() {
|
|||
void VlThreadPool::tearDownProfilingClientThread() {
|
||||
assert(t_profilep);
|
||||
delete t_profilep;
|
||||
t_profilep = NULL;
|
||||
t_profilep = nullptr;
|
||||
}
|
||||
|
||||
void VlThreadPool::setupProfilingClientThread() {
|
||||
|
|
@ -127,9 +125,9 @@ void VlThreadPool::setupProfilingClientThread() {
|
|||
|
||||
void VlThreadPool::profileAppendAll(const VlProfileRec& rec) {
|
||||
const VerilatedLockGuard lk(m_mutex);
|
||||
for (ProfileSet::iterator it = m_allProfiles.begin(); it != m_allProfiles.end(); ++it) {
|
||||
for (const auto& profilep : m_allProfiles) {
|
||||
// Every thread's profile trace gets a copy of rec.
|
||||
(*it)->emplace_back(rec);
|
||||
profilep->emplace_back(rec);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,13 +152,12 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
|
|||
fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n", VlMTaskVertex::yields());
|
||||
|
||||
vluint32_t thread_id = 0;
|
||||
for (ProfileSet::const_iterator pit = m_allProfiles.begin(); pit != m_allProfiles.end();
|
||||
++pit) {
|
||||
for (const auto& pi : m_allProfiles) {
|
||||
++thread_id;
|
||||
|
||||
bool printing = false; // False while in warmup phase
|
||||
for (ProfileTrace::const_iterator eit = (*pit)->begin(); eit != (*pit)->end(); ++eit) {
|
||||
switch (eit->m_type) {
|
||||
for (const auto& ei : *pi) {
|
||||
switch (ei.m_type) {
|
||||
case VlProfileRec::TYPE_BARRIER: //
|
||||
printing = true;
|
||||
break;
|
||||
|
|
@ -170,9 +167,8 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
|
|||
"VLPROF mtask %d"
|
||||
" start %" VL_PRI64 "u end %" VL_PRI64 "u elapsed %" VL_PRI64 "u"
|
||||
" predict_time %u cpu %u on thread %u\n",
|
||||
eit->m_mtaskId, eit->m_startTime, eit->m_endTime,
|
||||
(eit->m_endTime - eit->m_startTime), eit->m_predictTime, eit->m_cpu,
|
||||
thread_id);
|
||||
ei.m_mtaskId, ei.m_startTime, ei.m_endTime,
|
||||
(ei.m_endTime - ei.m_startTime), ei.m_predictTime, ei.m_cpu, thread_id);
|
||||
break;
|
||||
default: assert(false); break; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,23 +119,16 @@ class VlProfileRec {
|
|||
protected:
|
||||
friend class VlThreadPool;
|
||||
enum VlProfileE { TYPE_MTASK_RUN, TYPE_BARRIER };
|
||||
VlProfileE m_type; // Record type
|
||||
vluint32_t m_mtaskId; // Mtask we're logging
|
||||
vluint32_t m_predictTime; // How long scheduler predicted would take
|
||||
vluint64_t m_startTime; // Tick at start of execution
|
||||
vluint64_t m_endTime; // Tick at end of execution
|
||||
VlProfileE m_type = TYPE_BARRIER; // Record type
|
||||
vluint32_t m_mtaskId = 0; // Mtask we're logging
|
||||
vluint32_t m_predictTime = 0; // How long scheduler predicted would take
|
||||
vluint64_t m_startTime = 0; // Tick at start of execution
|
||||
vluint64_t m_endTime = 0; // Tick at end of execution
|
||||
unsigned m_cpu; // Execution CPU number (at start anyways)
|
||||
public:
|
||||
class Barrier {};
|
||||
VlProfileRec() {}
|
||||
explicit VlProfileRec(Barrier) {
|
||||
m_type = TYPE_BARRIER;
|
||||
m_mtaskId = 0;
|
||||
m_predictTime = 0;
|
||||
m_startTime = 0;
|
||||
m_endTime = 0;
|
||||
m_cpu = getcpu();
|
||||
}
|
||||
explicit VlProfileRec(Barrier) { m_cpu = getcpu(); }
|
||||
void startRecord(vluint64_t time, uint32_t mtask, uint32_t predict) {
|
||||
m_type = VlProfileRec::TYPE_MTASK_RUN;
|
||||
m_mtaskId = mtask;
|
||||
|
|
@ -174,13 +167,13 @@ private:
|
|||
VlThrSymTab m_sym; // Symbol table to execute
|
||||
bool m_evenCycle; // Even/odd for flag alternation
|
||||
ExecRec()
|
||||
: m_fnp(NULL)
|
||||
, m_sym(NULL)
|
||||
, m_evenCycle(false) {}
|
||||
: m_fnp{nullptr}
|
||||
, m_sym{nullptr}
|
||||
, m_evenCycle{false} {}
|
||||
ExecRec(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym)
|
||||
: m_fnp(fnp)
|
||||
, m_sym(sym)
|
||||
, m_evenCycle(evenCycle) {}
|
||||
: m_fnp{fnp}
|
||||
, m_sym{sym}
|
||||
, m_evenCycle{evenCycle} {}
|
||||
};
|
||||
|
||||
// MEMBERS
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class VerilatedTraceCommand {
|
|||
public:
|
||||
// These must all fit in 4 bit at the moment, as the tracing routines
|
||||
// pack parameters in the top bits.
|
||||
enum {
|
||||
enum : vluint8_t {
|
||||
CHG_BIT_0 = 0x0,
|
||||
CHG_BIT_1 = 0x1,
|
||||
CHG_CDATA = 0x2,
|
||||
|
|
@ -130,11 +130,11 @@ private:
|
|||
};
|
||||
void* m_userp; // The user pointer to pass to the callback (the symbol table)
|
||||
CallbackRecord(initCb_t cb, void* userp)
|
||||
: m_initCb(cb)
|
||||
, m_userp(userp) {}
|
||||
: m_initCb{cb}
|
||||
, m_userp{userp} {}
|
||||
CallbackRecord(dumpCb_t cb, void* userp)
|
||||
: m_dumpCb(cb)
|
||||
, m_userp(userp) {}
|
||||
: m_dumpCb{cb}
|
||||
, m_userp{userp} {}
|
||||
};
|
||||
|
||||
vluint32_t* m_sigs_oldvalp; ///< Old value store
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
// Static utility functions
|
||||
|
||||
static double timescaleToDouble(const char* unitp) {
|
||||
char* endp = NULL;
|
||||
char* endp = nullptr;
|
||||
double value = strtod(unitp, &endp);
|
||||
// On error so we allow just "ns" to return 1e-9.
|
||||
if (value == 0.0 && endp == unitp) value = 1;
|
||||
|
|
@ -276,17 +276,19 @@ template <> void VerilatedTrace<VL_DERIVED_T>::onExit(void* selfp) {
|
|||
|
||||
template <>
|
||||
VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
|
||||
: m_sigs_oldvalp(NULL)
|
||||
, m_timeLastDump(0)
|
||||
, m_fullDump(true)
|
||||
, m_nextCode(0)
|
||||
, m_numSignals(0)
|
||||
, m_maxBits(0)
|
||||
, m_scopeEscape('.')
|
||||
, m_timeRes(1e-9)
|
||||
, m_timeUnit(1e-9)
|
||||
: m_sigs_oldvalp{nullptr}
|
||||
, m_timeLastDump{0}
|
||||
, m_fullDump{true}
|
||||
, m_nextCode{0}
|
||||
, m_numSignals{0}
|
||||
, m_maxBits{0}
|
||||
, m_scopeEscape{'.'}
|
||||
, m_timeRes{1e-9}
|
||||
, m_timeUnit {
|
||||
1e-9
|
||||
}
|
||||
#ifdef VL_TRACE_THREADED
|
||||
, m_numTraceBuffers(0)
|
||||
, m_numTraceBuffers { 0 }
|
||||
#endif
|
||||
{
|
||||
set_time_unit(Verilated::timeunitString());
|
||||
|
|
@ -294,7 +296,7 @@ VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
|
|||
}
|
||||
|
||||
template <> VerilatedTrace<VL_DERIVED_T>::~VerilatedTrace() {
|
||||
if (m_sigs_oldvalp) VL_DO_CLEAR(delete[] m_sigs_oldvalp, m_sigs_oldvalp = NULL);
|
||||
if (m_sigs_oldvalp) VL_DO_CLEAR(delete[] m_sigs_oldvalp, m_sigs_oldvalp = nullptr);
|
||||
Verilated::removeFlushCb(VerilatedTrace<VL_DERIVED_T>::onFlush, this);
|
||||
Verilated::removeExitCb(VerilatedTrace<VL_DERIVED_T>::onExit, this);
|
||||
#ifdef VL_TRACE_THREADED
|
||||
|
|
|
|||
|
|
@ -1,501 +0,0 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: pre-C++11 replacements for std::unordered_set
|
||||
// and std::unordered_map.
|
||||
//
|
||||
// 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.
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
//*************************************************************************
|
||||
// This file has clones of the std::unordered_set and std::unordered_map
|
||||
// hash table types. They are here so that Verilator can use hash tables
|
||||
// in pre-C++11 compilers, and the same client code can link against the
|
||||
// std:: types when they are available.
|
||||
//
|
||||
// The implementations in this file do not implement the complete APIs
|
||||
// of the std:: types. Nor are they correct in every detail,
|
||||
// notably, the const_iterators do not enforce constness. We can extend
|
||||
// these implementations to cover more of the std API as needed.
|
||||
//
|
||||
// TODO: In the future, when Verilator requires C++11 to compile,
|
||||
// remove this entire file and switch to the std:: types.
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#ifndef _VERILATED_UNORDERED_SET_MAP_H_
|
||||
#define _VERILATED_UNORDERED_SET_MAP_H_
|
||||
|
||||
#include "verilatedos.h"
|
||||
|
||||
#include <list>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
// Abstract 'vl_hash' and 'vl_equal_to' templates.
|
||||
template <typename T> struct vl_hash { size_t operator()(const T& k) const; };
|
||||
|
||||
template <typename T> struct vl_equal_to { bool operator()(const T& a, const T& b) const; };
|
||||
|
||||
// Specializations of 'vl_hash' and 'vl_equal_to'.
|
||||
inline size_t vl_hash_bytes(const void* vbufp, size_t nbytes) {
|
||||
const vluint8_t* bufp = static_cast<const vluint8_t*>(vbufp);
|
||||
size_t hash = 0;
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
hash = bufp[i] + 31U * hash; // the K&R classic!
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
template <> inline size_t vl_hash<int>::operator()(const int& k) const { return k; }
|
||||
|
||||
template <> inline bool vl_equal_to<int>::operator()(const int& a, const int& b) const {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
template <> inline size_t vl_hash<unsigned int>::operator()(const unsigned int& k) const {
|
||||
return k;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool vl_equal_to<unsigned int>::operator()(const unsigned int& a,
|
||||
const unsigned int& b) const {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
template <> inline size_t vl_hash<std::string>::operator()(const std::string& k) const {
|
||||
return vl_hash_bytes(k.data(), k.size());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool vl_equal_to<std::string>::operator()(const std::string& a,
|
||||
const std::string& b) const {
|
||||
// Don't scan the strings if the sizes are different.
|
||||
if (a.size() != b.size()) return false;
|
||||
return (0 == a.compare(b)); // Must scan.
|
||||
}
|
||||
|
||||
template <typename T> struct vl_hash<T*> {
|
||||
size_t operator()(T* kp) const {
|
||||
return ((sizeof(size_t) == sizeof(kp)) ? reinterpret_cast<size_t>(kp)
|
||||
: vl_hash_bytes(&kp, sizeof(kp)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct vl_equal_to<T*> {
|
||||
bool operator()(T* ap, T* bp) const { return ap == bp; }
|
||||
};
|
||||
|
||||
//===================================================================
|
||||
//
|
||||
/// Functional clone of the std::unordered_set hash table.
|
||||
template <class T_Key, class T_Hash = vl_hash<T_Key>, class T_Equal = vl_equal_to<T_Key> >
|
||||
class vl_unordered_set {
|
||||
public:
|
||||
// TYPES
|
||||
typedef std::list<T_Key> Bucket;
|
||||
enum RehashType { GROW, SHRINK };
|
||||
|
||||
template <class KK, class VV, class HH, class EQ> friend class vl_unordered_map;
|
||||
|
||||
class iterator {
|
||||
protected:
|
||||
// MEMBERS
|
||||
size_t m_bucketIdx; // Bucket this iterator points into
|
||||
typename Bucket::iterator m_bit; // Bucket-local iterator
|
||||
const vl_unordered_set* m_setp; // The containing set
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
iterator(size_t bucketIdx, typename Bucket::iterator bit, const vl_unordered_set* setp)
|
||||
: m_bucketIdx(bucketIdx)
|
||||
, m_bit(bit)
|
||||
, m_setp(setp) {}
|
||||
|
||||
// METHODS
|
||||
const T_Key& operator*() const { return *m_bit; }
|
||||
// This should really be 'const T_Key*' type for unordered_set,
|
||||
// however this iterator is shared with unordered_map whose
|
||||
// operator-> returns a non-const ValueType*, so keep this
|
||||
// non-const to avoid having to define a whole separate iterator
|
||||
// for unordered_map.
|
||||
T_Key* operator->() const { return &(*m_bit); }
|
||||
bool operator==(const iterator& other) const {
|
||||
return ((m_bucketIdx == other.m_bucketIdx) && (m_bit == other.m_bit));
|
||||
}
|
||||
bool operator!=(const iterator& other) const { return (!this->operator==(other)); }
|
||||
void advanceUntilValid() {
|
||||
while (true) {
|
||||
if (m_bit != m_setp->m_bucketsp[m_bucketIdx].end()) {
|
||||
// Valid iterator in this bucket; we're done.
|
||||
return;
|
||||
}
|
||||
|
||||
// Try the next bucket?
|
||||
m_bucketIdx++;
|
||||
if (m_bucketIdx == m_setp->numBuckets()) {
|
||||
// Ran past the end of buckets, set to end().
|
||||
*this = m_setp->end();
|
||||
return;
|
||||
}
|
||||
m_bit = m_setp->m_bucketsp[m_bucketIdx].begin();
|
||||
}
|
||||
}
|
||||
void operator++() {
|
||||
++m_bit;
|
||||
advanceUntilValid();
|
||||
}
|
||||
|
||||
typename Bucket::iterator bit() const { return m_bit; }
|
||||
};
|
||||
|
||||
// TODO: there's no real const enforcement on the 'const_iterator'.
|
||||
typedef iterator const_iterator;
|
||||
|
||||
private:
|
||||
// MEMBERS
|
||||
size_t m_numElements; // Number of entries present.
|
||||
size_t m_log2Buckets; // Log-base-2 of the number of buckets.
|
||||
mutable Bucket* m_bucketsp; // Hash table buckets. May be NULL;
|
||||
// // we'll allocate it on the fly when
|
||||
// // the first entries are created.
|
||||
Bucket m_emptyBucket; // A fake bucket, used to construct end().
|
||||
T_Hash m_hash; // Hash function provider.
|
||||
T_Equal m_equal; // Equal-to function provider.
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
vl_unordered_set()
|
||||
: m_numElements(0)
|
||||
, m_log2Buckets(initLog2Buckets())
|
||||
, m_bucketsp(NULL)
|
||||
, m_hash()
|
||||
, m_equal() {}
|
||||
|
||||
vl_unordered_set(const vl_unordered_set& other)
|
||||
: m_numElements(other.m_numElements)
|
||||
, m_log2Buckets(other.m_log2Buckets)
|
||||
, m_bucketsp(NULL)
|
||||
, m_hash()
|
||||
, m_equal() {
|
||||
if (other.m_bucketsp) {
|
||||
m_bucketsp = new Bucket[numBuckets()];
|
||||
for (size_t i = 0; i < numBuckets(); i++) m_bucketsp[i] = other.m_bucketsp[i];
|
||||
}
|
||||
}
|
||||
~vl_unordered_set() { VL_DO_DANGLING(delete[] m_bucketsp, m_bucketsp); }
|
||||
|
||||
vl_unordered_set& operator=(const vl_unordered_set& other) {
|
||||
if (this != &other) {
|
||||
clear();
|
||||
delete[] m_bucketsp;
|
||||
m_numElements = other.m_numElements;
|
||||
m_log2Buckets = other.m_log2Buckets;
|
||||
if (other.m_bucketsp) {
|
||||
m_bucketsp = new Bucket[numBuckets()];
|
||||
for (size_t i = 0; i < numBuckets(); i++) m_bucketsp[i] = other.m_bucketsp[i];
|
||||
} else {
|
||||
m_bucketsp = NULL;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// METHODS
|
||||
static size_t initLog2Buckets() { return 4; }
|
||||
|
||||
iterator begin() {
|
||||
if (m_numElements) {
|
||||
initBuckets();
|
||||
iterator result = iterator(0, m_bucketsp[0].begin(), this);
|
||||
result.advanceUntilValid();
|
||||
return result;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
const_iterator begin() const {
|
||||
if (m_numElements) {
|
||||
initBuckets();
|
||||
const_iterator result = iterator(0, m_bucketsp[0].begin(), this);
|
||||
result.advanceUntilValid();
|
||||
return result;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
const_iterator end() const {
|
||||
return iterator(0xFFFFFFFFFFFFFFFFULL, const_cast<Bucket&>(m_emptyBucket).begin(), this);
|
||||
}
|
||||
|
||||
bool empty() const { return m_numElements == 0; }
|
||||
|
||||
size_t size() const { return m_numElements; }
|
||||
|
||||
size_t count(const T_Key& key) const { return (find(key) == end()) ? 0 : 1; }
|
||||
|
||||
size_t hashToBucket(size_t hashVal) const { return hashToBucket(hashVal, m_log2Buckets); }
|
||||
static size_t hashToBucket(size_t hashVal, unsigned log2Buckets) {
|
||||
// Fibonacci hashing, see
|
||||
// https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization
|
||||
// -that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
|
||||
//
|
||||
// * The magic numbers below are UINT_MAX/phi where phi is the
|
||||
// golden ratio number (1.618...) for either 64- or 32-bit
|
||||
// values of UINT_MAX.
|
||||
//
|
||||
// * Fibonacci hashing mixes the result of the client's hash
|
||||
// function further. This permits the use of very fast client
|
||||
// hash funcs (like just returning the int or pointer value as
|
||||
// is!) and tolerates crappy client hash functions pretty well.
|
||||
size_t mult = hashVal * ((sizeof(size_t) == 8) ? 11400714819323198485ULL : 2654435769lu);
|
||||
size_t result = (mult >> (((sizeof(size_t) == 8) ? 64 : 32) - log2Buckets));
|
||||
return result;
|
||||
}
|
||||
|
||||
iterator find_internal(const T_Key& key, size_t& bucketIdxOut) {
|
||||
size_t hash = m_hash.operator()(key);
|
||||
bucketIdxOut = hashToBucket(hash);
|
||||
initBuckets();
|
||||
Bucket* bucketp = &m_bucketsp[bucketIdxOut];
|
||||
|
||||
for (typename Bucket::iterator it = bucketp->begin(); it != bucketp->end(); ++it) {
|
||||
if (m_equal.operator()(*it, key)) return iterator(bucketIdxOut, it, this);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
const_iterator find(const T_Key& key) const {
|
||||
size_t bucketIdx;
|
||||
return const_cast<vl_unordered_set*>(this)->find_internal(key, bucketIdx);
|
||||
}
|
||||
|
||||
iterator find(const T_Key& key) {
|
||||
size_t bucketIdx;
|
||||
return find_internal(key, bucketIdx);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const T_Key& val) {
|
||||
size_t bucketIdx;
|
||||
iterator existIt = find_internal(val, bucketIdx);
|
||||
if (existIt != end()) {
|
||||
// Collision with existing element.
|
||||
//
|
||||
// An element may be inserted only if it is not
|
||||
// equal to an existing element. So fail.
|
||||
return std::pair<iterator, bool>(end(), false);
|
||||
}
|
||||
|
||||
// No collision, so insert it.
|
||||
m_numElements++;
|
||||
|
||||
m_bucketsp[bucketIdx].push_front(val);
|
||||
|
||||
// Compute result iterator. This pointer will be valid
|
||||
// if we don't rehash:
|
||||
iterator result_it(bucketIdx, m_bucketsp[bucketIdx].begin(), this);
|
||||
|
||||
if (needToRehash(GROW)) {
|
||||
rehash(GROW);
|
||||
// ... since we rehashed, do a lookup to get the result iterator.
|
||||
result_it = find(val);
|
||||
}
|
||||
|
||||
return std::pair<iterator, bool>(result_it, true);
|
||||
}
|
||||
|
||||
iterator erase(iterator it) {
|
||||
iterator next_it = it;
|
||||
++next_it;
|
||||
erase(*it);
|
||||
return next_it;
|
||||
}
|
||||
|
||||
size_t erase(const T_Key& key) {
|
||||
size_t bucketIdx;
|
||||
iterator it = find_internal(key, bucketIdx);
|
||||
if (it != end()) {
|
||||
m_bucketsp[bucketIdx].erase(it.bit());
|
||||
m_numElements--;
|
||||
// Rehashing to handle a shrinking data set is important
|
||||
// for the Scoreboard in V3Partition, which begins tracking
|
||||
// a huge number of vertices and then tracks a successively
|
||||
// smaller number over time.
|
||||
if (needToRehash(SHRINK)) rehash(SHRINK);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (m_bucketsp) {
|
||||
delete[] m_bucketsp;
|
||||
m_bucketsp = NULL;
|
||||
}
|
||||
m_numElements = 0;
|
||||
m_log2Buckets = initLog2Buckets();
|
||||
}
|
||||
|
||||
private:
|
||||
size_t numBuckets() const { return (1ULL << m_log2Buckets); }
|
||||
|
||||
Bucket* getBucket(size_t idx) {
|
||||
initBuckets();
|
||||
return &m_bucketsp[idx];
|
||||
}
|
||||
|
||||
void initBuckets() const {
|
||||
if (!m_bucketsp) m_bucketsp = new Bucket[numBuckets()];
|
||||
}
|
||||
|
||||
bool needToRehash(RehashType rt) const {
|
||||
if (rt == GROW) {
|
||||
return ((4 * numBuckets()) < m_numElements);
|
||||
} else {
|
||||
return (numBuckets() > (4 * m_numElements));
|
||||
}
|
||||
}
|
||||
|
||||
void rehash(RehashType rt) {
|
||||
size_t new_log2Buckets;
|
||||
if (rt == GROW) {
|
||||
new_log2Buckets = m_log2Buckets + 2;
|
||||
} else {
|
||||
if (m_log2Buckets <= 4) {
|
||||
// On shrink, saturate m_log2Buckets at its
|
||||
// initial size of 2^4 == 16 buckets. Don't risk
|
||||
// underflowing!
|
||||
return;
|
||||
}
|
||||
new_log2Buckets = m_log2Buckets - 2;
|
||||
}
|
||||
|
||||
size_t new_num_buckets = 1ULL << new_log2Buckets;
|
||||
Bucket* new_bucketsp = new Bucket[new_num_buckets];
|
||||
|
||||
for (size_t i = 0; i < numBuckets(); i++) {
|
||||
while (!m_bucketsp[i].empty()) {
|
||||
typename Bucket::iterator bit = m_bucketsp[i].begin();
|
||||
size_t hash = m_hash.operator()(*bit);
|
||||
size_t new_idx = hashToBucket(hash, new_log2Buckets);
|
||||
// Avoid mallocing one list elem and freeing another;
|
||||
// splice just moves it over.
|
||||
new_bucketsp[new_idx].splice(new_bucketsp[new_idx].begin(), m_bucketsp[i], bit);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] m_bucketsp;
|
||||
m_bucketsp = new_bucketsp;
|
||||
m_log2Buckets = new_log2Buckets;
|
||||
}
|
||||
};
|
||||
|
||||
//===================================================================
|
||||
//
|
||||
/// Functional clone of the std::unordered_map hash table.
|
||||
template <class T_Key, class T_Value, class T_Hash = vl_hash<T_Key>,
|
||||
class T_Equal = vl_equal_to<T_Key> >
|
||||
class vl_unordered_map {
|
||||
private:
|
||||
// TYPES
|
||||
typedef std::pair<T_Key, T_Value> KeyValPair;
|
||||
|
||||
class KeyHash {
|
||||
private:
|
||||
T_Hash key_hash;
|
||||
|
||||
public:
|
||||
KeyHash() {}
|
||||
size_t operator()(const KeyValPair& kv_pair) const {
|
||||
return key_hash.operator()(kv_pair.first);
|
||||
}
|
||||
};
|
||||
|
||||
class KeyEqual {
|
||||
private:
|
||||
T_Equal key_eq;
|
||||
|
||||
public:
|
||||
KeyEqual() {}
|
||||
bool operator()(const KeyValPair& kv_a, const KeyValPair& kv_b) const {
|
||||
return key_eq.operator()(kv_a.first, kv_b.first);
|
||||
}
|
||||
};
|
||||
|
||||
// MEMBERS
|
||||
typedef vl_unordered_set<KeyValPair, KeyHash, KeyEqual> MapSet;
|
||||
MapSet m_set; // Wrap this vl_unordered_set which holds all state.
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
vl_unordered_map() {}
|
||||
~vl_unordered_map() {}
|
||||
|
||||
typedef typename MapSet::iterator iterator;
|
||||
typedef typename MapSet::const_iterator const_iterator;
|
||||
|
||||
// METHODS
|
||||
iterator begin() { return m_set.begin(); }
|
||||
const_iterator begin() const { return m_set.begin(); }
|
||||
const_iterator end() const { return m_set.end(); }
|
||||
bool empty() const { return m_set.empty(); }
|
||||
iterator find(const T_Key& k) {
|
||||
// We can't assume that T_Value() is defined.
|
||||
// ie, this does not work:
|
||||
// return m_set.find(std::make_pair(k, T_Value()));
|
||||
|
||||
// So, do this instead:
|
||||
T_Hash mapHash;
|
||||
T_Equal mapEq;
|
||||
size_t hash = mapHash.operator()(k);
|
||||
size_t bucketIdxOut = m_set.hashToBucket(hash);
|
||||
typename MapSet::Bucket* bucketp = m_set.getBucket(bucketIdxOut);
|
||||
|
||||
for (typename MapSet::Bucket::iterator it = bucketp->begin(); it != bucketp->end(); ++it) {
|
||||
if (mapEq.operator()(it->first, k)) return iterator(bucketIdxOut, it, &m_set);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
const_iterator find(const T_Key& k) const {
|
||||
return const_cast<vl_unordered_map*>(this)->find(k);
|
||||
}
|
||||
std::pair<iterator, bool> insert(const KeyValPair& val) { return m_set.insert(val); }
|
||||
iterator erase(iterator it) { return m_set.erase(it); }
|
||||
size_t erase(const T_Key& k) {
|
||||
iterator it = find(k);
|
||||
if (it == end()) return 0;
|
||||
m_set.erase(it);
|
||||
return 1;
|
||||
}
|
||||
T_Value& operator[](const T_Key& k) {
|
||||
// Here we can assume T_Value() is defined, as
|
||||
// std::unordered_map::operator[] relies on it too.
|
||||
KeyValPair dummy = std::make_pair(k, T_Value());
|
||||
iterator it = m_set.find(dummy);
|
||||
if (it == m_set.end()) it = m_set.insert(dummy).first;
|
||||
// For the 'set', it's generally not safe to modify
|
||||
// the value after deref. For the 'map' though, we know
|
||||
// it's safe to modify the value field and we can allow it:
|
||||
return it->second;
|
||||
}
|
||||
T_Value& at(const T_Key& k) {
|
||||
iterator it = find(k);
|
||||
if (it == end()) { throw std::out_of_range("sorry"); }
|
||||
return it->second;
|
||||
}
|
||||
const T_Value& at(const T_Key& k) const {
|
||||
iterator it = find(k);
|
||||
if (it == end()) { throw std::out_of_range("sorry"); }
|
||||
return it->second;
|
||||
}
|
||||
void clear() { m_set.clear(); }
|
||||
size_t size() const { return m_set.size(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -51,13 +51,14 @@
|
|||
// This size comes form VCD allowing use of printable ASCII characters between
|
||||
// '!' and '~' inclusive, which are a total of 94 different values. Encoding a
|
||||
// 32 bit code hence needs a maximum of ceil(log94(2**32-1)) == 5 bytes.
|
||||
#define VL_TRACE_MAX_VCD_CODE_SIZE 5 ///< Maximum length of a VCD string code
|
||||
constexpr unsigned VL_TRACE_MAX_VCD_CODE_SIZE = 5; ///< Maximum length of a VCD string code
|
||||
|
||||
// We use 8 bytes per code in a suffix buffer array.
|
||||
// 1 byte optional separator + VL_TRACE_MAX_VCD_CODE_SIZE bytes for code
|
||||
// + 1 byte '\n' + 1 byte suffix size. This luckily comes out to a power of 2,
|
||||
// meaning the array can be aligned such that entries never straddle multiple
|
||||
// cache-lines.
|
||||
#define VL_TRACE_SUFFIX_ENTRY_SIZE 8 ///< Size of a suffix entry
|
||||
constexpr unsigned VL_TRACE_SUFFIX_ENTRY_SIZE = 8; ///< Size of a suffix entry
|
||||
|
||||
//=============================================================================
|
||||
// Specialization of the generics for this trace format
|
||||
|
|
@ -88,21 +89,15 @@ ssize_t VerilatedVcdFile::write(const char* bufp, ssize_t len) VL_MT_UNSAFE {
|
|||
//=============================================================================
|
||||
// Opening/Closing
|
||||
|
||||
VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep)
|
||||
: m_isOpen(false)
|
||||
, m_rolloverMB(0)
|
||||
, m_modDepth(0) {
|
||||
VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep) {
|
||||
// Not in header to avoid link issue if header is included without this .cpp file
|
||||
m_fileNewed = (filep == NULL);
|
||||
m_fileNewed = (filep == nullptr);
|
||||
m_filep = m_fileNewed ? new VerilatedVcdFile : filep;
|
||||
m_namemapp = NULL;
|
||||
m_evcd = false;
|
||||
m_wrChunkSize = 8 * 1024;
|
||||
m_wrBufp = new char[m_wrChunkSize * 8];
|
||||
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||
m_writep = m_wrBufp;
|
||||
m_wroteBytes = 0;
|
||||
m_suffixesp = NULL;
|
||||
m_suffixesp = nullptr;
|
||||
}
|
||||
|
||||
void VerilatedVcd::open(const char* filename) {
|
||||
|
|
@ -191,15 +186,15 @@ void VerilatedVcd::makeNameMap() {
|
|||
// If no scope was specified, prefix everything with a "top"
|
||||
// This comes from user instantiations with no name - IE Vtop("").
|
||||
bool nullScope = false;
|
||||
for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
|
||||
const std::string& hiername = it->first;
|
||||
for (const auto& i : *m_namemapp) {
|
||||
const std::string& hiername = i.first;
|
||||
if (!hiername.empty() && hiername[0] == '\t') nullScope = true;
|
||||
}
|
||||
if (nullScope) {
|
||||
NameMap* newmapp = new NameMap;
|
||||
for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
|
||||
const std::string& hiername = it->first;
|
||||
const std::string& decl = it->second;
|
||||
for (const auto& i : *m_namemapp) {
|
||||
const std::string& hiername = i.first;
|
||||
const std::string& decl = i.second;
|
||||
std::string newname = std::string("top");
|
||||
if (hiername[0] != '\t') newname += ' ';
|
||||
newname += hiername;
|
||||
|
|
@ -211,14 +206,14 @@ void VerilatedVcd::makeNameMap() {
|
|||
}
|
||||
|
||||
void VerilatedVcd::deleteNameMap() {
|
||||
if (m_namemapp) VL_DO_CLEAR(delete m_namemapp, m_namemapp = NULL);
|
||||
if (m_namemapp) VL_DO_CLEAR(delete m_namemapp, m_namemapp = nullptr);
|
||||
}
|
||||
|
||||
VerilatedVcd::~VerilatedVcd() {
|
||||
close();
|
||||
if (m_wrBufp) VL_DO_CLEAR(delete[] m_wrBufp, m_wrBufp = NULL);
|
||||
if (m_wrBufp) VL_DO_CLEAR(delete[] m_wrBufp, m_wrBufp = nullptr);
|
||||
deleteNameMap();
|
||||
if (m_filep && m_fileNewed) VL_DO_CLEAR(delete m_filep, m_filep = NULL);
|
||||
if (m_filep && m_fileNewed) VL_DO_CLEAR(delete m_filep, m_filep = nullptr);
|
||||
}
|
||||
|
||||
void VerilatedVcd::closePrev() {
|
||||
|
|
@ -286,7 +281,7 @@ void VerilatedVcd::bufferResize(vluint64_t minsize) {
|
|||
memcpy(m_wrBufp, oldbufp, m_writep - oldbufp);
|
||||
m_writep = m_wrBufp + (m_writep - oldbufp);
|
||||
m_wrFlushp = m_wrBufp + m_wrChunkSize * 6;
|
||||
VL_DO_CLEAR(delete[] oldbufp, oldbufp = NULL);
|
||||
VL_DO_CLEAR(delete[] oldbufp, oldbufp = nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,7 +345,7 @@ void VerilatedVcd::printIndent(int level_change) {
|
|||
|
||||
void VerilatedVcd::dumpHeader() {
|
||||
printStr("$version Generated by VerilatedVcd $end\n");
|
||||
time_t time_str = time(NULL);
|
||||
time_t time_str = time(nullptr);
|
||||
printStr("$date ");
|
||||
printStr(ctime(&time_str));
|
||||
printStr(" $end\n");
|
||||
|
|
@ -373,9 +368,9 @@ void VerilatedVcd::dumpHeader() {
|
|||
|
||||
// Print the signal names
|
||||
const char* lastName = "";
|
||||
for (NameMap::const_iterator it = m_namemapp->begin(); it != m_namemapp->end(); ++it) {
|
||||
const std::string& hiernamestr = it->first;
|
||||
const std::string& decl = it->second;
|
||||
for (const auto& i : *m_namemapp) {
|
||||
const std::string& hiernamestr = i.first;
|
||||
const std::string& decl = i.second;
|
||||
|
||||
// Determine difference between the old and new names
|
||||
const char* hiername = hiernamestr.c_str();
|
||||
|
|
|
|||
|
|
@ -36,11 +36,10 @@ class VerilatedVcd;
|
|||
|
||||
class VerilatedVcdFile {
|
||||
private:
|
||||
int m_fd; ///< File descriptor we're writing to
|
||||
int m_fd = 0; ///< File descriptor we're writing to
|
||||
public:
|
||||
// METHODS
|
||||
VerilatedVcdFile()
|
||||
: m_fd(0) {}
|
||||
VerilatedVcdFile() {}
|
||||
virtual ~VerilatedVcdFile() {}
|
||||
virtual bool open(const std::string& name) VL_MT_UNSAFE;
|
||||
virtual void close() VL_MT_UNSAFE;
|
||||
|
|
@ -62,23 +61,23 @@ private:
|
|||
|
||||
VerilatedVcdFile* m_filep; ///< File we're writing to
|
||||
bool m_fileNewed; ///< m_filep needs destruction
|
||||
bool m_isOpen; ///< True indicates open file
|
||||
bool m_evcd; ///< True for evcd format
|
||||
bool m_isOpen = false; ///< True indicates open file
|
||||
bool m_evcd = false; ///< True for evcd format
|
||||
std::string m_filename; ///< Filename we're writing to (if open)
|
||||
vluint64_t m_rolloverMB; ///< MB of file size to rollover at
|
||||
int m_modDepth; ///< Depth of module hierarchy
|
||||
vluint64_t m_rolloverMB = 0; ///< MB of file size to rollover at
|
||||
int m_modDepth = 0; ///< Depth of module hierarchy
|
||||
|
||||
char* m_wrBufp; ///< Output buffer
|
||||
char* m_wrFlushp; ///< Output buffer flush trigger location
|
||||
char* m_writep; ///< Write pointer into output buffer
|
||||
vluint64_t m_wrChunkSize; ///< Output buffer size
|
||||
vluint64_t m_wroteBytes; ///< Number of bytes written to this file
|
||||
vluint64_t m_wroteBytes = 0; ///< Number of bytes written to this file
|
||||
|
||||
std::vector<char> m_suffixes; ///< VCD line end string codes + metadata
|
||||
const char* m_suffixesp; ///< Pointer to first element of above
|
||||
|
||||
typedef std::map<std::string, std::string> NameMap;
|
||||
NameMap* m_namemapp; ///< List of names for the header
|
||||
NameMap* m_namemapp = nullptr; ///< List of names for the header
|
||||
|
||||
void bufferResize(vluint64_t minsize);
|
||||
void bufferFlush() VL_MT_UNSAFE_ONE;
|
||||
|
|
@ -101,7 +100,7 @@ private:
|
|||
|
||||
void dumpHeader();
|
||||
|
||||
char* writeCode(char* writep, vluint32_t code);
|
||||
static char* writeCode(char* writep, vluint32_t code);
|
||||
|
||||
void finishLine(vluint32_t code, char* writep);
|
||||
|
||||
|
|
@ -113,11 +112,11 @@ protected:
|
|||
// Implementation of VerilatedTrace interface
|
||||
|
||||
// Implementations of protected virtual methods for VerilatedTrace
|
||||
void emitTimeChange(vluint64_t timeui) VL_OVERRIDE;
|
||||
virtual void emitTimeChange(vluint64_t timeui) override;
|
||||
|
||||
// Hooks called from VerilatedTrace
|
||||
bool preFullDump() VL_OVERRIDE { return isOpen(); }
|
||||
bool preChangeDump() VL_OVERRIDE;
|
||||
virtual bool preFullDump() override { return isOpen(); }
|
||||
virtual bool preChangeDump() override;
|
||||
|
||||
// Implementations of duck-typed methods for VerilatedTrace. These are
|
||||
// called from only one place (namely full*) so always inline them.
|
||||
|
|
@ -133,7 +132,7 @@ public:
|
|||
//=========================================================================
|
||||
// External interface to client code
|
||||
|
||||
explicit VerilatedVcd(VerilatedVcdFile* filep = NULL);
|
||||
explicit VerilatedVcd(VerilatedVcdFile* filep = nullptr);
|
||||
~VerilatedVcd();
|
||||
|
||||
// ACCESSORS
|
||||
|
|
@ -337,8 +336,8 @@ class VerilatedVcdC {
|
|||
VL_UNCOPYABLE(VerilatedVcdC);
|
||||
|
||||
public:
|
||||
explicit VerilatedVcdC(VerilatedVcdFile* filep = NULL)
|
||||
: m_sptrace(filep) {}
|
||||
explicit VerilatedVcdC(VerilatedVcdFile* filep = nullptr)
|
||||
: m_sptrace{filep} {}
|
||||
~VerilatedVcdC() { close(); }
|
||||
/// Routines can only be called from one thread; allow next call from different thread
|
||||
void changeThread() { spTrace()->changeThread(); }
|
||||
|
|
|
|||
|
|
@ -25,22 +25,21 @@
|
|||
//======================================================================
|
||||
|
||||
//--------------------------------------------------
|
||||
#if (SYSTEMC_VERSION >= 20050714)
|
||||
// SystemC 2.1.v1
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment(const std::string&) {}
|
||||
void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**) {}
|
||||
|
||||
// clang-format off
|
||||
# define DECL_TRACE_METHOD_A(tp) \
|
||||
#define DECL_TRACE_METHOD_A(tp) \
|
||||
void VerilatedVcdSc::trace(const tp& object, const std::string& name) {}
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
#define DECL_TRACE_METHOD_B(tp) \
|
||||
void VerilatedVcdSc::trace(const tp& object, const std::string& name, int width) {}
|
||||
|
||||
# if (SYSTEMC_VERSION >= 20171012)
|
||||
// clang-format off
|
||||
#if (SYSTEMC_VERSION >= 20171012)
|
||||
DECL_TRACE_METHOD_A( sc_event )
|
||||
DECL_TRACE_METHOD_A( sc_time )
|
||||
# endif
|
||||
#endif
|
||||
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||
|
|
@ -50,9 +49,9 @@ void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**
|
|||
DECL_TRACE_METHOD_B( unsigned short )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned long )
|
||||
# ifdef SYSTEMC_64BIT_PATCHES
|
||||
#ifdef SYSTEMC_64BIT_PATCHES
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
# endif
|
||||
#endif
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
|
|
@ -76,92 +75,6 @@ void VerilatedVcdSc::trace(const unsigned int&, const std::string&, const char**
|
|||
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
||||
// clang-format on
|
||||
|
||||
//--------------------------------------------------
|
||||
#elif (SYSTEMC_VERSION > 20011000)
|
||||
// SystemC 2.0.1
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment(const sc_string&) {}
|
||||
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
||||
|
||||
#define DECL_TRACE_METHOD_A(tp) \
|
||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
|
||||
#define DECL_TRACE_METHOD_B(tp) \
|
||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name, int width) {}
|
||||
|
||||
// clang-format off
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_bit )
|
||||
DECL_TRACE_METHOD_A( sc_logic )
|
||||
DECL_TRACE_METHOD_B( unsigned char )
|
||||
DECL_TRACE_METHOD_B( unsigned short )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned long )
|
||||
#ifdef SYSTEMC_64BIT_PATCHES
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
#endif
|
||||
#if (SYSTEMC_VERSION > 20041000)
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
DECL_TRACE_METHOD_B( long long)
|
||||
#endif
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
DECL_TRACE_METHOD_B( long )
|
||||
DECL_TRACE_METHOD_A( float )
|
||||
DECL_TRACE_METHOD_A( double )
|
||||
DECL_TRACE_METHOD_A( sc_int_base )
|
||||
DECL_TRACE_METHOD_A( sc_uint_base )
|
||||
DECL_TRACE_METHOD_A( sc_signed )
|
||||
DECL_TRACE_METHOD_A( sc_unsigned )
|
||||
DECL_TRACE_METHOD_A( sc_fxval )
|
||||
DECL_TRACE_METHOD_A( sc_fxval_fast )
|
||||
DECL_TRACE_METHOD_A( sc_fxnum )
|
||||
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
||||
DECL_TRACE_METHOD_A( sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_lv_base )
|
||||
// clang-format on
|
||||
|
||||
//--------------------------------------------------
|
||||
#else
|
||||
// SystemC 1.2.1beta
|
||||
// cppcheck-suppress unusedFunction
|
||||
void VerilatedVcdSc::write_comment(const sc_string&) {}
|
||||
void VerilatedVcdSc::trace(const unsigned int&, const sc_string&, const char**) {}
|
||||
|
||||
#define DECL_TRACE_METHOD_A(tp) \
|
||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name) {}
|
||||
#define DECL_TRACE_METHOD_B(tp) \
|
||||
void VerilatedVcdSc::trace(const tp& object, const sc_string& name, int width) {}
|
||||
|
||||
// clang-format off
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_B( unsigned char )
|
||||
DECL_TRACE_METHOD_B( short unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( long unsigned int )
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short int )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
DECL_TRACE_METHOD_B( long int )
|
||||
DECL_TRACE_METHOD_A( float )
|
||||
DECL_TRACE_METHOD_A( double )
|
||||
DECL_TRACE_METHOD_A( sc_bit )
|
||||
DECL_TRACE_METHOD_A( sc_logic )
|
||||
DECL_TRACE_METHOD_A( sc_bool_vector )
|
||||
DECL_TRACE_METHOD_A( sc_logic_vector )
|
||||
DECL_TRACE_METHOD_A( sc_signal_bool_vector )
|
||||
DECL_TRACE_METHOD_A( sc_signal_logic_vector )
|
||||
DECL_TRACE_METHOD_A( sc_uint_base )
|
||||
DECL_TRACE_METHOD_A( sc_int_base )
|
||||
DECL_TRACE_METHOD_A( sc_unsigned )
|
||||
DECL_TRACE_METHOD_A( sc_signed )
|
||||
DECL_TRACE_METHOD_A( sc_signal_resolved )
|
||||
DECL_TRACE_METHOD_A( sc_signal_resolved_vector )
|
||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#undef DECL_TRACE_METHOD_A
|
||||
#undef DECL_TRACE_METHOD_B
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ class VerilatedVcdSc : sc_trace_file, public VerilatedVcdC {
|
|||
public:
|
||||
VerilatedVcdSc() {
|
||||
sc_get_curr_simcontext()->add_trace_file(this);
|
||||
#if (SYSTEMC_VERSION >= 20060505)
|
||||
// We want to avoid a depreciated warning, but still be back compatible.
|
||||
// Turning off the message just for this still results in an
|
||||
// annoying "to turn off" message.
|
||||
|
|
@ -48,25 +47,13 @@ public:
|
|||
spTrace()->set_time_unit(tunits.to_string());
|
||||
}
|
||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||
#elif (SYSTEMC_VERSION > 20011000)
|
||||
// To confuse matters 2.1.beta returns a char* here, while 2.1.v1 returns a std::string
|
||||
// we allow both flavors with overloaded set_time_* functions.
|
||||
spTrace()->set_time_unit(sc_get_default_time_unit().to_string());
|
||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||
#endif
|
||||
}
|
||||
virtual ~VerilatedVcdSc() { close(); }
|
||||
|
||||
// METHODS
|
||||
/// Called by SystemC simulate()
|
||||
virtual void cycle(bool delta_cycle) {
|
||||
#if (SYSTEMC_VERSION > 20011000)
|
||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||
#else
|
||||
// VCD files must have integer timestamps, so we write all times in
|
||||
// increments of time_resolution
|
||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -76,26 +63,23 @@ private:
|
|||
// Cadence Incisive has these as abstract functions so we must create them
|
||||
virtual void set_time_unit(int exponent10_seconds) {} // deprecated
|
||||
#endif
|
||||
#if defined(NC_SYSTEMC) || (SYSTEMC_VERSION >= 20111100)
|
||||
virtual void set_time_unit(double v, sc_time_unit tu) {} // LCOV_EXCL_LINE
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------
|
||||
#if (SYSTEMC_VERSION >= 20050714)
|
||||
// SystemC 2.1.v1
|
||||
// clang-format off
|
||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
// SystemC 2.1.v1
|
||||
#define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
|
||||
#define DECL_TRACE_METHOD_B(tp) \
|
||||
virtual void trace(const tp& object, const std::string& name, int width);
|
||||
|
||||
virtual void write_comment(const std::string&);
|
||||
virtual void trace(const unsigned int&, const std::string&, const char**);
|
||||
|
||||
// clang-format off
|
||||
// Formatting matches that of sc_trace.h
|
||||
# if (SYSTEMC_VERSION >= 20171012)
|
||||
#if (SYSTEMC_VERSION >= 20171012)
|
||||
DECL_TRACE_METHOD_A( sc_event )
|
||||
DECL_TRACE_METHOD_A( sc_time )
|
||||
# endif
|
||||
#endif
|
||||
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_dt::sc_bit )
|
||||
|
|
@ -105,9 +89,9 @@ private:
|
|||
DECL_TRACE_METHOD_B( unsigned short )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned long )
|
||||
# ifdef SYSTEMC_64BIT_PATCHES
|
||||
#ifdef SYSTEMC_64BIT_PATCHES
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
# endif
|
||||
#endif
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
|
|
@ -131,90 +115,6 @@ private:
|
|||
DECL_TRACE_METHOD_A( sc_dt::sc_lv_base )
|
||||
// clang-format on
|
||||
|
||||
//--------------------------------------------------
|
||||
#elif (SYSTEMC_VERSION > 20011000)
|
||||
// SystemC 2.0.1
|
||||
// clang-format off
|
||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
virtual void trace(const tp& object, const sc_string& name, int width);
|
||||
|
||||
virtual void write_comment(const sc_string&);
|
||||
virtual void trace(const unsigned int&, const sc_string&, const char**);
|
||||
virtual void delta_cycles(bool) {}
|
||||
virtual void space(int n) {}
|
||||
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_A( sc_bit )
|
||||
DECL_TRACE_METHOD_A( sc_logic )
|
||||
DECL_TRACE_METHOD_B( unsigned char )
|
||||
DECL_TRACE_METHOD_B( unsigned short )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned long )
|
||||
# ifdef SYSTEMC_64BIT_PATCHES
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
# endif
|
||||
# if (SYSTEMC_VERSION > 20041000)
|
||||
DECL_TRACE_METHOD_B( unsigned long long)
|
||||
DECL_TRACE_METHOD_B( long long)
|
||||
# endif
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
DECL_TRACE_METHOD_B( long )
|
||||
DECL_TRACE_METHOD_A( float )
|
||||
DECL_TRACE_METHOD_A( double )
|
||||
DECL_TRACE_METHOD_A( sc_int_base )
|
||||
DECL_TRACE_METHOD_A( sc_uint_base )
|
||||
DECL_TRACE_METHOD_A( sc_signed )
|
||||
DECL_TRACE_METHOD_A( sc_unsigned )
|
||||
DECL_TRACE_METHOD_A( sc_fxval )
|
||||
DECL_TRACE_METHOD_A( sc_fxval_fast )
|
||||
DECL_TRACE_METHOD_A( sc_fxnum )
|
||||
DECL_TRACE_METHOD_A( sc_fxnum_fast )
|
||||
DECL_TRACE_METHOD_A( sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_lv_base )
|
||||
// clang-format on
|
||||
|
||||
//--------------------------------------------------
|
||||
#else
|
||||
// SystemC 1.2.1beta
|
||||
// clang-format off
|
||||
# define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const sc_string& name);
|
||||
# define DECL_TRACE_METHOD_B(tp) \
|
||||
virtual void trace(const tp& object, const sc_string& name, int width);
|
||||
|
||||
virtual void write_comment(const sc_string&);
|
||||
virtual void trace(const unsigned int&, const sc_string&, const char**);
|
||||
|
||||
DECL_TRACE_METHOD_A( bool )
|
||||
DECL_TRACE_METHOD_B( unsigned char )
|
||||
DECL_TRACE_METHOD_B( short unsigned int )
|
||||
DECL_TRACE_METHOD_B( unsigned int )
|
||||
DECL_TRACE_METHOD_B( long unsigned int )
|
||||
DECL_TRACE_METHOD_B( char )
|
||||
DECL_TRACE_METHOD_B( short int )
|
||||
DECL_TRACE_METHOD_B( int )
|
||||
DECL_TRACE_METHOD_B( long int )
|
||||
DECL_TRACE_METHOD_A( float )
|
||||
DECL_TRACE_METHOD_A( double )
|
||||
DECL_TRACE_METHOD_A( sc_bit )
|
||||
DECL_TRACE_METHOD_A( sc_logic )
|
||||
DECL_TRACE_METHOD_A( sc_bool_vector )
|
||||
DECL_TRACE_METHOD_A( sc_logic_vector )
|
||||
DECL_TRACE_METHOD_A( sc_signal_bool_vector )
|
||||
DECL_TRACE_METHOD_A( sc_signal_logic_vector )
|
||||
DECL_TRACE_METHOD_A( sc_uint_base )
|
||||
DECL_TRACE_METHOD_A( sc_int_base )
|
||||
DECL_TRACE_METHOD_A( sc_unsigned )
|
||||
DECL_TRACE_METHOD_A( sc_signed )
|
||||
DECL_TRACE_METHOD_A( sc_signal_resolved )
|
||||
DECL_TRACE_METHOD_A( sc_signal_resolved_vector )
|
||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_bv_base )
|
||||
DECL_TRACE_METHOD_A( sc_bv_ns::sc_lv_base )
|
||||
# endif
|
||||
// clang-format on
|
||||
|
||||
#undef DECL_TRACE_METHOD_A
|
||||
#undef DECL_TRACE_METHOD_B
|
||||
};
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
// Internal constants
|
||||
|
||||
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
|
||||
#define VL_VPI_LINE_SIZE 8192
|
||||
constexpr unsigned VL_VPI_LINE_SIZE = 8192;
|
||||
|
||||
//======================================================================
|
||||
// Internal macros
|
||||
|
|
@ -95,7 +95,7 @@ public:
|
|||
virtual const char* defname() const { return "<null>"; }
|
||||
virtual vluint32_t type() const { return 0; }
|
||||
virtual vluint32_t size() const { return 0; }
|
||||
virtual const VerilatedRange* rangep() const { return NULL; }
|
||||
virtual const VerilatedRange* rangep() const { return nullptr; }
|
||||
virtual vpiHandle dovpi_scan() { return 0; }
|
||||
};
|
||||
|
||||
|
|
@ -110,15 +110,15 @@ public:
|
|||
// cppcheck-suppress uninitVar // m_value
|
||||
VerilatedVpioCb(const t_cb_data* cbDatap, QData time)
|
||||
: m_cbData(*cbDatap)
|
||||
, m_time(time) {
|
||||
, m_time(time) { // Need () or GCC 4.8 false warning
|
||||
m_value.format = cbDatap->value ? cbDatap->value->format : vpiSuppressVal;
|
||||
m_cbData.value = &m_value;
|
||||
}
|
||||
virtual ~VerilatedVpioCb() {}
|
||||
virtual ~VerilatedVpioCb() override {}
|
||||
static inline VerilatedVpioCb* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioCb*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiCallback; }
|
||||
virtual vluint32_t type() const override { return vpiCallback; }
|
||||
vluint32_t reason() const { return m_cbData.reason; }
|
||||
VerilatedPliCb cb_rtnp() const { return m_cbData.cb_rtn; }
|
||||
t_cb_data* cb_datap() { return &(m_cbData); }
|
||||
|
|
@ -130,12 +130,12 @@ class VerilatedVpioConst : public VerilatedVpio {
|
|||
|
||||
public:
|
||||
explicit VerilatedVpioConst(vlsint32_t num)
|
||||
: m_num(num) {}
|
||||
virtual ~VerilatedVpioConst() {}
|
||||
: m_num{num} {}
|
||||
virtual ~VerilatedVpioConst() override {}
|
||||
static inline VerilatedVpioConst* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioConst*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiConstant; }
|
||||
virtual vluint32_t type() const override { return vpiConstant; }
|
||||
vlsint32_t num() const { return m_num; }
|
||||
};
|
||||
|
||||
|
|
@ -145,20 +145,20 @@ class VerilatedVpioParam : public VerilatedVpio {
|
|||
|
||||
public:
|
||||
VerilatedVpioParam(const VerilatedVar* varp, const VerilatedScope* scopep)
|
||||
: m_varp(varp)
|
||||
, m_scopep(scopep) {}
|
||||
: m_varp{varp}
|
||||
, m_scopep{scopep} {}
|
||||
|
||||
virtual ~VerilatedVpioParam() {}
|
||||
virtual ~VerilatedVpioParam() override {}
|
||||
|
||||
static inline VerilatedVpioParam* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioParam*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiParameter; }
|
||||
virtual vluint32_t type() const override { return vpiParameter; }
|
||||
const VerilatedVar* varp() const { return m_varp; }
|
||||
void* varDatap() const { return m_varp->datap(); }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
virtual const char* name() const { return m_varp->name(); }
|
||||
virtual const char* fullname() const {
|
||||
virtual const char* name() const override { return m_varp->name(); }
|
||||
virtual const char* fullname() const override {
|
||||
static VL_THREAD_LOCAL std::string out;
|
||||
out = std::string(m_scopep->name()) + "." + name();
|
||||
return out.c_str();
|
||||
|
|
@ -167,22 +167,21 @@ public:
|
|||
|
||||
class VerilatedVpioRange : public VerilatedVpio {
|
||||
const VerilatedRange* m_range;
|
||||
vlsint32_t m_iteration;
|
||||
vlsint32_t m_iteration = 0;
|
||||
|
||||
public:
|
||||
explicit VerilatedVpioRange(const VerilatedRange* range)
|
||||
: m_range(range)
|
||||
, m_iteration(0) {}
|
||||
virtual ~VerilatedVpioRange() {}
|
||||
: m_range{range} {}
|
||||
virtual ~VerilatedVpioRange() override {}
|
||||
static inline VerilatedVpioRange* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioRange*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiRange; }
|
||||
virtual vluint32_t size() const { return m_range->elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return m_range; }
|
||||
virtual vluint32_t type() const override { return vpiRange; }
|
||||
virtual vluint32_t size() const override { return m_range->elements(); }
|
||||
virtual const VerilatedRange* rangep() const override { return m_range; }
|
||||
int iteration() const { return m_iteration; }
|
||||
void iterationInc() { ++m_iteration; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
virtual vpiHandle dovpi_scan() override {
|
||||
if (!iteration()) {
|
||||
VerilatedVpioRange* nextp = new VerilatedVpioRange(*this);
|
||||
nextp->iterationInc();
|
||||
|
|
@ -198,15 +197,15 @@ protected:
|
|||
|
||||
public:
|
||||
explicit VerilatedVpioScope(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep) {}
|
||||
virtual ~VerilatedVpioScope() {}
|
||||
: m_scopep{scopep} {}
|
||||
virtual ~VerilatedVpioScope() override {}
|
||||
static inline VerilatedVpioScope* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioScope*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiScope; }
|
||||
virtual vluint32_t type() const override { return vpiScope; }
|
||||
const VerilatedScope* scopep() const { return m_scopep; }
|
||||
virtual const char* name() const { return m_scopep->name(); }
|
||||
virtual const char* fullname() const { return m_scopep->name(); }
|
||||
virtual const char* name() const override { return m_scopep->name(); }
|
||||
virtual const char* fullname() const override { return m_scopep->name(); }
|
||||
};
|
||||
|
||||
class VerilatedVpioVar : public VerilatedVpio {
|
||||
|
|
@ -228,16 +227,16 @@ protected:
|
|||
|
||||
public:
|
||||
VerilatedVpioVar(const VerilatedVar* varp, const VerilatedScope* scopep)
|
||||
: m_varp(varp)
|
||||
, m_scopep(scopep)
|
||||
, m_index(0) {
|
||||
m_prevDatap = NULL;
|
||||
: m_varp{varp}
|
||||
, m_scopep{scopep}
|
||||
, m_index{0} {
|
||||
m_prevDatap = nullptr;
|
||||
m_mask.u32 = VL_MASK_I(varp->packed().elements());
|
||||
m_entSize = varp->entSize();
|
||||
m_varDatap = varp->datap();
|
||||
}
|
||||
virtual ~VerilatedVpioVar() {
|
||||
if (m_prevDatap) VL_DO_CLEAR(delete[] m_prevDatap, m_prevDatap = NULL);
|
||||
virtual ~VerilatedVpioVar() override {
|
||||
if (m_prevDatap) VL_DO_CLEAR(delete[] m_prevDatap, m_prevDatap = nullptr);
|
||||
}
|
||||
static inline VerilatedVpioVar* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioVar*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
|
|
@ -247,14 +246,14 @@ public:
|
|||
vluint32_t mask() const { return m_mask.u32; }
|
||||
vluint8_t mask_byte(int idx) { return m_mask.u8[idx & 3]; }
|
||||
vluint32_t entSize() const { return m_entSize; }
|
||||
vluint32_t index() { return m_index; }
|
||||
virtual vluint32_t type() const {
|
||||
vluint32_t index() const { return m_index; }
|
||||
virtual vluint32_t type() const override {
|
||||
return (varp()->dims() > 1) ? vpiMemory : vpiReg; // but might be wire, logic
|
||||
}
|
||||
virtual vluint32_t size() const { return get_range().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &get_range(); }
|
||||
virtual const char* name() const { return m_varp->name(); }
|
||||
virtual const char* fullname() const {
|
||||
virtual vluint32_t size() const override { return get_range().elements(); }
|
||||
virtual const VerilatedRange* rangep() const override { return &get_range(); }
|
||||
virtual const char* name() const override { return m_varp->name(); }
|
||||
virtual const char* fullname() const override {
|
||||
static VL_THREAD_LOCAL std::string out;
|
||||
out = std::string(m_scopep->name()) + "." + name();
|
||||
return out.c_str();
|
||||
|
|
@ -273,18 +272,18 @@ class VerilatedVpioMemoryWord : public VerilatedVpioVar {
|
|||
public:
|
||||
VerilatedVpioMemoryWord(const VerilatedVar* varp, const VerilatedScope* scopep,
|
||||
vlsint32_t index, int offset)
|
||||
: VerilatedVpioVar(varp, scopep) {
|
||||
: VerilatedVpioVar{varp, scopep} {
|
||||
m_index = index;
|
||||
m_varDatap = (static_cast<vluint8_t*>(varp->datap())) + entSize() * offset;
|
||||
}
|
||||
virtual ~VerilatedVpioMemoryWord() {}
|
||||
virtual ~VerilatedVpioMemoryWord() override {}
|
||||
static inline VerilatedVpioMemoryWord* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioMemoryWord*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiMemoryWord; }
|
||||
virtual vluint32_t size() const { return varp()->packed().elements(); }
|
||||
virtual const VerilatedRange* rangep() const { return &(varp()->packed()); }
|
||||
virtual const char* fullname() const {
|
||||
virtual vluint32_t type() const override { return vpiMemoryWord; }
|
||||
virtual vluint32_t size() const override { return varp()->packed().elements(); }
|
||||
virtual const VerilatedRange* rangep() const override { return &(varp()->packed()); }
|
||||
virtual const char* fullname() const override {
|
||||
static VL_THREAD_LOCAL std::string out;
|
||||
char num[20];
|
||||
sprintf(num, "%d", m_index);
|
||||
|
|
@ -296,18 +295,17 @@ public:
|
|||
class VerilatedVpioVarIter : public VerilatedVpio {
|
||||
const VerilatedScope* m_scopep;
|
||||
VerilatedVarNameMap::const_iterator m_it;
|
||||
bool m_started;
|
||||
bool m_started = false;
|
||||
|
||||
public:
|
||||
explicit VerilatedVpioVarIter(const VerilatedScope* scopep)
|
||||
: m_scopep(scopep)
|
||||
, m_started(false) {}
|
||||
virtual ~VerilatedVpioVarIter() {}
|
||||
: m_scopep{scopep} {}
|
||||
virtual ~VerilatedVpioVarIter() override {}
|
||||
static inline VerilatedVpioVarIter* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioVarIter*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiIterator; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
virtual vluint32_t type() const override { return vpiIterator; }
|
||||
virtual vpiHandle dovpi_scan() override {
|
||||
if (VL_LIKELY(m_scopep->varsp())) {
|
||||
VerilatedVarNameMap* varsp = m_scopep->varsp();
|
||||
if (VL_UNLIKELY(!m_started)) {
|
||||
|
|
@ -330,24 +328,23 @@ class VerilatedVpioMemoryWordIter : public VerilatedVpio {
|
|||
const VerilatedVar* m_varp;
|
||||
vlsint32_t m_iteration;
|
||||
vlsint32_t m_direction;
|
||||
bool m_done;
|
||||
bool m_done = false;
|
||||
|
||||
public:
|
||||
VerilatedVpioMemoryWordIter(const vpiHandle handle, const VerilatedVar* varp)
|
||||
: m_handle(handle)
|
||||
, m_varp(varp)
|
||||
, m_iteration(varp->unpacked().right())
|
||||
, m_direction(VL_LIKELY(varp->unpacked().left() > varp->unpacked().right()) ? 1 : -1)
|
||||
, m_done(false) {}
|
||||
virtual ~VerilatedVpioMemoryWordIter() {}
|
||||
: m_handle{handle}
|
||||
, m_varp{varp}
|
||||
, m_iteration{varp->unpacked().right()}
|
||||
, m_direction{VL_LIKELY(varp->unpacked().left() > varp->unpacked().right()) ? 1 : -1} {}
|
||||
virtual ~VerilatedVpioMemoryWordIter() override {}
|
||||
static inline VerilatedVpioMemoryWordIter* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioMemoryWordIter*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiIterator; }
|
||||
virtual vluint32_t type() const override { return vpiIterator; }
|
||||
void iterationInc() {
|
||||
if (!(m_done = (m_iteration == m_varp->unpacked().left()))) m_iteration += m_direction;
|
||||
}
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
virtual vpiHandle dovpi_scan() override {
|
||||
vpiHandle result;
|
||||
if (m_done) return 0;
|
||||
result = vpi_handle_by_index(m_handle, m_iteration);
|
||||
|
|
@ -362,7 +359,7 @@ class VerilatedVpioModule : public VerilatedVpioScope {
|
|||
|
||||
public:
|
||||
explicit VerilatedVpioModule(const VerilatedScope* modulep)
|
||||
: VerilatedVpioScope(modulep) {
|
||||
: VerilatedVpioScope{modulep} {
|
||||
m_fullname = m_scopep->name();
|
||||
if (strncmp(m_fullname, "TOP.", 4) == 0) m_fullname += 4;
|
||||
m_name = m_scopep->identifier();
|
||||
|
|
@ -370,9 +367,9 @@ public:
|
|||
static inline VerilatedVpioModule* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioModule*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiModule; }
|
||||
virtual const char* name() const { return m_name; }
|
||||
virtual const char* fullname() const { return m_fullname; }
|
||||
virtual vluint32_t type() const override { return vpiModule; }
|
||||
virtual const char* name() const override { return m_name; }
|
||||
virtual const char* fullname() const override { return m_fullname; }
|
||||
};
|
||||
|
||||
class VerilatedVpioModuleIter : public VerilatedVpio {
|
||||
|
|
@ -381,15 +378,15 @@ class VerilatedVpioModuleIter : public VerilatedVpio {
|
|||
|
||||
public:
|
||||
explicit VerilatedVpioModuleIter(const std::vector<const VerilatedScope*>& vec)
|
||||
: m_vec(&vec) {
|
||||
: m_vec{&vec} {
|
||||
m_it = m_vec->begin();
|
||||
}
|
||||
virtual ~VerilatedVpioModuleIter() {}
|
||||
virtual ~VerilatedVpioModuleIter() override {}
|
||||
static inline VerilatedVpioModuleIter* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpioModuleIter*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
virtual vluint32_t type() const { return vpiIterator; }
|
||||
virtual vpiHandle dovpi_scan() {
|
||||
virtual vluint32_t type() const override { return vpiIterator; }
|
||||
virtual vpiHandle dovpi_scan() override {
|
||||
if (m_it == m_vec->end()) return 0;
|
||||
const VerilatedScope* modp = *m_it++;
|
||||
return (new VerilatedVpioModule(modp))->castVpiHandle();
|
||||
|
|
@ -421,13 +418,13 @@ class VerilatedVpiImp {
|
|||
|
||||
VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
|
||||
VpioTimedCbs m_timedCbs; // Time based callbacks
|
||||
VerilatedVpiError* m_errorInfop; // Container for vpi error info
|
||||
VerilatedVpiError* m_errorInfop = nullptr; // Container for vpi error info
|
||||
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
|
||||
|
||||
static VerilatedVpiImp s_s; // Singleton
|
||||
|
||||
public:
|
||||
VerilatedVpiImp() { m_errorInfop = NULL; }
|
||||
VerilatedVpiImp() {}
|
||||
~VerilatedVpiImp() {}
|
||||
static void assertOneCheck() { s_s.m_assertOne.check(); }
|
||||
static void cbReasonAdd(VerilatedVpioCb* vop) {
|
||||
|
|
@ -447,22 +444,22 @@ public:
|
|||
static void cbReasonRemove(VerilatedVpioCb* cbp) {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[cbp->reason()];
|
||||
// We do not remove it now as we may be iterating the list,
|
||||
// instead set to NULL and will cleanup later
|
||||
for (VpioCbList::iterator it = cbObjList.begin(); it != cbObjList.end(); ++it) {
|
||||
if (*it == cbp) *it = NULL;
|
||||
// instead set to nullptr and will cleanup later
|
||||
for (auto& ir : cbObjList) {
|
||||
if (ir == cbp) ir = nullptr;
|
||||
}
|
||||
}
|
||||
static void cbTimedRemove(VerilatedVpioCb* cbp) {
|
||||
VpioTimedCbs::iterator it = s_s.m_timedCbs.find(std::make_pair(cbp->time(), cbp));
|
||||
if (VL_LIKELY(it != s_s.m_timedCbs.end())) { s_s.m_timedCbs.erase(it); }
|
||||
const auto it = s_s.m_timedCbs.find(std::make_pair(cbp->time(), cbp));
|
||||
if (VL_LIKELY(it != s_s.m_timedCbs.end())) s_s.m_timedCbs.erase(it);
|
||||
}
|
||||
static void callTimedCbs() VL_MT_UNSAFE_ONE {
|
||||
assertOneCheck();
|
||||
QData time = VL_TIME_Q();
|
||||
for (VpioTimedCbs::iterator it = s_s.m_timedCbs.begin(); it != s_s.m_timedCbs.end();) {
|
||||
for (auto it = s_s.m_timedCbs.begin(); it != s_s.m_timedCbs.end();) {
|
||||
if (VL_UNLIKELY(it->first <= time)) {
|
||||
VerilatedVpioCb* vop = it->second;
|
||||
VpioTimedCbs::iterator last_it = it;
|
||||
const auto last_it = it;
|
||||
++it; // Timed callbacks are one-shot
|
||||
s_s.m_timedCbs.erase(last_it);
|
||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: timed_callback %p\n", vop););
|
||||
|
|
@ -473,14 +470,14 @@ public:
|
|||
}
|
||||
}
|
||||
static QData cbNextDeadline() {
|
||||
VpioTimedCbs::const_iterator it = s_s.m_timedCbs.begin();
|
||||
if (VL_LIKELY(it != s_s.m_timedCbs.end())) return it->first;
|
||||
const auto it = s_s.m_timedCbs.cbegin();
|
||||
if (VL_LIKELY(it != s_s.m_timedCbs.cend())) return it->first;
|
||||
return ~0ULL; // maxquad
|
||||
}
|
||||
static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE {
|
||||
VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
|
||||
bool called = false;
|
||||
for (VpioCbList::iterator it = cbObjList.begin(); it != cbObjList.end();) {
|
||||
for (auto it = cbObjList.begin(); it != cbObjList.end();) {
|
||||
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
|
||||
it = cbObjList.erase(it);
|
||||
continue;
|
||||
|
|
@ -497,7 +494,7 @@ public:
|
|||
VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
|
||||
typedef std::set<VerilatedVpioVar*> VpioVarSet;
|
||||
VpioVarSet update; // set of objects to update after callbacks
|
||||
for (VpioCbList::iterator it = cbObjList.begin(); it != cbObjList.end();) {
|
||||
for (auto it = cbObjList.begin(); it != cbObjList.end();) {
|
||||
if (VL_UNLIKELY(!*it)) { // Deleted earlier, cleanup
|
||||
it = cbObjList.erase(it);
|
||||
continue;
|
||||
|
|
@ -518,9 +515,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
for (VpioVarSet::const_iterator it = update.begin(); it != update.end(); ++it) {
|
||||
memcpy((*it)->prevDatap(), (*it)->varDatap(), (*it)->entSize());
|
||||
}
|
||||
for (const auto& ip : update) { memcpy(ip->prevDatap(), ip->varDatap(), ip->entSize()); }
|
||||
}
|
||||
|
||||
static VerilatedVpiError* error_info() VL_MT_UNSAFE_ONE; // getter for vpi error info
|
||||
|
|
@ -530,7 +525,7 @@ class VerilatedVpiError {
|
|||
//// Container for vpi error info
|
||||
|
||||
t_vpi_error_info m_errorInfo;
|
||||
bool m_flag;
|
||||
bool m_flag = false;
|
||||
char m_buff[VL_VPI_LINE_SIZE];
|
||||
void setError(PLI_BYTE8* message, PLI_BYTE8* code, PLI_BYTE8* file, PLI_INT32 line) {
|
||||
m_errorInfo.message = message;
|
||||
|
|
@ -551,8 +546,7 @@ class VerilatedVpiError {
|
|||
}
|
||||
|
||||
public:
|
||||
VerilatedVpiError()
|
||||
: m_flag(false) {
|
||||
VerilatedVpiError() {
|
||||
m_buff[0] = '\0';
|
||||
m_errorInfo.product = const_cast<PLI_BYTE8*>(Verilated::productName());
|
||||
}
|
||||
|
|
@ -572,11 +566,11 @@ public:
|
|||
va_end(args);
|
||||
m_errorInfo.state = vpiPLI;
|
||||
filehold = file;
|
||||
setError((PLI_BYTE8*)m_buff, NULL, const_cast<PLI_BYTE8*>(filehold.c_str()), line);
|
||||
setError((PLI_BYTE8*)m_buff, nullptr, const_cast<PLI_BYTE8*>(filehold.c_str()), line);
|
||||
}
|
||||
p_vpi_error_info getError() {
|
||||
if (m_flag) return &m_errorInfo;
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
void resetError() { m_flag = false; }
|
||||
static void vpi_unsupported() {
|
||||
|
|
@ -598,7 +592,7 @@ public:
|
|||
//======================================================================
|
||||
|
||||
VerilatedVpiImp VerilatedVpiImp::s_s; // Singleton
|
||||
VL_THREAD_LOCAL vluint8_t* VerilatedVpio::t_freeHead = NULL;
|
||||
VL_THREAD_LOCAL vluint8_t* VerilatedVpio::t_freeHead = nullptr;
|
||||
|
||||
//======================================================================
|
||||
// VerilatedVpi implementation
|
||||
|
|
@ -971,10 +965,10 @@ const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) VL_MT_SAFE {
|
|||
VL_FATAL_MT(__FILE__, __LINE__, "", msg.c_str()); \
|
||||
}
|
||||
|
||||
#define SELF_CHECK_ENUM_STR(fn, enum) \
|
||||
#define SELF_CHECK_ENUM_STR(fn, enumn) \
|
||||
do { \
|
||||
const char* strVal = VerilatedVpiError::fn(enum); \
|
||||
SELF_CHECK_RESULT_CSTR(strVal, #enum); \
|
||||
const char* strVal = VerilatedVpiError::fn(enumn); \
|
||||
SELF_CHECK_RESULT_CSTR(strVal, #enumn); \
|
||||
} while (0)
|
||||
|
||||
void VerilatedVpi::selfTest() VL_MT_UNSAFE_ONE { VerilatedVpiError::selfTest(); }
|
||||
|
|
@ -1020,7 +1014,7 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
|
|||
// cppcheck-suppress nullPointer
|
||||
if (VL_UNLIKELY(!cb_data_p)) {
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s : callback data pointer is null", VL_FUNC);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
switch (cb_data_p->reason) {
|
||||
case cbAfterDelay: {
|
||||
|
|
@ -1050,7 +1044,7 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
|
|||
default:
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported callback type %s", VL_FUNC,
|
||||
VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason));
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1082,9 +1076,9 @@ void vpi_get_systf_info(vpiHandle /*object*/, p_vpi_systf_data /*systf_data_p*/)
|
|||
vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
|
||||
VerilatedVpiImp::assertOneCheck();
|
||||
_VL_VPI_ERROR_RESET();
|
||||
if (VL_UNLIKELY(!namep)) return NULL;
|
||||
if (VL_UNLIKELY(!namep)) return nullptr;
|
||||
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_name %s %p\n", namep, scope););
|
||||
const VerilatedVar* varp = NULL;
|
||||
const VerilatedVar* varp = nullptr;
|
||||
const VerilatedScope* scopep;
|
||||
VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope);
|
||||
std::string scopeAndName = namep;
|
||||
|
|
@ -1117,11 +1111,11 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
|
|||
}
|
||||
if (!varp) {
|
||||
scopep = Verilated::scopeFind(scopename.c_str());
|
||||
if (!scopep) return NULL;
|
||||
if (!scopep) return nullptr;
|
||||
varp = scopep->varFind(baseNamep);
|
||||
}
|
||||
}
|
||||
if (!varp) return NULL;
|
||||
if (!varp) return nullptr;
|
||||
|
||||
if (varp->isParam()) {
|
||||
return (new VerilatedVpioParam(varp, scopep))->castVpiHandle();
|
||||
|
|
@ -1256,8 +1250,8 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
|
|||
case vpiModule: {
|
||||
VerilatedVpioModule* vop = VerilatedVpioModule::castp(object);
|
||||
const VerilatedHierarchyMap* map = VerilatedImp::hierarchyMap();
|
||||
const VerilatedScope* mod = vop ? vop->scopep() : NULL;
|
||||
VerilatedHierarchyMap::const_iterator it = map->find(const_cast<VerilatedScope*>(mod));
|
||||
const VerilatedScope* mod = vop ? vop->scopep() : nullptr;
|
||||
const auto it = vlstd::as_const(map)->find(const_cast<VerilatedScope*>(mod));
|
||||
if (it == map->end()) return 0;
|
||||
return ((new VerilatedVpioModuleIter(it->second))->castVpiHandle());
|
||||
}
|
||||
|
|
@ -1272,7 +1266,7 @@ vpiHandle vpi_scan(vpiHandle object) {
|
|||
VerilatedVpiImp::assertOneCheck();
|
||||
_VL_VPI_ERROR_RESET();
|
||||
VerilatedVpio* vop = VerilatedVpio::castp(object);
|
||||
if (VL_UNLIKELY(!vop)) return NULL;
|
||||
if (VL_UNLIKELY(!vop)) return nullptr;
|
||||
return vop->dovpi_scan();
|
||||
}
|
||||
|
||||
|
|
@ -1331,7 +1325,7 @@ PLI_BYTE8* vpi_get_str(PLI_INT32 property, vpiHandle object) {
|
|||
VerilatedVpiImp::assertOneCheck();
|
||||
VerilatedVpio* vop = VerilatedVpio::castp(object);
|
||||
_VL_VPI_ERROR_RESET();
|
||||
if (VL_UNLIKELY(!vop)) return NULL;
|
||||
if (VL_UNLIKELY(!vop)) return nullptr;
|
||||
switch (property) {
|
||||
case vpiName: {
|
||||
return const_cast<PLI_BYTE8*>(vop->name());
|
||||
|
|
@ -1521,7 +1515,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
|
|||
return;
|
||||
} else if (valuep->format == vpiDecStrVal) {
|
||||
valuep->value.str = outStr;
|
||||
// outStrSz does not include NULL termination so add one
|
||||
// outStrSz does not include nullptr termination so add one
|
||||
if (varp->vltype() == VLVT_UINT8) {
|
||||
VL_SNPRINTF(outStr, outStrSz + 1, "%hhu",
|
||||
static_cast<unsigned char>(*(reinterpret_cast<CData*>(varDatap))));
|
||||
|
|
@ -1612,7 +1606,6 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
|
|||
}
|
||||
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", VL_FUNC,
|
||||
VerilatedVpiError::strFromVpiVal(valuep->format), fullname);
|
||||
return;
|
||||
}
|
||||
|
||||
void vpi_get_value(vpiHandle object, p_vpi_value valuep) {
|
||||
|
|
@ -1645,7 +1638,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
|||
VerilatedVpiImp::assertOneCheck();
|
||||
_VL_VPI_ERROR_RESET();
|
||||
if (VL_UNLIKELY(!valuep)) {
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value with NULL value pointer");
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value with nullptr value pointer");
|
||||
return 0;
|
||||
}
|
||||
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
|
||||
|
|
@ -1663,7 +1656,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
|||
}
|
||||
if (!vl_check_format(vop->varp(), valuep, vop->fullname(), false)) return 0;
|
||||
if (valuep->format == vpiVectorVal) {
|
||||
if (VL_UNLIKELY(!valuep->value.vector)) return NULL;
|
||||
if (VL_UNLIKELY(!valuep->value.vector)) return nullptr;
|
||||
if (vop->varp()->vltype() == VLVT_UINT8) {
|
||||
*(reinterpret_cast<CData*>(vop->varDatap()))
|
||||
= valuep->value.vector[0].aval & vop->mask();
|
||||
|
|
@ -1714,7 +1707,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
|||
for (int i = 0; i < chars; ++i) {
|
||||
union {
|
||||
char byte[2];
|
||||
short half;
|
||||
vluint16_t half;
|
||||
} val;
|
||||
idx = div(i * 3, 8);
|
||||
if (i < len) {
|
||||
|
|
@ -1847,7 +1840,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
|||
}
|
||||
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s",
|
||||
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), vop->fullname());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
} else if (VerilatedVpioParam* vop = VerilatedVpioParam::castp(object)) {
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiParameter: %s",
|
||||
VL_FUNC, vop->fullname());
|
||||
|
|
@ -1858,7 +1851,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
|
|||
return 0;
|
||||
}
|
||||
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported vpiHandle (%p)", VL_FUNC, object);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void vpi_get_value_array(vpiHandle /*object*/, p_vpi_arrayvalue /*arrayvalue_p*/,
|
||||
|
|
@ -1877,7 +1870,7 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
|
|||
_VL_VPI_ERROR_RESET();
|
||||
// cppcheck-suppress nullPointer
|
||||
if (VL_UNLIKELY(!time_p)) {
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with NULL value pointer");
|
||||
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with nullptr value pointer");
|
||||
return;
|
||||
}
|
||||
if (time_p->type == vpiSimTime) {
|
||||
|
|
@ -1980,7 +1973,7 @@ PLI_INT32 vpi_compare_objects(vpiHandle /*object1*/, vpiHandle /*object2*/) {
|
|||
}
|
||||
PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
|
||||
// executing vpi_chk_error does not reset error
|
||||
// error_info_p can be NULL, so only return level in that case
|
||||
// error_info_p can be nullptr, so only return level in that case
|
||||
VerilatedVpiImp::assertOneCheck();
|
||||
p_vpi_error_info _error_info_p = VerilatedVpiImp::error_info()->getError();
|
||||
if (error_info_p && _error_info_p) *error_info_p = *_error_info_p;
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@
|
|||
# if defined(_MSC_VER) && _MSC_VER >= 1900
|
||||
# define VL_THREAD_LOCAL thread_local
|
||||
# elif defined(__GNUC__)
|
||||
# if (__cplusplus < 201103L) && !defined(VL_THREADED_NO_C11_WARNING)
|
||||
# if (__cplusplus < 201103L)
|
||||
# error "VL_THREADED/--threads support requires C++-11 or newer only; use newer compiler"
|
||||
# endif
|
||||
# else
|
||||
|
|
@ -152,14 +152,14 @@
|
|||
#if defined(VL_CPPCHECK) || defined(__clang_analyzer__) || __cplusplus < 201103L
|
||||
# define VL_DANGLING(var)
|
||||
#else
|
||||
/// After e.g. delete, set variable to NULL to indicate must not use later
|
||||
/// After e.g. delete, set variable to nullptr to indicate must not use later
|
||||
# define VL_DANGLING(var) \
|
||||
do { \
|
||||
*const_cast<const void**>(reinterpret_cast<const void* const*>(&var)) = NULL; \
|
||||
*const_cast<const void**>(reinterpret_cast<const void* const*>(&var)) = nullptr; \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
/// Perform an e.g. delete, then set variable to NULL to indicate must not use later.
|
||||
/// Perform an e.g. delete, then set variable to nullptr 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 { \
|
||||
|
|
@ -169,7 +169,7 @@
|
|||
VL_DANGLING(var); \
|
||||
} while (false)
|
||||
|
||||
/// Perform an e.g. delete, then set variable to NULL as a requirement
|
||||
/// Perform an e.g. delete, then set variable to nullptr as a requirement
|
||||
#define VL_DO_CLEAR(stmt, stmt2) \
|
||||
do { \
|
||||
do { \
|
||||
|
|
@ -184,30 +184,18 @@
|
|||
// C++-2011
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(VL_CPPCHECK)
|
||||
// These are deprecated historical defines. We leave them in case users referenced them.
|
||||
# define VL_EQ_DELETE = delete
|
||||
# define vl_unique_ptr std::unique_ptr
|
||||
// By default we use std:: types in C++11.
|
||||
// Define VL_USE_UNORDERED_TYPES to test these pre-C++11 classes
|
||||
# ifdef VL_USE_UNORDERED_TYPES
|
||||
# define VL_INCLUDE_UNORDERED_MAP "verilated_unordered_set_map.h"
|
||||
# define VL_INCLUDE_UNORDERED_SET "verilated_unordered_set_map.h"
|
||||
# else
|
||||
# define vl_unordered_map std::unordered_map
|
||||
# define vl_unordered_set std::unordered_set
|
||||
# define VL_INCLUDE_UNORDERED_MAP <unordered_map>
|
||||
# define VL_INCLUDE_UNORDERED_SET <unordered_set>
|
||||
# endif
|
||||
# define vl_unordered_map std::unordered_map
|
||||
# define vl_unordered_set std::unordered_set
|
||||
# define VL_INCLUDE_UNORDERED_MAP <unordered_map>
|
||||
# define VL_INCLUDE_UNORDERED_SET <unordered_set>
|
||||
# define VL_FINAL final
|
||||
# define VL_MUTABLE mutable
|
||||
# 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_MUTABLE
|
||||
# define VL_OVERRIDE
|
||||
# error "Verilator requires a C++11 or newer compiler"
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
|
|
@ -388,8 +376,8 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||
|
||||
// Used to declare a class as uncopyable; put after a private:
|
||||
#define VL_UNCOPYABLE(Type) \
|
||||
Type(const Type& other) VL_EQ_DELETE; \
|
||||
Type& operator=(const Type&) VL_EQ_DELETE
|
||||
Type(const Type& other) = delete; \
|
||||
Type& operator=(const Type&) = delete
|
||||
|
||||
//=========================================================================
|
||||
// Verilated function size macros
|
||||
|
|
@ -500,6 +488,14 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
|||
#define VL_STRINGIFY(x) VL_STRINGIFY2(x)
|
||||
#define VL_STRINGIFY2(x) #x
|
||||
|
||||
//=========================================================================
|
||||
// Conversions
|
||||
|
||||
namespace vlstd {
|
||||
// C++17's std::as_const
|
||||
template <class T> T const& as_const(T& v) { return v; }
|
||||
}; // namespace vlstd
|
||||
|
||||
//=========================================================================
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -203,6 +203,7 @@ RAW_OBJS = \
|
|||
V3GraphPathChecker.o \
|
||||
V3GraphTest.o \
|
||||
V3Hashed.o \
|
||||
V3HierBlock.o \
|
||||
V3Inline.o \
|
||||
V3Inst.o \
|
||||
V3InstrCount.o \
|
||||
|
|
|
|||
103
src/V3Active.cpp
103
src/V3Active.cpp
|
|
@ -36,7 +36,7 @@
|
|||
#include "V3Const.h"
|
||||
#include "V3SenTree.h" // for SenTreeSet
|
||||
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
|
||||
//***** See below for main transformation engine
|
||||
|
||||
|
|
@ -51,36 +51,36 @@ protected:
|
|||
class ActiveNamer : public ActiveBaseVisitor {
|
||||
private:
|
||||
// STATE
|
||||
AstScope* m_scopep; // Current scope to add statement to
|
||||
AstActive* m_iActivep; // For current scope, the IActive we're building
|
||||
AstActive* m_cActivep; // For current scope, the SActive(combo) we're building
|
||||
AstScope* m_scopep = nullptr; // Current scope to add statement to
|
||||
AstActive* m_iActivep = nullptr; // For current scope, the IActive we're building
|
||||
AstActive* m_cActivep = nullptr; // For current scope, the SActive(combo) we're building
|
||||
|
||||
SenTreeSet m_activeSens; // Sen lists for each active we've made
|
||||
typedef vl_unordered_map<AstSenTree*, AstActive*> ActiveMap;
|
||||
typedef std::unordered_map<AstSenTree*, AstActive*> ActiveMap;
|
||||
ActiveMap m_activeMap; // Map sentree to active, for folding.
|
||||
|
||||
// METHODS
|
||||
void addActive(AstActive* nodep) {
|
||||
UASSERT_OBJ(m_scopep, nodep, "NULL scope");
|
||||
UASSERT_OBJ(m_scopep, nodep, "nullptr scope");
|
||||
m_scopep->addActivep(nodep);
|
||||
}
|
||||
// VISITORS
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
m_scopep = nodep;
|
||||
m_iActivep = NULL;
|
||||
m_cActivep = NULL;
|
||||
m_iActivep = nullptr;
|
||||
m_cActivep = nullptr;
|
||||
m_activeSens.clear();
|
||||
m_activeMap.clear();
|
||||
iterateChildren(nodep);
|
||||
// Don't clear scopep, the namer persists beyond this visit
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenTree* nodep) override {
|
||||
// Simplify sensitivity list
|
||||
VL_DO_DANGLING(V3Const::constifyExpensiveEdit(nodep), nodep);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeStmt*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
|
|
@ -106,10 +106,10 @@ public:
|
|||
AstActive* getActive(FileLine* fl, AstSenTree* sensesp) {
|
||||
// Return a sentree in this scope that matches given sense list.
|
||||
|
||||
AstActive* activep = NULL;
|
||||
AstActive* activep = nullptr;
|
||||
AstSenTree* activeSenp = m_activeSens.find(sensesp);
|
||||
if (activeSenp) {
|
||||
ActiveMap::iterator it = m_activeMap.find(activeSenp);
|
||||
const auto it = m_activeMap.find(activeSenp);
|
||||
UASSERT(it != m_activeMap.end(), "Corrupt active map");
|
||||
activep = it->second;
|
||||
}
|
||||
|
|
@ -129,14 +129,9 @@ public:
|
|||
return activep;
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
ActiveNamer() {
|
||||
m_scopep = NULL;
|
||||
m_iActivep = NULL;
|
||||
m_cActivep = NULL;
|
||||
}
|
||||
virtual ~ActiveNamer() {}
|
||||
ActiveNamer() {}
|
||||
virtual ~ActiveNamer() override {}
|
||||
void main(AstScope* nodep) { iterate(nodep); }
|
||||
};
|
||||
|
||||
|
|
@ -145,14 +140,14 @@ public:
|
|||
|
||||
class ActiveDlyVisitor : public ActiveBaseVisitor {
|
||||
public:
|
||||
enum CheckType { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
|
||||
enum CheckType : uint8_t { CT_SEQ, CT_COMBO, CT_INITIAL, CT_LATCH };
|
||||
|
||||
private:
|
||||
CheckType m_check; // Combo logic or other
|
||||
AstNode* m_alwaysp; // Always we're under
|
||||
AstNode* m_assignp; // In assign
|
||||
AstNode* m_assignp = nullptr; // In assign
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignDly* nodep) override {
|
||||
if (m_check != CT_SEQ) {
|
||||
// Convert to a non-delayed assignment
|
||||
UINFO(5, " ASSIGNDLY " << nodep << endl);
|
||||
|
|
@ -174,7 +169,7 @@ private:
|
|||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssign* nodep) override {
|
||||
if (m_check == CT_SEQ) {
|
||||
AstNode* las = m_assignp;
|
||||
m_assignp = nodep;
|
||||
|
|
@ -182,7 +177,7 @@ private:
|
|||
m_assignp = las;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
AstVar* varp = nodep->varp();
|
||||
if (m_check == CT_SEQ && m_assignp && !varp->isUsedLoopIdx() // Ignore loop indices
|
||||
&& !varp->isTemp()) {
|
||||
|
|
@ -201,17 +196,16 @@ private:
|
|||
}
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
ActiveDlyVisitor(AstNode* nodep, CheckType check) {
|
||||
m_alwaysp = nodep;
|
||||
m_check = check;
|
||||
m_assignp = NULL;
|
||||
ActiveDlyVisitor(AstNode* nodep, CheckType check)
|
||||
: m_check{check}
|
||||
, m_alwaysp{nodep} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~ActiveDlyVisitor() {}
|
||||
virtual ~ActiveDlyVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -225,23 +219,23 @@ private:
|
|||
|
||||
// STATE
|
||||
ActiveNamer m_namer; // Tracking of active names
|
||||
AstCFunc* m_scopeFinalp; // Final function for this scope
|
||||
bool m_itemCombo; // Found a SenItem combo
|
||||
bool m_itemSequent; // Found a SenItem sequential
|
||||
AstCFunc* m_scopeFinalp = nullptr; // Final function for this scope
|
||||
bool m_itemCombo = false; // Found a SenItem combo
|
||||
bool m_itemSequent = false; // Found a SenItem sequential
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) 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
|
||||
m_namer.main(nodep);
|
||||
m_scopeFinalp = NULL;
|
||||
m_scopeFinalp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
// Actives are being formed, so we can ignore any already made
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstInitial* nodep) override {
|
||||
// Relink to IACTIVE, unless already under it
|
||||
UINFO(4, " INITIAL " << nodep << endl);
|
||||
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_INITIAL);
|
||||
|
|
@ -249,28 +243,28 @@ private:
|
|||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignAlias* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignW* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstCoverToggle* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstFinal* nodep) override {
|
||||
// Relink to CFUNC for the final
|
||||
UINFO(4, " FINAL " << nodep << endl);
|
||||
if (!nodep->bodysp()) { // Empty, Kill it.
|
||||
|
|
@ -321,7 +315,7 @@ private:
|
|||
sequent = false;
|
||||
}
|
||||
|
||||
AstActive* wantactivep = NULL;
|
||||
AstActive* wantactivep = nullptr;
|
||||
if (combo && !sequent) {
|
||||
// Combo: Relink to ACTIVE(combo)
|
||||
wantactivep = m_namer.getCActive(nodep->fileline());
|
||||
|
|
@ -358,7 +352,7 @@ private:
|
|||
ActiveDlyVisitor dlyvisitor(nodep, ActiveDlyVisitor::CT_SEQ);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAlways* nodep) override {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4, " ALW " << nodep << endl);
|
||||
// if (debug() >= 9) nodep->dumpTree(cout, " Alw: ");
|
||||
|
|
@ -370,13 +364,13 @@ private:
|
|||
}
|
||||
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAlwaysPublic* nodep) 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(AstSenItem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
if (nodep->varrefp()) {
|
||||
if (AstBasicDType* basicp = nodep->varrefp()->dtypep()->basicp()) {
|
||||
if (basicp->isEventValue()) {
|
||||
|
|
@ -405,19 +399,14 @@ private:
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstVarScope*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
virtual void visit(AstVarScope*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ActiveVisitor(AstNetlist* nodep)
|
||||
: m_scopeFinalp(NULL)
|
||||
, m_itemCombo(false)
|
||||
, m_itemSequent(false) {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~ActiveVisitor() {}
|
||||
explicit ActiveVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ActiveVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -45,31 +45,31 @@ private:
|
|||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
AstTopScope* m_topscopep; // Top scope for adding sentrees under
|
||||
AstTopScope* m_topscopep = nullptr; // Top scope for adding sentrees under
|
||||
SenTreeFinder m_finder; // Find global sentree's and add them
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTopScope* nodep) override {
|
||||
m_topscopep = nodep;
|
||||
m_finder.init(m_topscopep);
|
||||
iterateChildren(nodep);
|
||||
m_topscopep = NULL;
|
||||
m_topscopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
UINFO(4, " ACTIVE " << nodep << endl);
|
||||
// Remove duplicate clocks and such; sensesp() may change!
|
||||
V3Const::constifyExpensiveEdit(nodep);
|
||||
AstSenTree* sensesp = nodep->sensesp();
|
||||
UASSERT_OBJ(sensesp, nodep, "NULL");
|
||||
UASSERT_OBJ(sensesp, nodep, "nullptr");
|
||||
if (sensesp->sensesp() && VN_IS(sensesp->sensesp(), SenItem)
|
||||
&& VN_CAST(sensesp->sensesp(), SenItem)->isNever()) {
|
||||
// Never executing. Kill it.
|
||||
|
|
@ -108,30 +108,27 @@ private:
|
|||
// No need to do statements under it, they're already moved.
|
||||
// iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeProcedure* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
||||
virtual void visit(AstNodeProcedure* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
||||
virtual void visit(AstAssignAlias* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
||||
virtual void visit(AstAssignW* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
||||
virtual void visit(AstAlwaysPublic* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstVarScope*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
virtual void visit(AstVarScope*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ActiveTopVisitor(AstNetlist* nodep)
|
||||
: m_topscopep(NULL) {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~ActiveTopVisitor() {}
|
||||
explicit ActiveTopVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ActiveTopVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ private:
|
|||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Last module
|
||||
AstBegin* m_beginp; // Last begin
|
||||
unsigned m_modPastNum; // Module past numbering
|
||||
AstNodeModule* m_modp = nullptr; // Last module
|
||||
AstBegin* m_beginp = nullptr; // Last begin
|
||||
unsigned m_modPastNum = 0; // Module past numbering
|
||||
VDouble0 m_statCover; // Statistic tracking
|
||||
VDouble0 m_statAsNotImm; // Statistic tracking
|
||||
VDouble0 m_statAsImm; // Statistic tracking
|
||||
|
|
@ -74,15 +74,15 @@ private:
|
|||
(v3Global.opt.assertOn()
|
||||
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
|
||||
: static_cast<AstNode*>(new AstConst(fl, AstConst::LogicFalse()))),
|
||||
nodep, NULL);
|
||||
nodep, nullptr);
|
||||
newp->user1(true); // Don't assert/cover this if
|
||||
return newp;
|
||||
}
|
||||
|
||||
AstNode* newFireAssertUnchecked(AstNode* nodep, const string& message) {
|
||||
// Like newFireAssert() but omits the asserts-on check
|
||||
AstDisplay* dispp
|
||||
= new AstDisplay(nodep->fileline(), AstDisplayType::DT_ERROR, message, NULL, NULL);
|
||||
AstDisplay* dispp = new AstDisplay(nodep->fileline(), AstDisplayType::DT_ERROR, message,
|
||||
nullptr, nullptr);
|
||||
AstNode* bodysp = dispp;
|
||||
replaceDisplay(dispp, "%%Error"); // Convert to standard DISPLAY format
|
||||
bodysp->addNext(new AstStop(nodep->fileline(), true));
|
||||
|
|
@ -112,9 +112,9 @@ private:
|
|||
sentreep->unlinkFrBack();
|
||||
}
|
||||
//
|
||||
AstNode* bodysp = NULL;
|
||||
AstNode* bodysp = nullptr;
|
||||
bool selfDestruct = false;
|
||||
AstIf* ifp = NULL;
|
||||
AstIf* ifp = nullptr;
|
||||
if (AstCover* snodep = VN_CAST(nodep, Cover)) {
|
||||
++m_statCover;
|
||||
if (!v3Global.opt.coverageUser()) {
|
||||
|
|
@ -129,7 +129,7 @@ private:
|
|||
}
|
||||
|
||||
if (bodysp && passsp) bodysp = bodysp->addNext(passsp);
|
||||
ifp = new AstIf(nodep->fileline(), propp, bodysp, NULL);
|
||||
ifp = new AstIf(nodep->fileline(), propp, bodysp, nullptr);
|
||||
bodysp = ifp;
|
||||
} else if (VN_IS(nodep, Assert)) {
|
||||
if (nodep->immediate()) {
|
||||
|
|
@ -141,7 +141,7 @@ private:
|
|||
if (failsp) failsp = newIfAssertOn(failsp);
|
||||
if (!failsp) failsp = newFireAssertUnchecked(nodep, "'assert' failed.");
|
||||
ifp = new AstIf(nodep->fileline(), propp, passsp, failsp);
|
||||
// It's more LIKELY that we'll take the NULL if clause
|
||||
// It's more LIKELY that we'll take the nullptr if clause
|
||||
// than the sim-killing else clause:
|
||||
ifp->branchPred(VBranchPred::BP_LIKELY);
|
||||
bodysp = newIfAssertOn(ifp);
|
||||
|
|
@ -169,11 +169,11 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstIf* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstIf* nodep) override {
|
||||
if (nodep->user1SetOnce()) return;
|
||||
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||
AstNodeIf* ifp = nodep;
|
||||
AstNode* propp = NULL;
|
||||
AstNode* propp = nullptr;
|
||||
bool hasDefaultElse = false;
|
||||
do {
|
||||
// If this statement ends with 'else if', then nextIf will point to the
|
||||
|
|
@ -226,7 +226,7 @@ private:
|
|||
}
|
||||
|
||||
//========== Case assertions
|
||||
virtual void visit(AstCase* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCase* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (!nodep->user1SetOnce()) {
|
||||
bool has_default = false;
|
||||
|
|
@ -239,7 +239,7 @@ private:
|
|||
++m_statAsFull;
|
||||
if (!has_default) {
|
||||
nodep->addItemsp(new AstCaseItem(
|
||||
nodep->fileline(), NULL /*DEFAULT*/,
|
||||
nodep->fileline(), nullptr /*DEFAULT*/,
|
||||
newFireAssert(nodep, "synthesis full_case, but non-match found")));
|
||||
}
|
||||
}
|
||||
|
|
@ -250,7 +250,7 @@ private:
|
|||
if (!has_default && !nodep->itemsp()) {
|
||||
// Not parallel, but harmlessly so.
|
||||
} else {
|
||||
AstNode* propp = NULL;
|
||||
AstNode* propp = nullptr;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_CAST(itemp->nextp(), CaseItem)) {
|
||||
for (AstNode* icondp = itemp->condsp(); icondp; icondp = icondp->nextp()) {
|
||||
|
|
@ -287,7 +287,7 @@ private:
|
|||
nodep->fileline(), new AstLogNot(nodep->fileline(), ohot),
|
||||
newFireAssert(nodep,
|
||||
"synthesis parallel_case, but multiple matches found"),
|
||||
NULL);
|
||||
nullptr);
|
||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
nodep->addNotParallelp(ifp);
|
||||
}
|
||||
|
|
@ -296,7 +296,7 @@ private:
|
|||
}
|
||||
|
||||
//========== Past
|
||||
virtual void visit(AstPast* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstPast* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
uint32_t ticks = 1;
|
||||
if (nodep->ticksp()) {
|
||||
|
|
@ -306,10 +306,11 @@ private:
|
|||
}
|
||||
UASSERT_OBJ(ticks >= 1, nodep, "0 tick should have been checked in V3Width");
|
||||
AstNode* inp = nodep->exprp()->unlinkFrBack();
|
||||
AstVar* invarp = NULL;
|
||||
AstVar* invarp = nullptr;
|
||||
AstSenTree* sentreep = nodep->sentreep();
|
||||
sentreep->unlinkFrBack();
|
||||
AstAlways* alwaysp = new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, NULL);
|
||||
AstAlways* alwaysp
|
||||
= new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, nullptr);
|
||||
m_modp->addStmtp(alwaysp);
|
||||
for (uint32_t i = 0; i < ticks; ++i) {
|
||||
AstVar* outvarp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP,
|
||||
|
|
@ -325,13 +326,13 @@ private:
|
|||
}
|
||||
nodep->replaceWith(inp);
|
||||
}
|
||||
virtual void visit(AstSampled* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSampled* nodep) override {
|
||||
nodep->replaceWith(nodep->exprp()->unlinkFrBack());
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
|
||||
//========== Statements
|
||||
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Replace the special types with standard text
|
||||
if (nodep->displayType() == AstDisplayType::DT_INFO) {
|
||||
|
|
@ -344,54 +345,45 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstAssert* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssert* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, nodep->failsp());
|
||||
}
|
||||
virtual void visit(AstCover* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCover* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, NULL);
|
||||
newPslAssertion(nodep, nullptr);
|
||||
}
|
||||
virtual void visit(AstRestrict* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstRestrict* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// IEEE says simulator ignores these
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
unsigned origPastNum = m_modPastNum;
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_modPastNum);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_modPastNum = 0;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
m_modPastNum = origPastNum;
|
||||
}
|
||||
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstBegin* nodep) override {
|
||||
// This code is needed rather than a visitor in V3Begin,
|
||||
// because V3Assert is called before V3Begin
|
||||
AstBegin* lastp = m_beginp;
|
||||
VL_RESTORER(m_beginp);
|
||||
{
|
||||
m_beginp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_beginp = lastp;
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit AssertVisitor(AstNetlist* nodep) {
|
||||
m_beginp = NULL;
|
||||
m_modp = NULL;
|
||||
m_modPastNum = 0;
|
||||
// Process
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~AssertVisitor() {
|
||||
explicit AssertVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~AssertVisitor() override {
|
||||
V3Stats::addStat("Assertions, assert non-immediate statements", m_statAsNotImm);
|
||||
V3Stats::addStat("Assertions, assert immediate statements", m_statAsImm);
|
||||
V3Stats::addStat("Assertions, cover statements", m_statCover);
|
||||
|
|
|
|||
|
|
@ -34,35 +34,35 @@ private:
|
|||
// NODE STATE/TYPES
|
||||
// STATE
|
||||
// Reset each module:
|
||||
AstSenItem* m_seniDefaultp; // Default sensitivity (from AstDefClock)
|
||||
AstSenItem* m_seniDefaultp = nullptr; // Default sensitivity (from AstDefClock)
|
||||
// Reset each assertion:
|
||||
AstSenItem* m_senip; // Last sensitivity
|
||||
AstSenItem* m_senip = nullptr; // Last sensitivity
|
||||
// Reset each always:
|
||||
AstSenItem* m_seniAlwaysp; // Last sensitivity in always
|
||||
AstSenItem* m_seniAlwaysp = nullptr; // Last sensitivity in always
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
AstSenTree* newSenTree(AstNode* nodep) {
|
||||
// Create sentree based on clocked or default clock
|
||||
// Return NULL for always
|
||||
AstSenTree* newp = NULL;
|
||||
// Return nullptr for always
|
||||
AstSenTree* newp = nullptr;
|
||||
AstSenItem* senip = m_senip;
|
||||
if (!senip) senip = m_seniDefaultp;
|
||||
if (!senip) senip = m_seniAlwaysp;
|
||||
if (!senip) {
|
||||
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Unclocked assertion");
|
||||
newp = new AstSenTree(nodep->fileline(), NULL);
|
||||
newp = new AstSenTree(nodep->fileline(), nullptr);
|
||||
} else {
|
||||
newp = new AstSenTree(nodep->fileline(), senip->cloneTree(true));
|
||||
}
|
||||
return newp;
|
||||
}
|
||||
void clearAssertInfo() { m_senip = NULL; }
|
||||
void clearAssertInfo() { m_senip = nullptr; }
|
||||
|
||||
// VISITORS
|
||||
//========== Statements
|
||||
virtual void visit(AstClocking* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstClocking* nodep) override {
|
||||
UINFO(8, " CLOCKING" << nodep << endl);
|
||||
// Store the new default clock, reset on new module
|
||||
m_seniDefaultp = nodep->sensesp();
|
||||
|
|
@ -74,14 +74,14 @@ private:
|
|||
}
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAlways* nodep) override {
|
||||
iterateAndNextNull(nodep->sensesp());
|
||||
if (nodep->sensesp()) m_seniAlwaysp = nodep->sensesp()->sensesp();
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
m_seniAlwaysp = NULL;
|
||||
m_seniAlwaysp = nullptr;
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeCoverOrAssert* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCoverOrAssert* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
clearAssertInfo();
|
||||
// Find Clocking's buried under nodep->exprsp
|
||||
|
|
@ -89,13 +89,13 @@ private:
|
|||
if (!nodep->immediate()) nodep->sentreep(newSenTree(nodep));
|
||||
clearAssertInfo();
|
||||
}
|
||||
virtual void visit(AstFell* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFell* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
iterateChildren(nodep);
|
||||
FileLine* fl = nodep->fileline();
|
||||
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
||||
if (exprp->width() > 1) exprp = new AstSel(fl, exprp, 0, 1);
|
||||
AstNode* past = new AstPast(fl, exprp, NULL);
|
||||
AstNode* past = new AstPast(fl, exprp, nullptr);
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstAnd(fl, past, new AstNot(fl, exprp->cloneTree(false)));
|
||||
exprp->dtypeSetLogicBool();
|
||||
|
|
@ -103,18 +103,18 @@ private:
|
|||
nodep->sentreep(newSenTree(nodep));
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstPast* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstPast* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
iterateChildren(nodep);
|
||||
nodep->sentreep(newSenTree(nodep));
|
||||
}
|
||||
virtual void visit(AstRose* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstRose* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
iterateChildren(nodep);
|
||||
FileLine* fl = nodep->fileline();
|
||||
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
||||
if (exprp->width() > 1) exprp = new AstSel(fl, exprp, 0, 1);
|
||||
AstNode* past = new AstPast(fl, exprp, NULL);
|
||||
AstNode* past = new AstPast(fl, exprp, nullptr);
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstAnd(fl, new AstNot(fl, past), exprp->cloneTree(false));
|
||||
exprp->dtypeSetLogicBool();
|
||||
|
|
@ -122,12 +122,12 @@ private:
|
|||
nodep->sentreep(newSenTree(nodep));
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstStable* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstStable* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
iterateChildren(nodep);
|
||||
FileLine* fl = nodep->fileline();
|
||||
AstNode* exprp = nodep->exprp()->unlinkFrBack();
|
||||
AstNode* past = new AstPast(fl, exprp, NULL);
|
||||
AstNode* past = new AstPast(fl, exprp, nullptr);
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstEq(fl, past,
|
||||
exprp->cloneTree(false)); // new AstVarRef(fl, exprp, true)
|
||||
|
|
@ -137,7 +137,7 @@ private:
|
|||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstPropClocked* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstPropClocked* nodep) override {
|
||||
// No need to iterate the body, once replace will get iterated
|
||||
iterateAndNextNull(nodep->sensesp());
|
||||
if (m_senip)
|
||||
|
|
@ -160,23 +160,21 @@ private:
|
|||
nodep->replaceWith(blockp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Reset defaults
|
||||
m_seniDefaultp = NULL;
|
||||
m_seniDefaultp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit AssertPreVisitor(AstNetlist* nodep) {
|
||||
m_seniDefaultp = NULL;
|
||||
m_seniAlwaysp = NULL;
|
||||
clearAssertInfo();
|
||||
// Process
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~AssertPreVisitor() {}
|
||||
virtual ~AssertPreVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
108
src/V3Ast.cpp
108
src/V3Ast.cpp
|
|
@ -60,17 +60,17 @@ std::ostream& operator<<(std::ostream& os, AstType rhs);
|
|||
|
||||
void AstNode::init() {
|
||||
editCountInc();
|
||||
m_fileline = NULL;
|
||||
m_nextp = NULL;
|
||||
m_backp = NULL;
|
||||
m_fileline = nullptr;
|
||||
m_nextp = nullptr;
|
||||
m_backp = nullptr;
|
||||
m_headtailp = this; // When made, we're a list of only a single element
|
||||
m_op1p = NULL;
|
||||
m_op2p = NULL;
|
||||
m_op3p = NULL;
|
||||
m_op4p = NULL;
|
||||
m_iterpp = NULL;
|
||||
m_dtypep = NULL;
|
||||
m_clonep = NULL;
|
||||
m_op1p = nullptr;
|
||||
m_op2p = nullptr;
|
||||
m_op3p = nullptr;
|
||||
m_op4p = nullptr;
|
||||
m_iterpp = nullptr;
|
||||
m_dtypep = nullptr;
|
||||
m_clonep = nullptr;
|
||||
m_cloneCnt = 0;
|
||||
// Attributes
|
||||
m_didWidth = false;
|
||||
|
|
@ -275,8 +275,8 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) {
|
|||
// New tail needs the head
|
||||
AstNode* newtailp = newp->m_headtailp;
|
||||
AstNode* headp = oldtailp->m_headtailp;
|
||||
oldtailp->m_headtailp = NULL; // May be written again as new head
|
||||
newp->m_headtailp = NULL; // May be written again as new tail
|
||||
oldtailp->m_headtailp = nullptr; // May be written again as new head
|
||||
newp->m_headtailp = nullptr; // May be written again as new tail
|
||||
newtailp->m_headtailp = headp;
|
||||
headp->m_headtailp = newtailp;
|
||||
newp->editCountInc();
|
||||
|
|
@ -321,17 +321,17 @@ void AstNode::addNextHere(AstNode* newp) {
|
|||
// tail (oldheadtailp && !oldnextp) // this was tail of list, might also
|
||||
// be head of one-node list
|
||||
//
|
||||
newp->m_headtailp = NULL; // Not at head any longer
|
||||
addlastp->m_headtailp = NULL; // Presume middle of list
|
||||
newp->m_headtailp = nullptr; // Not at head any longer
|
||||
addlastp->m_headtailp = nullptr; // Presume middle of list
|
||||
// newp might happen to be head/tail after all, if so will be set again below
|
||||
if (oldheadtailp) { // else in middle of list, no change
|
||||
if (oldheadtailp == this) { // this was one node
|
||||
this->m_headtailp = addlastp; // Was head/tail, now a tail
|
||||
addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or NULL)
|
||||
addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or nullptr)
|
||||
} else if (!oldnextp) { // this was tail
|
||||
this->m_headtailp = NULL; // No longer a tail
|
||||
this->m_headtailp = nullptr; // No longer a tail
|
||||
oldheadtailp->m_headtailp = addlastp; // Head gets new tail
|
||||
addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or NULL)
|
||||
addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or nullptr)
|
||||
} // else is head, and we're inserting into the middle, so no other change
|
||||
}
|
||||
|
||||
|
|
@ -470,7 +470,7 @@ AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) {
|
|||
}
|
||||
}
|
||||
if (backp->m_nextp == oldp) {
|
||||
backp->m_nextp = NULL;
|
||||
backp->m_nextp = nullptr;
|
||||
// Old list gets truncated
|
||||
// New list becomes a list upon itself
|
||||
// Most common case is unlinking a entire operand tree
|
||||
|
|
@ -486,21 +486,21 @@ AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) {
|
|||
oldp->m_headtailp = oldtailp;
|
||||
oldp->m_headtailp->m_headtailp = oldp;
|
||||
} else if (backp->m_op1p == oldp) {
|
||||
backp->m_op1p = NULL;
|
||||
backp->m_op1p = nullptr;
|
||||
} else if (backp->m_op2p == oldp) {
|
||||
backp->m_op2p = NULL;
|
||||
backp->m_op2p = nullptr;
|
||||
} else if (backp->m_op3p == oldp) {
|
||||
backp->m_op3p = NULL;
|
||||
backp->m_op3p = nullptr;
|
||||
} else if (backp->m_op4p == oldp) {
|
||||
backp->m_op4p = NULL;
|
||||
backp->m_op4p = nullptr;
|
||||
} else {
|
||||
this->v3fatalSrc("Unlink of node with back not pointing to it.");
|
||||
}
|
||||
// Relink
|
||||
oldp->m_backp = NULL;
|
||||
oldp->m_backp = nullptr;
|
||||
// Iterator fixup
|
||||
if (oldp->m_iterpp) *(oldp->m_iterpp) = NULL;
|
||||
oldp->m_iterpp = NULL;
|
||||
if (oldp->m_iterpp) *(oldp->m_iterpp) = nullptr;
|
||||
oldp->m_iterpp = nullptr;
|
||||
oldp->debugTreeChange("-unlinkWNextOut: ", __LINE__, true);
|
||||
return oldp;
|
||||
}
|
||||
|
|
@ -561,10 +561,10 @@ AstNode* AstNode::unlinkFrBack(AstNRelinker* linkerp) {
|
|||
// Iterator fixup
|
||||
if (oldp->m_iterpp) *(oldp->m_iterpp) = oldp->m_nextp;
|
||||
// Relink
|
||||
oldp->m_nextp = NULL;
|
||||
oldp->m_backp = NULL;
|
||||
oldp->m_nextp = nullptr;
|
||||
oldp->m_backp = nullptr;
|
||||
oldp->m_headtailp = this;
|
||||
oldp->m_iterpp = NULL;
|
||||
oldp->m_iterpp = nullptr;
|
||||
oldp->debugTreeChange("-unlinkFrBkOut: ", __LINE__, true);
|
||||
return oldp;
|
||||
}
|
||||
|
|
@ -598,7 +598,7 @@ void AstNode::relink(AstNRelinker* linkerp) {
|
|||
}
|
||||
// Relink
|
||||
newp->m_backp = backp;
|
||||
linkerp->m_backp = NULL;
|
||||
linkerp->m_backp = nullptr;
|
||||
// Iterator fixup
|
||||
if (linkerp->m_iterpp) {
|
||||
// If we're iterating over a next() link, we need to follow links off the
|
||||
|
|
@ -610,7 +610,7 @@ void AstNode::relink(AstNRelinker* linkerp) {
|
|||
newp->m_iterpp = linkerp->m_iterpp;
|
||||
}
|
||||
// Empty the linker so not used twice accidentally
|
||||
linkerp->m_backp = NULL;
|
||||
linkerp->m_backp = nullptr;
|
||||
this->debugTreeChange("-relinkOut: ", __LINE__, true);
|
||||
}
|
||||
|
||||
|
|
@ -633,8 +633,8 @@ void AstNode::relinkOneLink(AstNode*& pointpr, // Ref to pointer that gets set
|
|||
newlistlastp->m_nextp = pointpr;
|
||||
pointpr->m_backp = newlistlastp;
|
||||
// Head/tail
|
||||
pointpr->m_headtailp = NULL; // Old head
|
||||
newlistlastp->m_headtailp = NULL; // Old tail
|
||||
pointpr->m_headtailp = nullptr; // Old head
|
||||
newlistlastp->m_headtailp = nullptr; // Old tail
|
||||
newp->m_headtailp = oldlistlastp; // Head points to tail
|
||||
oldlistlastp->m_headtailp = newp; // Tail points to head
|
||||
}
|
||||
|
|
@ -668,7 +668,7 @@ AstNode* AstNode::cloneTreeIter() {
|
|||
if (this->m_op2p) newp->op2p(this->m_op2p->cloneTreeIterList());
|
||||
if (this->m_op3p) newp->op3p(this->m_op3p->cloneTreeIterList());
|
||||
if (this->m_op4p) newp->op4p(this->m_op4p->cloneTreeIterList());
|
||||
newp->m_iterpp = NULL;
|
||||
newp->m_iterpp = nullptr;
|
||||
newp->clonep(this); // Save pointers to/from both to simplify relinking.
|
||||
this->clonep(newp); // Save pointers to/from both to simplify relinking.
|
||||
return newp;
|
||||
|
|
@ -676,12 +676,12 @@ AstNode* AstNode::cloneTreeIter() {
|
|||
|
||||
AstNode* AstNode::cloneTreeIterList() {
|
||||
// private: Clone list of nodes, set m_headtailp
|
||||
AstNode* newheadp = NULL;
|
||||
AstNode* newtailp = NULL;
|
||||
// Audited to make sure this is never NULL
|
||||
AstNode* newheadp = nullptr;
|
||||
AstNode* newtailp = nullptr;
|
||||
// Audited to make sure this is never nullptr
|
||||
for (AstNode* oldp = this; oldp; oldp = oldp->m_nextp) {
|
||||
AstNode* newp = oldp->cloneTreeIter();
|
||||
newp->m_headtailp = NULL;
|
||||
newp->m_headtailp = nullptr;
|
||||
newp->m_backp = newtailp;
|
||||
if (newtailp) newtailp->m_nextp = newp;
|
||||
if (!newheadp) newheadp = newp;
|
||||
|
|
@ -700,10 +700,10 @@ AstNode* AstNode::cloneTree(bool cloneNextLink) {
|
|||
newp = cloneTreeIterList();
|
||||
} else {
|
||||
newp = cloneTreeIter();
|
||||
newp->m_nextp = NULL;
|
||||
newp->m_nextp = nullptr;
|
||||
newp->m_headtailp = newp;
|
||||
}
|
||||
newp->m_backp = NULL;
|
||||
newp->m_backp = nullptr;
|
||||
newp->cloneRelinkTree();
|
||||
newp->debugTreeChange("-cloneOut: ", __LINE__, true);
|
||||
return newp;
|
||||
|
|
@ -739,7 +739,7 @@ void AstNode::deleteNode() {
|
|||
|
||||
void AstNode::deleteTreeIter() {
|
||||
// private: Delete list of nodes. Publicly call deleteTree() instead.
|
||||
// Audited to make sure this is never NULL
|
||||
// Audited to make sure this is never nullptr
|
||||
for (AstNode *nodep = this, *nnextp; nodep; nodep = nnextp) {
|
||||
nnextp = nodep->m_nextp;
|
||||
// MUST be depth first!
|
||||
|
|
@ -747,8 +747,8 @@ void AstNode::deleteTreeIter() {
|
|||
if (nodep->m_op2p) nodep->m_op2p->deleteTreeIter();
|
||||
if (nodep->m_op3p) nodep->m_op3p->deleteTreeIter();
|
||||
if (nodep->m_op4p) nodep->m_op4p->deleteTreeIter();
|
||||
nodep->m_nextp = NULL;
|
||||
nodep->m_backp = NULL;
|
||||
nodep->m_nextp = nullptr;
|
||||
nodep->m_backp = nullptr;
|
||||
nodep->deleteNode();
|
||||
}
|
||||
}
|
||||
|
|
@ -831,11 +831,11 @@ void AstNode::iterateAndNext(AstNVisitor& v) {
|
|||
niterp->m_iterpp = &niterp;
|
||||
niterp->accept(v);
|
||||
// accept may do a replaceNode and change niterp on us...
|
||||
// niterp maybe NULL, so need cast if printing
|
||||
// niterp maybe nullptr, so need cast if printing
|
||||
// if (niterp != nodep) UINFO(1,"iterateAndNext edited "<<cvtToHex(nodep)
|
||||
// <<" now into "<<cvtToHex(niterp)<<endl);
|
||||
if (!niterp) return; // Perhaps node deleted inside accept
|
||||
niterp->m_iterpp = NULL;
|
||||
niterp->m_iterpp = nullptr;
|
||||
if (VL_UNLIKELY(niterp != nodep)) { // Edited node inside accept
|
||||
nodep = niterp;
|
||||
} else { // Unchanged node, just continue loop
|
||||
|
|
@ -853,7 +853,7 @@ void AstNode::iterateListBackwards(AstNVisitor& v) {
|
|||
if (nodep->backp()->m_nextp == nodep) {
|
||||
nodep = nodep->backp();
|
||||
} else {
|
||||
nodep = NULL;
|
||||
nodep = nullptr;
|
||||
} // else: backp points up the tree.
|
||||
}
|
||||
}
|
||||
|
|
@ -900,7 +900,7 @@ AstNode* AstNode::iterateSubtreeReturnEdits(AstNVisitor& v) {
|
|||
} else {
|
||||
// Use back to determine who's pointing at us (IE assume new node
|
||||
// grafts into same place as old one)
|
||||
AstNode** nextnodepp = NULL;
|
||||
AstNode** nextnodepp = nullptr;
|
||||
if (this->m_backp->m_op1p == this) {
|
||||
nextnodepp = &(this->m_backp->m_op1p);
|
||||
} else if (this->m_backp->m_op2p == this) {
|
||||
|
|
@ -974,9 +974,7 @@ std::ostream& operator<<(std::ostream& os, const V3Hash& rhs) {
|
|||
|
||||
V3Hash::V3Hash(const string& name) {
|
||||
uint32_t val = 0;
|
||||
for (string::const_iterator it = name.begin(); it != name.end(); ++it) {
|
||||
val = val * 31 + *it;
|
||||
}
|
||||
for (const auto& c : name) val = val * 31 + c;
|
||||
setBoth(1, val);
|
||||
}
|
||||
|
||||
|
|
@ -999,7 +997,7 @@ void AstNode::checkTreeIter(AstNode* backp) {
|
|||
|
||||
void AstNode::checkTreeIterList(AstNode* backp) {
|
||||
// private: Check a (possible) list of nodes, this is always the head of the list
|
||||
// Audited to make sure this is never NULL
|
||||
// Audited to make sure this is never nullptr
|
||||
AstNode* headp = this;
|
||||
AstNode* tailp = this;
|
||||
for (AstNode* nodep = headp; nodep; nodep = nodep->nextp()) {
|
||||
|
|
@ -1052,7 +1050,7 @@ void AstNode::checkIter() const {
|
|||
if (m_iterpp) {
|
||||
dumpPtrs(cout);
|
||||
// Perhaps something forgot to clear m_iterpp?
|
||||
this->v3fatalSrc("Iteration link should be NULL");
|
||||
this->v3fatalSrc("Iteration link should be nullptr");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1108,7 +1106,7 @@ void AstNode::dumpTree(std::ostream& os, const string& indent, int maxDepth) con
|
|||
}
|
||||
|
||||
void AstNode::dumpTreeAndNext(std::ostream& os, const string& indent, int maxDepth) const {
|
||||
// Audited to make sure this is never NULL
|
||||
// Audited to make sure this is never nullptr
|
||||
for (const AstNode* nodep = this; nodep; nodep = nodep->nextp()) {
|
||||
nodep->dumpTree(os, indent, maxDepth);
|
||||
}
|
||||
|
|
@ -1119,7 +1117,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump) {
|
|||
if (doDump) {
|
||||
{ // Write log & close
|
||||
UINFO(2, "Dumping " << filename << endl);
|
||||
const vl_unique_ptr<std::ofstream> logsp(V3File::new_ofstream(filename, append));
|
||||
const std::unique_ptr<std::ofstream> logsp(V3File::new_ofstream(filename, append));
|
||||
if (logsp->fail()) v3fatal("Can't write " << filename);
|
||||
*logsp << "Verilator Tree Dump (format 0x3900) from <e" << std::dec << editCountLast();
|
||||
*logsp << "> to <e" << std::dec << editCountGbl() << ">" << endl;
|
||||
|
|
@ -1267,8 +1265,6 @@ AstNodeDType* AstNode::findVoidDType() const {
|
|||
// AstNVisitor
|
||||
|
||||
void AstNVisitor::doDeletes() {
|
||||
for (std::vector<AstNode*>::iterator it = m_deleteps.begin(); it != m_deleteps.end(); ++it) {
|
||||
(*it)->deleteTree();
|
||||
}
|
||||
for (AstNode* nodep : m_deleteps) nodep->deleteTree();
|
||||
m_deleteps.clear();
|
||||
}
|
||||
|
|
|
|||
716
src/V3Ast.h
716
src/V3Ast.h
File diff suppressed because it is too large
Load Diff
|
|
@ -22,7 +22,7 @@
|
|||
#include "V3Global.h"
|
||||
#include "V3Graph.h"
|
||||
#include "V3PartitionGraph.h" // Just for mtask dumping
|
||||
#include "V3String.h" // For VString::parseDouble
|
||||
#include "V3String.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
|
@ -36,7 +36,7 @@ const char* AstIfaceRefDType::broken() const {
|
|||
BROKEN_RTN(m_ifacep && !m_ifacep->brokeExists());
|
||||
BROKEN_RTN(m_cellp && !m_cellp->brokeExists());
|
||||
BROKEN_RTN(m_modportp && !m_modportp->brokeExists());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AstIface* AstIfaceRefDType::ifaceViaCellp() const {
|
||||
|
|
@ -46,7 +46,7 @@ AstIface* AstIfaceRefDType::ifaceViaCellp() const {
|
|||
const char* AstNodeVarRef::broken() const {
|
||||
BROKEN_RTN(m_varScopep && !m_varScopep->brokeExists());
|
||||
BROKEN_RTN(m_varp && !m_varp->brokeExists());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AstNodeVarRef::cloneRelink() {
|
||||
|
|
@ -74,7 +74,7 @@ void AstNodeUOrStructDType::repairMemberCache() {
|
|||
}
|
||||
|
||||
const char* AstNodeUOrStructDType::broken() const {
|
||||
vl_unordered_set<AstMemberDType*> exists;
|
||||
std::unordered_set<AstMemberDType*> exists;
|
||||
for (AstMemberDType* itemp = membersp(); itemp; itemp = VN_CAST(itemp->nextp(), MemberDType)) {
|
||||
exists.insert(itemp);
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ const char* AstNodeUOrStructDType::broken() const {
|
|||
return "member broken";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AstNodeCCall::dump(std::ostream& str) const {
|
||||
|
|
@ -101,7 +101,7 @@ void AstNodeCCall::cloneRelink() {
|
|||
}
|
||||
const char* AstNodeCCall::broken() const {
|
||||
BROKEN_RTN(m_funcp && !m_funcp->brokeExists());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
bool AstNodeCCall::isPure() const { return funcp()->pure(); }
|
||||
string AstNodeCCall::hiernameProtect() const {
|
||||
|
|
@ -212,7 +212,7 @@ AstNodeBiop* AstEqWild::newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp) {
|
|||
}
|
||||
|
||||
AstExecGraph::AstExecGraph(FileLine* fileline)
|
||||
: AstNode(AstType::atExecGraph, fileline) {
|
||||
: AstNode{AstType::atExecGraph, fileline} {
|
||||
m_depGraphp = new V3Graph;
|
||||
}
|
||||
AstExecGraph::~AstExecGraph() { VL_DO_DANGLING(delete m_depGraphp, m_depGraphp); }
|
||||
|
|
@ -253,7 +253,7 @@ AstConst* AstConst::parseParamLiteral(FileLine* fl, const string& literal) {
|
|||
return new AstConst(fl, AstConst::StringToParse(), literal.c_str());
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AstNetlist::timeprecisionMerge(FileLine*, const VTimescale& value) {
|
||||
|
|
@ -315,7 +315,7 @@ public:
|
|||
bool m_isRef; // Is it a reference?
|
||||
string m_type; // The base type, e.g.: "Foo_t"s
|
||||
string m_dims; // Array dimensions, e.g.: "[3][2][1]"
|
||||
string render(const string& name) {
|
||||
string render(const string& name) const {
|
||||
string out;
|
||||
out += m_type;
|
||||
out += " ";
|
||||
|
|
@ -462,7 +462,7 @@ string AstVar::vlEnumDir() const {
|
|||
return out;
|
||||
}
|
||||
|
||||
string AstVar::vlPropDecl(string propName) const {
|
||||
string AstVar::vlPropDecl(const string& propName) const {
|
||||
string out;
|
||||
|
||||
std::vector<int> ulims; // Unpacked dimension limits
|
||||
|
|
@ -481,9 +481,9 @@ string AstVar::vlPropDecl(string propName) const {
|
|||
out += "static const int " + propName + "__ulims[";
|
||||
out += cvtToStr(ulims.size());
|
||||
out += "] = {";
|
||||
std::vector<int>::const_iterator it = ulims.begin();
|
||||
auto it = ulims.cbegin();
|
||||
out += cvtToStr(*it);
|
||||
while (++it != ulims.end()) {
|
||||
while (++it != ulims.cend()) {
|
||||
out += ", ";
|
||||
out += cvtToStr(*it);
|
||||
}
|
||||
|
|
@ -604,13 +604,13 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
|||
if (anodep->isSc()) {
|
||||
return anodep;
|
||||
} else {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
} else if (VN_IS(nodep, VarRef)) {
|
||||
if (VN_CAST(nodep, VarRef)->varp()->isSc()) {
|
||||
return VN_CAST(nodep, VarRef)->varp();
|
||||
} else {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
} else if (VN_IS(nodep, ArraySel)) {
|
||||
if (nodep->op1p()) {
|
||||
|
|
@ -626,15 +626,13 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
|||
if (AstVar* p = scVarRecurse(nodep->op4p())) return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
string AstVar::mtasksString() const {
|
||||
std::ostringstream os;
|
||||
os << "all: ";
|
||||
for (MTaskIdSet::const_iterator it = m_mtaskIds.begin(); it != m_mtaskIds.end(); ++it) {
|
||||
os << *it << " ";
|
||||
}
|
||||
for (const auto& id : m_mtaskIds) os << id << " ";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
|
@ -664,17 +662,17 @@ AstNodeDType* AstNodeDType::dtypeDimensionp(int dimension) {
|
|||
if (adtypep->isRanged()) {
|
||||
if ((dim++) == dimension) return adtypep;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
} else if (AstNodeUOrStructDType* adtypep = VN_CAST(dtypep, NodeUOrStructDType)) {
|
||||
if (adtypep->packed()) {
|
||||
if ((dim++) == dimension) return adtypep;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
// Node no ->next in loop; use continue where necessary
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t AstNodeDType::arrayUnpackedElements() {
|
||||
|
|
@ -761,7 +759,7 @@ AstNode* AstArraySel::baseFromp(AstNode* nodep) {
|
|||
|
||||
const char* AstJumpBlock::broken() const {
|
||||
BROKEN_RTN(!labelp()->brokeExistsBelow());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
void AstJumpBlock::cloneRelink() {
|
||||
if (m_labelp->clonep()) m_labelp = m_labelp->clonep();
|
||||
|
|
@ -772,7 +770,7 @@ const char* AstScope::broken() const {
|
|||
BROKEN_RTN(m_aboveCellp && !m_aboveCellp->brokeExists());
|
||||
BROKEN_RTN(!m_modp);
|
||||
BROKEN_RTN(m_modp && !m_modp->brokeExists());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
void AstScope::cloneRelink() {
|
||||
if (m_aboveScopep && m_aboveScopep->clonep()) m_aboveScopep->clonep();
|
||||
|
|
@ -846,7 +844,7 @@ void AstTypeTable::clearCache() {
|
|||
// When we mass-change widthMin in V3WidthCommit, we need to correct the table.
|
||||
// Just clear out the maps; the search functions will be used to rebuild the map
|
||||
for (int i = 0; i < static_cast<int>(AstBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||
m_basicps[i] = NULL;
|
||||
m_basicps[i] = nullptr;
|
||||
}
|
||||
m_detailedMap.clear();
|
||||
// Clear generic()'s so dead detection will work
|
||||
|
|
@ -904,8 +902,9 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kw
|
|||
return newp;
|
||||
}
|
||||
|
||||
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, VNumRange range,
|
||||
int widthMin, VSigning numeric) {
|
||||
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
|
||||
const VNumRange& range, int widthMin,
|
||||
VSigning numeric) {
|
||||
AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, range, widthMin);
|
||||
AstBasicDType* newp = findInsertSameDType(new1p);
|
||||
if (newp != new1p) {
|
||||
|
|
@ -920,7 +919,7 @@ AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
|
|||
VBasicTypeKey key(nodep->width(), nodep->widthMin(), nodep->numeric(), nodep->keyword(),
|
||||
nodep->nrange());
|
||||
DetailedMap& mapr = m_detailedMap;
|
||||
DetailedMap::const_iterator it = mapr.find(key);
|
||||
const auto it = mapr.find(key);
|
||||
if (it != mapr.end()) return it->second;
|
||||
mapr.insert(make_pair(key, nodep));
|
||||
nodep->generic(true);
|
||||
|
|
@ -1079,10 +1078,12 @@ void AstCellInline::dump(std::ostream& str) const {
|
|||
const char* AstClassPackage::broken() const {
|
||||
BROKEN_BASE_RTN(AstNodeModule::broken());
|
||||
BROKEN_RTN(m_classp && !m_classp->brokeExists());
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
void AstClass::insertCache(AstNode* nodep) {
|
||||
if (VN_IS(nodep, Var) || VN_IS(nodep, NodeFTask) || VN_IS(nodep, EnumItemRef)) {
|
||||
bool doit = (VN_IS(nodep, Var) || VN_IS(nodep, EnumItemRef)
|
||||
|| (VN_IS(nodep, NodeFTask) && !VN_CAST(nodep, NodeFTask)->isExternProto()));
|
||||
if (doit) {
|
||||
if (m_members.find(nodep->name()) != m_members.end()) {
|
||||
nodep->v3error("Duplicate declaration of member name: " << nodep->prettyNameQ());
|
||||
} else {
|
||||
|
|
@ -1094,7 +1095,11 @@ void AstClass::repairCache() {
|
|||
clearCache();
|
||||
for (AstNode* itemp = membersp(); itemp; itemp = itemp->nextp()) { insertCache(itemp); }
|
||||
}
|
||||
void AstClass::dump(std::ostream& str) const { this->AstNode::dump(str); }
|
||||
void AstClass::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (isExtended()) str << " [EXT]";
|
||||
if (isVirtual()) str << " [VIRT]";
|
||||
}
|
||||
AstClass* AstClassExtends::classp() const {
|
||||
AstClassRefDType* refp = VN_CAST(dtypep(), ClassRefDType);
|
||||
UASSERT_OBJ(refp, this, "class extends non-ref");
|
||||
|
|
|
|||
5402
src/V3AstNodes.h
5402
src/V3AstNodes.h
File diff suppressed because it is too large
Load Diff
|
|
@ -42,11 +42,10 @@ private:
|
|||
// Entire netlist:
|
||||
// AstNodeFTask::user1 -> bool, 1=processed
|
||||
AstUser1InUse m_inuser1;
|
||||
bool m_anyFuncInBegin;
|
||||
bool m_anyFuncInBegin = false;
|
||||
|
||||
public:
|
||||
BeginState()
|
||||
: m_anyFuncInBegin(false) {}
|
||||
BeginState() {}
|
||||
~BeginState() {}
|
||||
void userMarkChanged(AstNode* nodep) {
|
||||
nodep->user1(true);
|
||||
|
|
@ -61,25 +60,24 @@ class BeginVisitor : public AstNVisitor {
|
|||
private:
|
||||
// STATE
|
||||
BeginState* m_statep; // Current global state
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstNodeFTask* m_ftaskp; // Current function/task
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
string m_namedScope; // Name of begin blocks above us
|
||||
string m_unnamedScope; // Name of begin blocks, including unnamed blocks
|
||||
int m_ifDepth; // Current if depth
|
||||
int m_ifDepth = 0; // Current if depth
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeFTask* nodep) override {
|
||||
UINFO(8, " " << nodep << endl);
|
||||
// Rename it
|
||||
if (m_unnamedScope != "") {
|
||||
|
|
@ -92,19 +90,17 @@ private:
|
|||
// naming; so that any begin's inside the function will rename
|
||||
// inside the function.
|
||||
// Process children
|
||||
string oldScope = m_namedScope;
|
||||
string oldUnnamed = m_unnamedScope;
|
||||
VL_RESTORER(m_namedScope);
|
||||
VL_RESTORER(m_unnamedScope);
|
||||
{
|
||||
m_namedScope = "";
|
||||
m_unnamedScope = "";
|
||||
m_ftaskp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_ftaskp = NULL;
|
||||
m_ftaskp = nullptr;
|
||||
}
|
||||
m_namedScope = oldScope;
|
||||
m_unnamedScope = oldUnnamed;
|
||||
}
|
||||
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstBegin* nodep) override {
|
||||
// Begin blocks were only useful in variable creation, change names and delete
|
||||
UINFO(8, " " << nodep << endl);
|
||||
string oldScope = m_namedScope;
|
||||
|
|
@ -147,7 +143,7 @@ private:
|
|||
m_unnamedScope = oldUnnamed;
|
||||
|
||||
// Cleanup
|
||||
AstNode* addsp = NULL;
|
||||
AstNode* addsp = nullptr;
|
||||
if (AstNode* stmtsp = nodep->stmtsp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
if (addsp) {
|
||||
|
|
@ -163,7 +159,7 @@ private:
|
|||
}
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
if (m_unnamedScope != "") {
|
||||
// Rename it
|
||||
nodep->name(m_unnamedScope + "__DOT__" + nodep->name());
|
||||
|
|
@ -177,7 +173,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTypedef* nodep) override {
|
||||
if (m_unnamedScope != "") {
|
||||
// Rename it
|
||||
nodep->name(m_unnamedScope + "__DOT__" + nodep->name());
|
||||
|
|
@ -192,7 +188,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
UINFO(8, " CELL " << nodep << endl);
|
||||
if (m_namedScope != "") {
|
||||
m_statep->userMarkChanged(nodep);
|
||||
|
|
@ -205,14 +201,14 @@ private:
|
|||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarXRef* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstScopeName* nodep) 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
|
||||
|
|
@ -225,15 +221,15 @@ private:
|
|||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCoverDecl* nodep) 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) VL_OVERRIDE { // not AstNodeIf; other types not covered
|
||||
virtual void visit(AstIf* nodep) override { // not AstNodeIf; other types not covered
|
||||
// Check IFDEPTH warning - could be in other transform files if desire
|
||||
int prevIfDepth = m_ifDepth;
|
||||
VL_RESTORER(m_ifDepth);
|
||||
if (m_ifDepth == -1 || v3Global.opt.ifDepth() < 1) { // Turned off
|
||||
} else if (nodep->uniquePragma() || nodep->unique0Pragma() || nodep->priorityPragma()) {
|
||||
m_ifDepth = -1;
|
||||
|
|
@ -244,20 +240,16 @@ private:
|
|||
m_ifDepth = -1;
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
m_ifDepth = prevIfDepth;
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
BeginVisitor(AstNetlist* nodep, BeginState* statep) {
|
||||
m_statep = statep;
|
||||
m_modp = NULL;
|
||||
m_ftaskp = NULL;
|
||||
m_ifDepth = 0;
|
||||
BeginVisitor(AstNetlist* nodep, BeginState* statep)
|
||||
: m_statep{statep} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~BeginVisitor() {}
|
||||
virtual ~BeginVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -270,21 +262,21 @@ private:
|
|||
// AstNodeFTask::user1p // Node replaced, rename it
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeFTaskRef* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstIfaceRefDType* nodep) override {
|
||||
// May have changed cell names
|
||||
// TypeTable is always after all modules, so names are stable
|
||||
UINFO(8, " IFACEREFDTYPE " << nodep << endl);
|
||||
|
|
@ -293,12 +285,12 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
BeginRelinkVisitor(AstNetlist* nodep, BeginState*) { iterate(nodep); }
|
||||
virtual ~BeginRelinkVisitor() {}
|
||||
virtual ~BeginRelinkVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -65,10 +65,10 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
UINFO(4, " IF: " << nodep << endl);
|
||||
int lastLikely = m_likely;
|
||||
int lastUnlikely = m_unlikely;
|
||||
VL_RESTORER(m_likely);
|
||||
VL_RESTORER(m_unlikely);
|
||||
{
|
||||
// Do if
|
||||
reset();
|
||||
|
|
@ -88,28 +88,25 @@ private:
|
|||
nodep->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
} // else leave unknown
|
||||
}
|
||||
m_likely = lastLikely;
|
||||
m_unlikely = lastUnlikely;
|
||||
}
|
||||
virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCCall* nodep) override {
|
||||
checkUnlikely(nodep);
|
||||
nodep->funcp()->user1Inc();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
checkUnlikely(nodep);
|
||||
m_cfuncsp.push_back(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
checkUnlikely(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
// METHODS
|
||||
void calc_tasks() {
|
||||
for (CFuncVec::iterator it = m_cfuncsp.begin(); it != m_cfuncsp.end(); ++it) {
|
||||
AstCFunc* nodep = *it;
|
||||
for (AstCFunc* nodep : m_cfuncsp) {
|
||||
if (!nodep->dontInline()) nodep->isInline(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +118,7 @@ public:
|
|||
iterateChildren(nodep);
|
||||
calc_tasks();
|
||||
}
|
||||
virtual ~BranchVisitor() {}
|
||||
virtual ~BranchVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include "V3AstConstOnly.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
|
||||
//######################################################################
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ class BrokenTable : public AstNVisitor {
|
|||
private:
|
||||
// MEMBERS
|
||||
// For each node, we keep if it exists or not.
|
||||
typedef vl_unordered_map<const AstNode*, int> NodeMap; // Performance matters (when --debug)
|
||||
typedef std::unordered_map<const AstNode*, int> NodeMap; // Performance matters (when --debug)
|
||||
static NodeMap s_nodes; // Set of all nodes that exist
|
||||
// BITMASK
|
||||
enum { FLAG_ALLOCATED = 0x01 }; // new() and not delete()ed
|
||||
|
|
@ -49,12 +49,13 @@ private:
|
|||
enum { FLAG_LINKABLE = 0x04 }; // Is in netlist tree, can be linked to
|
||||
enum { FLAG_LEAKED = 0x08 }; // Known to have been leaked
|
||||
enum { FLAG_UNDER_NOW = 0x10 }; // Is in tree as parent of current node
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
static void deleted(const AstNode* nodep) {
|
||||
// Called by operator delete on any node - only if VL_LEAK_CHECKS
|
||||
if (debug() >= 9) cout << "-nodeDel: " << cvtToHex(nodep) << endl;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
const auto iter = s_nodes.find(nodep);
|
||||
UASSERT_OBJ(!(iter == s_nodes.end() || !(iter->second & FLAG_ALLOCATED)),
|
||||
reinterpret_cast<const AstNode*>(nodep),
|
||||
"Deleting AstNode object that was never tracked or already deleted");
|
||||
|
|
@ -67,7 +68,7 @@ public:
|
|||
static void addNewed(const AstNode* nodep) {
|
||||
// Called by operator new on any node - only if VL_LEAK_CHECKS
|
||||
if (debug() >= 9) cout << "-nodeNew: " << cvtToHex(nodep) << endl;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
const auto iter = s_nodes.find(nodep);
|
||||
UASSERT_OBJ(!(iter != s_nodes.end() && (iter->second & FLAG_ALLOCATED)), nodep,
|
||||
"Newing AstNode object that is already allocated");
|
||||
if (iter == s_nodes.end()) {
|
||||
|
|
@ -78,7 +79,7 @@ public:
|
|||
static void setUnder(const AstNode* nodep, bool flag) {
|
||||
// Called by BrokenCheckVisitor when each node entered/exited
|
||||
if (!okIfLinkedTo(nodep)) return;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
const auto iter = s_nodes.find(nodep);
|
||||
if (iter != s_nodes.end()) {
|
||||
iter->second &= ~FLAG_UNDER_NOW;
|
||||
if (flag) iter->second |= FLAG_UNDER_NOW;
|
||||
|
|
@ -89,7 +90,7 @@ public:
|
|||
// cppcheck-suppress knownConditionTrueFalse
|
||||
if (!linkable) return; // save some time, else the map will get huge!
|
||||
#endif
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
const auto iter = s_nodes.find(nodep);
|
||||
if (VL_UNCOVERABLE(iter == s_nodes.end())) {
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
nodep->v3fatalSrc("AstNode is in tree, but not allocated");
|
||||
|
|
@ -113,7 +114,7 @@ public:
|
|||
// Some generic node has a pointer to this node. Is it allocated?
|
||||
// Use this when might not be in tree; otherwise use okIfLinkedTo().
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
const auto iter = s_nodes.find(nodep);
|
||||
if (iter == s_nodes.end()) return false;
|
||||
if (!(iter->second & FLAG_ALLOCATED)) return false;
|
||||
#endif
|
||||
|
|
@ -121,7 +122,7 @@ public:
|
|||
}
|
||||
static bool okIfLinkedTo(const AstNode* nodep) {
|
||||
// Some node in tree has a pointer to this node. Is it kosher?
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
const auto iter = s_nodes.find(nodep);
|
||||
if (iter == s_nodes.end()) return false;
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
if (!(iter->second & FLAG_ALLOCATED)) return false;
|
||||
|
|
@ -133,7 +134,7 @@ public:
|
|||
static bool okIfAbove(const AstNode* nodep) {
|
||||
// Must be linked to and below current node
|
||||
if (!okIfLinkedTo(nodep)) return false;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
const auto iter = s_nodes.find(nodep);
|
||||
if (iter == s_nodes.end()) return false;
|
||||
if ((iter->second & FLAG_UNDER_NOW)) return false;
|
||||
return true;
|
||||
|
|
@ -141,7 +142,7 @@ public:
|
|||
static bool okIfBelow(const AstNode* nodep) {
|
||||
// Must be linked to and below current node
|
||||
if (!okIfLinkedTo(nodep)) return false;
|
||||
NodeMap::iterator iter = s_nodes.find(nodep);
|
||||
const auto iter = s_nodes.find(nodep);
|
||||
if (iter == s_nodes.end()) return false;
|
||||
if (!(iter->second & FLAG_UNDER_NOW)) return false;
|
||||
return true;
|
||||
|
|
@ -188,10 +189,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
BrokenTable() {}
|
||||
virtual ~BrokenTable() {}
|
||||
virtual ~BrokenTable() override {}
|
||||
};
|
||||
|
||||
BrokenTable::NodeMap BrokenTable::s_nodes;
|
||||
|
|
@ -223,7 +223,7 @@ private:
|
|||
iterateChildrenConst(nodep);
|
||||
}
|
||||
// VISITORS
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
// Process not just iterate
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
|
|
@ -231,7 +231,7 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit BrokenMarkVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~BrokenMarkVisitor() {}
|
||||
virtual ~BrokenMarkVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -239,7 +239,7 @@ public:
|
|||
|
||||
class BrokenCheckVisitor : public AstNVisitor {
|
||||
private:
|
||||
void checkWidthMin(const AstNode* nodep) {
|
||||
static void checkWidthMin(const AstNode* nodep) {
|
||||
UASSERT_OBJ(nodep->width() == nodep->widthMin()
|
||||
|| v3Global.widthMinUsage() != VWidthMinUsage::MATCHES_WIDTH,
|
||||
nodep, "Width != WidthMin");
|
||||
|
|
@ -271,14 +271,14 @@ private:
|
|||
iterateChildrenConst(nodep);
|
||||
BrokenTable::setUnder(nodep, false);
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
processAndIterate(nodep);
|
||||
UASSERT_OBJ(!(v3Global.assertDTypesResolved() && nodep->brokeLhsMustBeLvalue()
|
||||
&& VN_IS(nodep->lhsp(), NodeVarRef)
|
||||
&& !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue()),
|
||||
nodep, "Assignment LHS is not an lvalue");
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
// Process not just iterate
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
|
|
@ -286,7 +286,7 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit BrokenCheckVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~BrokenCheckVisitor() {}
|
||||
virtual ~BrokenCheckVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ private:
|
|||
public:
|
||||
void add(AstNode* nodep) {
|
||||
if (v3Global.opt.outputSplitCFuncs() && v3Global.opt.outputSplitCFuncs() < m_numStmts) {
|
||||
m_funcp = NULL;
|
||||
m_funcp = nullptr;
|
||||
}
|
||||
if (!m_funcp) {
|
||||
m_funcp = new AstCFunc(m_modp->fileline(), m_basename + "_" + cvtToStr(++m_funcNum),
|
||||
NULL, "void");
|
||||
nullptr, "void");
|
||||
m_funcp->isStatic(false);
|
||||
m_funcp->declPrivate(true);
|
||||
m_funcp->slow(!VN_IS(m_modp, Class)); // Only classes construct on fast path
|
||||
|
|
@ -78,7 +78,7 @@ public:
|
|||
m_modp = nodep;
|
||||
m_numStmts = 0;
|
||||
m_funcNum = 0;
|
||||
m_tlFuncp = new AstCFunc(nodep->fileline(), basename, NULL, "void");
|
||||
m_tlFuncp = new AstCFunc(nodep->fileline(), basename, nullptr, "void");
|
||||
m_tlFuncp->declPrivate(true);
|
||||
m_tlFuncp->isStatic(false);
|
||||
m_tlFuncp->slow(!VN_IS(m_modp, Class)); // Only classes construct on fast path
|
||||
|
|
@ -97,7 +97,7 @@ private:
|
|||
|
||||
void V3CCtors::evalAsserts() {
|
||||
AstNodeModule* modp = v3Global.rootp()->modulesp(); // Top module wrapper
|
||||
AstCFunc* funcp = new AstCFunc(modp->fileline(), "_eval_debug_assertions", NULL, "void");
|
||||
AstCFunc* funcp = new AstCFunc(modp->fileline(), "_eval_debug_assertions", nullptr, "void");
|
||||
funcp->declPrivate(true);
|
||||
funcp->isStatic(false);
|
||||
funcp->slow(false);
|
||||
|
|
@ -170,10 +170,12 @@ void V3CCtors::cctorsAll() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (VN_IS(modp, Class)) {
|
||||
AstCFunc* funcp = new AstCFunc(modp->fileline(), "~", NULL, "");
|
||||
if (AstClass* classp = VN_CAST(modp, Class)) {
|
||||
AstCFunc* funcp = new AstCFunc(modp->fileline(), "~", nullptr, "");
|
||||
funcp->isDestructor(true);
|
||||
funcp->isStatic(false);
|
||||
// If can be referred to by base pointer, need virtual delete
|
||||
funcp->isVirtual(classp->isExtended());
|
||||
funcp->slow(false);
|
||||
modp->addStmtp(funcp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include "V3Ast.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
|
||||
//######################################################################
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
// CONSTRUCTORS
|
||||
explicit CUseState(AstNodeModule* nodep)
|
||||
: m_modInsertp(nodep) {}
|
||||
: m_modInsertp{nodep} {}
|
||||
virtual ~CUseState() {}
|
||||
VL_UNCOPYABLE(CUseState);
|
||||
};
|
||||
|
|
@ -78,27 +78,26 @@ public:
|
|||
class CUseDTypeVisitor : public AstNVisitor {
|
||||
// MEMBERS
|
||||
CUseState& m_stater; // State for inserter
|
||||
bool m_impOnly; // In details needed only for implementation
|
||||
bool m_impOnly = false; // In details needed only for implementation
|
||||
// METHODS
|
||||
virtual void visit(AstClassRefDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstClassRefDType* nodep) override {
|
||||
if (nodep->user2SetOnce()) return; // Process once
|
||||
if (!m_impOnly) m_stater.newUse(nodep, VUseType::INT_FWD_CLASS, nodep->classp()->name());
|
||||
// No class.h, it's inside the class package's h file
|
||||
m_stater.newUse(nodep, VUseType::IMP_INCLUDE, nodep->classp()->packagep()->name());
|
||||
// Need to include extends() when we implement, but no need for pointers to know
|
||||
bool oldImpOnly = m_impOnly;
|
||||
VL_RESTORER(m_impOnly);
|
||||
{
|
||||
m_impOnly = true;
|
||||
iterateChildren(nodep->classp()); // This also gets all extend classes
|
||||
}
|
||||
m_impOnly = oldImpOnly;
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeDType* nodep) override {
|
||||
if (nodep->user2SetOnce()) return; // Process once
|
||||
if (nodep->virtRefDTypep()) iterate(nodep->virtRefDTypep());
|
||||
if (nodep->virtRefDType2p()) iterate(nodep->virtRefDType2p());
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
if (nodep->user2SetOnce()) return; // Process once
|
||||
if (nodep->dtypep() && !nodep->dtypep()->user2()) iterate(nodep->dtypep());
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -107,11 +106,10 @@ class CUseDTypeVisitor : public AstNVisitor {
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CUseDTypeVisitor(AstNodeModule* nodep, CUseState& stater)
|
||||
: m_stater(stater)
|
||||
, m_impOnly(false) {
|
||||
: m_stater(stater) { // Need () or GCC 4.8 false warning
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CUseDTypeVisitor() {}
|
||||
virtual ~CUseDTypeVisitor() override {}
|
||||
VL_UNCOPYABLE(CUseDTypeVisitor);
|
||||
};
|
||||
|
||||
|
|
@ -132,7 +130,7 @@ class CUseVisitor : public AstNVisitor {
|
|||
}
|
||||
}
|
||||
void makeVlToString(AstClass* nodep) {
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "VL_TO_STRING", NULL, "std::string");
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "VL_TO_STRING", nullptr, "std::string");
|
||||
funcp->argTypes("const VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(nodep)
|
||||
+ ">& obj");
|
||||
funcp->isMethod(false);
|
||||
|
|
@ -145,7 +143,7 @@ class CUseVisitor : public AstNVisitor {
|
|||
nodep->addStmtp(funcp);
|
||||
}
|
||||
void makeToString(AstClass* nodep) {
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "to_string", NULL, "std::string");
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "to_string", nullptr, "std::string");
|
||||
funcp->isConst(true);
|
||||
funcp->isStatic(false);
|
||||
funcp->protect(false);
|
||||
|
|
@ -156,7 +154,8 @@ class CUseVisitor : public AstNVisitor {
|
|||
nodep->addStmtp(funcp);
|
||||
}
|
||||
void makeToStringMiddle(AstClass* nodep) {
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "to_string_middle", NULL, "std::string");
|
||||
AstCFunc* funcp
|
||||
= new AstCFunc(nodep->fileline(), "to_string_middle", nullptr, "std::string");
|
||||
funcp->isConst(true);
|
||||
funcp->isStatic(false);
|
||||
funcp->protect(false);
|
||||
|
|
@ -189,7 +188,7 @@ class CUseVisitor : public AstNVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
if (v3Global.opt.trace()) {
|
||||
AstCUse* usep
|
||||
= m_state.newUse(nodep, VUseType::INT_FWD_CLASS, v3Global.opt.traceClassBase());
|
||||
|
|
@ -203,15 +202,15 @@ class CUseVisitor : public AstNVisitor {
|
|||
makeToStringMiddle(classp);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode*) VL_OVERRIDE {} // All in AstNodeModule
|
||||
virtual void visit(AstNode*) override {} // All in AstNodeModule
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CUseVisitor(AstNodeModule* nodep)
|
||||
: m_state(nodep) {
|
||||
: m_state{nodep} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CUseVisitor() {}
|
||||
virtual ~CUseVisitor() override {}
|
||||
VL_UNCOPYABLE(CUseVisitor);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -52,12 +52,13 @@
|
|||
|
||||
class CaseLintVisitor : public AstNVisitor {
|
||||
private:
|
||||
AstNodeCase* m_caseExprp; // Under a CASE value node, if so the relevant case statement
|
||||
AstNodeCase* m_caseExprp
|
||||
= nullptr; // Under a CASE value node, if so the relevant case statement
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
virtual void visit(AstNodeCase* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCase* nodep) 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)");
|
||||
}
|
||||
|
|
@ -81,10 +82,10 @@ private:
|
|||
itemp = VN_CAST(itemp->nextp(), CaseItem)) {
|
||||
iterateAndNextNull(itemp->condsp());
|
||||
}
|
||||
m_caseExprp = NULL;
|
||||
m_caseExprp = nullptr;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConst* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstConst* nodep) override {
|
||||
// See also neverItem
|
||||
if (m_caseExprp && nodep->num().isFourState()) {
|
||||
if (VN_IS(m_caseExprp, GenCase)) {
|
||||
|
|
@ -105,15 +106,12 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CaseLintVisitor(AstNodeCase* nodep) {
|
||||
m_caseExprp = NULL;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CaseLintVisitor() {}
|
||||
explicit CaseLintVisitor(AstNodeCase* nodep) { iterate(nodep); }
|
||||
virtual ~CaseLintVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -131,9 +129,9 @@ private:
|
|||
VDouble0 m_statCaseSlow; // Statistic tracking
|
||||
|
||||
// Per-CASE
|
||||
int m_caseWidth; // Width of valueItems
|
||||
int m_caseItems; // Number of caseItem unique values
|
||||
bool m_caseNoOverlapsAllCovered; // Proven to be synopsys parallel_case compliant
|
||||
int m_caseWidth = 0; // Width of valueItems
|
||||
int m_caseItems = 0; // Number of caseItem unique values
|
||||
bool m_caseNoOverlapsAllCovered = false; // Proven to be synopsys parallel_case compliant
|
||||
// For each possible value, the case branch we need
|
||||
AstNode* m_valueItem[1 << CASE_OVERLAP_WIDTH];
|
||||
|
||||
|
|
@ -161,7 +159,7 @@ private:
|
|||
}
|
||||
UINFO(8, "Simple case statement: " << nodep << endl);
|
||||
// Zero list of items for each value
|
||||
for (uint32_t i = 0; i < (1UL << m_caseWidth); ++i) m_valueItem[i] = NULL;
|
||||
for (uint32_t i = 0; i < (1UL << m_caseWidth); ++i) m_valueItem[i] = nullptr;
|
||||
// Now pick up the values for each assignment
|
||||
// We can cheat and use uint32_t's because we only support narrow case's
|
||||
bool bitched = false;
|
||||
|
|
@ -218,7 +216,7 @@ private:
|
|||
}
|
||||
|
||||
// Convert valueItem from AstCaseItem* to the expression
|
||||
// Not done earlier, as we may now have a NULL because it's just a ";" NOP branch
|
||||
// Not done earlier, as we may now have a nullptr because it's just a ";" NOP branch
|
||||
for (uint32_t i = 0; i < (1UL << m_caseWidth); ++i) {
|
||||
m_valueItem[i] = VN_CAST(m_valueItem[i], CaseItem)->bodysp();
|
||||
}
|
||||
|
|
@ -324,13 +322,13 @@ private:
|
|||
hadDefault = true;
|
||||
} else {
|
||||
// Expressioned clause
|
||||
AstNode* icondNextp = NULL;
|
||||
AstNode* ifexprp = NULL; // If expression to test
|
||||
AstNode* icondNextp = nullptr;
|
||||
AstNode* ifexprp = nullptr; // If expression to test
|
||||
for (AstNode* icondp = itemp->condsp(); icondp; icondp = icondNextp) {
|
||||
icondNextp = icondp->nextp();
|
||||
icondp->unlinkFrBack();
|
||||
|
||||
AstNode* condp = NULL; // Default is to use and1p/and2p
|
||||
AstNode* condp = nullptr; // Default is to use and1p/and2p
|
||||
AstConst* iconstp = VN_CAST(icondp, Const);
|
||||
if (iconstp && neverItem(nodep, iconstp)) {
|
||||
// X in casez can't ever be executed
|
||||
|
|
@ -377,8 +375,9 @@ private:
|
|||
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.
|
||||
nodep->addItemsp(new AstCaseItem(
|
||||
nodep->fileline(), new AstConst(nodep->fileline(), AstConst::LogicTrue()), NULL));
|
||||
nodep->addItemsp(
|
||||
new AstCaseItem(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), AstConst::LogicTrue()), nullptr));
|
||||
}
|
||||
if (debug() >= 9) nodep->dumpTree(cout, " _comp_COND: ");
|
||||
// Now build the IF statement tree
|
||||
|
|
@ -388,9 +387,9 @@ private:
|
|||
// should pull out the most common item from here and instead make
|
||||
// it the first IF branch.
|
||||
int depth = 0;
|
||||
AstNode* grouprootp = NULL;
|
||||
AstIf* groupnextp = NULL;
|
||||
AstIf* itemnextp = NULL;
|
||||
AstNode* grouprootp = nullptr;
|
||||
AstIf* groupnextp = nullptr;
|
||||
AstIf* itemnextp = nullptr;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_CAST(itemp->nextp(), CaseItem)) {
|
||||
AstNode* istmtsp = itemp->bodysp(); // Maybe null -- no action.
|
||||
|
|
@ -400,9 +399,9 @@ private:
|
|||
{ // Prepare for next group
|
||||
if (++depth > CASE_ENCODER_GROUP_DEPTH) depth = 1;
|
||||
if (depth == 1) { // First group or starting new group
|
||||
itemnextp = NULL;
|
||||
itemnextp = nullptr;
|
||||
AstIf* newp
|
||||
= new AstIf(itemp->fileline(), ifexprp->cloneTree(true), NULL, NULL);
|
||||
= new AstIf(itemp->fileline(), ifexprp->cloneTree(true), nullptr, nullptr);
|
||||
if (groupnextp) {
|
||||
groupnextp->addElsesp(newp);
|
||||
} else {
|
||||
|
|
@ -422,7 +421,7 @@ private:
|
|||
VL_DO_DANGLING(itemexprp->deleteTree(), itemexprp);
|
||||
itemexprp = new AstConst(itemp->fileline(), AstConst::LogicTrue());
|
||||
}
|
||||
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, NULL);
|
||||
AstIf* newp = new AstIf(itemp->fileline(), itemexprp, istmtsp, nullptr);
|
||||
if (itemnextp) {
|
||||
itemnextp->addElsesp(newp);
|
||||
} else {
|
||||
|
|
@ -467,7 +466,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstCase* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCase* nodep) override {
|
||||
V3Case::caseLint(nodep);
|
||||
iterateChildren(nodep);
|
||||
if (debug() >= 9) nodep->dumpTree(cout, " case_old: ");
|
||||
|
|
@ -482,18 +481,15 @@ private:
|
|||
}
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CaseVisitor(AstNetlist* nodep) {
|
||||
m_caseWidth = 0;
|
||||
m_caseItems = 0;
|
||||
m_caseNoOverlapsAllCovered = false;
|
||||
for (uint32_t i = 0; i < (1UL << CASE_OVERLAP_WIDTH); ++i) m_valueItem[i] = NULL;
|
||||
for (uint32_t i = 0; i < (1UL << CASE_OVERLAP_WIDTH); ++i) m_valueItem[i] = nullptr;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CaseVisitor() {
|
||||
virtual ~CaseVisitor() override {
|
||||
V3Stats::addStat("Optimizations, Cases parallelized", m_statCaseFast);
|
||||
V3Stats::addStat("Optimizations, Cases complex", m_statCaseSlow);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,25 +109,25 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeUniop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
|
||||
}
|
||||
virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeBiop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1());
|
||||
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
|
||||
if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp());
|
||||
}
|
||||
virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeTriop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1() | nodep->thsp()->user1());
|
||||
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
|
||||
if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp());
|
||||
if (nodep->sizeMattersThs()) ensureCast(nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstNodeQuadop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeQuadop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1() | nodep->thsp()->user1()
|
||||
| nodep->fhsp()->user1());
|
||||
|
|
@ -136,12 +136,12 @@ private:
|
|||
if (nodep->sizeMattersThs()) ensureCast(nodep->thsp());
|
||||
if (nodep->sizeMattersFhs()) ensureCast(nodep->fhsp());
|
||||
}
|
||||
virtual void visit(AstCCast* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCCast* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureLower32Cast(nodep);
|
||||
nodep->user1(1);
|
||||
}
|
||||
virtual void visit(AstNegate* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNegate* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
if (nodep->lhsp()->widthMin() == 1) {
|
||||
|
|
@ -153,7 +153,7 @@ private:
|
|||
ensureCast(nodep->lhsp());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
if (!nodep->lvalue() && !VN_IS(nodep->backp(), CCast) && VN_IS(nodep->backp(), NodeMath)
|
||||
&& !VN_IS(nodep->backp(), ArraySel) && nodep->backp()->width()
|
||||
&& castSize(nodep) != castSize(nodep->varp())) {
|
||||
|
|
@ -163,7 +163,7 @@ private:
|
|||
}
|
||||
nodep->user1(1);
|
||||
}
|
||||
virtual void visit(AstConst* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstConst* nodep) 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)#).
|
||||
|
|
@ -171,29 +171,29 @@ private:
|
|||
}
|
||||
|
||||
// Null dereference protection
|
||||
virtual void visit(AstNullCheck* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNullCheck* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
}
|
||||
virtual void visit(AstCMethodCall* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCMethodCall* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureNullChecked(nodep->fromp());
|
||||
}
|
||||
virtual void visit(AstMemberSel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstMemberSel* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureNullChecked(nodep->fromp());
|
||||
}
|
||||
|
||||
// NOPs
|
||||
virtual void visit(AstVar*) VL_OVERRIDE {}
|
||||
virtual void visit(AstVar*) override {}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CastVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~CastVisitor() {}
|
||||
virtual ~CastVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
190
src/V3Cdc.cpp
190
src/V3Cdc.cpp
|
|
@ -37,7 +37,7 @@
|
|||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
#define CDC_WEIGHT_ASYNC 0x1000 // Weight for edges that feed async logic
|
||||
constexpr int CDC_WEIGHT_ASYNC = 0x1000; // Weight for edges that feed async logic
|
||||
|
||||
//######################################################################
|
||||
|
||||
|
|
@ -52,25 +52,23 @@ public:
|
|||
class CdcEitherVertex : public V3GraphVertex {
|
||||
AstScope* m_scopep;
|
||||
AstNode* m_nodep;
|
||||
AstSenTree* m_srcDomainp;
|
||||
AstSenTree* m_dstDomainp;
|
||||
AstSenTree* m_srcDomainp = nullptr;
|
||||
AstSenTree* m_dstDomainp = nullptr;
|
||||
bool m_srcDomainSet : 1;
|
||||
bool m_dstDomainSet : 1;
|
||||
bool m_asyncPath : 1;
|
||||
|
||||
public:
|
||||
CdcEitherVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_scopep(scopep)
|
||||
, m_nodep(nodep)
|
||||
, m_srcDomainp(NULL)
|
||||
, m_dstDomainp(NULL)
|
||||
, m_srcDomainSet(false)
|
||||
, m_dstDomainSet(false)
|
||||
, m_asyncPath(false) {}
|
||||
virtual ~CdcEitherVertex() {}
|
||||
: V3GraphVertex{graphp}
|
||||
, m_scopep{scopep}
|
||||
, m_nodep{nodep}
|
||||
, m_srcDomainSet{false}
|
||||
, m_dstDomainSet{false}
|
||||
, m_asyncPath{false} {}
|
||||
virtual ~CdcEitherVertex() override {}
|
||||
// ACCESSORS
|
||||
virtual FileLine* fileline() const { return nodep()->fileline(); }
|
||||
virtual FileLine* fileline() const override { return nodep()->fileline(); }
|
||||
AstScope* scopep() const { return m_scopep; }
|
||||
AstNode* nodep() const { return m_nodep; }
|
||||
AstSenTree* srcDomainp() const { return m_srcDomainp; }
|
||||
|
|
@ -87,20 +85,18 @@ public:
|
|||
|
||||
class CdcVarVertex : public CdcEitherVertex {
|
||||
AstVarScope* m_varScp;
|
||||
int m_cntAsyncRst;
|
||||
bool m_fromFlop;
|
||||
int m_cntAsyncRst = 0;
|
||||
bool m_fromFlop = false;
|
||||
|
||||
public:
|
||||
CdcVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: CdcEitherVertex(graphp, scopep, varScp)
|
||||
, m_varScp(varScp)
|
||||
, m_cntAsyncRst(0)
|
||||
, m_fromFlop(false) {}
|
||||
virtual ~CdcVarVertex() {}
|
||||
: CdcEitherVertex{graphp, scopep, varScp}
|
||||
, m_varScp{varScp} {}
|
||||
virtual ~CdcVarVertex() override {}
|
||||
// ACCESSORS
|
||||
AstVarScope* varScp() const { return m_varScp; }
|
||||
virtual string name() const { return (cvtToHex(m_varScp) + " " + varScp()->name()); }
|
||||
virtual string dotColor() const {
|
||||
virtual string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); }
|
||||
virtual string dotColor() const override {
|
||||
return fromFlop() ? "green" : cntAsyncRst() ? "red" : "blue";
|
||||
}
|
||||
int cntAsyncRst() const { return m_cntAsyncRst; }
|
||||
|
|
@ -115,16 +111,18 @@ class CdcLogicVertex : public CdcEitherVertex {
|
|||
|
||||
public:
|
||||
CdcLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstSenTree* sensenodep)
|
||||
: CdcEitherVertex(graphp, scopep, nodep)
|
||||
, m_hazard(false)
|
||||
, m_isFlop(false) {
|
||||
: CdcEitherVertex{graphp, scopep, nodep}
|
||||
, m_hazard{false}
|
||||
, m_isFlop{false} {
|
||||
srcDomainp(sensenodep);
|
||||
dstDomainp(sensenodep);
|
||||
}
|
||||
virtual ~CdcLogicVertex() {}
|
||||
virtual ~CdcLogicVertex() override {}
|
||||
// ACCESSORS
|
||||
virtual string name() const { return (cvtToHex(nodep()) + "@" + scopep()->prettyName()); }
|
||||
virtual string dotColor() const { return hazard() ? "black" : "yellow"; }
|
||||
virtual string name() const override {
|
||||
return (cvtToHex(nodep()) + "@" + scopep()->prettyName());
|
||||
}
|
||||
virtual string dotColor() const override { return hazard() ? "black" : "yellow"; }
|
||||
bool hazard() const { return m_hazard; }
|
||||
void setHazard(AstNode* nodep) {
|
||||
m_hazard = true;
|
||||
|
|
@ -145,7 +143,7 @@ private:
|
|||
std::ofstream* m_ofp; // Output file
|
||||
string m_prefix;
|
||||
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
*m_ofp << m_prefix;
|
||||
if (nodep->user3()) {
|
||||
*m_ofp << " %%";
|
||||
|
|
@ -167,22 +165,22 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
CdcDumpVisitor(AstNode* nodep, std::ofstream* ofp, const string& prefix) {
|
||||
m_ofp = ofp;
|
||||
m_prefix = prefix;
|
||||
CdcDumpVisitor(AstNode* nodep, std::ofstream* ofp, const string& prefix)
|
||||
: m_ofp{ofp}
|
||||
, m_prefix{prefix} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CdcDumpVisitor() {}
|
||||
virtual ~CdcDumpVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class CdcWidthVisitor : public CdcBaseVisitor {
|
||||
private:
|
||||
int m_maxLineno;
|
||||
size_t m_maxFilenameLen;
|
||||
int m_maxLineno = 0;
|
||||
size_t m_maxFilenameLen = 0;
|
||||
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Keeping line+filename lengths separate is much faster than calling ascii().length()
|
||||
if (nodep->fileline()->lineno() >= m_maxLineno) {
|
||||
|
|
@ -195,14 +193,10 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CdcWidthVisitor(AstNode* nodep) {
|
||||
m_maxLineno = 0;
|
||||
m_maxFilenameLen = 0;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CdcWidthVisitor() {}
|
||||
explicit CdcWidthVisitor(AstNode* nodep) { iterate(nodep); }
|
||||
virtual ~CdcWidthVisitor() override {}
|
||||
// ACCESSORS
|
||||
int maxWidth() {
|
||||
int maxWidth() const {
|
||||
size_t width = 1;
|
||||
width += m_maxFilenameLen;
|
||||
width += 1; // The :
|
||||
|
|
@ -229,16 +223,16 @@ private:
|
|||
|
||||
// STATE
|
||||
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
||||
CdcLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored
|
||||
AstScope* m_scopep; // Current scope being processed
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstSenTree* m_domainp; // Current sentree
|
||||
bool m_inDly; // In delayed assign
|
||||
int m_inSenItem; // Number of senitems
|
||||
CdcLogicVertex* m_logicVertexp = nullptr; // Current statement being tracked, nullptr=ignored
|
||||
AstScope* m_scopep = nullptr; // Current scope being processed
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstSenTree* m_domainp = nullptr; // Current sentree
|
||||
bool m_inDly = false; // In delayed assign
|
||||
int m_inSenItem = 0; // Number of senitems
|
||||
string m_ofFilename; // Output filename
|
||||
std::ofstream* m_ofp; // Output file
|
||||
uint32_t m_userGeneration; // Generation count to avoid slow userClearVertices
|
||||
int m_filelineWidth; // Characters in longest fileline
|
||||
uint32_t m_userGeneration = 0; // Generation count to avoid slow userClearVertices
|
||||
int m_filelineWidth = 0; // Characters in longest fileline
|
||||
|
||||
// METHODS
|
||||
void iterateNewStmt(AstNode* nodep) {
|
||||
|
|
@ -253,7 +247,7 @@ private:
|
|||
m_logicVertexp->dstDomainSet(true);
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
m_logicVertexp = NULL;
|
||||
m_logicVertexp = nullptr;
|
||||
|
||||
if (false && debug() >= 9) {
|
||||
UINFO(9, "Trace Logic:\n");
|
||||
|
|
@ -273,7 +267,7 @@ private:
|
|||
// Create IO vertex - note it's relative to the pointed to var, not where we are
|
||||
// now This allows reporting to easily print the input statement
|
||||
CdcLogicVertex* ioVertexp
|
||||
= new CdcLogicVertex(&m_graph, varscp->scopep(), varscp->varp(), NULL);
|
||||
= new CdcLogicVertex(&m_graph, varscp->scopep(), varscp->varp(), nullptr);
|
||||
if (varscp->varp()->isWritable()) {
|
||||
new V3GraphEdge(&m_graph, vertexp, ioVertexp, 1);
|
||||
} else {
|
||||
|
|
@ -364,7 +358,7 @@ private:
|
|||
UINFO(8, " Trace One async: " << vvertexp << endl);
|
||||
// Twice, as we need to detect, then propagate
|
||||
CdcEitherVertex* markp = traceAsyncRecurse(vvertexp, false);
|
||||
if (markp) { // Mark is non-NULL if something bad on this path
|
||||
if (markp) { // Mark is non-nullptr if something bad on this path
|
||||
UINFO(9, " Trace One bad! " << vvertexp << endl);
|
||||
m_userGeneration++; // Effectively a userClearVertices()
|
||||
traceAsyncRecurse(vvertexp, true);
|
||||
|
|
@ -377,12 +371,12 @@ private:
|
|||
}
|
||||
|
||||
CdcEitherVertex* traceAsyncRecurse(CdcEitherVertex* vertexp, bool mark) {
|
||||
// First pass: Return vertex of any hazardous stuff attached, or NULL if OK
|
||||
// First pass: Return vertex of any hazardous stuff attached, or nullptr if OK
|
||||
// If first pass returns true, second pass calls asyncPath() on appropriate nodes
|
||||
if (vertexp->user() >= m_userGeneration) return NULL; // Processed - prevent loop
|
||||
if (vertexp->user() >= m_userGeneration) return nullptr; // Processed - prevent loop
|
||||
vertexp->user(m_userGeneration);
|
||||
|
||||
CdcEitherVertex* mark_outp = NULL;
|
||||
CdcEitherVertex* mark_outp = nullptr;
|
||||
UINFO(9, " Trace: " << vertexp << endl);
|
||||
|
||||
// Clear out in prep for marking next path
|
||||
|
|
@ -401,7 +395,7 @@ private:
|
|||
CdcEitherVertex* eFromVertexp = static_cast<CdcEitherVertex*>(edgep->fromp());
|
||||
eFromVertexp->asyncPath(true);
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
// Also ok if from flop, but partially trace the flop so more obvious to users
|
||||
if (vvertexp->fromFlop()) {
|
||||
|
|
@ -409,7 +403,7 @@ private:
|
|||
CdcEitherVertex* eFromVertexp = static_cast<CdcEitherVertex*>(edgep->fromp());
|
||||
eFromVertexp->asyncPath(true);
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -514,7 +508,7 @@ private:
|
|||
}
|
||||
|
||||
string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__cdc_edges.txt";
|
||||
const vl_unique_ptr<std::ofstream> ofp(V3File::new_ofstream(filename));
|
||||
const std::unique_ptr<std::ofstream> ofp(V3File::new_ofstream(filename));
|
||||
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||
*ofp << "Edge Report for " << v3Global.opt.prefix() << endl;
|
||||
|
||||
|
|
@ -549,9 +543,7 @@ private:
|
|||
}
|
||||
}
|
||||
stable_sort(report.begin(), report.end());
|
||||
for (std::deque<string>::iterator it = report.begin(); it != report.end(); ++it) {
|
||||
*ofp << *it;
|
||||
}
|
||||
for (const auto& line : report) *ofp << line;
|
||||
}
|
||||
|
||||
void edgeDomainRecurse(CdcEitherVertex* vertexp, bool traceDests, int level) {
|
||||
|
|
@ -594,7 +586,7 @@ private:
|
|||
}
|
||||
|
||||
// Convert list of senses into one sense node
|
||||
AstSenTree* senoutp = NULL;
|
||||
AstSenTree* senoutp = nullptr;
|
||||
bool senedited = false;
|
||||
for (SenSet::iterator it = senouts.begin(); it != senouts.end(); ++it) {
|
||||
if (!senoutp) {
|
||||
|
|
@ -633,22 +625,21 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
UINFO(4, " SCOPE " << nodep << endl);
|
||||
m_scopep = nodep;
|
||||
m_logicVertexp = NULL;
|
||||
m_logicVertexp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
m_scopep = NULL;
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
// Create required blocks and add to module
|
||||
UINFO(4, " BLOCK " << nodep << endl);
|
||||
AstNode::user2ClearTree();
|
||||
|
|
@ -657,10 +648,10 @@ private:
|
|||
|| m_domainp->hasClocked()) { // IE not hasSettle/hasInitial
|
||||
iterateNewStmt(nodep);
|
||||
}
|
||||
m_domainp = NULL;
|
||||
m_domainp = nullptr;
|
||||
AstNode::user2ClearTree();
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
if (m_scopep) {
|
||||
UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block");
|
||||
AstVarScope* varscp = nodep->varScopep();
|
||||
|
|
@ -688,64 +679,55 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignDly* nodep) override {
|
||||
m_inDly = true;
|
||||
iterateChildren(nodep);
|
||||
m_inDly = false;
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
m_inSenItem = true;
|
||||
iterateChildren(nodep);
|
||||
m_inSenItem = false;
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAlways* nodep) override { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
// CDC doesn't care about public variables
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAssignW* nodep) VL_OVERRIDE { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstCFunc* nodep) override { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAssignAlias* nodep) override { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAssignW* nodep) override { iterateNewStmt(nodep); }
|
||||
|
||||
// Math that shouldn't cause us to clear hazard
|
||||
virtual void visit(AstConst*) VL_OVERRIDE {}
|
||||
virtual void visit(AstReplicate* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstConcat* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNot* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstSel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstConst*) override {}
|
||||
virtual void visit(AstReplicate* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstConcat* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstNot* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
if (!VN_IS(nodep->lsbp(), Const)) setNodeHazard(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeSel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeSel* nodep) override {
|
||||
if (!VN_IS(nodep->bitp(), Const)) setNodeHazard(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
// Ignores
|
||||
virtual void visit(AstInitial*) VL_OVERRIDE {}
|
||||
virtual void visit(AstTraceDecl*) VL_OVERRIDE {}
|
||||
virtual void visit(AstCoverToggle*) VL_OVERRIDE {}
|
||||
virtual void visit(AstNodeDType*) VL_OVERRIDE {}
|
||||
virtual void visit(AstInitial*) override {}
|
||||
virtual void visit(AstTraceDecl*) override {}
|
||||
virtual void visit(AstCoverToggle*) override {}
|
||||
virtual void visit(AstNodeDType*) override {}
|
||||
|
||||
//--------------------
|
||||
// Default
|
||||
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeMath* nodep) override {
|
||||
setNodeHazard(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CdcVisitor(AstNode* nodep) {
|
||||
m_logicVertexp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_modp = NULL;
|
||||
m_domainp = NULL;
|
||||
m_inDly = false;
|
||||
m_inSenItem = 0;
|
||||
m_userGeneration = 0;
|
||||
m_filelineWidth = 0;
|
||||
|
||||
// Make report of all signal names and what clock edges they have
|
||||
string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__cdc.txt";
|
||||
m_ofp = V3File::new_ofstream(filename);
|
||||
|
|
@ -763,12 +745,12 @@ public:
|
|||
if (debug() >= 1) edgeReport(); // Not useful to users at the moment
|
||||
if (false) {
|
||||
*m_ofp << "\nDBG-test-dumper\n";
|
||||
V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ", 40, NULL, true);
|
||||
V3EmitV::verilogPrefixedTree(nodep, *m_ofp, "DBG ", 40, nullptr, true);
|
||||
*m_ofp << endl;
|
||||
}
|
||||
}
|
||||
virtual ~CdcVisitor() {
|
||||
if (m_ofp) VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
|
||||
virtual ~CdcVisitor() override {
|
||||
if (m_ofp) VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -41,21 +41,14 @@
|
|||
class ChangedState {
|
||||
public:
|
||||
// STATE
|
||||
AstNodeModule* m_topModp; // Top module
|
||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||
AstCFunc* m_chgFuncp; // Change function we're building
|
||||
AstCFunc* m_tlChgFuncp; // Top level change function we're building
|
||||
int m_numStmts; // Number of statements added to m_chgFuncp
|
||||
int m_funcNum; // Number of change functions emitted
|
||||
AstNodeModule* m_topModp = nullptr; // Top module
|
||||
AstScope* m_scopetopp = nullptr; // Scope under TOPSCOPE
|
||||
AstCFunc* m_chgFuncp = nullptr; // Change function we're building
|
||||
AstCFunc* m_tlChgFuncp = nullptr; // Top level change function we're building
|
||||
int m_numStmts = 0; // Number of statements added to m_chgFuncp
|
||||
int m_funcNum = 0; // Number of change functions emitted
|
||||
|
||||
ChangedState() {
|
||||
m_topModp = NULL;
|
||||
m_chgFuncp = NULL;
|
||||
m_scopetopp = NULL;
|
||||
m_tlChgFuncp = NULL;
|
||||
m_numStmts = 0;
|
||||
m_funcNum = 0;
|
||||
}
|
||||
ChangedState() {}
|
||||
~ChangedState() {}
|
||||
|
||||
void maybeCreateChgFuncp() {
|
||||
|
|
@ -142,34 +135,33 @@ private:
|
|||
m_statep->m_numStmts += visitor.count();
|
||||
}
|
||||
|
||||
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE { //
|
||||
virtual void visit(AstBasicDType*) override { //
|
||||
newChangeDet();
|
||||
}
|
||||
virtual void visit(AstPackArrayDType* nodep) VL_OVERRIDE { //
|
||||
virtual void visit(AstPackArrayDType*) override { //
|
||||
newChangeDet();
|
||||
}
|
||||
virtual void visit(AstUnpackArrayDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstUnpackArrayDType* nodep) override {
|
||||
for (int index = 0; index < nodep->elementsConst(); ++index) {
|
||||
AstNode* origVEp = m_varEqnp;
|
||||
AstNode* origNLEp = m_newLvEqnp;
|
||||
AstNode* origNREp = m_newRvEqnp;
|
||||
VL_RESTORER(m_varEqnp);
|
||||
VL_RESTORER(m_newLvEqnp);
|
||||
VL_RESTORER(m_newRvEqnp);
|
||||
{
|
||||
m_varEqnp = new AstArraySel(nodep->fileline(), m_varEqnp->cloneTree(true), index);
|
||||
m_newLvEqnp
|
||||
= new AstArraySel(nodep->fileline(), m_newLvEqnp->cloneTree(true), index);
|
||||
m_newRvEqnp
|
||||
= new AstArraySel(nodep->fileline(), m_newRvEqnp->cloneTree(true), index);
|
||||
|
||||
m_varEqnp = new AstArraySel(nodep->fileline(), m_varEqnp->cloneTree(true), index);
|
||||
m_newLvEqnp = new AstArraySel(nodep->fileline(), m_newLvEqnp->cloneTree(true), index);
|
||||
m_newRvEqnp = new AstArraySel(nodep->fileline(), m_newRvEqnp->cloneTree(true), index);
|
||||
iterate(nodep->subDTypep()->skipRefp());
|
||||
|
||||
iterate(nodep->subDTypep()->skipRefp());
|
||||
|
||||
m_varEqnp->deleteTree();
|
||||
m_newLvEqnp->deleteTree();
|
||||
m_newRvEqnp->deleteTree();
|
||||
|
||||
m_varEqnp = origVEp;
|
||||
m_newLvEqnp = origNLEp;
|
||||
m_newRvEqnp = origNREp;
|
||||
m_varEqnp->deleteTree();
|
||||
m_newLvEqnp->deleteTree();
|
||||
m_newRvEqnp->deleteTree();
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeUOrStructDType* nodep) override {
|
||||
if (nodep->packedUnsup()) {
|
||||
newChangeDet();
|
||||
} else {
|
||||
|
|
@ -179,7 +171,7 @@ private:
|
|||
<< m_vscp->varp()->prettyNameQ());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (debug()) nodep->dumpTree(cout, "-DETECTARRAY-general-");
|
||||
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
|
||||
|
|
@ -216,7 +208,7 @@ public:
|
|||
m_newLvEqnp->deleteTree();
|
||||
m_newRvEqnp->deleteTree();
|
||||
}
|
||||
virtual ~ChangedInsertVisitor() {}
|
||||
virtual ~ChangedInsertVisitor() override {}
|
||||
VL_UNCOPYABLE(ChangedInsertVisitor);
|
||||
};
|
||||
|
||||
|
|
@ -242,13 +234,13 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
if (nodep->isTop()) m_statep->m_topModp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTopScope* nodep) override {
|
||||
UINFO(4, " TS " << nodep << endl);
|
||||
// Clearing
|
||||
AstNode::user1ClearTree();
|
||||
|
|
@ -267,27 +259,28 @@ private:
|
|||
// Each change detection function needs at least one AstChangeDet
|
||||
// to ensure that V3EmitC outputs the necessary code.
|
||||
m_statep->maybeCreateChgFuncp();
|
||||
m_statep->m_chgFuncp->addStmtsp(new AstChangeDet(nodep->fileline(), NULL, NULL, false));
|
||||
m_statep->m_chgFuncp->addStmtsp(
|
||||
new AstChangeDet(nodep->fileline(), nullptr, nullptr, false));
|
||||
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarScope* nodep) override {
|
||||
if (nodep->isCircular()) {
|
||||
UINFO(8, " CIRC " << nodep << endl);
|
||||
if (!nodep->user1SetOnce()) genChangeDet(nodep);
|
||||
}
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
ChangedVisitor(AstNetlist* nodep, ChangedState* statep) {
|
||||
m_statep = statep;
|
||||
ChangedVisitor(AstNetlist* nodep, ChangedState* statep)
|
||||
: m_statep{statep} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~ChangedVisitor() {}
|
||||
virtual ~ChangedVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ private:
|
|||
// MEMBERS
|
||||
AstUser1InUse m_inuser1;
|
||||
string m_prefix; // String prefix to add to name based on hier
|
||||
AstScope* m_classScopep; // Package moving scopes into
|
||||
typedef std::vector<std::pair<AstNode*, AstScope*> > MoveVector;
|
||||
AstScope* m_classScopep = nullptr; // Package moving scopes into
|
||||
typedef std::vector<std::pair<AstNode*, AstScope*>> MoveVector;
|
||||
MoveVector m_moves;
|
||||
|
||||
// NODE STATE
|
||||
|
|
@ -44,7 +44,7 @@ private:
|
|||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
virtual void visit(AstClass* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstClass* nodep) override {
|
||||
if (nodep->user1SetOnce()) return;
|
||||
// Move this class
|
||||
nodep->name(m_prefix + nodep->name());
|
||||
|
|
@ -59,12 +59,12 @@ private:
|
|||
v3Global.rootp()->addModulep(packagep);
|
||||
// Add package to hierarchy
|
||||
AstCell* cellp = new AstCell(packagep->fileline(), packagep->fileline(), packagep->name(),
|
||||
packagep->name(), NULL, NULL, NULL);
|
||||
packagep->name(), nullptr, nullptr, nullptr);
|
||||
cellp->modp(packagep);
|
||||
v3Global.rootp()->topModulep()->addStmtp(cellp);
|
||||
// Find class's scope
|
||||
// Alternative would be to move this and related to V3Scope
|
||||
AstScope* classScopep = NULL;
|
||||
AstScope* classScopep = nullptr;
|
||||
for (AstNode* itp = nodep->stmtsp(); itp; itp = itp->nextp()) {
|
||||
if ((classScopep = VN_CAST(itp, Scope))) break;
|
||||
}
|
||||
|
|
@ -75,25 +75,23 @@ private:
|
|||
classScopep->aboveScopep(), classScopep->aboveCellp());
|
||||
packagep->addStmtp(scopep);
|
||||
// Iterate
|
||||
string prevPrefix = m_prefix;
|
||||
VL_RESTORER(m_prefix);
|
||||
{
|
||||
m_classScopep = classScopep;
|
||||
m_prefix = nodep->name() + "__02e"; // .
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_prefix = prevPrefix;
|
||||
m_classScopep = NULL;
|
||||
m_classScopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstPackage* nodep) VL_OVERRIDE {
|
||||
string prevPrefix = m_prefix;
|
||||
virtual void visit(AstPackage* nodep) override {
|
||||
VL_RESTORER(m_prefix);
|
||||
{
|
||||
m_prefix = nodep->name() + "__03a__03a"; // ::
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_prefix = prevPrefix;
|
||||
}
|
||||
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Don't move now, or wouldn't keep interating the class
|
||||
// TODO move class statics only
|
||||
|
|
@ -101,7 +99,7 @@ private:
|
|||
// m_moves.push_back(make_pair(nodep, m_classScopep));
|
||||
//}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Don't move now, or wouldn't keep interating the class
|
||||
// TODO move function statics only
|
||||
|
|
@ -110,17 +108,14 @@ private:
|
|||
//}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {} // Short circuit
|
||||
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {} // Short circuit
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeMath* nodep) override {} // Short circuit
|
||||
virtual void visit(AstNodeStmt* nodep) override {} // Short circuit
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ClassVisitor(AstNetlist* nodep)
|
||||
: m_classScopep(NULL) {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~ClassVisitor() {
|
||||
explicit ClassVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ClassVisitor() override {
|
||||
for (MoveVector::iterator it = m_moves.begin(); it != m_moves.end(); ++it) {
|
||||
it->second->addVarp(it->first->unlinkFrBack());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ private:
|
|||
AstUser3InUse m_inuser3;
|
||||
|
||||
// TYPES
|
||||
enum CleanState { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
|
||||
enum CleanState : uint8_t { CS_UNKNOWN, CS_CLEAN, CS_DIRTY };
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp;
|
||||
AstNodeModule* m_modp = nullptr;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -170,65 +170,64 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeUniop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
if (nodep->cleanLhs()) ensureClean(nodep->lhsp());
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeBiop* nodep) override {
|
||||
operandBiop(nodep);
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstAnd* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAnd* nodep) override {
|
||||
operandBiop(nodep);
|
||||
setClean(nodep, isClean(nodep->lhsp()) || isClean(nodep->rhsp()));
|
||||
}
|
||||
virtual void visit(AstXor* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstXor* nodep) override {
|
||||
operandBiop(nodep);
|
||||
setClean(nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
|
||||
}
|
||||
virtual void visit(AstOr* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstOr* nodep) override {
|
||||
operandBiop(nodep);
|
||||
setClean(nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
|
||||
}
|
||||
virtual void visit(AstNodeQuadop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeQuadop* nodep) override {
|
||||
operandQuadop(nodep);
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeMath* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
if (nodep->cleanRhs()) ensureClean(nodep->rhsp());
|
||||
}
|
||||
virtual void visit(AstText* nodep) VL_OVERRIDE { //
|
||||
virtual void visit(AstText* nodep) override { //
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep) VL_OVERRIDE { //
|
||||
virtual void visit(AstScopeName* nodep) override { //
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstCNew* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCNew* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstSel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
operandTriop(nodep);
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstUCFunc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
setClean(nodep, false);
|
||||
|
|
@ -236,75 +235,72 @@ private:
|
|||
if (!VN_IS(nodep->backp(), And)) insertClean(nodep);
|
||||
ensureCleanAndNext(nodep->bodysp());
|
||||
}
|
||||
virtual void visit(AstTraceDecl* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTraceDecl* nodep) override {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstTraceInc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTraceInc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->valuep());
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTypedef* nodep) override {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstParamTypeDType* nodep) override {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
// Control flow operators
|
||||
virtual void visit(AstNodeCond* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCond* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureClean(nodep->condp());
|
||||
setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p()));
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureClean(nodep->condp());
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureClean(nodep->condp());
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSFormatF* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->exprsp());
|
||||
setClean(nodep, true); // generates a string, so not relevant
|
||||
}
|
||||
virtual void visit(AstUCStmt* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstUCStmt* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->bodysp());
|
||||
}
|
||||
virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCCall* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->argsp());
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstCMethodHard* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCMethodHard* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->pinsp());
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstIntfRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstIntfRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
setClean(nodep, true); // generates a string, so not relevant
|
||||
}
|
||||
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CleanVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CleanVisitor() {}
|
||||
explicit CleanVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~CleanVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
141
src/V3Clock.cpp
141
src/V3Clock.cpp
|
|
@ -48,16 +48,16 @@ private:
|
|||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstTopScope* m_topScopep; // Current top scope
|
||||
AstScope* m_scopep; // Current scope
|
||||
AstCFunc* m_evalFuncp; // Top eval function we are creating
|
||||
AstCFunc* m_initFuncp; // Top initial function we are creating
|
||||
AstCFunc* m_finalFuncp; // Top final function we are creating
|
||||
AstCFunc* m_settleFuncp; // Top settlement function we are creating
|
||||
AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates.
|
||||
AstIf* m_lastIfp; // Last sensitivity if active to add more under
|
||||
AstMTaskBody* m_mtaskBodyp; // Current mtask body
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstTopScope* m_topScopep = nullptr; // Current top scope
|
||||
AstScope* m_scopep = nullptr; // Current scope
|
||||
AstCFunc* m_evalFuncp = nullptr; // Top eval function we are creating
|
||||
AstCFunc* m_initFuncp = nullptr; // Top initial function we are creating
|
||||
AstCFunc* m_finalFuncp = nullptr; // Top final function we are creating
|
||||
AstCFunc* m_settleFuncp = nullptr; // Top settlement function we are creating
|
||||
AstSenTree* m_lastSenp = nullptr; // Last sensitivity match, so we can detect duplicates.
|
||||
AstIf* m_lastIfp = nullptr; // Last sensitivity if active to add more under
|
||||
AstMTaskBody* m_mtaskBodyp = nullptr; // Current mtask body
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -101,11 +101,11 @@ private:
|
|||
// BOTHEDGE: var ^ var_last
|
||||
// HIGHEDGE: var
|
||||
// LOWEDGE: ~var
|
||||
AstNode* newp = NULL;
|
||||
AstNode* newp = nullptr;
|
||||
if (nodep->edgeType() == VEdgeType::ET_ILLEGAL) {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: Complicated event expression in sensitive activity list");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
AstVarScope* clkvscp = nodep->varrefp()->varScopep();
|
||||
if (nodep->edgeType() == VEdgeType::ET_POSEDGE) {
|
||||
|
|
@ -138,7 +138,7 @@ private:
|
|||
}
|
||||
AstNode* createSenseEquation(AstSenItem* nodesp) {
|
||||
// Nodep may be a list of elements; we need to walk it
|
||||
AstNode* senEqnp = NULL;
|
||||
AstNode* senEqnp = nullptr;
|
||||
for (AstSenItem* senp = nodesp; senp; senp = VN_CAST(senp->nextp(), SenItem)) {
|
||||
AstNode* const senOnep = createSenItemEquation(senp);
|
||||
if (senEqnp) {
|
||||
|
|
@ -153,16 +153,53 @@ private:
|
|||
AstIf* makeActiveIf(AstSenTree* sensesp) {
|
||||
AstNode* senEqnp = createSenseEquation(sensesp->sensesp());
|
||||
UASSERT_OBJ(senEqnp, sensesp, "No sense equation, shouldn't be in sequent activation.");
|
||||
AstIf* newifp = new AstIf(sensesp->fileline(), senEqnp, NULL, NULL);
|
||||
AstIf* newifp = new AstIf(sensesp->fileline(), senEqnp, nullptr, nullptr);
|
||||
return newifp;
|
||||
}
|
||||
void clearLastSen() {
|
||||
m_lastSenp = NULL;
|
||||
m_lastIfp = NULL;
|
||||
m_lastSenp = nullptr;
|
||||
m_lastIfp = nullptr;
|
||||
}
|
||||
void splitCheck(AstCFunc* ofuncp) {
|
||||
if (!v3Global.opt.outputSplitCFuncs() || !ofuncp->stmtsp()) return;
|
||||
if (EmitCBaseCounterVisitor(ofuncp->stmtsp()).count() < v3Global.opt.outputSplitCFuncs())
|
||||
return;
|
||||
|
||||
int funcnum = 0;
|
||||
int func_stmts = 0;
|
||||
AstCFunc* funcp = nullptr;
|
||||
|
||||
// Unlink all statements, then add item by item to new sub-functions
|
||||
AstBegin* tempp = new AstBegin{ofuncp->fileline(), "[EditWrapper]",
|
||||
ofuncp->stmtsp()->unlinkFrBackWithNext()};
|
||||
if (ofuncp->finalsp()) tempp->addStmtsp(ofuncp->finalsp()->unlinkFrBackWithNext());
|
||||
while (tempp->stmtsp()) {
|
||||
AstNode* itemp = tempp->stmtsp()->unlinkFrBack();
|
||||
int stmts = EmitCBaseCounterVisitor(itemp).count();
|
||||
if (!funcp || (func_stmts + stmts) > v3Global.opt.outputSplitCFuncs()) {
|
||||
// Make a new function
|
||||
funcp = new AstCFunc{ofuncp->fileline(), ofuncp->name() + cvtToStr(++funcnum),
|
||||
m_topScopep->scopep()};
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->slow(ofuncp->slow());
|
||||
m_topScopep->scopep()->addActivep(funcp);
|
||||
//
|
||||
AstCCall* callp = new AstCCall{funcp->fileline(), funcp};
|
||||
callp->argTypes("vlSymsp");
|
||||
ofuncp->addStmtsp(callp);
|
||||
func_stmts = 0;
|
||||
}
|
||||
funcp->addStmtsp(itemp);
|
||||
func_stmts += stmts;
|
||||
}
|
||||
VL_DO_DANGLING(tempp->deleteTree(), tempp);
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTopScope* nodep) override {
|
||||
UINFO(4, " TOPSCOPE " << nodep << endl);
|
||||
m_topScopep = nodep;
|
||||
m_scopep = nodep->scopep();
|
||||
|
|
@ -172,28 +209,29 @@ private:
|
|||
AstNode::user1ClearTree();
|
||||
// Make top functions
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep);
|
||||
AstCFunc* funcp = new AstCFunc{nodep->fileline(), "_eval", m_topScopep->scopep()};
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_topScopep->scopep()->addActivep(funcp);
|
||||
m_evalFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep);
|
||||
AstCFunc* funcp
|
||||
= new AstCFunc{nodep->fileline(), "_eval_initial", m_topScopep->scopep()};
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_topScopep->scopep()->addActivep(funcp);
|
||||
m_initFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "final", m_scopep);
|
||||
AstCFunc* funcp = new AstCFunc{nodep->fileline(), "final", m_topScopep->scopep()};
|
||||
funcp->skipDecl(true);
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
|
|
@ -204,38 +242,44 @@ private:
|
|||
+ " = this->__VlSymsp;\n"));
|
||||
funcp->addInitsp(
|
||||
new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n"));
|
||||
m_scopep->addActivep(funcp);
|
||||
m_topScopep->scopep()->addActivep(funcp);
|
||||
m_finalFuncp = funcp;
|
||||
}
|
||||
{
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep);
|
||||
AstCFunc* funcp
|
||||
= new AstCFunc{nodep->fileline(), "_eval_settle", m_topScopep->scopep()};
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->dontCombine(true);
|
||||
funcp->slow(true);
|
||||
funcp->isStatic(true);
|
||||
funcp->symProlog(true);
|
||||
funcp->entryPoint(true);
|
||||
m_scopep->addActivep(funcp);
|
||||
m_topScopep->scopep()->addActivep(funcp);
|
||||
m_settleFuncp = funcp;
|
||||
}
|
||||
// Process the activates
|
||||
iterateChildren(nodep);
|
||||
UINFO(4, " TOPSCOPE iter done " << nodep << endl);
|
||||
// Split large functions
|
||||
splitCheck(m_evalFuncp);
|
||||
splitCheck(m_initFuncp);
|
||||
splitCheck(m_finalFuncp);
|
||||
splitCheck(m_settleFuncp);
|
||||
// Done, clear so we can detect errors
|
||||
UINFO(4, " TOPSCOPEDONE " << nodep << endl);
|
||||
clearLastSen();
|
||||
m_topScopep = NULL;
|
||||
m_scopep = NULL;
|
||||
m_topScopep = nullptr;
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
// UINFO(4, " MOD " << nodep << endl);
|
||||
AstNodeModule* origModp = m_modp;
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
// UINFO(4, " SCOPE " << nodep << endl);
|
||||
m_scopep = nodep;
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -244,9 +288,9 @@ private:
|
|||
movep->unlinkFrBackWithNext();
|
||||
m_evalFuncp->addFinalsp(movep);
|
||||
}
|
||||
m_scopep = NULL;
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAlways* nodep) override {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
|
|
@ -255,7 +299,7 @@ private:
|
|||
}
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstAlwaysPost* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAlwaysPost* nodep) override {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
|
|
@ -264,7 +308,7 @@ private:
|
|||
}
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCoverToggle* nodep) override {
|
||||
// nodep->dumpTree(cout, "ct:");
|
||||
// COVERTOGGLE(INC, ORIG, CHANGE) ->
|
||||
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
|
||||
|
|
@ -272,7 +316,7 @@ private:
|
|||
AstNode* origp = nodep->origp()->unlinkFrBack();
|
||||
AstNode* changep = nodep->changep()->unlinkFrBack();
|
||||
AstIf* newp = new AstIf(nodep->fileline(), new AstXor(nodep->fileline(), origp, changep),
|
||||
incp, NULL);
|
||||
incp, nullptr);
|
||||
// We could add another IF to detect posedges, and only increment if so.
|
||||
// It's another whole branch though versus a potential memory miss.
|
||||
// We'll go with the miss.
|
||||
|
|
@ -281,7 +325,7 @@ private:
|
|||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstInitial* nodep) override {
|
||||
AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true);
|
||||
nodep->replaceWith(cmtp);
|
||||
if (AstNode* stmtsp = nodep->bodysp()) {
|
||||
|
|
@ -290,7 +334,7 @@ private:
|
|||
}
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Link to global function
|
||||
if (nodep->formCallTree()) {
|
||||
|
|
@ -300,7 +344,7 @@ private:
|
|||
m_finalFuncp->addStmtsp(callp);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenTree* nodep) override {
|
||||
// Delete it later; Actives still pointing to it
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep);
|
||||
|
|
@ -314,7 +358,7 @@ private:
|
|||
void addToInitial(AstNode* stmtsp) {
|
||||
m_initFuncp->addStmtsp(stmtsp); // add to top level function
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) 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()) {
|
||||
|
|
@ -382,7 +426,7 @@ private:
|
|||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstExecGraph* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstExecGraph* nodep) override {
|
||||
for (m_mtaskBodyp = VN_CAST(nodep->op1p(), MTaskBody); m_mtaskBodyp;
|
||||
m_mtaskBodyp = VN_CAST(m_mtaskBodyp->nextp(), MTaskBody)) {
|
||||
clearLastSen();
|
||||
|
|
@ -397,28 +441,17 @@ private:
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ClockVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
m_evalFuncp = NULL;
|
||||
m_initFuncp = NULL;
|
||||
m_finalFuncp = NULL;
|
||||
m_settleFuncp = NULL;
|
||||
m_topScopep = NULL;
|
||||
m_lastSenp = NULL;
|
||||
m_lastIfp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_mtaskBodyp = NULL;
|
||||
//
|
||||
iterate(nodep);
|
||||
// Allow downstream modules to find _eval()
|
||||
// easily without iterating through the tree.
|
||||
nodep->evalp(m_evalFuncp);
|
||||
}
|
||||
virtual ~ClockVisitor() {}
|
||||
virtual ~ClockVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@
|
|||
|
||||
//######################################################################
|
||||
|
||||
#define COMBINE_MIN_STATEMENTS 50 // Min # of statements to be worth making a function
|
||||
#ifdef VL_COMBINE_STATEMENTS
|
||||
constexpr int COMBINE_MIN_STATEMENTS = 50; // Min # of statements to be worth making a function
|
||||
#endif
|
||||
|
||||
//######################################################################
|
||||
|
||||
|
|
@ -54,7 +56,7 @@ protected:
|
|||
// STATE
|
||||
|
||||
// METHODS
|
||||
virtual ~CombBaseVisitor() {}
|
||||
virtual ~CombBaseVisitor() override {}
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
};
|
||||
|
||||
|
|
@ -108,8 +110,8 @@ public:
|
|||
void deleteCall(AstCCall* nodep) {
|
||||
std::pair<CallMmap::iterator, CallMmap::iterator> eqrange
|
||||
= m_callMmap.equal_range(nodep->funcp());
|
||||
for (CallMmap::iterator nextit = eqrange.first; nextit != eqrange.second;) {
|
||||
CallMmap::iterator eqit = nextit++;
|
||||
for (auto nextit = eqrange.first; nextit != eqrange.second;) {
|
||||
const auto eqit = nextit++;
|
||||
AstCCall* callp = eqit->second;
|
||||
if (callp == nodep) {
|
||||
m_callMmap.erase(eqit);
|
||||
|
|
@ -121,16 +123,16 @@ public:
|
|||
|
||||
private:
|
||||
// VISITORS
|
||||
virtual void visit(AstCCall* nodep) VL_OVERRIDE { addCall(nodep); }
|
||||
virtual void visit(AstCCall* nodep) override { addCall(nodep); }
|
||||
// Speed things up
|
||||
virtual void visit(AstNodeAssign*) VL_OVERRIDE {}
|
||||
virtual void visit(AstNodeMath*) VL_OVERRIDE {}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeAssign*) override {}
|
||||
virtual void visit(AstNodeMath*) override {}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
CombCallVisitor() {}
|
||||
virtual ~CombCallVisitor() {}
|
||||
virtual ~CombCallVisitor() override {}
|
||||
void main(AstNetlist* nodep) { iterate(nodep); }
|
||||
};
|
||||
|
||||
|
|
@ -143,7 +145,7 @@ private:
|
|||
// OUTPUT:
|
||||
// AstNode::user3() -> bool. True to indicate duplicated
|
||||
// VISITORS
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
nodep->user3(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
@ -151,7 +153,7 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CombMarkVisitor(AstNode* nodep) { iterate(nodep); }
|
||||
virtual ~CombMarkVisitor() {}
|
||||
virtual ~CombMarkVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -171,15 +173,17 @@ private:
|
|||
// AstUser4InUse part of V3Hashed
|
||||
|
||||
// STATE
|
||||
typedef enum { STATE_IDLE, STATE_HASH, STATE_DUP } CombineState;
|
||||
typedef enum : uint8_t { STATE_IDLE, STATE_HASH, STATE_DUP } CombineState;
|
||||
VDouble0 m_statCombs; // Statistic tracking
|
||||
CombineState m_state; // Major state
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp; // Current function
|
||||
CombineState m_state = STATE_IDLE; // Major state
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstCFunc* m_funcp = nullptr; // Current function
|
||||
CombCallVisitor m_call; // Tracking of function call users
|
||||
int m_modNFuncs; // Number of functions made
|
||||
AstNode* m_walkLast1p; // Final node that is the same in duplicate list
|
||||
AstNode* m_walkLast2p; // Final node that is the same in duplicate list
|
||||
int m_modNFuncs = 0; // Number of functions made
|
||||
#ifdef VL_COMBINE_STATEMENTS
|
||||
AstNode* m_walkLast1p = nullptr; // Final node that is the same in duplicate list
|
||||
#endif
|
||||
AstNode* m_walkLast2p = nullptr; // Final node that is the same in duplicate list
|
||||
V3Hashed m_hashed; // Hash for every node in module
|
||||
|
||||
// METHODS
|
||||
|
|
@ -191,12 +195,11 @@ private:
|
|||
#ifdef VL_COMBINE_STATEMENTS
|
||||
void hashFunctions(AstCFunc* nodep) {
|
||||
// Compute hash of all statement trees in the function
|
||||
CombineState oldState = m_state;
|
||||
VL_RESTORER(m_state);
|
||||
{
|
||||
m_state = STATE_HASH;
|
||||
iterate(nodep);
|
||||
}
|
||||
m_state = oldState;
|
||||
}
|
||||
#endif
|
||||
void walkEmptyFuncs() {
|
||||
|
|
@ -208,7 +211,7 @@ private:
|
|||
<< oldfuncp << endl);
|
||||
// Mark user3p on entire old tree, so we don't process it more
|
||||
CombMarkVisitor visitor(oldfuncp);
|
||||
m_call.replaceFunc(oldfuncp, NULL);
|
||||
m_call.replaceFunc(oldfuncp, nullptr);
|
||||
oldfuncp->unlinkFrBack();
|
||||
VL_DO_DANGLING(pushDeletep(oldfuncp), oldfuncp);
|
||||
}
|
||||
|
|
@ -251,8 +254,8 @@ private:
|
|||
void replaceOnlyCallFunc(AstCCall* nodep) {
|
||||
if (AstCFunc* oldfuncp = VN_CAST(nodep->backp(), CFunc)) {
|
||||
// oldfuncp->dumpTree(cout, "MAYDEL: ");
|
||||
if (nodep->nextp() == NULL && oldfuncp->initsp() == NULL && oldfuncp->stmtsp() == nodep
|
||||
&& oldfuncp->finalsp() == NULL) {
|
||||
if (nodep->nextp() == nullptr && oldfuncp->initsp() == nullptr
|
||||
&& oldfuncp->stmtsp() == nodep && oldfuncp->finalsp() == nullptr) {
|
||||
UINFO(9, " Function only has call " << oldfuncp << endl);
|
||||
m_call.deleteCall(nodep);
|
||||
CombMarkVisitor visitor(oldfuncp);
|
||||
|
|
@ -266,9 +269,9 @@ private:
|
|||
// UINFO(4," STMT " << hashval << " " << node1p << endl);
|
||||
//
|
||||
int bestDepth = 0; // Best substitution found in the search
|
||||
AstNode* bestNode2p = NULL;
|
||||
AstNode* bestLast1p = NULL;
|
||||
AstNode* bestLast2p = NULL;
|
||||
AstNode* bestNode2p = nullptr;
|
||||
AstNode* bestLast1p = nullptr;
|
||||
AstNode* bestLast2p = nullptr;
|
||||
//
|
||||
std::pair<V3Hashed::iterator, V3Hashed::iterator> eqrange
|
||||
= m_hashed.mmap().equal_range(hashval);
|
||||
|
|
@ -279,8 +282,8 @@ private:
|
|||
// We need to mark iteration to prevent matching code inside
|
||||
// code (abab matching in ababab)
|
||||
AstNode::user1ClearTree(); // user1p() used on entire tree
|
||||
m_walkLast1p = NULL;
|
||||
m_walkLast2p = NULL;
|
||||
m_walkLast1p = nullptr;
|
||||
m_walkLast2p = nullptr;
|
||||
int depth = walkDupCodeNext(node1p, node2p, 1);
|
||||
if (depth > COMBINE_MIN_STATEMENTS && depth > bestDepth) {
|
||||
bestDepth = depth;
|
||||
|
|
@ -332,7 +335,7 @@ private:
|
|||
if ((pos = oldname.find("_common")) != string::npos) oldname.erase(pos);
|
||||
if ((pos = oldname.find("__")) != string::npos) oldname.erase(pos);
|
||||
AstCFunc* newfuncp = new AstCFunc(node1p->fileline(),
|
||||
oldname + "_common" + cvtToStr(++m_modNFuncs), NULL);
|
||||
oldname + "_common" + cvtToStr(++m_modNFuncs), nullptr);
|
||||
m_modp->addStmtp(newfuncp);
|
||||
// Create calls
|
||||
AstCCall* call1p = new AstCCall(node1p->fileline(), newfuncp);
|
||||
|
|
@ -381,7 +384,7 @@ private:
|
|||
#endif
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
// Track all callers of each function
|
||||
m_call.main(nodep);
|
||||
//
|
||||
|
|
@ -390,11 +393,11 @@ private:
|
|||
// Required so that a module instantiating another can benefit from collapsing.
|
||||
iterateChildrenBackwards(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
m_modp = nodep;
|
||||
m_modNFuncs = 0;
|
||||
m_walkLast2p = NULL;
|
||||
m_walkLast2p = nullptr;
|
||||
m_hashed.clear();
|
||||
// Compute hash of all statement trees in the function
|
||||
m_state = STATE_HASH;
|
||||
|
|
@ -417,9 +420,9 @@ private:
|
|||
m_state = STATE_IDLE;
|
||||
}
|
||||
#endif
|
||||
m_modp = NULL;
|
||||
m_modp = nullptr;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
m_funcp = nodep;
|
||||
if (!nodep->dontCombine()) {
|
||||
if (m_state == STATE_HASH) {
|
||||
|
|
@ -431,9 +434,9 @@ private:
|
|||
}
|
||||
#endif
|
||||
}
|
||||
m_funcp = NULL;
|
||||
m_funcp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeStmt* nodep) override {
|
||||
if (!nodep->isStatement()) {
|
||||
iterateChildren(nodep);
|
||||
return;
|
||||
|
|
@ -450,23 +453,15 @@ private:
|
|||
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
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); }
|
||||
virtual void visit(AstVar*) override {}
|
||||
virtual void visit(AstTraceDecl*) override {}
|
||||
virtual void visit(AstTraceInc*) override {}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CombineVisitor(AstNetlist* nodep) {
|
||||
m_state = STATE_IDLE;
|
||||
m_modp = NULL;
|
||||
m_funcp = NULL;
|
||||
m_modNFuncs = 0;
|
||||
m_walkLast1p = NULL;
|
||||
m_walkLast2p = NULL;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CombineVisitor() { //
|
||||
explicit CombineVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~CombineVisitor() override { //
|
||||
V3Stats::addStat("Optimizations, Combined CFuncs", m_statCombs);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@ public:
|
|||
// 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);
|
||||
auto it = m_mapResolved.find(name);
|
||||
if (VL_UNLIKELY(it != m_mapResolved.end())) { return &it->second; }
|
||||
|
||||
T* newp = NULL;
|
||||
T* newp = nullptr;
|
||||
// Cannot be resolved, create if matched
|
||||
|
||||
// Update this entity with all matches in the wildcards
|
||||
|
|
@ -87,8 +87,8 @@ 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) {}
|
||||
: m_type{type}
|
||||
, m_sentreep{sentreep} {}
|
||||
};
|
||||
|
||||
// Overload vector with the required update function and to apply all entries
|
||||
|
|
@ -105,7 +105,7 @@ public:
|
|||
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));
|
||||
newp->addNext(new AstAlwaysPublic(varp->fileline(), it->m_sentreep, nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -118,15 +118,12 @@ typedef V3ConfigWildcardResolver<V3ConfigVar> V3ConfigVarResolver;
|
|||
|
||||
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
|
||||
bool m_isolate = false; // Isolate function return
|
||||
bool m_noinline = false; // Don't inline function/task
|
||||
bool m_public = false; // Public function/task
|
||||
|
||||
public:
|
||||
V3ConfigFTask()
|
||||
: m_isolate(false)
|
||||
, m_noinline(false)
|
||||
, m_public(false) {}
|
||||
V3ConfigFTask() {}
|
||||
void update(const V3ConfigFTask& f) {
|
||||
// Don't overwrite true with false
|
||||
if (f.m_isolate) m_isolate = true;
|
||||
|
|
@ -141,7 +138,7 @@ public:
|
|||
void setNoInline(bool set) { m_noinline = set; }
|
||||
void setPublic(bool set) { m_public = set; }
|
||||
|
||||
void apply(AstNodeFTask* ftaskp) {
|
||||
void apply(AstNodeFTask* ftaskp) const {
|
||||
if (m_noinline)
|
||||
ftaskp->addStmtsp(new AstPragma(ftaskp->fileline(), AstPragmaType::NO_INLINE_TASK));
|
||||
if (m_public)
|
||||
|
|
@ -157,28 +154,23 @@ typedef V3ConfigWildcardResolver<V3ConfigFTask> V3ConfigFTaskResolver;
|
|||
// Modules have tasks, variables, named blocks and properties
|
||||
|
||||
class V3ConfigModule {
|
||||
typedef vl_unordered_set<string> StringSet;
|
||||
typedef std::unordered_set<string> StringSet;
|
||||
typedef std::set<AstPragmaType> PragmaSet;
|
||||
|
||||
V3ConfigFTaskResolver m_tasks; // Functions/tasks in module
|
||||
V3ConfigVarResolver m_vars; // Variables in module
|
||||
StringSet m_coverageOffBlocks; // List of block names for coverage_off
|
||||
PragmaSet m_modPragmas; // List of Pragmas for modules
|
||||
bool m_inline; // Whether to force the inline
|
||||
bool m_inlineValue; // The inline value (on/off)
|
||||
bool m_inline = false; // Whether to force the inline
|
||||
bool m_inlineValue = false; // The inline value (on/off)
|
||||
|
||||
public:
|
||||
V3ConfigModule()
|
||||
: m_inline(false)
|
||||
, m_inlineValue(false) {}
|
||||
V3ConfigModule() {}
|
||||
|
||||
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);
|
||||
}
|
||||
for (const string& i : m.m_coverageOffBlocks) m_coverageOffBlocks.insert(i);
|
||||
if (!m_inline) {
|
||||
m_inline = m.m_inline;
|
||||
m_inlineValue = m.m_inlineValue;
|
||||
|
|
@ -215,9 +207,8 @@ public:
|
|||
void applyBlock(AstNodeBlock* 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)) {
|
||||
for (const string& i : m_coverageOffBlocks) {
|
||||
if (VString::wildmatch(nodep->name(), i)) {
|
||||
nodep->addStmtsp(new AstPragma(nodep->fileline(), pragma));
|
||||
}
|
||||
}
|
||||
|
|
@ -239,9 +230,9 @@ public:
|
|||
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) {}
|
||||
: 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;
|
||||
|
|
|
|||
177
src/V3Const.cpp
177
src/V3Const.cpp
|
|
@ -41,10 +41,10 @@ class ConstVarMarkVisitor : public AstNVisitor {
|
|||
// AstVar::user4p -> bool, Var marked, 0=not set yet
|
||||
private:
|
||||
// VISITORS
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
if (nodep->varp()) nodep->varp()->user4(1);
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -52,29 +52,26 @@ public:
|
|||
AstNode::user4ClearTree(); // Check marked InUse before we're called
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~ConstVarMarkVisitor() {}
|
||||
virtual ~ConstVarMarkVisitor() override {}
|
||||
};
|
||||
|
||||
class ConstVarFindVisitor : public AstNVisitor {
|
||||
// NODE STATE
|
||||
// AstVar::user4p -> bool, input from ConstVarMarkVisitor
|
||||
// MEMBERS
|
||||
bool m_found;
|
||||
bool m_found = false;
|
||||
|
||||
private:
|
||||
// VISITORS
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
if (nodep->varp() && nodep->varp()->user4()) m_found = true;
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ConstVarFindVisitor(AstNode* nodep) {
|
||||
m_found = false;
|
||||
iterateAndNextNull(nodep);
|
||||
}
|
||||
virtual ~ConstVarFindVisitor() {}
|
||||
explicit ConstVarFindVisitor(AstNode* nodep) { iterateAndNextNull(nodep); }
|
||||
virtual ~ConstVarFindVisitor() override {}
|
||||
// METHODS
|
||||
bool found() const { return m_found; }
|
||||
};
|
||||
|
|
@ -92,20 +89,20 @@ private:
|
|||
// AstEnum::user4 -> bool. Recursing.
|
||||
|
||||
// STATE
|
||||
bool m_params; // If true, propagate parameterized and true numbers only
|
||||
bool m_required; // If true, must become a constant
|
||||
bool m_wremove; // Inside scope, no assignw removal
|
||||
bool m_warn; // Output warnings
|
||||
bool m_doExpensive; // Enable computationally expensive optimizations
|
||||
bool m_doNConst; // Enable non-constant-child simplifications
|
||||
bool m_doShort; // Remove expressions that short circuit
|
||||
bool m_doV; // Verilog, not C++ conversion
|
||||
bool m_doGenerate; // Postpone width checking inside generate
|
||||
bool m_hasJumpDelay; // JumpGo or Delay under this while
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstArraySel* m_selp; // Current select
|
||||
AstNode* m_scopep; // Current scope
|
||||
AstAttrOf* m_attrp; // Current attribute
|
||||
bool m_params = false; // If true, propagate parameterized and true numbers only
|
||||
bool m_required = false; // If true, must become a constant
|
||||
bool m_wremove = true; // Inside scope, no assignw removal
|
||||
bool m_warn = false; // Output warnings
|
||||
bool m_doExpensive = false; // Enable computationally expensive optimizations
|
||||
bool m_doNConst = false; // Enable non-constant-child simplifications
|
||||
bool m_doShort = true; // Remove expressions that short circuit
|
||||
bool m_doV = false; // Verilog, not C++ conversion
|
||||
bool m_doGenerate = false; // Postpone width checking inside generate
|
||||
bool m_hasJumpDelay = false; // JumpGo or Delay under this while
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstArraySel* m_selp = nullptr; // Current select
|
||||
AstNode* m_scopep = nullptr; // Current scope
|
||||
AstAttrOf* m_attrp = nullptr; // Current attribute
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -1115,7 +1112,7 @@ private:
|
|||
AstSel* sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2 - lsb2 + 1);
|
||||
// Make new assigns of same flavor as old one
|
||||
//*** Not cloneTree; just one node.
|
||||
AstNode* newp = NULL;
|
||||
AstNode* newp = nullptr;
|
||||
if (!need_temp) {
|
||||
AstNodeAssign* asn1ap = VN_CAST(nodep->cloneType(lc1p, sel1p), NodeAssign);
|
||||
AstNodeAssign* asn2ap = VN_CAST(nodep->cloneType(lc2p, sel2p), NodeAssign);
|
||||
|
|
@ -1282,32 +1279,31 @@ private:
|
|||
//----------------------------------------
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
// Iterate modules backwards, in bottom-up order. That's faster
|
||||
iterateChildrenBackwards(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
// No ASSIGNW removals under scope, we've long eliminated INITIALs
|
||||
m_scopep = nodep;
|
||||
m_wremove = false;
|
||||
iterateChildren(nodep);
|
||||
m_wremove = true;
|
||||
m_scopep = NULL;
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
|
||||
void swapSides(AstNodeBiCom* nodep) {
|
||||
|
|
@ -1373,16 +1369,16 @@ private:
|
|||
}
|
||||
|
||||
// Special cases
|
||||
virtual void visit(AstConst*) VL_OVERRIDE {} // Already constant
|
||||
virtual void visit(AstConst*) override {} // Already constant
|
||||
|
||||
virtual void visit(AstCell* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
if (m_params) {
|
||||
iterateAndNextNull(nodep->paramsp());
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstPin* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstPin* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
void replaceLogEq(AstLogEq* nodep) {
|
||||
// LOGEQ(a,b) => AstLogAnd{AstLogOr{AstLogNot{a},b},AstLogOr{AstLogNot{b},a}}
|
||||
|
|
@ -1563,14 +1559,15 @@ private:
|
|||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstAttrOf* nodep) VL_OVERRIDE {
|
||||
AstAttrOf* oldAttr = m_attrp;
|
||||
m_attrp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_attrp = oldAttr;
|
||||
virtual void visit(AstAttrOf* nodep) override {
|
||||
VL_RESTORER(m_attrp);
|
||||
{
|
||||
m_attrp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstArraySel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstArraySel* nodep) override {
|
||||
iterateAndNextNull(nodep->bitp());
|
||||
if (VN_IS(nodep->bitp(), Const)
|
||||
&& VN_IS(nodep->fromp(), VarRef)
|
||||
|
|
@ -1594,9 +1591,9 @@ private:
|
|||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
}
|
||||
m_selp = NULL;
|
||||
m_selp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
UASSERT_OBJ(nodep->varp(), nodep, "Not linked");
|
||||
bool did = false;
|
||||
|
|
@ -1650,7 +1647,7 @@ private:
|
|||
<< nodep->varp()->prettyNameQ());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstEnumItemRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
UASSERT_OBJ(nodep->itemp(), nodep, "Not linked");
|
||||
bool did = false;
|
||||
|
|
@ -1675,7 +1672,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// virtual void visit(AstCvtPackString* nodep) VL_OVERRIDE {
|
||||
// virtual void visit(AstCvtPackString* nodep) override {
|
||||
// Not constant propagated (for today) because AstNodeMath::isOpaque is set
|
||||
// Someday if lower is constant, convert to quoted "string".
|
||||
|
||||
|
|
@ -1683,7 +1680,7 @@ private:
|
|||
// Only one if it's not in a list
|
||||
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst
|
||||
&& (VN_IS(nodep->sensp(), Const) || VN_IS(nodep->sensp(), EnumItemRef)
|
||||
|
|
@ -1750,7 +1747,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
virtual void visit(AstSenTree* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenTree* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doExpensive) {
|
||||
// cout<<endl; nodep->dumpTree(cout, "ssin: ");
|
||||
|
|
@ -1784,21 +1781,15 @@ private:
|
|||
SenItemCmp cmp;
|
||||
if (nextp && !cmp(senp, nextp)) {
|
||||
// Something's out of order, sort it
|
||||
senp = NULL;
|
||||
senp = nullptr;
|
||||
std::vector<AstSenItem*> vec;
|
||||
for (AstSenItem* senp = VN_CAST(nodep->sensesp(), SenItem); senp;
|
||||
senp = VN_CAST(senp->nextp(), SenItem)) {
|
||||
vec.push_back(senp);
|
||||
}
|
||||
stable_sort(vec.begin(), vec.end(), SenItemCmp());
|
||||
for (std::vector<AstSenItem*>::iterator it = vec.begin(); it != vec.end();
|
||||
++it) {
|
||||
(*it)->unlinkFrBack();
|
||||
}
|
||||
for (std::vector<AstSenItem*>::iterator it = vec.begin(); it != vec.end();
|
||||
++it) {
|
||||
nodep->addSensesp(*it);
|
||||
}
|
||||
for (const auto& ip : vec) ip->unlinkFrBack();
|
||||
for (const auto& ip : vec) nodep->addSensesp(ip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1842,17 +1833,17 @@ private:
|
|||
|
||||
//-----
|
||||
// Zero elimination
|
||||
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignAlias* nodep) override {
|
||||
// Don't perform any optimizations, keep the alias around
|
||||
}
|
||||
virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignVarScope* nodep) override {
|
||||
// Don't perform any optimizations, the node won't be linked yet
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignW* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
AstNodeVarRef* varrefp = VN_CAST(
|
||||
|
|
@ -1879,11 +1870,11 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst) {
|
||||
if (const AstConst* constp = VN_CAST(nodep->condp(), Const)) {
|
||||
AstNode* keepp = NULL;
|
||||
AstNode* keepp = nullptr;
|
||||
if (constp->isZero()) {
|
||||
UINFO(4, "IF(0,{any},{x}) => {x}: " << nodep << endl);
|
||||
keepp = nodep->elsesp();
|
||||
|
|
@ -1907,7 +1898,7 @@ private:
|
|||
// effects in the condition itself
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
} else if (!afterComment(nodep->ifsp())) {
|
||||
UINFO(4, "IF({x}) NULL {...} => IF(NOT{x}}: " << nodep << endl);
|
||||
UINFO(4, "IF({x}) nullptr {...} => IF(NOT{x}}: " << nodep << endl);
|
||||
AstNode* condp = nodep->condp();
|
||||
AstNode* elsesp = nodep->elsesp();
|
||||
condp->unlinkFrBackWithNext();
|
||||
|
|
@ -1958,7 +1949,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
// DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2))
|
||||
iterateChildren(nodep);
|
||||
if (stmtDisplayDisplay(nodep)) return;
|
||||
|
|
@ -2003,7 +1994,7 @@ private:
|
|||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return true;
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSFormatF* nodep) 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.
|
||||
|
|
@ -2022,8 +2013,7 @@ private:
|
|||
bool inPct = false;
|
||||
AstNode* argp = nodep->exprsp();
|
||||
string text = nodep->text();
|
||||
for (string::const_iterator it = text.begin(); it != text.end(); ++it) {
|
||||
char ch = *it;
|
||||
for (const char ch : text) {
|
||||
if (!inPct && ch == '%') {
|
||||
inPct = true;
|
||||
fmt = ch;
|
||||
|
|
@ -2071,17 +2061,17 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstFuncRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFuncRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_params) { // Only parameters force us to do constant function call propagation
|
||||
replaceWithSimulation(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstArg* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstArg* nodep) override {
|
||||
// replaceWithSimulation on the Arg's parent FuncRef replaces these
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
bool oldHasJumpDelay = m_hasJumpDelay;
|
||||
m_hasJumpDelay = false;
|
||||
{ iterateChildren(nodep); }
|
||||
|
|
@ -2107,22 +2097,22 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstInitItem* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstUnbounded* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstInitArray* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstInitItem* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstUnbounded* nodep) 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*) VL_OVERRIDE {}
|
||||
virtual void visit(AstNodePreSel*) override {}
|
||||
|
||||
// Ignored, can eliminate early
|
||||
virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSysIgnore* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst) { VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); }
|
||||
}
|
||||
|
||||
// Simplify
|
||||
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstBasicDType* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->cvtRangeConst();
|
||||
}
|
||||
|
|
@ -2130,11 +2120,11 @@ private:
|
|||
//-----
|
||||
// Jump elimination
|
||||
|
||||
virtual void visit(AstDelay* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstDelay* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
m_hasJumpDelay = true;
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstJumpGo* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Jump to label where label immediately follows label is not useful
|
||||
if (nodep->labelp() == VN_CAST(nodep->nextp(), JumpLabel)) {
|
||||
|
|
@ -2165,7 +2155,7 @@ private:
|
|||
m_hasJumpDelay = true;
|
||||
}
|
||||
|
||||
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstJumpBlock* nodep) 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
|
||||
|
|
@ -2173,7 +2163,7 @@ private:
|
|||
// AstJumpGo's below here that point to this node will set user4
|
||||
if (m_doExpensive && !nodep->user4()) {
|
||||
UINFO(4, "JUMPLABEL => unused " << nodep << endl);
|
||||
AstNode* underp = NULL;
|
||||
AstNode* underp = nullptr;
|
||||
if (nodep->stmtsp()) underp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
if (underp) {
|
||||
nodep->replaceWith(underp);
|
||||
|
|
@ -2219,8 +2209,8 @@ private:
|
|||
|
||||
TREEOP1("AstSel{warnSelect(nodep)}", "NEVER");
|
||||
// Generic constants on both side. Do this first to avoid other replacements
|
||||
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque()}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeBiop {$lhsp.castConst, $rhsp.castConst, nodep->isPredictOptimizable()}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeUniop{$lhsp.castConst, !nodep->isOpaque(), nodep->isPredictOptimizable()}", "replaceConst(nodep)");
|
||||
TREEOPC("AstNodeQuadop{$lhsp.castConst, $rhsp.castConst, $thsp.castConst, $fhsp.castConst}", "replaceConst(nodep)");
|
||||
// Zero on one side or the other
|
||||
TREEOP ("AstAdd {$lhsp.isZero, $rhsp}", "replaceWRhs(nodep)");
|
||||
|
|
@ -2519,7 +2509,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) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
// Default: Just iterate
|
||||
if (m_required) {
|
||||
if (VN_IS(nodep, NodeDType) || VN_IS(nodep, Range)) {
|
||||
|
|
@ -2537,7 +2527,7 @@ private:
|
|||
|
||||
public:
|
||||
// Processing Mode Enum
|
||||
enum ProcMode {
|
||||
enum ProcMode : uint8_t {
|
||||
PROC_PARAMS,
|
||||
PROC_GENERATE,
|
||||
PROC_LIVE,
|
||||
|
|
@ -2549,21 +2539,6 @@ public:
|
|||
|
||||
// CONSTRUCTORS
|
||||
explicit ConstVisitor(ProcMode pmode) {
|
||||
m_params = false;
|
||||
m_required = false;
|
||||
m_doExpensive = false;
|
||||
m_doNConst = false;
|
||||
m_doShort = true; // Presently always done
|
||||
m_doV = false;
|
||||
m_doGenerate = false; // Inside generate conditionals
|
||||
m_hasJumpDelay = false;
|
||||
m_warn = false;
|
||||
m_wremove = true; // Overridden in visitors
|
||||
m_modp = NULL;
|
||||
m_selp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_attrp = NULL;
|
||||
//
|
||||
// clang-format off
|
||||
switch (pmode) {
|
||||
case PROC_PARAMS: m_doV = true; m_doNConst = true; m_params = true;
|
||||
|
|
@ -2579,7 +2554,7 @@ public:
|
|||
}
|
||||
// clang-format on
|
||||
}
|
||||
virtual ~ConstVisitor() {}
|
||||
virtual ~ConstVisitor() override {}
|
||||
AstNode* mainAcceptEdit(AstNode* nodep) {
|
||||
// Operate starting at a random place
|
||||
return iterateSubtreeReturnEdits(nodep);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include "V3Ast.h"
|
||||
|
||||
#include <map>
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
|
||||
//######################################################################
|
||||
// Coverage state, as a visitor of each AstNode
|
||||
|
|
@ -40,41 +40,37 @@
|
|||
class CoverageVisitor : public AstNVisitor {
|
||||
private:
|
||||
// TYPES
|
||||
typedef vl_unordered_map<string, int> VarNameMap;
|
||||
typedef std::unordered_map<string, int> VarNameMap;
|
||||
typedef std::set<int> LinenoSet;
|
||||
typedef vl_unordered_map<int, LinenoSet> HandleLines;
|
||||
typedef std::unordered_map<int, LinenoSet> HandleLines;
|
||||
|
||||
struct ToggleEnt {
|
||||
string m_comment; // Comment for coverage dump
|
||||
AstNode* m_varRefp; // How to get to this element
|
||||
AstNode* m_chgRefp; // How to get to this element
|
||||
ToggleEnt(const string& comment, AstNode* vp, AstNode* cp)
|
||||
: m_comment(comment)
|
||||
, m_varRefp(vp)
|
||||
, m_chgRefp(cp) {}
|
||||
: m_comment{comment}
|
||||
, m_varRefp{vp}
|
||||
, m_chgRefp{cp} {}
|
||||
~ToggleEnt() {}
|
||||
void cleanup() {
|
||||
VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = NULL);
|
||||
VL_DO_CLEAR(m_chgRefp->deleteTree(), m_chgRefp = NULL);
|
||||
VL_DO_CLEAR(m_varRefp->deleteTree(), m_varRefp = nullptr);
|
||||
VL_DO_CLEAR(m_chgRefp->deleteTree(), m_chgRefp = nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
struct CheckState { // State save-restored on each new coverage scope/block
|
||||
bool m_on; // Should this block get covered?
|
||||
bool m_inModOff; // In module with no coverage
|
||||
int m_handle; // Opaque handle for index into line tracking
|
||||
const AstNode* m_nodep; // Node establishing this state
|
||||
CheckState()
|
||||
: m_on(false)
|
||||
, m_inModOff(false)
|
||||
, m_handle(0)
|
||||
, m_nodep(NULL) {}
|
||||
bool lineCoverageOn(const AstNode* nodep) {
|
||||
bool m_on = false; // Should this block get covered?
|
||||
bool m_inModOff = false; // In module with no coverage
|
||||
int m_handle = 0; // Opaque handle for index into line tracking
|
||||
const AstNode* m_nodep = nullptr; // Node establishing this state
|
||||
CheckState() {}
|
||||
bool lineCoverageOn(const AstNode* nodep) const {
|
||||
return m_on && !m_inModOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageLine();
|
||||
}
|
||||
};
|
||||
int m_nextHandle;
|
||||
int m_nextHandle = 0;
|
||||
|
||||
// NODE STATE
|
||||
// Entire netlist:
|
||||
|
|
@ -83,8 +79,8 @@ private:
|
|||
|
||||
// STATE
|
||||
CheckState m_state; // State save-restored on each new coverage scope/block
|
||||
AstNodeModule* m_modp; // Current module to add statement to
|
||||
bool m_inToggleOff; // In function/task etc
|
||||
AstNodeModule* m_modp = nullptr; // Current module to add statement to
|
||||
bool m_inToggleOff = false; // In function/task etc
|
||||
VarNameMap m_varnames; // Uniquification of inserted variable names
|
||||
string m_beginHier; // AstBegin hier name for user coverage points
|
||||
HandleLines m_handleLines; // All line numbers for a given m_stateHandle
|
||||
|
|
@ -106,7 +102,7 @@ private:
|
|||
}
|
||||
// We allow this, though tracing doesn't
|
||||
// if (nodep->arrayp(1)) return "Unsupported: Multi-dimensional array";
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AstCoverInc* newCoverInc(FileLine* fl, const string& hier, const string& page_prefix,
|
||||
|
|
@ -144,7 +140,7 @@ private:
|
|||
string traceNameForLine(AstNode* nodep, const string& type) {
|
||||
string name = "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__"
|
||||
+ cvtToStr(nodep->fileline()->lineno()) + "_" + type;
|
||||
VarNameMap::iterator it = m_varnames.find(name);
|
||||
const auto it = m_varnames.find(name);
|
||||
if (it == m_varnames.end()) {
|
||||
m_varnames.insert(make_pair(name, 1));
|
||||
} else {
|
||||
|
|
@ -212,9 +208,9 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS - BOTH
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
CheckState lastState = m_state;
|
||||
VL_RESTORER(m_state);
|
||||
{
|
||||
createHandle(nodep);
|
||||
m_modp = nodep;
|
||||
|
|
@ -228,17 +224,16 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
m_state = lastState;
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeProcedure* nodep) VL_OVERRIDE { iterateProcedure(nodep); }
|
||||
virtual void visit(AstWhile* nodep) VL_OVERRIDE { iterateProcedure(nodep); }
|
||||
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeProcedure* nodep) override { iterateProcedure(nodep); }
|
||||
virtual void visit(AstWhile* nodep) override { iterateProcedure(nodep); }
|
||||
virtual void visit(AstNodeFTask* nodep) override {
|
||||
if (!nodep->dpiImport()) iterateProcedure(nodep);
|
||||
}
|
||||
void iterateProcedure(AstNode* nodep) {
|
||||
CheckState lastState = m_state;
|
||||
bool oldtog = m_inToggleOff;
|
||||
VL_RESTORER(m_state);
|
||||
VL_RESTORER(m_inToggleOff);
|
||||
{
|
||||
m_inToggleOff = true;
|
||||
createHandle(nodep);
|
||||
|
|
@ -259,12 +254,10 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
m_state = lastState;
|
||||
m_inToggleOff = oldtog;
|
||||
}
|
||||
|
||||
// VISITORS - TOGGLE COVERAGE
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_modp && !m_inToggleOff && !m_state.m_inModOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageToggle()) {
|
||||
|
|
@ -387,7 +380,7 @@ private:
|
|||
|
||||
// VISITORS - LINE COVERAGE
|
||||
// Note not AstNodeIf; other types don't get covered
|
||||
virtual void visit(AstIf* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstIf* nodep) override {
|
||||
UINFO(4, " IF: " << nodep << endl);
|
||||
if (m_state.m_on) {
|
||||
// An else-if. When we iterate the if, use "elsif" marking
|
||||
|
|
@ -463,12 +456,12 @@ private:
|
|||
}
|
||||
UINFO(9, " done HANDLE " << m_state.m_handle << " for " << nodep << endl);
|
||||
}
|
||||
virtual void visit(AstCaseItem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCaseItem* nodep) override {
|
||||
// We don't add an explicit "default" coverage if not provided,
|
||||
// as we already have a warning when there is no default.
|
||||
UINFO(4, " CASEI: " << nodep << endl);
|
||||
if (m_state.lineCoverageOn(nodep)) {
|
||||
CheckState lastState = m_state;
|
||||
VL_RESTORER(m_state);
|
||||
{
|
||||
createHandle(nodep);
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
|
|
@ -480,12 +473,11 @@ private:
|
|||
traceNameForLine(nodep, "case")));
|
||||
}
|
||||
}
|
||||
m_state = lastState;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCover* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCover* nodep) override {
|
||||
UINFO(4, " COVER: " << nodep << endl);
|
||||
CheckState lastState = m_state;
|
||||
VL_RESTORER(m_state);
|
||||
{
|
||||
m_state.m_on = true; // Always do cover blocks, even if there's a $stop
|
||||
createHandle(nodep);
|
||||
|
|
@ -498,13 +490,12 @@ private:
|
|||
m_beginHier + "_vlCoverageUserTrace"));
|
||||
}
|
||||
}
|
||||
m_state = lastState;
|
||||
}
|
||||
virtual void visit(AstStop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstStop* nodep) override {
|
||||
UINFO(4, " STOP: " << nodep << endl);
|
||||
m_state.m_on = false;
|
||||
}
|
||||
virtual void visit(AstPragma* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstPragma* nodep) override {
|
||||
if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
|
||||
// Skip all NEXT nodes under this block, and skip this if/case branch
|
||||
UINFO(4, " OFF: h" << m_state.m_handle << " " << nodep << endl);
|
||||
|
|
@ -515,14 +506,14 @@ private:
|
|||
lineTrack(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstBegin* nodep) 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.
|
||||
// (Currently ignored for line coverage, since any generate iteration
|
||||
// covers the code in that line.)
|
||||
string oldHier = m_beginHier;
|
||||
bool oldtog = m_inToggleOff;
|
||||
VL_RESTORER(m_beginHier);
|
||||
VL_RESTORER(m_inToggleOff);
|
||||
{
|
||||
m_inToggleOff = true;
|
||||
if (nodep->name() != "") {
|
||||
|
|
@ -531,27 +522,18 @@ private:
|
|||
iterateChildren(nodep);
|
||||
lineTrack(nodep);
|
||||
}
|
||||
m_beginHier = oldHier;
|
||||
m_inToggleOff = oldtog;
|
||||
}
|
||||
|
||||
// VISITORS - BOTH
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
lineTrack(nodep);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CoverageVisitor(AstNetlist* rootp) {
|
||||
// Operate on all modules
|
||||
m_nextHandle = 0;
|
||||
m_modp = NULL;
|
||||
m_beginHier = "";
|
||||
m_inToggleOff = false;
|
||||
iterateChildren(rootp);
|
||||
}
|
||||
virtual ~CoverageVisitor() {}
|
||||
explicit CoverageVisitor(AstNetlist* rootp) { iterateChildren(rootp); }
|
||||
virtual ~CoverageVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -54,20 +54,16 @@ private:
|
|||
// Note uses user4
|
||||
V3Hashed hashed; // Duplicate code detection
|
||||
// Hash all of the original signals we toggle cover
|
||||
for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
|
||||
AstCoverToggle* nodep = *it;
|
||||
hashed.hashAndInsert(nodep->origp());
|
||||
}
|
||||
for (AstCoverToggle* nodep : m_toggleps) hashed.hashAndInsert(nodep->origp());
|
||||
// Find if there are any duplicates
|
||||
for (ToggleList::iterator it = m_toggleps.begin(); it != m_toggleps.end(); ++it) {
|
||||
AstCoverToggle* nodep = *it;
|
||||
for (AstCoverToggle* nodep : m_toggleps) {
|
||||
// nodep->backp() is null if we already detected it's a duplicate and unlinked it.
|
||||
if (nodep->backp()) {
|
||||
// Want to choose a base node, and keep finding duplicates that are identical.
|
||||
// This prevents making chains where a->b, then c->d, then b->c, as we'll
|
||||
// find a->b, a->c, a->d directly.
|
||||
while (true) {
|
||||
V3Hashed::iterator dupit = hashed.findDuplicate(nodep->origp());
|
||||
const auto dupit = hashed.findDuplicate(nodep->origp());
|
||||
if (dupit == hashed.end()) break;
|
||||
//
|
||||
AstNode* duporigp = hashed.iteratorNodep(dupit);
|
||||
|
|
@ -97,24 +93,24 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
// Find all Coverage's
|
||||
iterateChildren(nodep);
|
||||
// Simplify
|
||||
detectDuplicates();
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCoverToggle* nodep) override {
|
||||
m_toggleps.push_back(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CoverageJoinVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~CoverageJoinVisitor() {
|
||||
virtual ~CoverageJoinVisitor() override {
|
||||
V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -52,18 +52,18 @@ private:
|
|||
// NODE STATE
|
||||
// ** Shared with DeadVisitor **
|
||||
// VISITORS
|
||||
virtual void visit(AstCell* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->modp()->user1Inc(-1);
|
||||
}
|
||||
//-----
|
||||
virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DeadModVisitor(AstNodeModule* nodep) { iterate(nodep); }
|
||||
virtual ~DeadModVisitor() {}
|
||||
virtual ~DeadModVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -119,8 +119,8 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
if (!nodep->dead()) {
|
||||
|
|
@ -135,14 +135,13 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->aboveScopep()) nodep->aboveScopep()->user1Inc();
|
||||
|
|
@ -153,14 +152,14 @@ private:
|
|||
m_scopesp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
m_cellsp.push_back(nodep);
|
||||
nodep->modp()->user1Inc();
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->varScopep()) {
|
||||
|
|
@ -170,28 +169,28 @@ private:
|
|||
if (nodep->varp()) nodep->varp()->user1Inc();
|
||||
if (nodep->packagep()) {
|
||||
if (m_elimCells) {
|
||||
nodep->packagep(NULL);
|
||||
nodep->packagep(nullptr);
|
||||
} else {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeFTaskRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
if (m_elimCells) {
|
||||
nodep->packagep(NULL);
|
||||
nodep->packagep(nullptr);
|
||||
} else {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstMethodCall* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstMethodCall* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstRefDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstRefDType* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
|
|
@ -199,49 +198,49 @@ private:
|
|||
"RefDType should point to data type before typedefs removed");
|
||||
if (nodep->packagep()) {
|
||||
if (m_elimCells) {
|
||||
nodep->packagep(NULL);
|
||||
nodep->packagep(nullptr);
|
||||
} else {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstClassRefDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstClassRefDType* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
if (m_elimCells) {
|
||||
nodep->packagep(NULL);
|
||||
nodep->packagep(nullptr);
|
||||
} else {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
if (nodep->classp()) nodep->classp()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeDType* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstEnumItemRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->packagep()) {
|
||||
if (m_elimCells) {
|
||||
nodep->packagep(NULL);
|
||||
nodep->packagep(nullptr);
|
||||
} else {
|
||||
nodep->packagep()->user1Inc();
|
||||
}
|
||||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstMemberSel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstMemberSel* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (nodep->varp()) nodep->varp()->user1Inc();
|
||||
if (nodep->fromp()->dtypep()) nodep->fromp()->dtypep()->user1Inc(); // classref
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstModport* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstModport* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_elimCells) {
|
||||
if (!nodep->varsp()) {
|
||||
|
|
@ -251,7 +250,7 @@ private:
|
|||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTypedef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_elimCells && !nodep->attrPublic()) {
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
|
|
@ -262,19 +261,19 @@ 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) VL_OVERRIDE {
|
||||
virtual void visit(AstVarScope* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||
if (mightElimVar(nodep->varp())) m_vscsp.push_back(nodep);
|
||||
}
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->isSigPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc();
|
||||
if (mightElimVar(nodep)) m_varsp.push_back(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
// See if simple assignments to variables may be eliminated because
|
||||
// that variable is never used.
|
||||
// Similar code in V3Life
|
||||
|
|
@ -294,7 +293,7 @@ private:
|
|||
}
|
||||
|
||||
//-----
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
if (nodep->isOutputter()) m_sideEffect = true;
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
|
|
@ -329,7 +328,12 @@ private:
|
|||
if (nodep->isSigPublic()) return false; // Can't elim publics!
|
||||
if (nodep->isIO() || nodep->isClassMember()) return false;
|
||||
if (nodep->isTemp() && !nodep->isTrace()) return true;
|
||||
if (nodep->isParam() && !nodep->isTrace() && !v3Global.opt.xmlOnly()) return true;
|
||||
if (nodep->isParam()) {
|
||||
const bool overriddenForHierBlock
|
||||
= m_modp && m_modp->hierBlock() && nodep->overriddenParam();
|
||||
if (!nodep->isTrace() && !overriddenForHierBlock && !v3Global.opt.xmlOnly())
|
||||
return true;
|
||||
}
|
||||
return m_elimUserVars; // Post-Trace can kill most anything
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +349,7 @@ private:
|
|||
scp->aboveScopep()->user1Inc(-1);
|
||||
if (scp->dtypep()) scp->dtypep()->user1Inc(-1);
|
||||
VL_DO_DANGLING(scp->unlinkFrBack()->deleteTree(), scp);
|
||||
*it = NULL;
|
||||
*it = nullptr;
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -353,8 +357,7 @@ private:
|
|||
}
|
||||
|
||||
void deadCheckCells() {
|
||||
for (std::vector<AstCell*>::iterator it = m_cellsp.begin(); it != m_cellsp.end(); ++it) {
|
||||
AstCell* cellp = *it;
|
||||
for (AstCell* cellp : m_cellsp) {
|
||||
if (cellp->user1() == 0 && !cellp->modp()->stmtsp()) {
|
||||
cellp->modp()->user1Inc(-1);
|
||||
VL_DO_DANGLING(cellp->unlinkFrBack()->deleteTree(), cellp);
|
||||
|
|
@ -366,12 +369,12 @@ private:
|
|||
retry = false;
|
||||
for (std::vector<AstClass*>::iterator it = m_classesp.begin(); it != m_classesp.end();
|
||||
++it) {
|
||||
if (AstClass* nodep = *it) { // NULL if deleted earlier
|
||||
if (AstClass* nodep = *it) { // nullptr if deleted earlier
|
||||
if (nodep->user1() == 0) {
|
||||
if (nodep->extendsp()) nodep->extendsp()->user1Inc(-1);
|
||||
if (nodep->packagep()) nodep->packagep()->user1Inc(-1);
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
*it = NULL;
|
||||
*it = nullptr;
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -381,8 +384,7 @@ private:
|
|||
|
||||
void deadCheckVar() {
|
||||
// Delete any unused varscopes
|
||||
for (std::vector<AstVarScope*>::iterator it = m_vscsp.begin(); it != m_vscsp.end(); ++it) {
|
||||
AstVarScope* vscp = *it;
|
||||
for (AstVarScope* vscp : m_vscsp) {
|
||||
if (vscp->user1() == 0) {
|
||||
UINFO(4, " Dead " << vscp << endl);
|
||||
std::pair<AssignMap::iterator, AssignMap::iterator> eqrange
|
||||
|
|
@ -407,7 +409,7 @@ private:
|
|||
UINFO(4, " Dead " << varp << endl);
|
||||
if (varp->dtypep()) varp->dtypep()->user1Inc(-1);
|
||||
VL_DO_DANGLING(varp->unlinkFrBack()->deleteTree(), varp);
|
||||
*it = NULL;
|
||||
*it = nullptr;
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -438,7 +440,7 @@ public:
|
|||
// CONSTRUCTORS
|
||||
DeadVisitor(AstNetlist* nodep, bool elimUserVars, bool elimDTypes, bool elimScopes,
|
||||
bool elimCells) {
|
||||
m_modp = NULL;
|
||||
m_modp = nullptr;
|
||||
m_elimCells = elimCells;
|
||||
m_elimUserVars = elimUserVars;
|
||||
m_elimDTypes = elimDTypes;
|
||||
|
|
@ -460,7 +462,7 @@ public:
|
|||
// We may have removed some datatypes, cleanup
|
||||
nodep->typeTablep()->repairCache();
|
||||
}
|
||||
virtual ~DeadVisitor() {}
|
||||
virtual ~DeadVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -86,15 +86,15 @@ private:
|
|||
AstUser4InUse m_inuser4;
|
||||
AstUser5InUse m_inuser5;
|
||||
|
||||
enum VarUsage { VU_NONE = 0, VU_DLY = 1, VU_NONDLY = 2 };
|
||||
enum VarUsage : uint8_t { VU_NONE = 0, VU_DLY = 1, VU_NONDLY = 2 };
|
||||
|
||||
// STATE
|
||||
AstActive* m_activep; // Current activate
|
||||
AstCFunc* m_cfuncp; // Current public C Function
|
||||
AstAssignDly* m_nextDlyp; // Next delayed assignment in a list of assignments
|
||||
bool m_inDly; // True in delayed assignments
|
||||
bool m_inLoop; // True in for loops
|
||||
bool m_inInitial; // True in initial blocks
|
||||
AstActive* m_activep = nullptr; // Current activate
|
||||
AstCFunc* m_cfuncp = nullptr; // Current public C Function
|
||||
AstAssignDly* m_nextDlyp = nullptr; // Next delayed assignment in a list of assignments
|
||||
bool m_inDly = false; // True in delayed assignments
|
||||
bool m_inLoop = false; // True in for loops
|
||||
bool m_inInitial = false; // True in initial blocks
|
||||
typedef std::map<std::pair<AstNodeModule*, string>, AstVar*> VarMap;
|
||||
VarMap m_modVarMap; // Table of new var names created under module
|
||||
VDouble0 m_statSharedSet; // Statistic tracking
|
||||
|
|
@ -120,7 +120,7 @@ private:
|
|||
AstVar* varp;
|
||||
AstNodeModule* addmodp = oldvarscp->scopep()->modp();
|
||||
// We need a new AstVar, but only one for all scopes, to match the new AstVarScope
|
||||
VarMap::iterator it = m_modVarMap.find(make_pair(addmodp, name));
|
||||
const auto it = m_modVarMap.find(make_pair(addmodp, name));
|
||||
if (it != m_modVarMap.end()) {
|
||||
// Created module's AstVar earlier under some other scope
|
||||
varp = it->second;
|
||||
|
|
@ -189,9 +189,9 @@ private:
|
|||
// See top of this file for transformation
|
||||
// Return the new LHS for the assignment, Null = unlink
|
||||
// Find selects
|
||||
AstNode* newlhsp = NULL; // NULL = unlink old assign
|
||||
AstSel* bitselp = NULL;
|
||||
AstArraySel* arrayselp = NULL;
|
||||
AstNode* newlhsp = nullptr; // nullptr = unlink old assign
|
||||
AstSel* bitselp = nullptr;
|
||||
AstArraySel* arrayselp = nullptr;
|
||||
if (VN_IS(lhsp, Sel)) {
|
||||
bitselp = VN_CAST(lhsp, Sel);
|
||||
arrayselp = VN_CAST(bitselp->fromp(), ArraySel);
|
||||
|
|
@ -226,7 +226,7 @@ private:
|
|||
string bitvarname = (string("__Vdlyvdim") + cvtToStr(dimension) + "__"
|
||||
+ oldvarp->shortName() + "__v" + cvtToStr(modVecNum));
|
||||
AstVarScope* bitvscp
|
||||
= createVarSc(varrefp->varScopep(), bitvarname, dimp->width(), NULL);
|
||||
= createVarSc(varrefp->varScopep(), bitvarname, dimp->width(), nullptr);
|
||||
AstAssign* bitassignp = new AstAssign(
|
||||
nodep->fileline(), new AstVarRef(nodep->fileline(), bitvscp, true), dimp);
|
||||
nodep->addNextHere(bitassignp);
|
||||
|
|
@ -235,7 +235,7 @@ private:
|
|||
}
|
||||
//
|
||||
//=== Bitselect: __Vdlyvlsb__
|
||||
AstNode* bitreadp = NULL; // Code to read Vdlyvlsb
|
||||
AstNode* bitreadp = nullptr; // Code to read Vdlyvlsb
|
||||
if (bitselp) {
|
||||
AstNode* lsbvaluep = bitselp->lsbp()->unlinkFrBack();
|
||||
if (VN_IS(bitselp->fromp(), Const)) {
|
||||
|
|
@ -245,7 +245,7 @@ private:
|
|||
string bitvarname = (string("__Vdlyvlsb__") + oldvarp->shortName() + "__v"
|
||||
+ cvtToStr(modVecNum));
|
||||
AstVarScope* bitvscp
|
||||
= createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width(), NULL);
|
||||
= createVarSc(varrefp->varScopep(), bitvarname, lsbvaluep->width(), nullptr);
|
||||
AstAssign* bitassignp = new AstAssign(
|
||||
nodep->fileline(), new AstVarRef(nodep->fileline(), bitvscp, true), lsbvaluep);
|
||||
nodep->addNextHere(bitassignp);
|
||||
|
|
@ -269,7 +269,7 @@ private:
|
|||
//
|
||||
//=== Setting/not setting boolean: __Vdlyvset__
|
||||
AstVarScope* setvscp;
|
||||
AstAssignPre* setinitp = NULL;
|
||||
AstAssignPre* setinitp = nullptr;
|
||||
|
||||
if (nodep->user3p()) {
|
||||
// Simplistic optimization. If the previous statement in same scope was also a =>,
|
||||
|
|
@ -281,7 +281,7 @@ private:
|
|||
} else { // Create new one
|
||||
string setvarname
|
||||
= (string("__Vdlyvset__") + oldvarp->shortName() + "__v" + cvtToStr(modVecNum));
|
||||
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1, NULL);
|
||||
setvscp = createVarSc(varrefp->varScopep(), setvarname, 1, nullptr);
|
||||
setinitp = new AstAssignPre(nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), setvscp, true),
|
||||
new AstConst(nodep->fileline(), 0));
|
||||
|
|
@ -316,7 +316,7 @@ private:
|
|||
checkActivePost(varrefp, oldactivep);
|
||||
if (setinitp) oldactivep->addStmtsp(setinitp);
|
||||
} else { // first time we've dealt with this memory
|
||||
finalp = new AstAlwaysPost(nodep->fileline(), NULL /*sens*/, NULL /*body*/);
|
||||
finalp = new AstAlwaysPost(nodep->fileline(), nullptr /*sens*/, nullptr /*body*/);
|
||||
UINFO(9, " Created " << finalp << endl);
|
||||
AstActive* newactp = createActivePost(varrefp);
|
||||
newactp->addStmtsp(finalp);
|
||||
|
|
@ -332,8 +332,9 @@ private:
|
|||
UASSERT_OBJ(postLogicp, nodep,
|
||||
"Delayed assignment misoptimized; prev var found w/o associated IF");
|
||||
} else {
|
||||
postLogicp = new AstIf(nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), setvscp, false), NULL, NULL);
|
||||
postLogicp
|
||||
= new AstIf(nodep->fileline(), new AstVarRef(nodep->fileline(), setvscp, false),
|
||||
nullptr, nullptr);
|
||||
UINFO(9, " Created " << postLogicp << endl);
|
||||
finalp->addBodysp(postLogicp);
|
||||
finalp->user3p(setvscp); // Remember IF's vset variable
|
||||
|
|
@ -344,34 +345,35 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
// VV***** We reset all userp() on the netlist
|
||||
m_modVarMap.clear();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
AstNode::user3ClearTree();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
m_cfuncp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_cfuncp = NULL;
|
||||
m_cfuncp = nullptr;
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
m_activep = nodep;
|
||||
bool oldinit = m_inInitial;
|
||||
m_inInitial = nodep->hasInitial();
|
||||
AstNode::user3ClearTree(); // Two sets to same variable in different
|
||||
// actives must use different vars.
|
||||
iterateChildren(nodep);
|
||||
m_inInitial = oldinit;
|
||||
VL_RESTORER(m_inInitial);
|
||||
{
|
||||
m_inInitial = nodep->hasInitial();
|
||||
// Two sets to same variable in different actives must use different vars.
|
||||
AstNode::user3ClearTree();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignDly* nodep) override {
|
||||
m_inDly = true;
|
||||
m_nextDlyp
|
||||
= VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe NULL.
|
||||
= VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe nullptr.
|
||||
if (m_cfuncp) {
|
||||
nodep->v3warn(E_UNSUPPORTED,
|
||||
"Unsupported: Delayed assignment inside public function/task");
|
||||
|
|
@ -399,10 +401,10 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
m_inDly = false;
|
||||
m_nextDlyp = NULL;
|
||||
m_nextDlyp = nullptr;
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
if (!nodep->user2Inc()) { // Not done yet
|
||||
if (m_inDly && nodep->lvalue()) {
|
||||
UINFO(4, "AssignDlyVar: " << nodep << endl);
|
||||
|
|
@ -421,7 +423,7 @@ private:
|
|||
}
|
||||
if (!dlyvscp) { // First use of this delayed variable
|
||||
string newvarname = (string("__Vdly__") + nodep->varp()->shortName());
|
||||
dlyvscp = createVarSc(oldvscp, newvarname, 0, NULL);
|
||||
dlyvscp = createVarSc(oldvscp, newvarname, 0, nullptr);
|
||||
AstNodeAssign* prep;
|
||||
AstBasicDType* basicp = oldvscp->dtypep()->basicp();
|
||||
if (basicp && basicp->isEventValue()) {
|
||||
|
|
@ -459,33 +461,25 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeFor* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
||||
virtual void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc(
|
||||
"For statements should have been converted to while statements in V3Begin");
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
||||
bool oldloop = m_inLoop;
|
||||
m_inLoop = true;
|
||||
iterateChildren(nodep);
|
||||
m_inLoop = oldloop;
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
VL_RESTORER(m_inLoop);
|
||||
{
|
||||
m_inLoop = true;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DelayedVisitor(AstNetlist* nodep) {
|
||||
m_inDly = false;
|
||||
m_activep = NULL;
|
||||
m_cfuncp = NULL;
|
||||
m_nextDlyp = NULL;
|
||||
m_inLoop = false;
|
||||
m_inInitial = false;
|
||||
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~DelayedVisitor() {
|
||||
explicit DelayedVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~DelayedVisitor() override {
|
||||
V3Stats::addStat("Optimizations, Delayed shared-sets", m_statSharedSet);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ private:
|
|||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp; // Current block
|
||||
AstNode* m_stmtp; // Current statement
|
||||
int m_depth; // How deep in an expression
|
||||
int m_maxdepth; // Maximum depth in an expression
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstCFunc* m_funcp = nullptr; // Current block
|
||||
AstNode* m_stmtp = nullptr; // Current statement
|
||||
int m_depth = 0; // How deep in an expression
|
||||
int m_maxdepth = 0; // Maximum depth in an expression
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -76,31 +76,30 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
AstNodeModule* origModp = m_modp;
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_funcp = NULL;
|
||||
m_funcp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
m_funcp = nodep;
|
||||
m_depth = 0;
|
||||
m_maxdepth = 0;
|
||||
iterateChildren(nodep);
|
||||
m_funcp = NULL;
|
||||
m_funcp = nullptr;
|
||||
}
|
||||
void visitStmt(AstNodeStmt* nodep) {
|
||||
m_depth = 0;
|
||||
m_maxdepth = 0;
|
||||
m_stmtp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_stmtp = NULL;
|
||||
m_stmtp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeStmt* nodep) override {
|
||||
if (!nodep->isStatement()) {
|
||||
iterateChildren(nodep);
|
||||
} else {
|
||||
|
|
@ -108,8 +107,8 @@ private:
|
|||
}
|
||||
}
|
||||
// Operators
|
||||
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {}
|
||||
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeTermop* nodep) override {}
|
||||
virtual void visit(AstNodeMath* nodep) 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,32 +134,24 @@ private:
|
|||
m_funcp->isStatic(false);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstUCFunc* nodep) override {
|
||||
needNonStaticFunc(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstUCStmt* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstUCStmt* nodep) override {
|
||||
needNonStaticFunc(nodep);
|
||||
visitStmt(nodep);
|
||||
}
|
||||
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DepthVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
m_funcp = NULL;
|
||||
m_stmtp = NULL;
|
||||
m_depth = 0;
|
||||
m_maxdepth = 0;
|
||||
//
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~DepthVisitor() {}
|
||||
explicit DepthVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~DepthVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -37,10 +37,10 @@ private:
|
|||
// NODE STATE
|
||||
|
||||
// STATE
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp; // Current function
|
||||
int m_depth; // How deep in an expression
|
||||
int m_deepNum; // How many functions made
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstCFunc* m_funcp = nullptr; // Current function
|
||||
int m_depth = 0; // How deep in an expression
|
||||
int m_deepNum = 0; // How many functions made
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -50,7 +50,7 @@ private:
|
|||
nodep->unlinkFrBack(&relinkHandle);
|
||||
// Create function
|
||||
string name = m_funcp->name() + "__deep" + cvtToStr(++m_deepNum);
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, NULL);
|
||||
AstCFunc* funcp = new AstCFunc(nodep->fileline(), name, nullptr);
|
||||
funcp->argTypes(EmitCBaseVisitor::symClassVar());
|
||||
funcp->symProlog(true);
|
||||
funcp->slow(m_funcp->slow());
|
||||
|
|
@ -66,27 +66,24 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
AstNodeModule* origModp = m_modp;
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_deepNum = 0;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
// We recurse into this.
|
||||
int lastDepth = m_depth;
|
||||
AstCFunc* lastFuncp = m_funcp;
|
||||
VL_RESTORER(m_depth);
|
||||
VL_RESTORER(m_funcp);
|
||||
{
|
||||
m_depth = 0;
|
||||
m_funcp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_depth = lastDepth;
|
||||
m_funcp = lastFuncp;
|
||||
}
|
||||
void visitStmt(AstNodeStmt* nodep) {
|
||||
m_depth++;
|
||||
|
|
@ -104,7 +101,7 @@ private:
|
|||
}
|
||||
m_depth--;
|
||||
}
|
||||
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeStmt* nodep) override {
|
||||
if (!nodep->isStatement()) {
|
||||
iterateChildren(nodep);
|
||||
} else {
|
||||
|
|
@ -112,22 +109,15 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
//--------------------
|
||||
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DepthBlockVisitor(AstNetlist* nodep) {
|
||||
m_modp = NULL;
|
||||
m_funcp = NULL;
|
||||
m_depth = 0;
|
||||
m_deepNum = 0;
|
||||
//
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~DepthBlockVisitor() {}
|
||||
explicit DepthBlockVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~DepthBlockVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ private:
|
|||
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
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstScope* m_scopep = nullptr; // Current scope
|
||||
bool m_modSingleton = false; // m_modp is only instanced once
|
||||
bool m_allowThis = false; // Allow function non-static
|
||||
bool m_needThis = false; // Make function non-static
|
||||
FuncMmap m_modFuncs; // Name of public functions added
|
||||
|
||||
// METHODS
|
||||
|
|
@ -76,7 +76,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 = nullptr) {
|
||||
UASSERT(scopep, "Var/Func not scoped");
|
||||
hierThisr = (scopep == m_scopep);
|
||||
|
||||
|
|
@ -148,7 +148,7 @@ private:
|
|||
for (FuncMmap::iterator it = m_modFuncs.begin(); it != m_modFuncs.end(); ++it) {
|
||||
string name = it->first;
|
||||
AstCFunc* topFuncp = it->second;
|
||||
FuncMmap::iterator nextIt1 = it;
|
||||
auto nextIt1 = it;
|
||||
++nextIt1;
|
||||
bool moreOfSame1 = (nextIt1 != m_modFuncs.end() && nextIt1->first == name);
|
||||
if (moreOfSame1) {
|
||||
|
|
@ -171,7 +171,7 @@ private:
|
|||
eachIt != m_modFuncs.end() && eachIt->first == name; ++eachIt) {
|
||||
it = eachIt;
|
||||
AstCFunc* funcp = eachIt->second;
|
||||
FuncMmap::iterator nextIt2 = eachIt;
|
||||
auto nextIt2 = eachIt;
|
||||
++nextIt2;
|
||||
bool moreOfSame = (nextIt2 != m_modFuncs.end() && nextIt2->first == name);
|
||||
UASSERT_OBJ(funcp->scopep(), funcp, "Not scoped");
|
||||
|
|
@ -180,7 +180,7 @@ private:
|
|||
UINFO(6,
|
||||
" at " << newfuncp->argTypes() << " und " << funcp->argTypes() << endl);
|
||||
funcp->declPrivate(true);
|
||||
AstNode* argsp = NULL;
|
||||
AstNode* argsp = nullptr;
|
||||
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (AstVar* portp = VN_CAST(stmtp, Var)) {
|
||||
if (portp->isIO() && !portp->isFuncReturn()) {
|
||||
|
|
@ -202,7 +202,7 @@ private:
|
|||
new AstCMath(funcp->fileline(),
|
||||
string("&(") + funcp->scopep()->nameVlSym() + ")",
|
||||
64)),
|
||||
returnp, NULL);
|
||||
returnp, nullptr);
|
||||
newfuncp->addStmtsp(ifp);
|
||||
} else {
|
||||
newfuncp->addStmtsp(returnp);
|
||||
|
|
@ -213,7 +213,7 @@ private:
|
|||
// newfuncp->addStmtsp(new AstDisplay(newfuncp->fileline(),
|
||||
// AstDisplayType::DT_WARNING,
|
||||
// string("%%Error: ")+name+"() called with bad
|
||||
// scope", NULL));
|
||||
// scope", nullptr));
|
||||
// newfuncp->addStmtsp(new AstStop(newfuncp->fileline()));
|
||||
if (debug() >= 9) newfuncp->dumpTree(cout, " newfunc: ");
|
||||
} else {
|
||||
|
|
@ -225,8 +225,8 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_modFuncs.clear();
|
||||
|
|
@ -234,19 +234,18 @@ private:
|
|||
iterateChildren(nodep);
|
||||
makePublicFuncWrappers();
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
m_scopep = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_scopep = NULL;
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarScope* nodep) override {
|
||||
// Delete the varscope when we're finished
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Convert the hierch name
|
||||
UASSERT_OBJ(m_scopep, nodep, "Node not under scope");
|
||||
|
|
@ -254,9 +253,9 @@ private:
|
|||
nodep->hiername(descopedName(nodep->varScopep()->scopep(), hierThis /*ref*/,
|
||||
nodep->varScopep()->varp()));
|
||||
nodep->hierThis(hierThis);
|
||||
nodep->varScopep(NULL);
|
||||
nodep->varScopep(nullptr);
|
||||
}
|
||||
virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCCall* nodep) override {
|
||||
// UINFO(9, " " << nodep << endl);
|
||||
iterateChildren(nodep);
|
||||
// Convert the hierch name
|
||||
|
|
@ -265,9 +264,9 @@ private:
|
|||
bool hierThis;
|
||||
nodep->hiername(descopedName(nodep->funcp()->scopep(), hierThis /*ref*/));
|
||||
// Can't do this, as we may have more calls later
|
||||
// nodep->funcp()->scopep(NULL);
|
||||
// nodep->funcp()->scopep(nullptr);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
if (!nodep->user1()) {
|
||||
m_needThis = false;
|
||||
m_allowThis = nodep->isStatic().falseUnknown(); // Non-static or unknown if static
|
||||
|
|
@ -288,20 +287,13 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVar*) VL_OVERRIDE {}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstVar*) override {}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DescopeVisitor(AstNetlist* nodep)
|
||||
: m_modp(NULL)
|
||||
, m_scopep(NULL)
|
||||
, m_modSingleton(false)
|
||||
, m_allowThis(false)
|
||||
, m_needThis(false) {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~DescopeVisitor() {}
|
||||
explicit DescopeVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~DescopeVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
381
src/V3EmitC.cpp
381
src/V3EmitC.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -33,8 +33,8 @@
|
|||
class EmitCBaseVisitor : public AstNVisitor {
|
||||
public:
|
||||
// STATE
|
||||
V3OutCFile* m_ofp;
|
||||
bool m_trackText; // Always track AstText nodes
|
||||
V3OutCFile* m_ofp = nullptr;
|
||||
bool m_trackText = false; // Always track AstText nodes
|
||||
// METHODS
|
||||
V3OutCFile* ofp() const { return m_ofp; }
|
||||
void puts(const string& str) { ofp()->puts(str); }
|
||||
|
|
@ -106,11 +106,8 @@ public:
|
|||
}
|
||||
|
||||
// CONSTRUCTORS
|
||||
EmitCBaseVisitor() {
|
||||
m_ofp = NULL;
|
||||
m_trackText = false;
|
||||
}
|
||||
virtual ~EmitCBaseVisitor() {}
|
||||
EmitCBaseVisitor() {}
|
||||
virtual ~EmitCBaseVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -119,20 +116,17 @@ public:
|
|||
class EmitCBaseCounterVisitor : public AstNVisitor {
|
||||
private:
|
||||
// MEMBERS
|
||||
int m_count; // Number of statements
|
||||
int m_count = 0; // Number of statements
|
||||
// VISITORS
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
m_count++;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit EmitCBaseCounterVisitor(AstNode* nodep) {
|
||||
m_count = 0;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~EmitCBaseCounterVisitor() {}
|
||||
explicit EmitCBaseCounterVisitor(AstNode* nodep) { iterate(nodep); }
|
||||
virtual ~EmitCBaseCounterVisitor() override {}
|
||||
int count() const { return m_count; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,25 +35,24 @@ class EmitCInlines : EmitCBaseVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstClass* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstClass* nodep) override {
|
||||
checkHeavy(nodep);
|
||||
v3Global.needC11(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCNew* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCNew* nodep) override {
|
||||
checkHeavy(nodep);
|
||||
if (v3Global.opt.savable())
|
||||
v3warn(E_UNSUPPORTED, "Unsupported: --savable with dynamic new");
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstDumpCtl* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstDumpCtl* nodep) override {
|
||||
checkHeavy(nodep);
|
||||
if (v3Global.opt.trace()) v3Global.needTraceDumper(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
checkHeavy(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,11 @@ class EmitCMain : EmitCBaseVisitor {
|
|||
|
||||
// VISITORS
|
||||
// This visitor doesn't really iterate, but exist to appease base class
|
||||
virtual void visit(AstNode* nodep) { iterateChildren(nodep); } // LCOV_EXCL_LINE
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } // LCOV_EXCL_LINE
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit EmitCMain(AstNetlist* nodep) { emitInt(); }
|
||||
explicit EmitCMain(AstNetlist*) { emitInt(); }
|
||||
|
||||
private:
|
||||
// MAIN METHOD
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "V3Os.h"
|
||||
#include "V3EmitCMake.h"
|
||||
#include "V3EmitCBase.h"
|
||||
#include "V3HierBlock.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -39,11 +40,11 @@ class CMakeEmitter {
|
|||
string s;
|
||||
if (strs.begin() != strs.end()) {
|
||||
s.append("\"");
|
||||
s.append(*strs.begin());
|
||||
s.append(VString::quoteAny(*strs.begin(), '"', '\\'));
|
||||
s.append("\"");
|
||||
for (typename List::const_iterator it = ++strs.begin(); it != strs.end(); ++it) {
|
||||
s.append(" \"");
|
||||
s.append(*it);
|
||||
s.append(VString::quoteAny(*it, '"', '\\'));
|
||||
s.append("\"");
|
||||
}
|
||||
}
|
||||
|
|
@ -77,7 +78,7 @@ class CMakeEmitter {
|
|||
}
|
||||
|
||||
static void emitOverallCMake() {
|
||||
const vl_unique_ptr<std::ofstream> of(
|
||||
const std::unique_ptr<std::ofstream> of(
|
||||
V3File::new_ofstream(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + ".cmake"));
|
||||
string name = v3Global.opt.prefix();
|
||||
|
||||
|
|
@ -124,7 +125,11 @@ class CMakeEmitter {
|
|||
: "0");
|
||||
|
||||
*of << "\n### Sources...\n";
|
||||
std::vector<string> classes_fast, classes_slow, support_fast, support_slow, global;
|
||||
std::vector<string> classes_fast;
|
||||
std::vector<string> classes_slow;
|
||||
std::vector<string> support_fast;
|
||||
std::vector<string> support_slow;
|
||||
std::vector<string> global;
|
||||
for (AstNodeFile* nodep = v3Global.rootp()->filesp(); nodep;
|
||||
nodep = VN_CAST(nodep->nextp(), NodeFile)) {
|
||||
AstCFile* cfilep = VN_CAST(nodep, CFile);
|
||||
|
|
@ -195,6 +200,55 @@ class CMakeEmitter {
|
|||
|
||||
*of << "# User .cpp files (from .cpp's on Verilator command line)\n";
|
||||
cmake_set_raw(*of, name + "_USER_CLASSES", deslash(cmake_list(v3Global.opt.cppFiles())));
|
||||
if (const V3HierBlockPlan* planp = v3Global.hierPlanp()) {
|
||||
*of << "# Verilate hierarchical blocks\n";
|
||||
// Sorted hierarchical blocks in order of leaf-first.
|
||||
const V3HierBlockPlan::HierVector& hierBlocks = planp->hierBlocksSorted();
|
||||
const string topTarget = v3Global.opt.protectLib().empty() ? v3Global.opt.prefix()
|
||||
: v3Global.opt.protectLib();
|
||||
for (V3HierBlockPlan::HierVector::const_iterator it = hierBlocks.begin();
|
||||
it != hierBlocks.end(); ++it) {
|
||||
const V3HierBlock* hblockp = *it;
|
||||
const V3HierBlock::HierBlockSet& children = hblockp->children();
|
||||
const string prefix = hblockp->hierPrefix();
|
||||
*of << "add_library(" << prefix << " STATIC)\n";
|
||||
*of << "target_link_libraries(" << topTarget << " PRIVATE " << prefix << ")\n";
|
||||
if (!children.empty()) {
|
||||
*of << "target_link_libraries(" << prefix << " INTERFACE";
|
||||
for (V3HierBlock::HierBlockSet::const_iterator child = children.begin();
|
||||
child != children.end(); ++child) {
|
||||
*of << " " << (*child)->hierPrefix();
|
||||
}
|
||||
*of << ")\n";
|
||||
}
|
||||
*of << "verilate(" << prefix << " PREFIX " << prefix << " TOP_MODULE "
|
||||
<< hblockp->modp()->name() << " DIRECTORY "
|
||||
<< deslash("${CMAKE_CURRENT_BINARY_DIR}/" + prefix) << " SOURCES ";
|
||||
for (V3HierBlock::HierBlockSet::const_iterator child = children.begin();
|
||||
child != children.end(); ++child) {
|
||||
*of << deslash(" ${CMAKE_CURRENT_BINARY_DIR}/" + (*child)->hierWrapper(true));
|
||||
}
|
||||
*of << " ";
|
||||
const V3StringList& vFiles = v3Global.opt.vFiles();
|
||||
for (const string& i : vFiles) *of << V3Os::filenameRealPath(i);
|
||||
*of << " VERILATOR_ARGS ";
|
||||
*of << "-f " << deslash(hblockp->commandArgsFileName(true))
|
||||
<< " -CFLAGS -fPIC" // hierarchical block will be static, but may be linked
|
||||
// with .so
|
||||
<< ")\n";
|
||||
}
|
||||
*of << "\n# Verilate the top module that refers protect-lib wrappers of above\n";
|
||||
*of << "verilate(" << topTarget << " PREFIX " << v3Global.opt.prefix()
|
||||
<< " TOP_MODULE " << v3Global.rootp()->topModulep()->name() << " DIRECTORY "
|
||||
<< deslash("${CMAKE_CURRENT_BINARY_DIR}/" + topTarget + ".dir") << " SOURCES ";
|
||||
for (V3HierBlockPlan::const_iterator it = planp->begin(); it != planp->end(); ++it) {
|
||||
*of << deslash(" ${CMAKE_CURRENT_BINARY_DIR}/" + it->second->hierWrapper(true));
|
||||
}
|
||||
*of << " " << deslash(cmake_list(v3Global.opt.vFiles()));
|
||||
*of << " VERILATOR_ARGS ";
|
||||
*of << "-f " << deslash(planp->topCommandArgsFileName(true));
|
||||
*of << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -43,19 +43,19 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
string m_type;
|
||||
ScopeData(const string& symName, const string& prettyName, int timeunit,
|
||||
const string& type)
|
||||
: m_symName(symName)
|
||||
, m_prettyName(prettyName)
|
||||
, m_timeunit(timeunit)
|
||||
, m_type(type) {}
|
||||
: m_symName{symName}
|
||||
, m_prettyName{prettyName}
|
||||
, m_timeunit{timeunit}
|
||||
, m_type{type} {}
|
||||
};
|
||||
struct ScopeFuncData {
|
||||
AstScopeName* m_scopep;
|
||||
AstCFunc* m_funcp;
|
||||
AstNodeModule* m_modp;
|
||||
ScopeFuncData(AstScopeName* scopep, AstCFunc* funcp, AstNodeModule* modp)
|
||||
: m_scopep(scopep)
|
||||
, m_funcp(funcp)
|
||||
, m_modp(modp) {}
|
||||
: m_scopep{scopep}
|
||||
, m_funcp{funcp}
|
||||
, m_modp{modp} {}
|
||||
};
|
||||
struct ScopeVarData {
|
||||
string m_scopeName;
|
||||
|
|
@ -65,11 +65,11 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
AstScope* m_scopep;
|
||||
ScopeVarData(const string& scopeName, const string& varBasePretty, AstVar* varp,
|
||||
AstNodeModule* modp, AstScope* scopep)
|
||||
: m_scopeName(scopeName)
|
||||
, m_varBasePretty(varBasePretty)
|
||||
, m_varp(varp)
|
||||
, m_modp(modp)
|
||||
, m_scopep(scopep) {}
|
||||
: m_scopeName{scopeName}
|
||||
, m_varBasePretty{varBasePretty}
|
||||
, m_varp{varp}
|
||||
, m_modp{modp}
|
||||
, m_scopep{scopep} {}
|
||||
};
|
||||
typedef std::map<string, ScopeFuncData> ScopeFuncs;
|
||||
typedef std::map<string, ScopeVarData> ScopeVars;
|
||||
|
|
@ -94,8 +94,8 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
};
|
||||
|
||||
// STATE
|
||||
AstCFunc* m_funcp; // Current function
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCFunc* m_funcp = nullptr; // Current function
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
std::vector<ScopeModPair> m_scopes; // Every scope by module
|
||||
std::vector<AstCFunc*> m_dpis; // DPI functions
|
||||
std::vector<ModVarPair> m_modVars; // Each public {mod,var}
|
||||
|
|
@ -104,11 +104,11 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
ScopeVars m_scopeVars; // Each {scope,public-var}
|
||||
ScopeNames m_vpiScopeCandidates; // All scopes for VPI
|
||||
ScopeNameHierarchy m_vpiScopeHierarchy; // The actual hierarchy of scopes
|
||||
int m_coverBins; // Coverage bin number
|
||||
int m_coverBins = 0; // Coverage bin number
|
||||
bool m_dpiHdrOnly; // Only emit the DPI header
|
||||
int m_numStmts; // Number of statements output
|
||||
int m_funcNum; // CFunc split function number
|
||||
V3OutCFile* m_ofpBase; // Base (not split) C file
|
||||
int m_numStmts = 0; // Number of statements output
|
||||
int m_funcNum = 0; // CFunc split function number
|
||||
V3OutCFile* m_ofpBase = nullptr; // Base (not split) C file
|
||||
std::map<int, bool> m_usesVfinal; // Split method uses __Vfinal
|
||||
|
||||
// METHODS
|
||||
|
|
@ -120,7 +120,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
void emitDpiHdr();
|
||||
void emitDpiImp();
|
||||
|
||||
void nameCheck(AstNode* nodep) {
|
||||
static void nameCheck(AstNode* nodep) {
|
||||
// Prevent GCC compile time error; name check all things that reach C++ code
|
||||
if (nodep->name() != ""
|
||||
&& !(VN_IS(nodep, CFunc)
|
||||
|
|
@ -139,7 +139,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
string scopeSymString(const string& scpname) {
|
||||
static string scopeSymString(const string& scpname) {
|
||||
string out = scpname;
|
||||
string::size_type pos;
|
||||
while ((pos = out.find("__PVT__")) != string::npos) out.replace(pos, 7, "");
|
||||
|
|
@ -150,7 +150,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
return out;
|
||||
}
|
||||
|
||||
string scopeDecodeIdentifier(const string& scpname) {
|
||||
static string scopeDecodeIdentifier(const string& scpname) {
|
||||
string out = scpname;
|
||||
// Remove hierarchy
|
||||
string::size_type pos = out.rfind('.');
|
||||
|
|
@ -168,7 +168,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
|
||||
void varHierarchyScopes(string scp) {
|
||||
while (!scp.empty()) {
|
||||
ScopeNames::const_iterator scpit = m_vpiScopeCandidates.find(scp);
|
||||
const auto scpit = m_vpiScopeCandidates.find(scp);
|
||||
if ((scpit != m_vpiScopeCandidates.end())
|
||||
&& (m_scopeNames.find(scp) == m_scopeNames.end())) {
|
||||
m_scopeNames.insert(make_pair(scpit->second.m_symName, scpit->second));
|
||||
|
|
@ -252,7 +252,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
// Collect list of scopes
|
||||
iterateChildren(nodep);
|
||||
varsExpand();
|
||||
|
|
@ -274,16 +274,15 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
if (!m_dpiHdrOnly) emitDpiImp();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
nameCheck(nodep);
|
||||
AstNodeModule* origModp = m_modp;
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstCellInline* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCellInline* nodep) override {
|
||||
if (v3Global.opt.vpi()) {
|
||||
string type = (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER" : "SCOPE_MODULE";
|
||||
string name = nodep->scopep()->name() + "__DOT__" + nodep->name();
|
||||
|
|
@ -293,7 +292,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
make_pair(name, ScopeData(scopeSymString(name), name_dedot, timeunit, type)));
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
if (VN_IS(m_modp, Class)) return; // The ClassPackage is what is visible
|
||||
nameCheck(nodep);
|
||||
|
||||
|
|
@ -307,7 +306,7 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
timeunit, "SCOPE_MODULE")));
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScopeName* nodep) override {
|
||||
string name = nodep->scopeSymName();
|
||||
// UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()
|
||||
// <<" ss"<<name<<endl);
|
||||
|
|
@ -329,38 +328,32 @@ class EmitCSyms : EmitCBaseVisitor {
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
nameCheck(nodep);
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isSigUserRdPublic()) { m_modVars.push_back(make_pair(m_modp, nodep)); }
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCoverDecl* nodep) 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) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
nameCheck(nodep);
|
||||
if (nodep->dpiImport() || nodep->dpiExportWrapper()) m_dpis.push_back(nodep);
|
||||
m_funcp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_funcp = NULL;
|
||||
m_funcp = nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
virtual void visit(AstConst*) VL_OVERRIDE {}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstConst*) override {}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
explicit EmitCSyms(AstNetlist* nodep, bool dpiHdrOnly)
|
||||
: m_dpiHdrOnly(dpiHdrOnly) {
|
||||
m_funcp = NULL;
|
||||
m_modp = NULL;
|
||||
m_coverBins = 0;
|
||||
m_numStmts = 0;
|
||||
m_funcNum = 0;
|
||||
m_ofpBase = NULL;
|
||||
: m_dpiHdrOnly{dpiHdrOnly} {
|
||||
iterate(nodep);
|
||||
}
|
||||
};
|
||||
|
|
@ -496,14 +489,14 @@ void EmitCSyms::emitSymHdr() {
|
|||
puts("} VL_ATTR_ALIGNED(VL_CACHE_LINE_BYTES);\n");
|
||||
|
||||
ofp()->putsEndGuard();
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
}
|
||||
|
||||
void EmitCSyms::closeSplit() {
|
||||
if (!m_ofp || m_ofp == m_ofpBase) return;
|
||||
|
||||
puts("}\n");
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
}
|
||||
|
||||
void EmitCSyms::checkSplit(bool usesVfinal) {
|
||||
|
|
@ -617,7 +610,7 @@ void EmitCSyms::emitSymImp() {
|
|||
puts(" : __Vm_namep(namep)\n"); // No leak, as gets destroyed when the top is destroyed
|
||||
if (v3Global.needTraceDumper()) {
|
||||
puts(" , __Vm_dumping(false)\n");
|
||||
puts(" , __Vm_dumperp(NULL)\n");
|
||||
puts(" , __Vm_dumperp(nullptr)\n");
|
||||
}
|
||||
if (v3Global.opt.trace()) {
|
||||
puts(" , __Vm_activity(false)\n");
|
||||
|
|
@ -710,8 +703,8 @@ void EmitCSyms::emitSymImp() {
|
|||
++lit) {
|
||||
string fromname = scopeSymString(it->first);
|
||||
string toname = scopeSymString(*lit);
|
||||
ScopeNames::const_iterator from = m_scopeNames.find(fromname);
|
||||
ScopeNames::const_iterator to = m_scopeNames.find(toname);
|
||||
const auto from = vlstd::as_const(m_scopeNames).find(fromname);
|
||||
const auto to = vlstd::as_const(m_scopeNames).find(toname);
|
||||
UASSERT(from != m_scopeNames.end(), fromname + " not in m_scopeNames");
|
||||
UASSERT(to != m_scopeNames.end(), toname + " not in m_scopeNames");
|
||||
puts("__Vhier.add(");
|
||||
|
|
@ -806,16 +799,16 @@ void EmitCSyms::emitSymImp() {
|
|||
if (varp->isParam()) {
|
||||
if (varp->vlEnumType() == "VLVT_STRING") {
|
||||
puts(", const_cast<void*>(static_cast<const void*>(");
|
||||
puts(varName.c_str());
|
||||
puts(varName);
|
||||
puts(".c_str())), ");
|
||||
} else {
|
||||
puts(", const_cast<void*>(static_cast<const void*>(&(");
|
||||
puts(varName.c_str());
|
||||
puts(varName);
|
||||
puts("))), ");
|
||||
}
|
||||
} else {
|
||||
puts(", &(");
|
||||
puts(varName.c_str());
|
||||
puts(varName);
|
||||
puts("), ");
|
||||
}
|
||||
|
||||
|
|
@ -835,7 +828,7 @@ void EmitCSyms::emitSymImp() {
|
|||
|
||||
m_ofpBase->puts("}\n");
|
||||
closeSplit();
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = NULL);
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -865,8 +858,7 @@ void EmitCSyms::emitDpiHdr() {
|
|||
|
||||
int firstExp = 0;
|
||||
int firstImp = 0;
|
||||
for (std::vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) {
|
||||
AstCFunc* nodep = *it;
|
||||
for (AstCFunc* nodep : m_dpis) {
|
||||
if (nodep->dpiExportWrapper()) {
|
||||
if (!firstExp++) puts("\n// DPI EXPORTS\n");
|
||||
puts("// DPI export" + ifNoProtect(" at " + nodep->fileline()->ascii()) + "\n");
|
||||
|
|
@ -915,8 +907,7 @@ void EmitCSyms::emitDpiImp() {
|
|||
puts("#include \"" + topClassName() + ".h\"\n");
|
||||
puts("\n");
|
||||
|
||||
for (std::vector<AstCFunc*>::iterator it = m_dpis.begin(); it != m_dpis.end(); ++it) {
|
||||
AstCFunc* nodep = *it;
|
||||
for (AstCFunc* nodep : m_dpis) {
|
||||
if (nodep->dpiExportWrapper()) {
|
||||
puts("#ifndef _VL_DPIDECL_" + nodep->name() + "\n");
|
||||
puts("#define _VL_DPIDECL_" + nodep->name() + "\n");
|
||||
|
|
|
|||
200
src/V3EmitMk.cpp
200
src/V3EmitMk.cpp
|
|
@ -18,6 +18,7 @@
|
|||
#include "verilatedos.h"
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3HierBlock.h"
|
||||
#include "V3Os.h"
|
||||
#include "V3EmitMk.h"
|
||||
#include "V3EmitCBase.h"
|
||||
|
|
@ -46,11 +47,8 @@ public:
|
|||
of.puts("# See " + v3Global.opt.prefix() + ".mk" + " for the caller.\n");
|
||||
|
||||
of.puts("\n### Switches...\n");
|
||||
of.puts("# C11 constructs required? 0/1 (from --threads, "
|
||||
"--trace-threads or use of classes)\n");
|
||||
of.puts("VM_C11 = ");
|
||||
of.puts(v3Global.needC11() || v3Global.opt.threads() ? "1" : "0");
|
||||
of.puts("\n");
|
||||
of.puts("# C11 constructs required? 0/1 (always on now)\n");
|
||||
of.puts("VM_C11 = 1\n");
|
||||
of.puts("# Coverage output mode? 0/1 (from --coverage)\n");
|
||||
of.puts("VM_COVERAGE = ");
|
||||
of.puts(v3Global.opt.coverage() ? "1" : "0");
|
||||
|
|
@ -94,7 +92,10 @@ public:
|
|||
of.puts(support == 2 ? "VM_GLOBAL" : support == 1 ? "VM_SUPPORT" : "VM_CLASSES");
|
||||
of.puts(slow ? "_SLOW" : "_FAST");
|
||||
of.puts(" += \\\n");
|
||||
if (support == 2 && !slow) {
|
||||
if (support == 2 && v3Global.opt.hierChild()) {
|
||||
// Do nothing because VM_GLOBAL is necessary per executable. Top module will
|
||||
// have them.
|
||||
} else if (support == 2 && !slow) {
|
||||
putMakeClassEntry(of, "verilated.cpp");
|
||||
if (v3Global.dpi()) { putMakeClassEntry(of, "verilated_dpi.cpp"); }
|
||||
if (v3Global.opt.vpi()) { putMakeClassEntry(of, "verilated_vpi.cpp"); }
|
||||
|
|
@ -189,25 +190,20 @@ public:
|
|||
of.puts("VM_USER_CFLAGS = \\\n");
|
||||
if (!v3Global.opt.protectLib().empty()) of.puts("\t-fPIC \\\n");
|
||||
const V3StringList& cFlags = v3Global.opt.cFlags();
|
||||
for (V3StringList::const_iterator it = cFlags.begin(); it != cFlags.end(); ++it) {
|
||||
of.puts("\t" + *it + " \\\n");
|
||||
}
|
||||
for (const string& i : cFlags) of.puts("\t" + i + " \\\n");
|
||||
of.puts("\n");
|
||||
|
||||
of.puts("# User LDLIBS (from -LDFLAGS on Verilator command line)\n");
|
||||
of.puts("VM_USER_LDLIBS = \\\n");
|
||||
const V3StringList& ldLibs = v3Global.opt.ldLibs();
|
||||
for (V3StringList::const_iterator it = ldLibs.begin(); it != ldLibs.end(); ++it) {
|
||||
of.puts("\t" + *it + " \\\n");
|
||||
}
|
||||
for (const string& i : ldLibs) of.puts("\t" + i + " \\\n");
|
||||
of.puts("\n");
|
||||
|
||||
V3StringSet dirs;
|
||||
of.puts("# User .cpp files (from .cpp's on Verilator command line)\n");
|
||||
of.puts("VM_USER_CLASSES = \\\n");
|
||||
const V3StringSet& cppFiles = v3Global.opt.cppFiles();
|
||||
for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) {
|
||||
string cppfile = *it;
|
||||
for (const auto& cppfile : cppFiles) {
|
||||
of.puts("\t" + V3Os::filenameNonExt(cppfile) + " \\\n");
|
||||
string dir = V3Os::filenameDir(cppfile);
|
||||
dirs.insert(dir);
|
||||
|
|
@ -216,14 +212,16 @@ public:
|
|||
|
||||
of.puts("# User .cpp directories (from .cpp's on Verilator command line)\n");
|
||||
of.puts("VM_USER_DIR = \\\n");
|
||||
for (V3StringSet::iterator it = dirs.begin(); it != dirs.end(); ++it) {
|
||||
of.puts("\t" + *it + " \\\n");
|
||||
}
|
||||
for (const auto& i : dirs) of.puts("\t" + i + " \\\n");
|
||||
of.puts("\n");
|
||||
|
||||
of.puts("\n### Default rules...\n");
|
||||
of.puts("# Include list of all generated classes\n");
|
||||
of.puts("include " + v3Global.opt.prefix() + "_classes.mk\n");
|
||||
if (v3Global.opt.hierTop()) {
|
||||
of.puts("# Include rules for hierarchical blocks\n");
|
||||
of.puts("include " + v3Global.opt.prefix() + "_hier.mk\n");
|
||||
}
|
||||
of.puts("# Include global rules\n");
|
||||
of.puts("include $(VERILATOR_ROOT)/include/verilated.mk\n");
|
||||
|
||||
|
|
@ -231,8 +229,7 @@ public:
|
|||
of.puts("\n### Executable rules... (from --exe)\n");
|
||||
of.puts("VPATH += $(VM_USER_DIR)\n");
|
||||
of.puts("\n");
|
||||
for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) {
|
||||
string cppfile = *it;
|
||||
for (const string& cppfile : cppFiles) {
|
||||
string basename = V3Os::filenameNonExt(cppfile);
|
||||
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
||||
of.puts(basename + ".o: " + cppfile + "\n");
|
||||
|
|
@ -241,24 +238,39 @@ public:
|
|||
|
||||
of.puts("\n### Link rules... (from --exe)\n");
|
||||
of.puts(v3Global.opt.exeName()
|
||||
+ ": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a\n");
|
||||
+ ": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a $(VM_HIER_LIBS)\n");
|
||||
of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) $(LIBS) $(SC_LIBS) -o $@\n");
|
||||
of.puts("\n");
|
||||
}
|
||||
|
||||
if (!v3Global.opt.protectLib().empty()) {
|
||||
const string protectLibDeps
|
||||
= "$(VK_OBJS) $(VK_GLOBAL_OBJS) " + v3Global.opt.protectLib() + ".o";
|
||||
const string protectLibDeps = "$(VK_OBJS) $(VK_GLOBAL_OBJS) "
|
||||
+ v3Global.opt.protectLib() + ".o $(VM_HIER_LIBS)";
|
||||
of.puts("\n### Library rules from --protect-lib\n");
|
||||
// The rule to create .a is defined in verilated.mk, so just define dependency here.
|
||||
of.puts(v3Global.opt.protectLibName(false) + ": " + protectLibDeps + "\n");
|
||||
of.puts("\tar rc $@ $^\n");
|
||||
of.puts("\n");
|
||||
of.puts(v3Global.opt.protectLibName(true) + ": " + protectLibDeps + "\n");
|
||||
of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -shared -o $@ $^\n");
|
||||
of.puts("\n");
|
||||
|
||||
of.puts("lib" + v3Global.opt.protectLib() + ": " + v3Global.opt.protectLibName(false)
|
||||
+ " " + v3Global.opt.protectLibName(true) + "\n");
|
||||
if (v3Global.opt.hierChild()) {
|
||||
// Hierarchical child does not need .so because hierTop() will create .so from .a
|
||||
of.puts("lib" + v3Global.opt.protectLib() + ": "
|
||||
+ v3Global.opt.protectLibName(false) + "\n");
|
||||
} else {
|
||||
of.puts(v3Global.opt.protectLibName(true) + ": " + protectLibDeps + "\n");
|
||||
// Linker on mac emits an error if all symbols are not found here,
|
||||
// but some symbols that are referred as "DPI-C" can not be found at this moment.
|
||||
// So add dynamic_lookup
|
||||
of.puts("ifeq ($(shell uname -s),Darwin)\n");
|
||||
of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -undefined "
|
||||
"dynamic_lookup -shared -flat_namespace -o $@ $^\n");
|
||||
of.puts("else\n");
|
||||
of.puts(
|
||||
"\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -shared -o $@ $^\n");
|
||||
of.puts("endif\n");
|
||||
of.puts("\n");
|
||||
of.puts("lib" + v3Global.opt.protectLib() + ": "
|
||||
+ v3Global.opt.protectLibName(false) + " "
|
||||
+ v3Global.opt.protectLibName(true) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
of.puts("\n");
|
||||
|
|
@ -273,6 +285,131 @@ public:
|
|||
virtual ~EmitMk() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
class EmitMkHierVerilation {
|
||||
const V3HierBlockPlan* const m_planp;
|
||||
const string m_makefile; // path of this makefile
|
||||
void emitCommonOpts(V3OutMkFile& of) const {
|
||||
const string cwd = V3Os::filenameRealPath(".");
|
||||
of.puts("# Verilation of hierarchical blocks are executed in this directory\n");
|
||||
of.puts("VM_HIER_RUN_DIR := " + cwd + "\n");
|
||||
of.puts("# Common options for hierarchical blocks\n");
|
||||
const string fullpath_bin = V3Os::filenameRealPath(v3Global.opt.bin());
|
||||
const string perl_wrapper = V3Os::filenameDir(fullpath_bin) + "/verilator";
|
||||
of.puts("VM_HIER_VERILATOR := " + perl_wrapper + "\n");
|
||||
of.puts("VM_HIER_INPUT_FILES := \\\n");
|
||||
const V3StringList& vFiles = v3Global.opt.vFiles();
|
||||
for (const string& i : vFiles) of.puts("\t" + V3Os::filenameRealPath(i) + " \\\n");
|
||||
of.puts("\n");
|
||||
const V3StringSet& libraryFiles = v3Global.opt.libraryFiles();
|
||||
of.puts("VM_HIER_VERILOG_LIBS := \\\n");
|
||||
for (const string& i : libraryFiles) {
|
||||
of.puts("\t" + V3Os::filenameRealPath(i) + " \\\n");
|
||||
}
|
||||
of.puts("\n");
|
||||
}
|
||||
void emitOpts(V3OutMkFile& of, const V3StringList& opts) const {
|
||||
for (const string& i : opts) { of.puts("\t\t" + i + " \\\n"); }
|
||||
}
|
||||
void emitLaunchVerilator(V3OutMkFile& of, const string& argsFile) const {
|
||||
of.puts("\t@$(MAKE) -C $(VM_HIER_RUN_DIR) -f " + m_makefile
|
||||
+ " hier_launch_verilator \\\n");
|
||||
of.puts("\t\tVM_HIER_LAUNCH_VERILATOR_ARGSFILE=\"" + argsFile + "\"\n");
|
||||
}
|
||||
void emit(V3OutMkFile& of) const {
|
||||
of.puts("# Hierarchical Verilation -*- Makefile -*-\n");
|
||||
of.puts("# DESCR"
|
||||
"IPTION: Verilator output: Makefile for hierarchical verilatrion\n");
|
||||
of.puts("#\n");
|
||||
of.puts("# The main makefile " + v3Global.opt.prefix() + ".mk calls this makefile\n");
|
||||
of.puts("\n");
|
||||
of.puts("ifndef VM_HIER_VERILATION_INCLUDED\n");
|
||||
of.puts("VM_HIER_VERILATION_INCLUDED = 1\n\n");
|
||||
|
||||
of.puts(".SUFFIXES:\n");
|
||||
of.puts(".PHONY: hier_build hier_verilation hier_launch_verilator\n");
|
||||
|
||||
of.puts("# Libraries of hierarchical blocks\n");
|
||||
of.puts("VM_HIER_LIBS := \\\n");
|
||||
const V3HierBlockPlan::HierVector blocks
|
||||
= m_planp->hierBlocksSorted(); // leaf comes first
|
||||
// List in order of leaf-last order so that linker can resolve dependency
|
||||
for (auto it = blocks.rbegin(); it != blocks.rend(); ++it) {
|
||||
of.puts("\t" + (*it)->hierLib(true) + " \\\n");
|
||||
}
|
||||
of.puts("\n");
|
||||
|
||||
// Build hierarchical libraries as soon as possible to get maximum parallelism
|
||||
of.puts("hier_build: $(VM_HIER_LIBS) " + v3Global.opt.prefix() + ".mk\n");
|
||||
of.puts("\t$(MAKE) -f " + v3Global.opt.prefix() + ".mk\n");
|
||||
of.puts("hier_verilation: " + v3Global.opt.prefix() + ".mk\n");
|
||||
emitCommonOpts(of);
|
||||
|
||||
// Instead of direct execute of "cd $(VM_HIER_RUN_DIR) && $(VM_HIER_VERILATOR)",
|
||||
// call via make to get message of "Entering directory" and "Leaving directory".
|
||||
// This will make some editors and IDEs happy when viewing a logfile.
|
||||
of.puts("# VM_HIER_LAUNCH_VERILATOR_ARGSFILE must be passed as a command argument\n");
|
||||
of.puts("hier_launch_verilator:\n");
|
||||
of.puts("\t$(VM_HIER_VERILATOR) -f $(VM_HIER_LAUNCH_VERILATOR_ARGSFILE)\n");
|
||||
|
||||
// Top level module
|
||||
{
|
||||
const string argsFile = v3Global.hierPlanp()->topCommandArgsFileName(false);
|
||||
of.puts("\n# Verilate the top module\n");
|
||||
of.puts(v3Global.opt.prefix()
|
||||
+ ".mk: $(VM_HIER_INPUT_FILES) $(VM_HIER_VERILOG_LIBS) ");
|
||||
of.puts(V3Os::filenameNonDir(argsFile) + " ");
|
||||
for (V3HierBlockPlan::const_iterator it = m_planp->begin(); it != m_planp->end();
|
||||
++it) {
|
||||
of.puts(it->second->hierWrapper(true) + " ");
|
||||
}
|
||||
of.puts("\n");
|
||||
emitLaunchVerilator(of, argsFile);
|
||||
}
|
||||
|
||||
// Rules to process hierarchical blocks
|
||||
of.puts("\n# Verilate hierarchical blocks\n");
|
||||
for (V3HierBlockPlan::const_iterator it = m_planp->begin(); it != m_planp->end(); ++it) {
|
||||
const string prefix = it->second->hierPrefix();
|
||||
const string argsFile = it->second->commandArgsFileName(false);
|
||||
of.puts(it->second->hierGenerated(true));
|
||||
of.puts(": $(VM_HIER_INPUT_FILES) $(VM_HIER_VERILOG_LIBS) ");
|
||||
of.puts(V3Os::filenameNonDir(argsFile) + " ");
|
||||
const V3HierBlock::HierBlockSet& children = it->second->children();
|
||||
for (V3HierBlock::HierBlockSet::const_iterator child = children.begin();
|
||||
child != children.end(); ++child) {
|
||||
of.puts((*child)->hierWrapper(true) + " ");
|
||||
}
|
||||
of.puts("\n");
|
||||
emitLaunchVerilator(of, argsFile);
|
||||
|
||||
// Rule to build lib*.a
|
||||
of.puts(it->second->hierLib(true));
|
||||
of.puts(": ");
|
||||
of.puts(it->second->hierMk(true));
|
||||
of.puts(" ");
|
||||
for (V3HierBlock::HierBlockSet::const_iterator child = children.begin();
|
||||
child != children.end(); ++child) {
|
||||
of.puts((*child)->hierLib(true));
|
||||
of.puts(" ");
|
||||
}
|
||||
of.puts("\n\t$(MAKE) -f " + it->second->hierMk(false) + " -C " + prefix);
|
||||
of.puts(" VM_PREFIX=" + prefix);
|
||||
of.puts("\n\n");
|
||||
}
|
||||
of.puts("endif # Guard\n");
|
||||
}
|
||||
|
||||
public:
|
||||
explicit EmitMkHierVerilation(const V3HierBlockPlan* planp)
|
||||
: m_planp{planp}
|
||||
, m_makefile{v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "_hier.mk"} {
|
||||
V3OutMkFile of(m_makefile);
|
||||
emit(of);
|
||||
}
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Gate class functions
|
||||
|
||||
|
|
@ -280,3 +417,8 @@ void V3EmitMk::emitmk() {
|
|||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
EmitMk emitter;
|
||||
}
|
||||
|
||||
void V3EmitMk::emitHierVerilation(const V3HierBlockPlan* planp) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
EmitMkHierVerilation emitter(planp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,14 @@
|
|||
#include "config_build.h"
|
||||
#include "verilatedos.h"
|
||||
|
||||
class V3HierBlockPlan;
|
||||
|
||||
//============================================================================
|
||||
|
||||
class V3EmitMk {
|
||||
public:
|
||||
static void emitmk();
|
||||
static void emitHierVerilation(const V3HierBlockPlan* planp);
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
275
src/V3EmitV.cpp
275
src/V3EmitV.cpp
|
|
@ -30,8 +30,8 @@
|
|||
|
||||
class EmitVBaseVisitor : public EmitCBaseVisitor {
|
||||
// MEMBERS
|
||||
bool m_suppressSemi;
|
||||
AstSenTree* m_sensesp;
|
||||
bool m_suppressSemi = false;
|
||||
AstSenTree* m_sensesp; // Domain for printing one a ALWAYS under a ACTIVE
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -51,13 +51,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n");
|
||||
iterateChildren(nodep);
|
||||
putqs(nodep, "end" + nodep->verilogKwd() + "\n");
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeFTask* nodep) override {
|
||||
putfs(nodep, nodep->isFunction() ? "function" : "task");
|
||||
puts(" ");
|
||||
puts(nodep->prettyName());
|
||||
|
|
@ -68,7 +68,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
putqs(nodep, "end\n");
|
||||
}
|
||||
|
||||
virtual void visit(AstBegin* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstBegin* nodep) override {
|
||||
if (nodep->name() == "") {
|
||||
putbs("begin\n");
|
||||
} else {
|
||||
|
|
@ -77,7 +77,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateChildren(nodep);
|
||||
puts("end\n");
|
||||
}
|
||||
virtual void visit(AstFork* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFork* nodep) override {
|
||||
if (nodep->name() == "") {
|
||||
putbs("fork\n");
|
||||
} else {
|
||||
|
|
@ -87,17 +87,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
puts(nodep->joinType().verilogKwd());
|
||||
puts("\n");
|
||||
}
|
||||
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFinal* nodep) override {
|
||||
putfs(nodep, "final begin\n");
|
||||
iterateChildren(nodep);
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstInitial* nodep) override {
|
||||
putfs(nodep, "initial begin\n");
|
||||
iterateChildren(nodep);
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAlways* nodep) override {
|
||||
putfs(nodep, "always ");
|
||||
if (m_sensesp) {
|
||||
iterateAndNextNull(m_sensesp);
|
||||
|
|
@ -109,7 +109,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->bodysp());
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
putfs(nodep, "/*verilator public_flat_rw ");
|
||||
if (m_sensesp) {
|
||||
iterateAndNextNull(m_sensesp);
|
||||
|
|
@ -121,37 +121,37 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->bodysp());
|
||||
putqs(nodep, "*/\n");
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
putfs(nodep, " " + nodep->verilogKwd() + " ");
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstAssignDly* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignDly* nodep) override {
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
putfs(nodep, " <= ");
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignAlias* nodep) override {
|
||||
putbs("alias ");
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
putfs(nodep, " = ");
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignW* nodep) override {
|
||||
putfs(nodep, "assign ");
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
putbs(" = ");
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstBreak* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstBreak*) override {
|
||||
putbs("break");
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenTree* nodep) override {
|
||||
// AstSenItem is called for dumping in isolation by V3Order
|
||||
putfs(nodep, "@(");
|
||||
for (AstNode* expp = nodep->sensesp(); expp; expp = expp->nextp()) {
|
||||
|
|
@ -160,13 +160,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
putfs(nodep, "");
|
||||
puts(nodep->edgeType().verilogKwd());
|
||||
if (nodep->sensp()) puts(" ");
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeCase* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCase* nodep) override {
|
||||
putfs(nodep, "");
|
||||
if (const AstCase* casep = VN_CAST(nodep, Case)) {
|
||||
if (casep->priorityPragma()) puts("priority ");
|
||||
|
|
@ -187,7 +187,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->itemsp());
|
||||
putqs(nodep, "endcase\n");
|
||||
}
|
||||
virtual void visit(AstCaseItem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCaseItem* nodep) override {
|
||||
if (nodep->condsp()) {
|
||||
iterateAndNextNull(nodep->condsp());
|
||||
} else {
|
||||
|
|
@ -197,17 +197,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->bodysp());
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstComment* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstComment* nodep) override {
|
||||
puts(string("// ") + nodep->name() + "\n");
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstContinue* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstContinue*) override {
|
||||
putbs("continue");
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstCoverDecl*) VL_OVERRIDE {} // N/A
|
||||
virtual void visit(AstCoverInc*) VL_OVERRIDE {} // N/A
|
||||
virtual void visit(AstCoverToggle*) VL_OVERRIDE {} // N/A
|
||||
virtual void visit(AstCoverDecl*) override {} // N/A
|
||||
virtual void visit(AstCoverInc*) override {} // N/A
|
||||
virtual void visit(AstCoverToggle*) override {} // N/A
|
||||
|
||||
void visitNodeDisplay(AstNode* nodep, AstNode* fileOrStrgp, const string& text,
|
||||
AstNode* exprsp) {
|
||||
|
|
@ -224,28 +224,26 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstDisable* nodep) VL_OVERRIDE {
|
||||
putbs("disable " + nodep->name() + ";\n");
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstDisable* nodep) override { putbs("disable " + nodep->name() + ";\n"); }
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
}
|
||||
virtual void visit(AstElabDisplay* nodep) VL_OVERRIDE {
|
||||
visitNodeDisplay(nodep, NULL, nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
virtual void visit(AstElabDisplay* nodep) override {
|
||||
visitNodeDisplay(nodep, nullptr, nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFScanF* nodep) override {
|
||||
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSScanF* nodep) override {
|
||||
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstSFormat* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSFormat* nodep) override {
|
||||
visitNodeDisplay(nodep, nodep->lhsp(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep) VL_OVERRIDE {
|
||||
visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp());
|
||||
virtual void visit(AstSFormatF* nodep) override {
|
||||
visitNodeDisplay(nodep, nullptr, nodep->text(), nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstFOpen* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFOpen* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs("(");
|
||||
iterateAndNextNull(nodep->filenamep());
|
||||
|
|
@ -253,36 +251,36 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->modep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFOpenMcd* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs("(");
|
||||
iterateAndNextNull(nodep->filenamep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFClose* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFClose* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
if (nodep->filep()) iterateAndNextNull(nodep->filep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstFFlush* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
if (nodep->filep()) iterateAndNextNull(nodep->filep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstJumpBlock* nodep) override {
|
||||
putbs("begin : label" + cvtToStr(nodep->labelNum()) + "\n");
|
||||
if (nodep->stmtsp()) iterateAndNextNull(nodep->stmtsp());
|
||||
puts("end\n");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstJumpGo* nodep) override {
|
||||
putbs("disable label" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n");
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstJumpLabel* nodep) override {
|
||||
putbs("// " + cvtToStr(nodep->blockp()) + ":\n");
|
||||
}
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
if (nodep->filenamep()) iterateAndNextNull(nodep->filenamep());
|
||||
|
|
@ -298,17 +296,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstSysFuncAsTask* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSysFuncAsTask* nodep) override {
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSysIgnore* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
iterateAndNextNull(nodep->exprsp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstNodeFor* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeFor* nodep) override {
|
||||
putfs(nodep, "for (");
|
||||
m_suppressSemi = true;
|
||||
iterateAndNextNull(nodep->initsp());
|
||||
|
|
@ -321,14 +319,14 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->bodysp());
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstRepeat* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstRepeat* nodep) override {
|
||||
putfs(nodep, "repeat (");
|
||||
iterateAndNextNull(nodep->countp());
|
||||
puts(") begin\n");
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
putfs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
iterateAndNextNull(nodep->precondsp());
|
||||
putfs(nodep, "while (");
|
||||
iterateAndNextNull(nodep->condp());
|
||||
|
|
@ -338,7 +336,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop
|
||||
putfs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
putfs(nodep, "");
|
||||
if (const AstIf* ifp = VN_CAST(nodep, If)) {
|
||||
if (ifp->priorityPragma()) puts("priority ");
|
||||
|
|
@ -356,7 +354,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstPast* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstPast* nodep) override {
|
||||
putfs(nodep, "$past(");
|
||||
iterateAndNextNull(nodep->exprp());
|
||||
if (nodep->ticksp()) {
|
||||
|
|
@ -365,53 +363,53 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstReturn* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstReturn* nodep) override {
|
||||
putfs(nodep, "return ");
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstStop* nodep) VL_OVERRIDE { putfs(nodep, "$stop;\n"); }
|
||||
virtual void visit(AstFinish* nodep) VL_OVERRIDE { putfs(nodep, "$finish;\n"); }
|
||||
virtual void visit(AstNodeSimpleText* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstStop* nodep) override { putfs(nodep, "$stop;\n"); }
|
||||
virtual void visit(AstFinish* nodep) override { putfs(nodep, "$finish;\n"); }
|
||||
virtual void visit(AstNodeSimpleText* nodep) override {
|
||||
if (nodep->tracking() || m_trackText) {
|
||||
puts(nodep->text());
|
||||
} else {
|
||||
putsNoTracking(nodep->text());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstTextBlock* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTextBlock* nodep) 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) VL_OVERRIDE {}
|
||||
virtual void visit(AstCStmt* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScopeName* nodep) override {}
|
||||
virtual void visit(AstCStmt* nodep) override {
|
||||
putfs(nodep, "$_CSTMT(");
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstCMath* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCMath* nodep) override {
|
||||
putfs(nodep, "$_CMATH(");
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstUCStmt* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstUCStmt* nodep) override {
|
||||
putfs(nodep, "$c(");
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstUCFunc* nodep) override {
|
||||
putfs(nodep, "$c(");
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
puts(")");
|
||||
}
|
||||
|
||||
// Operators
|
||||
virtual void emitVerilogFormat(AstNode* nodep, const string& format, AstNode* lhsp = NULL,
|
||||
AstNode* rhsp = NULL, AstNode* thsp = NULL,
|
||||
AstNode* fhsp = NULL) {
|
||||
virtual void emitVerilogFormat(AstNode* nodep, const string& format, AstNode* lhsp = nullptr,
|
||||
AstNode* rhsp = nullptr, AstNode* thsp = nullptr,
|
||||
AstNode* fhsp = nullptr) {
|
||||
// Look at emitVerilog() format for term/uni/dual/triops,
|
||||
// and write out appropriate text.
|
||||
// %f Potential fileline-if-change and line break
|
||||
|
|
@ -423,16 +421,16 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
// %k Potential line break
|
||||
bool inPct = false;
|
||||
putbs("");
|
||||
for (string::const_iterator pos = format.begin(); pos != format.end(); ++pos) {
|
||||
if (pos[0] == '%') {
|
||||
for (const char c : format) {
|
||||
if (c == '%') {
|
||||
inPct = true;
|
||||
} else if (!inPct) { // Normal text
|
||||
string s;
|
||||
s += pos[0];
|
||||
s += c;
|
||||
puts(s);
|
||||
} else { // Format character
|
||||
inPct = false;
|
||||
switch (*pos) {
|
||||
switch (c) {
|
||||
case '%': puts("%"); break;
|
||||
case 'f': putfs(nodep, ""); break;
|
||||
case 'k': putbs(""); break;
|
||||
|
|
@ -461,26 +459,26 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->dtypep());
|
||||
break;
|
||||
}
|
||||
default: nodep->v3fatalSrc("Unknown emitVerilog format code: %" << pos[0]); break;
|
||||
default: nodep->v3fatalSrc("Unknown emitVerilog format code: %" << c); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeTermop* nodep) override {
|
||||
emitVerilogFormat(nodep, nodep->emitVerilog());
|
||||
}
|
||||
virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeUniop* nodep) override {
|
||||
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp());
|
||||
}
|
||||
virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeBiop* nodep) override {
|
||||
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp());
|
||||
}
|
||||
virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeTriop* nodep) override {
|
||||
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(),
|
||||
nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstAttrOf* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAttrOf* nodep) override {
|
||||
putfs(nodep, "$_ATTROF(");
|
||||
iterateAndNextNull(nodep->fromp());
|
||||
if (nodep->dimp()) {
|
||||
|
|
@ -489,7 +487,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstInitArray* nodep) override {
|
||||
putfs(nodep, "`{");
|
||||
int comma = 0;
|
||||
const AstInitArray::KeyItemMap& mapr = nodep->map();
|
||||
|
|
@ -502,7 +500,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
puts("}");
|
||||
}
|
||||
virtual void visit(AstNodeCond* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCond* nodep) override {
|
||||
putbs("(");
|
||||
iterateAndNextNull(nodep->condp());
|
||||
putfs(nodep, " ? ");
|
||||
|
|
@ -511,7 +509,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->expr2p());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstRange* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstRange* nodep) 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]
|
||||
|
|
@ -526,7 +524,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
puts("]");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
iterateAndNextNull(nodep->fromp());
|
||||
puts("[");
|
||||
if (VN_IS(nodep->lsbp(), Const)) {
|
||||
|
|
@ -550,18 +548,18 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
puts("]");
|
||||
}
|
||||
virtual void visit(AstSliceSel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSliceSel* nodep) override {
|
||||
iterateAndNextNull(nodep->fromp());
|
||||
puts(cvtToStr(nodep->declRange()));
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTypedef* nodep) override {
|
||||
putfs(nodep, "typedef ");
|
||||
iterateAndNextNull(nodep->dtypep());
|
||||
puts(" ");
|
||||
puts(nodep->prettyName());
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstBasicDType* nodep) override {
|
||||
if (nodep->isSigned()) putfs(nodep, "signed ");
|
||||
putfs(nodep, nodep->prettyName());
|
||||
if (nodep->rangep()) {
|
||||
|
|
@ -574,28 +572,28 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
puts(":0] ");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConstDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstConstDType* nodep) override {
|
||||
putfs(nodep, "const ");
|
||||
iterate(nodep->subDTypep());
|
||||
}
|
||||
virtual void visit(AstNodeArrayDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeArrayDType* nodep) override {
|
||||
iterate(nodep->subDTypep());
|
||||
iterateAndNextNull(nodep->rangep());
|
||||
}
|
||||
virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeUOrStructDType* nodep) override {
|
||||
puts(nodep->verilogKwd() + " ");
|
||||
if (nodep->packed()) puts("packed ");
|
||||
puts("\n");
|
||||
iterateAndNextNull(nodep->membersp());
|
||||
puts("}");
|
||||
}
|
||||
virtual void visit(AstMemberDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstMemberDType* nodep) override {
|
||||
iterate(nodep->subDTypep());
|
||||
puts(" ");
|
||||
puts(nodep->name());
|
||||
puts("}");
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeFTaskRef* nodep) override {
|
||||
if (nodep->dotted() != "") {
|
||||
putfs(nodep, nodep->dotted());
|
||||
puts(".");
|
||||
|
|
@ -607,9 +605,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
iterateAndNextNull(nodep->pinsp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstArg* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->exprp()); }
|
||||
virtual void visit(AstArg* nodep) override { iterateAndNextNull(nodep->exprp()); }
|
||||
// Terminals
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
if (nodep->varScopep()) {
|
||||
putfs(nodep, nodep->varScopep()->prettyName());
|
||||
} else {
|
||||
|
|
@ -617,19 +615,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
puts(nodep->varp()->prettyName());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarXRef* nodep) override {
|
||||
putfs(nodep, nodep->dotted());
|
||||
puts(".");
|
||||
puts(nodep->varp()->prettyName());
|
||||
}
|
||||
virtual void visit(AstConst* nodep) VL_OVERRIDE {
|
||||
putfs(nodep, nodep->num().ascii(true, true));
|
||||
}
|
||||
virtual void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); }
|
||||
|
||||
// Just iterate
|
||||
virtual void visit(AstTopScope* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTopScope* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstScope* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
puts(" ");
|
||||
iterate(nodep->dtypep());
|
||||
|
|
@ -641,20 +637,20 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
puts("\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
m_sensesp = nodep->sensesp();
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
m_sensesp = NULL;
|
||||
m_sensesp = nullptr;
|
||||
}
|
||||
virtual void visit(AstVarScope*) VL_OVERRIDE {}
|
||||
virtual void visit(AstNodeText*) VL_OVERRIDE {}
|
||||
virtual void visit(AstTraceDecl*) VL_OVERRIDE {}
|
||||
virtual void visit(AstTraceInc*) VL_OVERRIDE {}
|
||||
virtual void visit(AstVarScope*) override {}
|
||||
virtual void visit(AstNodeText*) override {}
|
||||
virtual void visit(AstTraceDecl*) override {}
|
||||
virtual void visit(AstTraceInc*) override {}
|
||||
// NOPs
|
||||
virtual void visit(AstPragma*) VL_OVERRIDE {}
|
||||
virtual void visit(AstCell*) VL_OVERRIDE {} // Handled outside the Visit class
|
||||
virtual void visit(AstPragma*) override {}
|
||||
virtual void visit(AstCell*) override {} // Handled outside the Visit class
|
||||
// Default
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
puts(string("\n???? // ") + nodep->prettyTypeName() + "\n");
|
||||
iterateChildren(nodep);
|
||||
// Not v3fatalSrc so we keep processing
|
||||
|
|
@ -662,14 +658,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
}
|
||||
|
||||
public:
|
||||
bool m_suppressVarSemi; // Suppress emitting semicolon for AstVars
|
||||
explicit EmitVBaseVisitor(AstSenTree* domainp = NULL) {
|
||||
// Domain for printing one a ALWAYS under a ACTIVE
|
||||
m_suppressSemi = false;
|
||||
m_suppressVarSemi = false;
|
||||
m_sensesp = domainp;
|
||||
}
|
||||
virtual ~EmitVBaseVisitor() {}
|
||||
bool m_suppressVarSemi = false; // Suppress emitting semicolon for AstVars
|
||||
explicit EmitVBaseVisitor(AstSenTree* domainp = nullptr)
|
||||
: m_sensesp{domainp} {}
|
||||
virtual ~EmitVBaseVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -680,11 +672,11 @@ class EmitVFileVisitor : public EmitVBaseVisitor {
|
|||
V3OutFile* m_ofp;
|
||||
// METHODS
|
||||
V3OutFile* ofp() const { return m_ofp; }
|
||||
virtual void puts(const string& str) { ofp()->puts(str); }
|
||||
virtual void putbs(const string& str) { ofp()->putbs(str); }
|
||||
virtual void putfs(AstNode*, const string& str) { putbs(str); }
|
||||
virtual void putqs(AstNode*, const string& str) { putbs(str); }
|
||||
virtual void putsNoTracking(const string& str) { ofp()->putsNoTracking(str); }
|
||||
virtual void puts(const string& str) override { ofp()->puts(str); }
|
||||
virtual void putbs(const string& str) override { ofp()->putbs(str); }
|
||||
virtual void putfs(AstNode*, const string& str) override { putbs(str); }
|
||||
virtual void putqs(AstNode*, const string& str) override { putbs(str); }
|
||||
virtual void putsNoTracking(const string& str) override { ofp()->putsNoTracking(str); }
|
||||
|
||||
public:
|
||||
EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp, bool trackText = false,
|
||||
|
|
@ -694,7 +686,7 @@ public:
|
|||
m_suppressVarSemi = suppressVarSemi;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~EmitVFileVisitor() {}
|
||||
virtual ~EmitVFileVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -704,18 +696,18 @@ class EmitVStreamVisitor : public EmitVBaseVisitor {
|
|||
// MEMBERS
|
||||
std::ostream& m_os;
|
||||
// METHODS
|
||||
virtual void putsNoTracking(const string& str) { m_os << str; }
|
||||
virtual void puts(const string& str) { putsNoTracking(str); }
|
||||
virtual void putbs(const string& str) { puts(str); }
|
||||
virtual void putfs(AstNode*, const string& str) { putbs(str); }
|
||||
virtual void putqs(AstNode*, const string& str) { putbs(str); }
|
||||
virtual void putsNoTracking(const string& str) override { m_os << str; }
|
||||
virtual void puts(const string& str) override { putsNoTracking(str); }
|
||||
virtual void putbs(const string& str) override { puts(str); }
|
||||
virtual void putfs(AstNode*, const string& str) override { putbs(str); }
|
||||
virtual void putqs(AstNode*, const string& str) override { putbs(str); }
|
||||
|
||||
public:
|
||||
EmitVStreamVisitor(AstNode* nodep, std::ostream& os)
|
||||
: m_os(os) {
|
||||
: m_os(os) { // Need () or GCC 4.8 false warning
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~EmitVStreamVisitor() {}
|
||||
virtual ~EmitVStreamVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -728,7 +720,7 @@ class EmitVPrefixedFormatter : public V3OutFormatter {
|
|||
int m_column; // Rough location; need just zero or non-zero
|
||||
FileLine* m_prefixFl;
|
||||
// METHODS
|
||||
virtual void putcOutput(char chr) {
|
||||
virtual void putcOutput(char chr) override {
|
||||
if (chr == '\n') {
|
||||
m_column = 0;
|
||||
m_os << chr;
|
||||
|
|
@ -750,15 +742,16 @@ public:
|
|||
FileLine* prefixFl() const { return m_prefixFl; }
|
||||
int column() const { return m_column; }
|
||||
EmitVPrefixedFormatter(std::ostream& os, const string& prefix, int flWidth)
|
||||
: V3OutFormatter("__STREAM", V3OutFormatter::LA_VERILOG)
|
||||
, m_os(os)
|
||||
, m_prefix(prefix)
|
||||
, m_flWidth(flWidth) {
|
||||
: V3OutFormatter{"__STREAM", V3OutFormatter::LA_VERILOG}
|
||||
, m_os(os) // Need () or GCC 4.8 false warning
|
||||
, m_prefix{prefix}
|
||||
, m_flWidth{flWidth} {
|
||||
m_column = 0;
|
||||
m_prefixFl = v3Global.rootp()
|
||||
->fileline(); // NETLIST's fileline instead of NULL to avoid NULL checks
|
||||
m_prefixFl
|
||||
= v3Global.rootp()
|
||||
->fileline(); // NETLIST's fileline instead of nullptr to avoid nullptr checks
|
||||
}
|
||||
virtual ~EmitVPrefixedFormatter() {
|
||||
virtual ~EmitVPrefixedFormatter() override {
|
||||
if (m_column) puts("\n");
|
||||
}
|
||||
};
|
||||
|
|
@ -768,13 +761,13 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor {
|
|||
EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the
|
||||
// inheritance is another unused V3OutFormatter)
|
||||
// METHODS
|
||||
virtual void putsNoTracking(const string& str) { m_formatter.putsNoTracking(str); }
|
||||
virtual void puts(const string& str) { m_formatter.puts(str); }
|
||||
virtual void putsNoTracking(const string& str) override { m_formatter.putsNoTracking(str); }
|
||||
virtual void puts(const string& str) override { m_formatter.puts(str); }
|
||||
// We don't use m_formatter's putbs because the tokens will change filelines
|
||||
// and insert returns at the proper locations
|
||||
virtual void putbs(const string& str) { m_formatter.puts(str); }
|
||||
virtual void putfs(AstNode* nodep, const string& str) { putfsqs(nodep, str, false); }
|
||||
virtual void putqs(AstNode* nodep, const string& str) { putfsqs(nodep, str, true); }
|
||||
virtual void putbs(const string& str) override { m_formatter.puts(str); }
|
||||
virtual void putfs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, false); }
|
||||
virtual void putqs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, true); }
|
||||
void putfsqs(AstNode* nodep, const string& str, bool quiet) {
|
||||
if (m_formatter.prefixFl() != nodep->fileline()) {
|
||||
m_formatter.prefixFl(nodep->fileline());
|
||||
|
|
@ -787,12 +780,12 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor {
|
|||
public:
|
||||
EmitVPrefixedVisitor(AstNode* nodep, std::ostream& os, const string& prefix, int flWidth,
|
||||
AstSenTree* domainp, bool user3mark)
|
||||
: EmitVBaseVisitor(domainp)
|
||||
, m_formatter(os, prefix, flWidth) {
|
||||
: EmitVBaseVisitor{domainp}
|
||||
, m_formatter{os, prefix, flWidth} {
|
||||
if (user3mark) { AstUser3InUse::check(); }
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~EmitVPrefixedVisitor() {}
|
||||
virtual ~EmitVPrefixedVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
|
||||
// MEMBERS
|
||||
V3OutFile* m_ofp;
|
||||
uint64_t m_id;
|
||||
uint64_t m_id = 0;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -100,11 +100,11 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstAssignW* nodep) override {
|
||||
outputTag(nodep, "contassign"); // IEEE: vpiContAssign
|
||||
outputChildrenEnd(nodep, "contassign");
|
||||
}
|
||||
virtual void visit(AstCell* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
outputTag(nodep, "instance"); // IEEE: vpiInstance
|
||||
puts(" defName=");
|
||||
putsQuoted(nodep->modName()); // IEEE vpiDefName
|
||||
|
|
@ -112,12 +112,12 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
putsQuoted(nodep->origName());
|
||||
outputChildrenEnd(nodep, "instance");
|
||||
}
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
puts("<netlist>\n");
|
||||
iterateChildren(nodep);
|
||||
puts("</netlist>\n");
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" origName=");
|
||||
putsQuoted(nodep->origName());
|
||||
|
|
@ -127,7 +127,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
if (nodep->modPublic()) puts(" public=\"true\"");
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
AstVarType typ = nodep->varType();
|
||||
string kw = nodep->verilogKwd();
|
||||
string vt = nodep->dtypep()->name();
|
||||
|
|
@ -144,25 +144,26 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
puts(" origName=");
|
||||
putsQuoted(nodep->origName());
|
||||
// Attributes
|
||||
if (nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES)
|
||||
if (nodep->attrClocker() == VVarAttrClocker::CLOCKER_YES) {
|
||||
puts(" clocker=\"true\"");
|
||||
else if (nodep->attrClocker() == VVarAttrClocker::CLOCKER_NO)
|
||||
} 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())
|
||||
if (nodep->isGParam()) {
|
||||
puts(" param=\"true\"");
|
||||
else if (nodep->isParam())
|
||||
} 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) VL_OVERRIDE {
|
||||
virtual void visit(AstPin* nodep) override {
|
||||
// What we call a pin in verilator is a port in the IEEE spec.
|
||||
outputTag(nodep, "port"); // IEEE: vpiPort
|
||||
if (nodep->modVarp()->isIO()) {
|
||||
|
|
@ -172,12 +173,12 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
|
||||
outputChildrenEnd(nodep, "port");
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" edgeType=\"" + cvtToStr(nodep->edgeType().ascii()) + "\""); // IEEE vpiTopModule
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstModportVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstModportVarRef* nodep) override {
|
||||
// Dump direction for Modport references
|
||||
string kw = nodep->direction().xmlKwd();
|
||||
outputTag(nodep, "");
|
||||
|
|
@ -185,7 +186,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
putsQuoted(kw);
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarXRef* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" dotted=");
|
||||
putsQuoted(nodep->dotted());
|
||||
|
|
@ -193,7 +194,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
}
|
||||
|
||||
// Data types
|
||||
virtual void visit(AstBasicDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstBasicDType* nodep) override {
|
||||
outputTag(nodep, "basicdtype");
|
||||
if (nodep->isRanged()) {
|
||||
puts(" left=\"" + cvtToStr(nodep->left()) + "\"");
|
||||
|
|
@ -201,7 +202,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
}
|
||||
puts("/>\n");
|
||||
}
|
||||
virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstIfaceRefDType* nodep) override {
|
||||
string mpn;
|
||||
outputTag(nodep, "");
|
||||
if (nodep->isModport()) mpn = nodep->modportName();
|
||||
|
|
@ -209,19 +210,19 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
putsQuoted(mpn);
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" displaytype=");
|
||||
putsQuoted(nodep->verilogKwd());
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstElabDisplay* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstElabDisplay* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" displaytype=");
|
||||
putsQuoted(nodep->verilogKwd());
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstExtend* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstExtend* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" width=");
|
||||
putsQuoted(cvtToStr(nodep->width()));
|
||||
|
|
@ -229,7 +230,7 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
putsQuoted(cvtToStr(nodep->lhsp()->widthMinV()));
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstExtendS* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstExtendS* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" width=");
|
||||
putsQuoted(cvtToStr(nodep->width()));
|
||||
|
|
@ -239,18 +240,17 @@ class EmitXmlFileVisitor : public AstNVisitor {
|
|||
}
|
||||
|
||||
// Default
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
|
||||
public:
|
||||
EmitXmlFileVisitor(AstNode* nodep, V3OutFile* ofp) {
|
||||
m_ofp = ofp;
|
||||
m_id = 0;
|
||||
EmitXmlFileVisitor(AstNode* nodep, V3OutFile* ofp)
|
||||
: m_ofp{ofp} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~EmitXmlFileVisitor() {}
|
||||
virtual ~EmitXmlFileVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -267,11 +267,11 @@ private:
|
|||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
// Children are iterated backwards to ensure correct compilation order
|
||||
iterateChildrenBackwards(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
// Only list modules and interfaces
|
||||
// Assumes modules and interfaces list is already sorted level wise
|
||||
if (!nodep->dead() && (VN_IS(nodep, Module) || VN_IS(nodep, Iface))
|
||||
|
|
@ -280,28 +280,25 @@ private:
|
|||
}
|
||||
}
|
||||
//-----
|
||||
virtual void visit(AstNode*) VL_OVERRIDE {
|
||||
virtual void visit(AstNode*) override {
|
||||
// All modules are present at root so no need to iterate on children
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
ModuleFilesXmlVisitor(AstNetlist* nodep, std::ostream& os)
|
||||
: m_os(os)
|
||||
, m_modulesCovered()
|
||||
, m_nodeModules() {
|
||||
: m_os(os) { // Need () or GCC 4.8 false warning
|
||||
// Operate on whole netlist
|
||||
nodep->accept(*this);
|
||||
// Xml output
|
||||
m_os << "<module_files>\n";
|
||||
for (std::deque<FileLine*>::iterator it = m_nodeModules.begin(); it != m_nodeModules.end();
|
||||
++it) {
|
||||
m_os << "<file id=\"" << (*it)->filenameLetters() << "\" filename=\""
|
||||
<< (*it)->filename() << "\" language=\"" << (*it)->language().ascii() << "\"/>\n";
|
||||
for (const FileLine* ifp : m_nodeModules) {
|
||||
m_os << "<file id=\"" << ifp->filenameLetters() << "\" filename=\"" << ifp->filename()
|
||||
<< "\" language=\"" << ifp->language().ascii() << "\"/>\n";
|
||||
}
|
||||
m_os << "</module_files>\n";
|
||||
}
|
||||
virtual ~ModuleFilesXmlVisitor() {}
|
||||
virtual ~ModuleFilesXmlVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -312,13 +309,13 @@ private:
|
|||
// MEMBERS
|
||||
std::ostream& m_os;
|
||||
std::string m_hier;
|
||||
bool m_hasChildren;
|
||||
bool m_hasChildren = false;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
if (nodep->level() >= 0
|
||||
&& nodep->level() <= 2) { // ==2 because we don't add wrapper when in XML mode
|
||||
m_os << "<cells>\n";
|
||||
|
|
@ -337,7 +334,7 @@ private:
|
|||
m_os << "</cells>\n";
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
if (nodep->modp()->dead()) { return; }
|
||||
if (!m_hasChildren) m_os << ">\n";
|
||||
m_os << "<cell " << nodep->fileline()->xml() << " "
|
||||
|
|
@ -357,18 +354,16 @@ private:
|
|||
m_hasChildren = true;
|
||||
}
|
||||
//-----
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
HierCellsXmlVisitor(AstNetlist* nodep, std::ostream& os)
|
||||
: m_os(os)
|
||||
, m_hier("")
|
||||
, m_hasChildren(false) {
|
||||
: m_os(os) { // Need () or GCC 4.8 false warning
|
||||
// Operate on whole netlist
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~HierCellsXmlVisitor() {}
|
||||
virtual ~HierCellsXmlVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ bool V3Error::s_describedEachWarn[V3ErrorCode::_ENUM_MAX];
|
|||
bool V3Error::s_describedWarnings = false;
|
||||
bool V3Error::s_pretendError[V3ErrorCode::_ENUM_MAX];
|
||||
V3Error::MessagesSet V3Error::s_messages;
|
||||
V3Error::ErrorExitCb V3Error::s_errorExitCb = NULL;
|
||||
V3Error::ErrorExitCb V3Error::s_errorExitCb = nullptr;
|
||||
|
||||
struct v3errorIniter {
|
||||
v3errorIniter() { V3Error::init(); }
|
||||
|
|
@ -174,12 +174,10 @@ void V3Error::vlAbort() {
|
|||
// Global Functions
|
||||
|
||||
void V3Error::suppressThisWarning() {
|
||||
if (s_errorCode >= V3ErrorCode::EC_MIN) {
|
||||
#ifndef _V3ERROR_NO_GLOBAL_
|
||||
V3Stats::addStatSum(string("Warnings, Suppressed ") + s_errorCode.ascii(), 1);
|
||||
V3Stats::addStatSum(string("Warnings, Suppressed ") + s_errorCode.ascii(), 1);
|
||||
#endif
|
||||
s_errorSuppressed = true;
|
||||
}
|
||||
s_errorSuppressed = true;
|
||||
}
|
||||
|
||||
string V3Error::warnMore() { return string(msgPrefix().size(), ' '); }
|
||||
|
|
@ -212,7 +210,7 @@ void V3Error::v3errorEnd(std::ostringstream& sstr, const string& locationStr) {
|
|||
s_messages.insert(msg);
|
||||
if (!locationStr.empty()) {
|
||||
string locationMsg = warnMore() + locationStr + "\n";
|
||||
size_t pos = msg.find("\n");
|
||||
size_t pos = msg.find('\n');
|
||||
msg.insert(pos + 1, locationMsg);
|
||||
}
|
||||
// Output
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
class V3ErrorCode {
|
||||
public:
|
||||
// clang-format off
|
||||
enum en {
|
||||
enum en: uint8_t {
|
||||
EC_MIN=0, // Keep first
|
||||
//
|
||||
EC_INFO, // General information out
|
||||
|
|
@ -80,6 +80,7 @@ public:
|
|||
DEPRECATED, // Feature will be deprecated
|
||||
ENDLABEL, // End lable name mismatch
|
||||
GENCLK, // Generated Clock
|
||||
HIERBLOCK, // Ignored hierarchical block setting
|
||||
IFDEPTH, // If statements too deep
|
||||
IGNOREDRETURN, // Ignoring return value (function as task)
|
||||
IMPERFECTSCH, // Imperfect schedule (disabled by default)
|
||||
|
|
@ -97,6 +98,7 @@ public:
|
|||
PINMISSING, // Cell pin not specified
|
||||
PINNOCONNECT, // Cell pin not connected
|
||||
PINCONNECTEMPTY,// Cell pin connected by name with empty reference
|
||||
PKGNODECL, // Error: Package/class needs to be predeclared
|
||||
PROCASSWIRE, // Procedural assignment on wire
|
||||
REALCVT, // Real conversion
|
||||
REDEFMACRO, // Redefining existing define macro
|
||||
|
|
@ -128,13 +130,13 @@ public:
|
|||
// clang-format on
|
||||
enum en m_e;
|
||||
inline V3ErrorCode()
|
||||
: m_e(EC_MIN) {}
|
||||
: m_e{EC_MIN} {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline V3ErrorCode(en _e)
|
||||
: m_e(_e) {}
|
||||
: m_e{_e} {}
|
||||
explicit V3ErrorCode(const char* msgp); // Matching code or ERROR
|
||||
explicit inline V3ErrorCode(int _e)
|
||||
: m_e(static_cast<en>(_e)) {}
|
||||
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
||||
operator en() const { return m_e; }
|
||||
const char* ascii() const {
|
||||
// clang-format off
|
||||
|
|
@ -152,13 +154,13 @@ public:
|
|||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CDCRSTLOGIC", "CLKDATA",
|
||||
"CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG",
|
||||
"DEFPARAM", "DECLFILENAME", "DEPRECATED",
|
||||
"ENDLABEL", "GENCLK",
|
||||
"ENDLABEL", "GENCLK", "HIERBLOCK",
|
||||
"IFDEPTH", "IGNOREDRETURN",
|
||||
"IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
|
||||
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
|
||||
"LITENDIAN", "MODDUP",
|
||||
"MULTIDRIVEN", "MULTITOP",
|
||||
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PROCASSWIRE",
|
||||
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY", "PKGNODECL", "PROCASSWIRE",
|
||||
"REALCVT", "REDEFMACRO",
|
||||
"SELRANGE", "SHORTREAL", "SPLITVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||
"TICKCOUNT", "TIMESCALEMOD",
|
||||
|
|
@ -181,7 +183,7 @@ public:
|
|||
// Later -Werror- options may make more of these.
|
||||
bool pretendError() const {
|
||||
return (m_e == ASSIGNIN || m_e == BLKANDNBLK || m_e == BLKLOOPINIT || m_e == CONTASSREG
|
||||
|| m_e == IMPURE || m_e == PROCASSWIRE //
|
||||
|| m_e == IMPURE || m_e == PKGNODECL || m_e == PROCASSWIRE //
|
||||
|| m_e == TIMESCALEMOD); // Says IEEE
|
||||
}
|
||||
// Warnings to mention manual
|
||||
|
|
@ -238,7 +240,7 @@ private:
|
|||
static MessagesSet s_messages; // What errors we've outputted
|
||||
static ErrorExitCb s_errorExitCb; // Callback when error occurs for dumping
|
||||
|
||||
enum MaxErrors { MAX_ERRORS = 50 }; // Fatal after this may errors
|
||||
static constexpr unsigned MAX_ERRORS = 50; // Fatal after this may errors
|
||||
|
||||
V3Error() {
|
||||
std::cerr << ("Static class");
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ private:
|
|||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
AstNode* m_stmtp; // Current statement
|
||||
AstNode* m_stmtp = nullptr; // Current statement
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
|
@ -292,7 +292,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstExtend* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstExtend* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isWide()) {
|
||||
|
|
@ -318,7 +318,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstSel* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
// Remember, Sel's may have non-integer rhs, so need to optimize for that!
|
||||
|
|
@ -341,7 +341,7 @@ private:
|
|||
AstNode* lowp = new AstShiftR(nodep->fileline(), lowwordp, newSelBitBit(nodep->lsbp()),
|
||||
nodep->width());
|
||||
// If > 1 bit, we might be crossing the word boundary
|
||||
AstNode* midp = NULL;
|
||||
AstNode* midp = nullptr;
|
||||
V3Number zero(nodep, longOrQuadWidth(nodep));
|
||||
if (nodep->widthConst() > 1) {
|
||||
AstNode* midwordp = // SEL(from,[1+wordnum])
|
||||
|
|
@ -378,7 +378,7 @@ private:
|
|||
}
|
||||
}
|
||||
// If > 32 bits, we might be crossing the second word boundary
|
||||
AstNode* hip = NULL;
|
||||
AstNode* hip = nullptr;
|
||||
if (nodep->widthConst() > VL_EDATASIZE) {
|
||||
AstNode* hiwordp = // SEL(from,[2+wordnum])
|
||||
newWordSel(nodep->fromp()->fileline(), nodep->fromp()->cloneTree(true),
|
||||
|
|
@ -600,7 +600,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstConcat* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstConcat* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isWide()) {
|
||||
|
|
@ -642,7 +642,7 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual void visit(AstReplicate* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstReplicate* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isWide()) {
|
||||
|
|
@ -705,16 +705,16 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual void visit(AstChangeXor* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstChangeXor* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
UINFO(8, " Wordize ChangeXor " << nodep << endl);
|
||||
// -> (0=={or{for each_word{WORDSEL(lhs,#)^WORDSEL(rhs,#)}}}
|
||||
AstNode* newp = NULL;
|
||||
AstNode* newp = nullptr;
|
||||
for (int w = 0; w < nodep->lhsp()->widthWords(); w++) {
|
||||
AstNode* eqp = new AstXor(nodep->fileline(), newAstWordSelClone(nodep->lhsp(), w),
|
||||
newAstWordSelClone(nodep->rhsp(), w));
|
||||
newp = (newp == NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp));
|
||||
newp = (newp == nullptr) ? eqp : (new AstOr(nodep->fileline(), newp, eqp));
|
||||
}
|
||||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
}
|
||||
|
|
@ -725,11 +725,11 @@ private:
|
|||
if (nodep->lhsp()->isWide()) {
|
||||
UINFO(8, " Wordize EQ/NEQ " << nodep << endl);
|
||||
// -> (0=={or{for each_word{WORDSEL(lhs,#)^WORDSEL(rhs,#)}}}
|
||||
AstNode* newp = NULL;
|
||||
AstNode* newp = nullptr;
|
||||
for (int w = 0; w < nodep->lhsp()->widthWords(); w++) {
|
||||
AstNode* eqp = new AstXor(nodep->fileline(), newAstWordSelClone(nodep->lhsp(), w),
|
||||
newAstWordSelClone(nodep->rhsp(), w));
|
||||
newp = (newp == NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp));
|
||||
newp = (newp == nullptr) ? eqp : (new AstOr(nodep->fileline(), newp, eqp));
|
||||
}
|
||||
if (VN_IS(nodep, Neq)) {
|
||||
newp
|
||||
|
|
@ -742,19 +742,19 @@ private:
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEq* nodep) VL_OVERRIDE { visitEqNeq(nodep); }
|
||||
virtual void visit(AstNeq* nodep) VL_OVERRIDE { visitEqNeq(nodep); }
|
||||
virtual void visit(AstEq* nodep) override { visitEqNeq(nodep); }
|
||||
virtual void visit(AstNeq* nodep) override { visitEqNeq(nodep); }
|
||||
|
||||
virtual void visit(AstRedOr* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstRedOr* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
UINFO(8, " Wordize REDOR " << nodep << endl);
|
||||
// -> (0!={or{for each_word{WORDSEL(lhs,#)}}}
|
||||
AstNode* newp = NULL;
|
||||
AstNode* newp = nullptr;
|
||||
for (int w = 0; w < nodep->lhsp()->widthWords(); w++) {
|
||||
AstNode* eqp = newAstWordSelClone(nodep->lhsp(), w);
|
||||
newp = (newp == NULL) ? eqp : (new AstOr(nodep->fileline(), newp, eqp));
|
||||
newp = (newp == nullptr) ? eqp : (new AstOr(nodep->fileline(), newp, eqp));
|
||||
}
|
||||
newp = new AstNeq(nodep->fileline(),
|
||||
new AstConst(nodep->fileline(), AstConst::SizedEData(), 0), newp);
|
||||
|
|
@ -769,13 +769,13 @@ private:
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedAnd* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstRedAnd* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
UINFO(8, " Wordize REDAND " << nodep << endl);
|
||||
// -> (0!={and{for each_word{WORDSEL(lhs,#)}}}
|
||||
AstNode* newp = NULL;
|
||||
AstNode* newp = nullptr;
|
||||
for (int w = 0; w < nodep->lhsp()->widthWords(); w++) {
|
||||
AstNode* eqp = newAstWordSelClone(nodep->lhsp(), w);
|
||||
if (w == nodep->lhsp()->widthWords() - 1) {
|
||||
|
|
@ -787,7 +787,7 @@ private:
|
|||
// cppcheck-suppress memleak
|
||||
eqp);
|
||||
}
|
||||
newp = (newp == NULL) ? eqp : (new AstAnd(nodep->fileline(), newp, eqp));
|
||||
newp = (newp == nullptr) ? eqp : (new AstAnd(nodep->fileline(), newp, eqp));
|
||||
}
|
||||
newp = new AstEq(
|
||||
nodep->fileline(),
|
||||
|
|
@ -802,16 +802,16 @@ private:
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedXor* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstRedXor* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
UINFO(8, " Wordize REDXOR " << nodep << endl);
|
||||
// -> (0!={redxor{for each_word{XOR(WORDSEL(lhs,#))}}}
|
||||
AstNode* newp = NULL;
|
||||
AstNode* newp = nullptr;
|
||||
for (int w = 0; w < nodep->lhsp()->widthWords(); w++) {
|
||||
AstNode* eqp = newAstWordSelClone(nodep->lhsp(), w);
|
||||
newp = (newp == NULL) ? eqp : (new AstXor(nodep->fileline(), newp, eqp));
|
||||
newp = (newp == nullptr) ? eqp : (new AstXor(nodep->fileline(), newp, eqp));
|
||||
}
|
||||
newp = new AstRedXor(nodep->fileline(), newp);
|
||||
UINFO(8, " Wordize REDXORnew " << newp << endl);
|
||||
|
|
@ -821,7 +821,7 @@ private:
|
|||
// which the inlined function does nicely.
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeStmt* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (!nodep->isStatement()) {
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -829,9 +829,9 @@ private:
|
|||
}
|
||||
m_stmtp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_stmtp = NULL;
|
||||
m_stmtp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
m_stmtp = nodep;
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -869,20 +869,17 @@ private:
|
|||
}
|
||||
// Cleanup common code
|
||||
if (did) VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
m_stmtp = NULL;
|
||||
m_stmtp = nullptr;
|
||||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ExpandVisitor(AstNetlist* nodep) {
|
||||
m_stmtp = NULL;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~ExpandVisitor() {}
|
||||
explicit ExpandVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ExpandVisitor() override {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
|||
140
src/V3File.cpp
140
src/V3File.cpp
|
|
@ -56,8 +56,8 @@
|
|||
|
||||
// If change this code, run a test with the below size set very small
|
||||
//#define INFILTER_IPC_BUFSIZ 16
|
||||
#define INFILTER_IPC_BUFSIZ (64 * 1024) // For debug, try this as a small number
|
||||
#define INFILTER_CACHE_MAX (64 * 1024) // Maximum bytes to cache if same file read twice
|
||||
constexpr int INFILTER_IPC_BUFSIZ = (64 * 1024); // For debug, try this as a small number
|
||||
constexpr int INFILTER_CACHE_MAX = (64 * 1024); // Maximum bytes to cache if same file read twice
|
||||
|
||||
//######################################################################
|
||||
// V3File Internal state
|
||||
|
|
@ -72,9 +72,9 @@ class V3FileDependImp {
|
|||
struct stat m_stat; // Stat information
|
||||
public:
|
||||
DependFile(const string& filename, bool target)
|
||||
: m_target(target)
|
||||
, m_exists(true)
|
||||
, m_filename(filename) {
|
||||
: m_target{target}
|
||||
, m_exists{true}
|
||||
, m_filename{filename} {
|
||||
m_stat.st_ctime = 0;
|
||||
m_stat.st_mtime = 0;
|
||||
}
|
||||
|
|
@ -146,29 +146,26 @@ V3FileDependImp dependImp; // Depend implementation class
|
|||
// V3FileDependImp
|
||||
|
||||
inline void V3FileDependImp::writeDepend(const string& filename) {
|
||||
const vl_unique_ptr<std::ofstream> ofp(V3File::new_ofstream(filename));
|
||||
const std::unique_ptr<std::ofstream> ofp(V3File::new_ofstream(filename));
|
||||
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||
|
||||
for (std::set<DependFile>::iterator iter = m_filenameList.begin();
|
||||
iter != m_filenameList.end(); ++iter) {
|
||||
if (iter->target()) { *ofp << iter->filename() << " "; }
|
||||
for (const DependFile& i : m_filenameList) {
|
||||
if (i.target()) *ofp << i.filename() << " ";
|
||||
}
|
||||
*ofp << " : ";
|
||||
*ofp << v3Global.opt.bin();
|
||||
*ofp << " ";
|
||||
|
||||
for (std::set<DependFile>::iterator iter = m_filenameList.begin();
|
||||
iter != m_filenameList.end(); ++iter) {
|
||||
if (!iter->target()) { *ofp << iter->filename() << " "; }
|
||||
for (const DependFile& i : m_filenameList) {
|
||||
if (!i.target()) *ofp << i.filename() << " ";
|
||||
}
|
||||
|
||||
*ofp << endl;
|
||||
|
||||
if (v3Global.opt.makePhony()) {
|
||||
*ofp << endl;
|
||||
for (std::set<DependFile>::iterator iter = m_filenameList.begin();
|
||||
iter != m_filenameList.end(); ++iter) {
|
||||
if (!iter->target()) { *ofp << iter->filename() << ":" << endl; }
|
||||
for (const DependFile& i : m_filenameList) {
|
||||
if (!i.target()) *ofp << i.filename() << ":" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -183,7 +180,7 @@ inline std::vector<string> V3FileDependImp::getAllDeps() const {
|
|||
}
|
||||
|
||||
inline void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) {
|
||||
const vl_unique_ptr<std::ofstream> ofp(V3File::new_ofstream(filename));
|
||||
const std::unique_ptr<std::ofstream> ofp(V3File::new_ofstream(filename));
|
||||
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||
|
||||
string cmdline = stripQuotes(cmdlineIn);
|
||||
|
|
@ -219,7 +216,7 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm
|
|||
}
|
||||
|
||||
inline bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn) {
|
||||
const vl_unique_ptr<std::ifstream> ifp(V3File::new_ifstream_nodepend(filename));
|
||||
const std::unique_ptr<std::ifstream> ifp(V3File::new_ifstream_nodepend(filename));
|
||||
if (ifp->fail()) {
|
||||
UINFO(2, " --check-times failed: no input " << filename << endl);
|
||||
return false;
|
||||
|
|
@ -326,6 +323,7 @@ void V3File::createMakeDir() {
|
|||
if (!created) {
|
||||
created = true;
|
||||
V3Os::createDir(v3Global.opt.makeDir());
|
||||
if (v3Global.opt.hierTop()) { V3Os::createDir(v3Global.opt.hierTopDataDir()); }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -337,16 +335,16 @@ class VInFilterImp {
|
|||
typedef VInFilter::StrList StrList;
|
||||
|
||||
FileContentsMap m_contentsMap; // Cache of file contents
|
||||
bool m_readEof; // Received EOF on read
|
||||
bool m_readEof = false; // Received EOF on read
|
||||
#ifdef INFILTER_PIPE
|
||||
pid_t m_pid; // fork() process id
|
||||
pid_t m_pid = 0; // fork() process id
|
||||
#else
|
||||
int m_pid; // fork() process id - always zero as disabled
|
||||
int m_pid = 0; // fork() process id - always zero as disabled
|
||||
#endif
|
||||
bool m_pidExited;
|
||||
int m_pidStatus;
|
||||
int m_writeFd; // File descriptor TO filter
|
||||
int m_readFd; // File descriptor FROM filter
|
||||
bool m_pidExited = false;
|
||||
int m_pidStatus = 0;
|
||||
int m_writeFd = 0; // File descriptor TO filter
|
||||
int m_readFd = 0; // File descriptor FROM filter
|
||||
|
||||
private:
|
||||
// METHODS
|
||||
|
|
@ -522,7 +520,7 @@ private:
|
|||
dup2(fd_stdout[P_WR], 1);
|
||||
// And stderr comes from parent
|
||||
|
||||
execl("/bin/sh", "sh", "-c", command.c_str(), static_cast<char*>(NULL));
|
||||
execl("/bin/sh", "sh", "-c", command.c_str(), static_cast<char*>(nullptr));
|
||||
// Don't use v3fatal, we don't share the common structures any more
|
||||
fprintf(stderr, "--pipe-filter: exec failed: %s\n", strerror(errno));
|
||||
_exit(1);
|
||||
|
|
@ -575,7 +573,7 @@ protected:
|
|||
friend class VInFilter;
|
||||
// Read file contents and return it
|
||||
bool readWholefile(const string& filename, StrList& outl) {
|
||||
FileContentsMap::iterator it = m_contentsMap.find(filename);
|
||||
const auto it = m_contentsMap.find(filename);
|
||||
if (it != m_contentsMap.end()) {
|
||||
outl.push_back(it->second);
|
||||
return true;
|
||||
|
|
@ -591,24 +589,16 @@ protected:
|
|||
}
|
||||
size_t listSize(StrList& sl) {
|
||||
size_t out = 0;
|
||||
for (StrList::iterator it = sl.begin(); it != sl.end(); ++it) out += it->length();
|
||||
for (const string& i : sl) out += i.length();
|
||||
return out;
|
||||
}
|
||||
string listString(StrList& sl) {
|
||||
string out;
|
||||
for (StrList::iterator it = sl.begin(); it != sl.end(); ++it) out += *it;
|
||||
for (const string& i : sl) out += i;
|
||||
return out;
|
||||
}
|
||||
// CONSTRUCTORS
|
||||
explicit VInFilterImp(const string& command) {
|
||||
m_readEof = false;
|
||||
m_pid = 0;
|
||||
m_pidExited = false;
|
||||
m_pidStatus = 0;
|
||||
m_writeFd = 0;
|
||||
m_readFd = 0;
|
||||
start(command);
|
||||
}
|
||||
explicit VInFilterImp(const string& command) { start(command); }
|
||||
~VInFilterImp() { stop(); }
|
||||
};
|
||||
|
||||
|
|
@ -618,7 +608,7 @@ protected:
|
|||
|
||||
VInFilter::VInFilter(const string& command) { m_impp = new VInFilterImp(command); }
|
||||
VInFilter::~VInFilter() {
|
||||
if (m_impp) VL_DO_CLEAR(delete m_impp, m_impp = NULL);
|
||||
if (m_impp) VL_DO_CLEAR(delete m_impp, m_impp = nullptr);
|
||||
}
|
||||
|
||||
bool VInFilter::readWholefile(const string& filename, VInFilter::StrList& outl) {
|
||||
|
|
@ -630,14 +620,8 @@ bool VInFilter::readWholefile(const string& filename, VInFilter::StrList& outl)
|
|||
// V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code.
|
||||
|
||||
V3OutFormatter::V3OutFormatter(const string& filename, V3OutFormatter::Language lang)
|
||||
: m_filename(filename)
|
||||
, m_lang(lang)
|
||||
, m_lineno(1)
|
||||
, m_column(0)
|
||||
, m_nobreak(false)
|
||||
, m_prependIndent(true)
|
||||
, m_indentLevel(0)
|
||||
, m_bracketLevel(0) {
|
||||
: m_filename{filename}
|
||||
, m_lang{lang} {
|
||||
m_blockIndent = v3Global.opt.decoration() ? 4 : 1;
|
||||
m_commaWidth = v3Global.opt.decoration() ? 50 : 150;
|
||||
}
|
||||
|
|
@ -844,14 +828,12 @@ void V3OutFormatter::putsQuoted(const string& strg) {
|
|||
// Don't use to quote a filename for #include - #include doesn't \ escape.
|
||||
putcNoTracking('"');
|
||||
string quoted = quoteNameControls(strg);
|
||||
for (string::const_iterator cp = quoted.begin(); cp != quoted.end(); ++cp) {
|
||||
putcNoTracking(*cp);
|
||||
}
|
||||
for (const char c : quoted) putcNoTracking(c);
|
||||
putcNoTracking('"');
|
||||
}
|
||||
void V3OutFormatter::putsNoTracking(const string& strg) {
|
||||
// Don't track {}'s, probably because it's a $display format string
|
||||
for (string::const_iterator cp = strg.begin(); cp != strg.end(); ++cp) putcNoTracking(*cp);
|
||||
for (const char c : strg) putcNoTracking(c);
|
||||
}
|
||||
|
||||
void V3OutFormatter::putcNoTracking(char chr) {
|
||||
|
|
@ -880,43 +862,43 @@ string V3OutFormatter::quoteNameControls(const string& namein, V3OutFormatter::L
|
|||
string out;
|
||||
if (lang == LA_XML) {
|
||||
// Encode chars into XML string
|
||||
for (string::const_iterator pos = namein.begin(); pos != namein.end(); ++pos) {
|
||||
if (pos[0] == '"') {
|
||||
for (const char c : namein) {
|
||||
if (c == '"') {
|
||||
out += string(""");
|
||||
} else if (pos[0] == '\'') {
|
||||
} else if (c == '\'') {
|
||||
out += string("'");
|
||||
} else if (pos[0] == '<') {
|
||||
} else if (c == '<') {
|
||||
out += string("<");
|
||||
} else if (pos[0] == '>') {
|
||||
} else if (c == '>') {
|
||||
out += string(">");
|
||||
} else if (pos[0] == '&') {
|
||||
} else if (c == '&') {
|
||||
out += string("&");
|
||||
} else if (isprint(pos[0])) {
|
||||
out += pos[0];
|
||||
} else if (isprint(c)) {
|
||||
out += c;
|
||||
} else {
|
||||
char decimal[10];
|
||||
sprintf(decimal, "&#%u;", (unsigned char)pos[0]);
|
||||
sprintf(decimal, "&#%u;", (unsigned char)c);
|
||||
out += decimal;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Encode control chars into C style escapes
|
||||
for (string::const_iterator pos = namein.begin(); pos != namein.end(); ++pos) {
|
||||
if (pos[0] == '\\' || pos[0] == '"') {
|
||||
out += string("\\") + pos[0];
|
||||
} else if (pos[0] == '\n') {
|
||||
for (const char c : namein) {
|
||||
if (c == '\\' || c == '"') {
|
||||
out += string("\\") + c;
|
||||
} else if (c == '\n') {
|
||||
out += "\\n";
|
||||
} else if (pos[0] == '\r') {
|
||||
} else if (c == '\r') {
|
||||
out += "\\r";
|
||||
} else if (pos[0] == '\t') {
|
||||
} else if (c == '\t') {
|
||||
out += "\\t";
|
||||
} else if (isprint(pos[0])) {
|
||||
out += pos[0];
|
||||
} else if (isprint(c)) {
|
||||
out += c;
|
||||
} else {
|
||||
// This will also cover \a etc
|
||||
// Can't use %03o as messes up when signed
|
||||
char octal[10];
|
||||
sprintf(octal, "\\%o%o%o", (pos[0] >> 6) & 3, (pos[0] >> 3) & 7, pos[0] & 7);
|
||||
sprintf(octal, "\\%o%o%o", (c >> 6) & 3, (c >> 3) & 7, c & 7);
|
||||
out += octal;
|
||||
}
|
||||
}
|
||||
|
|
@ -940,20 +922,20 @@ void V3OutFormatter::printf(const char* fmt...) {
|
|||
// V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code.
|
||||
|
||||
V3OutFile::V3OutFile(const string& filename, V3OutFormatter::Language lang)
|
||||
: V3OutFormatter(filename, lang) {
|
||||
if ((m_fp = V3File::new_fopen_w(filename)) == NULL) { v3fatal("Cannot write " << filename); }
|
||||
: V3OutFormatter{filename, lang} {
|
||||
if ((m_fp = V3File::new_fopen_w(filename)) == nullptr) {
|
||||
v3fatal("Cannot write " << filename);
|
||||
}
|
||||
}
|
||||
|
||||
V3OutFile::~V3OutFile() {
|
||||
if (m_fp) fclose(m_fp);
|
||||
m_fp = NULL;
|
||||
m_fp = nullptr;
|
||||
}
|
||||
|
||||
void V3OutFile::putsForceIncs() {
|
||||
const V3StringList& forceIncs = v3Global.opt.forceIncs();
|
||||
for (V3StringList::const_iterator it = forceIncs.begin(); it != forceIncs.end(); ++it) {
|
||||
puts("#include \"" + *it + "\"\n");
|
||||
}
|
||||
for (const string& i : forceIncs) { puts("#include \"" + i + "\"\n"); }
|
||||
}
|
||||
|
||||
void V3OutCFile::putsGuard() {
|
||||
|
|
@ -974,7 +956,7 @@ class VIdProtectImp {
|
|||
// MEMBERS
|
||||
typedef std::map<string, string> IdMap;
|
||||
IdMap m_nameMap; // Map of old name into new name
|
||||
typedef vl_unordered_set<std::string> IdSet;
|
||||
typedef std::unordered_set<std::string> IdSet;
|
||||
IdSet m_newIdSet; // Which new names exist
|
||||
protected:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -995,7 +977,7 @@ public:
|
|||
// METHODS
|
||||
string passthru(const string& old) {
|
||||
if (!v3Global.opt.protectIds()) return old;
|
||||
IdMap::iterator it = m_nameMap.find(old);
|
||||
const auto it = m_nameMap.find(old);
|
||||
if (it != m_nameMap.end()) {
|
||||
// No way to go back and correct the older crypt name
|
||||
UASSERT(old == it->second,
|
||||
|
|
@ -1008,10 +990,10 @@ public:
|
|||
}
|
||||
string protectIf(const string& old, bool doIt) {
|
||||
if (!v3Global.opt.protectIds() || old.empty() || !doIt) return old;
|
||||
IdMap::iterator it = m_nameMap.find(old);
|
||||
if (it != m_nameMap.end())
|
||||
const auto it = m_nameMap.find(old);
|
||||
if (it != m_nameMap.end()) {
|
||||
return it->second;
|
||||
else {
|
||||
} else {
|
||||
string out;
|
||||
if (v3Global.opt.debugProtect()) {
|
||||
// This lets us see the symbol being protected to debug cases
|
||||
|
|
|
|||
49
src/V3File.h
49
src/V3File.h
|
|
@ -101,10 +101,10 @@ public:
|
|||
|
||||
class V3OutFormatter {
|
||||
// TYPES
|
||||
enum MiscConsts { MAXSPACE = 80 }; // After this indent, stop indenting more
|
||||
static constexpr int MAXSPACE = 80; // After this indent, stop indenting more
|
||||
public:
|
||||
enum AlignClass { AL_AUTO = 0, AL_STATIC = 1 };
|
||||
enum Language {
|
||||
enum AlignClass : uint8_t { AL_AUTO = 0, AL_STATIC = 1 };
|
||||
enum Language : uint8_t {
|
||||
LA_C = 0,
|
||||
LA_VERILOG = 1,
|
||||
LA_MK = 2,
|
||||
|
|
@ -117,13 +117,13 @@ private:
|
|||
Language m_lang; // Indenting Verilog code
|
||||
int m_blockIndent; // Characters per block indent
|
||||
int m_commaWidth; // Width after which to break at ,'s
|
||||
int m_lineno;
|
||||
int m_column;
|
||||
int m_nobreak; // Basic operator or begin paren, don't break next
|
||||
bool m_prependIndent;
|
||||
int m_indentLevel; // Current {} indentation
|
||||
int m_lineno = 1;
|
||||
int m_column = 0;
|
||||
int m_nobreak = false; // Basic operator or begin paren, don't break next
|
||||
bool m_prependIndent = true;
|
||||
int m_indentLevel = 0; // Current {} indentation
|
||||
std::stack<int> m_parenVec; // Stack of columns where last ( was
|
||||
int m_bracketLevel; // Intenting = { block, indicates number of {'s seen.
|
||||
int m_bracketLevel = 0; // Intenting = { block, indicates number of {'s seen.
|
||||
|
||||
int endLevels(const char* strg);
|
||||
void putcNoTracking(char chr);
|
||||
|
|
@ -182,24 +182,23 @@ class V3OutFile : public V3OutFormatter {
|
|||
|
||||
public:
|
||||
V3OutFile(const string& filename, V3OutFormatter::Language lang);
|
||||
virtual ~V3OutFile();
|
||||
virtual ~V3OutFile() override;
|
||||
void putsForceIncs();
|
||||
|
||||
private:
|
||||
// CALLBACKS
|
||||
virtual void putcOutput(char chr) { fputc(chr, m_fp); }
|
||||
virtual void putcOutput(char chr) override { fputc(chr, m_fp); }
|
||||
};
|
||||
|
||||
class V3OutCFile : public V3OutFile {
|
||||
int m_guard; // Created header guard
|
||||
int m_guard = false; // Created header guard
|
||||
int m_private; // 1 = Most recently emitted private:, 2 = public:
|
||||
public:
|
||||
explicit V3OutCFile(const string& filename)
|
||||
: V3OutFile(filename, V3OutFormatter::LA_C)
|
||||
, m_guard(false) {
|
||||
: V3OutFile{filename, V3OutFormatter::LA_C} {
|
||||
resetPrivate();
|
||||
}
|
||||
virtual ~V3OutCFile() {}
|
||||
virtual ~V3OutCFile() override {}
|
||||
virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); }
|
||||
virtual void putsIntTopInclude() { putsForceIncs(); }
|
||||
virtual void putsGuard();
|
||||
|
|
@ -222,10 +221,10 @@ public:
|
|||
class V3OutScFile : public V3OutCFile {
|
||||
public:
|
||||
explicit V3OutScFile(const string& filename)
|
||||
: V3OutCFile(filename) {}
|
||||
virtual ~V3OutScFile() {}
|
||||
virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
virtual void putsIntTopInclude() {
|
||||
: V3OutCFile{filename} {}
|
||||
virtual ~V3OutScFile() override {}
|
||||
virtual void putsHeader() override { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
virtual void putsIntTopInclude() override {
|
||||
putsForceIncs();
|
||||
puts("#include \"systemc.h\"\n");
|
||||
puts("#include \"verilated_sc.h\"\n");
|
||||
|
|
@ -235,26 +234,26 @@ public:
|
|||
class V3OutVFile : public V3OutFile {
|
||||
public:
|
||||
explicit V3OutVFile(const string& filename)
|
||||
: V3OutFile(filename, V3OutFormatter::LA_VERILOG) {}
|
||||
virtual ~V3OutVFile() {}
|
||||
: V3OutFile{filename, V3OutFormatter::LA_VERILOG} {}
|
||||
virtual ~V3OutVFile() override {}
|
||||
virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); }
|
||||
};
|
||||
|
||||
class V3OutXmlFile : public V3OutFile {
|
||||
public:
|
||||
explicit V3OutXmlFile(const string& filename)
|
||||
: V3OutFile(filename, V3OutFormatter::LA_XML) {
|
||||
: V3OutFile{filename, V3OutFormatter::LA_XML} {
|
||||
blockIndent(2);
|
||||
}
|
||||
virtual ~V3OutXmlFile() {}
|
||||
virtual ~V3OutXmlFile() override {}
|
||||
virtual void putsHeader() { puts("<?xml version=\"1.0\" ?>\n"); }
|
||||
};
|
||||
|
||||
class V3OutMkFile : public V3OutFile {
|
||||
public:
|
||||
explicit V3OutMkFile(const string& filename)
|
||||
: V3OutFile(filename, V3OutFormatter::LA_MK) {}
|
||||
virtual ~V3OutMkFile() {}
|
||||
: V3OutFile{filename, V3OutFormatter::LA_MK} {}
|
||||
virtual ~V3OutMkFile() override {}
|
||||
virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); }
|
||||
// No automatic indentation yet.
|
||||
void puts(const char* strg) { putsNoTracking(strg); }
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include VL_INCLUDE_UNORDERED_SET
|
||||
#include <unordered_set>
|
||||
|
||||
//######################################################################
|
||||
// FileLineSingleton class functions
|
||||
|
|
@ -58,7 +58,7 @@ string FileLineSingleton::filenameLetters(int fileno) {
|
|||
//! We associate a language with each source file, so we also set the default
|
||||
//! for this.
|
||||
int FileLineSingleton::nameToNumber(const string& filename) {
|
||||
FileNameNumMap::const_iterator it = m_namemap.find(filename);
|
||||
const auto it = vlstd::as_const(m_namemap).find(filename);
|
||||
if (VL_LIKELY(it != m_namemap.end())) return it->second;
|
||||
int num = m_names.size();
|
||||
m_names.push_back(filename);
|
||||
|
|
@ -142,16 +142,16 @@ std::ostream& operator<<(std::ostream& os, VFileContent* contentp) {
|
|||
//######################################################################
|
||||
// FileLine class functions
|
||||
|
||||
FileLine::FileLine(FileLine::EmptySecret) {
|
||||
// Sort of a singleton
|
||||
m_firstLineno = 0;
|
||||
m_lastLineno = 0;
|
||||
m_firstColumn = 0;
|
||||
m_lastColumn = 0;
|
||||
// Sort of a singleton
|
||||
FileLine::FileLine(FileLine::EmptySecret)
|
||||
: m_firstLineno{0}
|
||||
, m_firstColumn{0}
|
||||
, m_lastLineno{0}
|
||||
, m_lastColumn{0}
|
||||
, m_contentLineno{0}
|
||||
, m_contentp{nullptr}
|
||||
, m_parent{nullptr} {
|
||||
m_filenameno = singleton().nameToNumber(FileLine::builtInFilename());
|
||||
m_contentp = NULL;
|
||||
m_contentLineno = 0;
|
||||
m_parent = NULL;
|
||||
|
||||
m_warnOn = 0;
|
||||
for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) {
|
||||
|
|
@ -250,7 +250,7 @@ FileLine* FileLine::copyOrSameFileLine() {
|
|||
#ifndef _V3ERROR_NO_GLOBAL_
|
||||
V3Config::applyIgnores(this); // Toggle warnings based on global config file
|
||||
#endif
|
||||
static FileLine* lastNewp = NULL;
|
||||
static FileLine* lastNewp = nullptr;
|
||||
if (lastNewp && *lastNewp == *this) { // Compares lineno, filename, etc
|
||||
return lastNewp;
|
||||
}
|
||||
|
|
@ -310,11 +310,6 @@ bool FileLine::warnOff(const string& msg, bool flag) {
|
|||
V3ErrorCode code(msg.c_str());
|
||||
if (code < V3ErrorCode::EC_FIRST_WARN) {
|
||||
return false;
|
||||
#ifndef _V3ERROR_NO_GLOBAL_
|
||||
} else if (v3Global.opt.lintOnly() // Lint mode is allowed to suppress some errors
|
||||
&& code < V3ErrorCode::EC_MIN) {
|
||||
return false;
|
||||
#endif
|
||||
} else {
|
||||
warnOff(code, flag);
|
||||
return true;
|
||||
|
|
@ -442,7 +437,7 @@ string FileLine::warnContext(bool secondary) const {
|
|||
}
|
||||
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
typedef vl_unordered_set<FileLine*> FileLineCheckSet;
|
||||
typedef std::unordered_set<FileLine*> FileLineCheckSet;
|
||||
FileLineCheckSet fileLineLeakChecks;
|
||||
|
||||
void* FileLine::operator new(size_t size) {
|
||||
|
|
@ -454,7 +449,7 @@ void* FileLine::operator new(size_t size) {
|
|||
void FileLine::operator delete(void* objp, size_t size) {
|
||||
if (!objp) return;
|
||||
FileLine* flp = static_cast<FileLine*>(objp);
|
||||
FileLineCheckSet::iterator it = fileLineLeakChecks.find(flp);
|
||||
const auto it = fileLineLeakChecks.find(flp);
|
||||
if (it != fileLineLeakChecks.end()) {
|
||||
fileLineLeakChecks.erase(it);
|
||||
} else {
|
||||
|
|
@ -470,7 +465,7 @@ void FileLine::deleteAllRemaining() {
|
|||
// that way. Unfortunately this makes our leak checking a big mess, so
|
||||
// only when leak checking we'll track them all and cleanup.
|
||||
while (true) {
|
||||
FileLineCheckSet::iterator it = fileLineLeakChecks.begin();
|
||||
const auto it = fileLineLeakChecks.begin();
|
||||
if (it == fileLineLeakChecks.end()) break;
|
||||
delete *it;
|
||||
// Operator delete will remove the iterated object from the list.
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ std::ostream& operator<<(std::ostream& os, VFileContent* contentp);
|
|||
//! language is held in tables in the FileLineSingleton class.
|
||||
class FileLine {
|
||||
// CONSTANTS
|
||||
enum { SHOW_SOURCE_MAX_LENGTH = 400 }; // Don't show source lines > this long
|
||||
static constexpr unsigned SHOW_SOURCE_MAX_LENGTH = 400; // Don't show source lines > this long
|
||||
|
||||
// MEMBERS
|
||||
// Columns here means number of chars from beginning (i.e. tabs count as one)
|
||||
|
|
@ -126,27 +126,27 @@ private:
|
|||
|
||||
public:
|
||||
explicit FileLine(const string& filename)
|
||||
: m_firstLineno(0)
|
||||
, m_firstColumn(0)
|
||||
, m_lastLineno(0)
|
||||
, m_lastColumn(0)
|
||||
, m_filenameno(singleton().nameToNumber(filename))
|
||||
, m_contentLineno(0)
|
||||
, m_contentp(NULL)
|
||||
, m_parent(NULL)
|
||||
, m_warnOn(defaultFileLine().m_warnOn)
|
||||
, m_waive(false) {}
|
||||
: m_firstLineno{0}
|
||||
, m_firstColumn{0}
|
||||
, m_lastLineno{0}
|
||||
, m_lastColumn{0}
|
||||
, m_filenameno{singleton().nameToNumber(filename)}
|
||||
, m_contentLineno{0}
|
||||
, m_contentp{nullptr}
|
||||
, m_parent{nullptr}
|
||||
, m_warnOn{defaultFileLine().m_warnOn}
|
||||
, m_waive{false} {}
|
||||
explicit FileLine(FileLine* fromp)
|
||||
: m_firstLineno(fromp->m_firstLineno)
|
||||
, m_firstColumn(fromp->m_firstColumn)
|
||||
, m_lastLineno(fromp->m_lastLineno)
|
||||
, m_lastColumn(fromp->m_lastColumn)
|
||||
, m_filenameno(fromp->m_filenameno)
|
||||
, m_contentLineno(fromp->m_contentLineno)
|
||||
, m_contentp(fromp->m_contentp)
|
||||
, m_parent(fromp->m_parent)
|
||||
, m_warnOn(fromp->m_warnOn)
|
||||
, m_waive(fromp->m_waive) {}
|
||||
: m_firstLineno{fromp->m_firstLineno}
|
||||
, m_firstColumn{fromp->m_firstColumn}
|
||||
, m_lastLineno{fromp->m_lastLineno}
|
||||
, m_lastColumn{fromp->m_lastColumn}
|
||||
, m_filenameno{fromp->m_filenameno}
|
||||
, m_contentLineno{fromp->m_contentLineno}
|
||||
, m_contentp{fromp->m_contentp}
|
||||
, m_parent{fromp->m_parent}
|
||||
, m_warnOn{fromp->m_warnOn}
|
||||
, m_waive{fromp->m_waive} {}
|
||||
struct EmptySecret {}; // Constructor selection
|
||||
explicit FileLine(EmptySecret);
|
||||
FileLine* copyOrSameFileLine();
|
||||
|
|
|
|||
360
src/V3Gate.cpp
360
src/V3Gate.cpp
|
|
@ -35,11 +35,11 @@
|
|||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include VL_INCLUDE_UNORDERED_SET
|
||||
#include <unordered_set>
|
||||
|
||||
typedef std::list<AstNodeVarRef*> GateVarRefList;
|
||||
|
||||
#define GATE_DEDUP_MAX_DEPTH 20
|
||||
constexpr int GATE_DEDUP_MAX_DEPTH = 20;
|
||||
|
||||
//######################################################################
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ class GateGraphBaseVisitor {
|
|||
public:
|
||||
V3Graph* m_graphp; // Graph this class is visiting
|
||||
explicit GateGraphBaseVisitor(V3Graph* graphp)
|
||||
: m_graphp(graphp) {}
|
||||
: m_graphp{graphp} {}
|
||||
virtual ~GateGraphBaseVisitor() {}
|
||||
virtual VNUser visit(GateLogicVertex* vertexp, VNUser vu = VNUser(0)) = 0;
|
||||
virtual VNUser visit(GateVarVertex* vertexp, VNUser vu = VNUser(0)) = 0;
|
||||
|
|
@ -68,19 +68,16 @@ public:
|
|||
|
||||
class GateEitherVertex : public V3GraphVertex {
|
||||
AstScope* m_scopep; // Scope vertex refers to
|
||||
bool m_reducible; // True if this node should be able to be eliminated
|
||||
bool m_dedupable; // True if this node should be able to be deduped
|
||||
bool m_consumed; // Output goes to something meaningful
|
||||
bool m_reducible = true; // True if this node should be able to be eliminated
|
||||
bool m_dedupable = true; // True if this node should be able to be deduped
|
||||
bool m_consumed = false; // Output goes to something meaningful
|
||||
public:
|
||||
GateEitherVertex(V3Graph* graphp, AstScope* scopep)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_scopep(scopep)
|
||||
, m_reducible(true)
|
||||
, m_dedupable(true)
|
||||
, m_consumed(false) {}
|
||||
virtual ~GateEitherVertex() {}
|
||||
: V3GraphVertex{graphp}
|
||||
, m_scopep{scopep} {}
|
||||
virtual ~GateEitherVertex() override {}
|
||||
// ACCESSORS
|
||||
virtual string dotStyle() const { return m_consumed ? "" : "dotted"; }
|
||||
virtual string dotStyle() const override { return m_consumed ? "" : "dotted"; }
|
||||
AstScope* scopep() const { return m_scopep; }
|
||||
bool reducible() const { return m_reducible; }
|
||||
bool dedupable() const { return m_dedupable; }
|
||||
|
|
@ -116,7 +113,7 @@ public:
|
|||
// iterateInEdges() will stop traversing edges if one is deleted
|
||||
VNUser iterateCurrentOutEdges(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) {
|
||||
VNUser ret = VNUser(0);
|
||||
V3GraphEdge* next_edgep = NULL;
|
||||
V3GraphEdge* next_edgep = nullptr;
|
||||
for (V3GraphEdge* edgep = outBeginp(); edgep; edgep = next_edgep) {
|
||||
// Need to find the next edge before visiting in case the edge is deleted
|
||||
next_edgep = edgep->outNextp();
|
||||
|
|
@ -128,23 +125,19 @@ public:
|
|||
|
||||
class GateVarVertex : public GateEitherVertex {
|
||||
AstVarScope* m_varScp;
|
||||
bool m_isTop;
|
||||
bool m_isClock;
|
||||
AstNode* m_rstSyncNodep; // Used as reset and not in SenItem, in clocked always
|
||||
AstNode* m_rstAsyncNodep; // Used as reset and in SenItem, in clocked always
|
||||
bool m_isTop = false;
|
||||
bool m_isClock = false;
|
||||
AstNode* m_rstSyncNodep = nullptr; // Used as reset and not in SenItem, in clocked always
|
||||
AstNode* m_rstAsyncNodep = nullptr; // Used as reset and in SenItem, in clocked always
|
||||
public:
|
||||
GateVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: GateEitherVertex(graphp, scopep)
|
||||
, m_varScp(varScp)
|
||||
, m_isTop(false)
|
||||
, m_isClock(false)
|
||||
, m_rstSyncNodep(NULL)
|
||||
, m_rstAsyncNodep(NULL) {}
|
||||
virtual ~GateVarVertex() {}
|
||||
: GateEitherVertex{graphp, scopep}
|
||||
, m_varScp{varScp} {}
|
||||
virtual ~GateVarVertex() override {}
|
||||
// ACCESSORS
|
||||
AstVarScope* varScp() const { return m_varScp; }
|
||||
virtual string name() const { return (cvtToHex(m_varScp) + " " + varScp()->name()); }
|
||||
virtual string dotColor() const { return "blue"; }
|
||||
virtual string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); }
|
||||
virtual string dotColor() const override { return "blue"; }
|
||||
bool isTop() const { return m_isTop; }
|
||||
void setIsTop() { m_isTop = true; }
|
||||
bool isClock() const { return m_isClock; }
|
||||
|
|
@ -165,29 +158,35 @@ public:
|
|||
setIsClock();
|
||||
}
|
||||
}
|
||||
VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) { return v.visit(this, vu); }
|
||||
virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) override {
|
||||
return v.visit(this, vu);
|
||||
}
|
||||
};
|
||||
|
||||
class GateLogicVertex : public GateEitherVertex {
|
||||
AstNode* m_nodep;
|
||||
AstActive* m_activep; // Under what active; NULL is ok (under cfunc or such)
|
||||
AstActive* m_activep; // Under what active; nullptr is ok (under cfunc or such)
|
||||
bool m_slow; // In slow block
|
||||
public:
|
||||
GateLogicVertex(V3Graph* graphp, AstScope* scopep, AstNode* nodep, AstActive* activep,
|
||||
bool slow)
|
||||
: GateEitherVertex(graphp, scopep)
|
||||
, m_nodep(nodep)
|
||||
, m_activep(activep)
|
||||
, m_slow(slow) {}
|
||||
virtual ~GateLogicVertex() {}
|
||||
: GateEitherVertex{graphp, scopep}
|
||||
, m_nodep{nodep}
|
||||
, m_activep{activep}
|
||||
, m_slow{slow} {}
|
||||
virtual ~GateLogicVertex() override {}
|
||||
// ACCESSORS
|
||||
virtual string name() const { return (cvtToHex(m_nodep) + "@" + scopep()->prettyName()); }
|
||||
virtual string dotColor() const { return "purple"; }
|
||||
virtual FileLine* fileline() const { return nodep()->fileline(); }
|
||||
virtual string name() const override {
|
||||
return (cvtToHex(m_nodep) + "@" + scopep()->prettyName());
|
||||
}
|
||||
virtual string dotColor() const override { return "purple"; }
|
||||
virtual FileLine* fileline() const override { return nodep()->fileline(); }
|
||||
AstNode* nodep() const { return m_nodep; }
|
||||
AstActive* activep() const { return m_activep; }
|
||||
bool slow() const { return m_slow; }
|
||||
VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) { return v.visit(this, vu); }
|
||||
virtual VNUser accept(GateGraphBaseVisitor& v, VNUser vu = VNUser(0)) override {
|
||||
return v.visit(this, vu);
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -196,14 +195,14 @@ public:
|
|||
class GateOkVisitor : public GateBaseVisitor {
|
||||
private:
|
||||
// RETURN STATE
|
||||
bool m_isSimple; // Set false when we know it isn't simple
|
||||
bool m_isSimple = true; // Set false when we know it isn't simple
|
||||
GateVarRefList m_rhsVarRefs; // VarRefs on rhs of assignment
|
||||
AstNode* m_substTreep; // What to replace the variable with
|
||||
AstNode* m_substTreep = nullptr; // What to replace the variable with
|
||||
// STATE
|
||||
bool m_buffersOnly; // Set when we only allow simple buffering, no equations (for clocks)
|
||||
AstNodeVarRef* m_lhsVarRef; // VarRef on lhs of assignment (what we're replacing)
|
||||
AstNodeVarRef* m_lhsVarRef = nullptr; // VarRef on lhs of assignment (what we're replacing)
|
||||
bool m_dedupe; // Set when we use isGateDedupable instead of isGateOptimizable
|
||||
int m_ops; // Operation count
|
||||
int m_ops = 0; // Operation count
|
||||
|
||||
// METHODS
|
||||
void clearSimple(const char* because) {
|
||||
|
|
@ -213,7 +212,7 @@ private:
|
|||
}
|
||||
}
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
++m_ops;
|
||||
iterateChildren(nodep);
|
||||
// We only allow a LHS ref for the var being set, and a RHS ref for
|
||||
|
|
@ -237,7 +236,7 @@ private:
|
|||
m_rhsVarRefs.push_back(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
m_substTreep = nodep->rhsp();
|
||||
if (!VN_IS(nodep->lhsp(), NodeVarRef)) {
|
||||
clearSimple("ASSIGN(non-VARREF)");
|
||||
|
|
@ -260,7 +259,7 @@ private:
|
|||
}
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
// *** Special iterator
|
||||
if (!m_isSimple) return; // Fastpath
|
||||
if (++m_ops > v3Global.opt.gateStmts()) { clearSimple("--gate-stmts exceeded"); }
|
||||
|
|
@ -276,12 +275,8 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
GateOkVisitor(AstNode* nodep, bool buffersOnly, bool dedupe) {
|
||||
m_isSimple = true;
|
||||
m_substTreep = NULL;
|
||||
m_buffersOnly = buffersOnly;
|
||||
m_lhsVarRef = NULL;
|
||||
m_dedupe = dedupe;
|
||||
m_ops = 0;
|
||||
// Iterate
|
||||
iterate(nodep);
|
||||
// Check results
|
||||
|
|
@ -294,7 +289,7 @@ public:
|
|||
}
|
||||
if (debug() >= 9 && !m_isSimple) nodep->dumpTree(cout, " gate!Ok: ");
|
||||
}
|
||||
virtual ~GateOkVisitor() {}
|
||||
virtual ~GateOkVisitor() override {}
|
||||
// PUBLIC METHODS
|
||||
bool isSimple() const { return m_isSimple; }
|
||||
AstNode* substTree() const { return m_substTreep; }
|
||||
|
|
@ -318,13 +313,13 @@ private:
|
|||
|
||||
// STATE
|
||||
V3Graph m_graph; // Scoreboard of var usages/dependencies
|
||||
GateLogicVertex* m_logicVertexp; // Current statement being tracked, NULL=ignored
|
||||
AstScope* m_scopep; // Current scope being processed
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstActive* m_activep; // Current active
|
||||
bool m_activeReducible; // Is activation block reducible?
|
||||
bool m_inSenItem; // Underneath AstSenItem; any varrefs are clocks
|
||||
bool m_inSlow; // Inside a slow structure
|
||||
GateLogicVertex* m_logicVertexp = nullptr; // Current statement being tracked, nullptr=ignored
|
||||
AstScope* m_scopep = nullptr; // Current scope being processed
|
||||
AstNodeModule* m_modp = nullptr; // Current module
|
||||
AstActive* m_activep = nullptr; // Current active
|
||||
bool m_activeReducible = true; // Is activation block reducible?
|
||||
bool m_inSenItem = false; // Underneath AstSenItem; any varrefs are clocks
|
||||
bool m_inSlow = false; // Inside a slow structure
|
||||
VDouble0 m_statSigs; // Statistic tracking
|
||||
VDouble0 m_statRefs; // Statistic tracking
|
||||
VDouble0 m_statDedupLogic; // Statistic tracking
|
||||
|
|
@ -346,7 +341,7 @@ private:
|
|||
if (consumeReason) m_logicVertexp->setConsumed(consumeReason);
|
||||
if (VN_IS(nodep, SenItem)) m_logicVertexp->setConsumed("senItem");
|
||||
iterateChildren(nodep);
|
||||
m_logicVertexp = NULL;
|
||||
m_logicVertexp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -385,7 +380,7 @@ private:
|
|||
void decomposeClkVectors();
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// if (debug() > 6) m_graph.dump();
|
||||
if (debug() > 6) m_graph.dumpDotFilePrefixed("gate_pre");
|
||||
|
|
@ -416,23 +411,22 @@ private:
|
|||
consumedMove();
|
||||
replaceAssigns();
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
AstNodeModule* origModp = m_modp;
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
m_activeReducible = true;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_modp = origModp;
|
||||
}
|
||||
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
UINFO(4, " SCOPE " << nodep << endl);
|
||||
m_scopep = nodep;
|
||||
m_logicVertexp = NULL;
|
||||
m_logicVertexp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
m_scopep = NULL;
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
// Create required blocks and add to module
|
||||
UINFO(4, " BLOCK " << nodep << endl);
|
||||
m_activeReducible = !(nodep->hasClocked()); // Seq logic outputs aren't reducible
|
||||
|
|
@ -440,10 +434,10 @@ private:
|
|||
AstNode::user2ClearTree();
|
||||
iterateChildren(nodep);
|
||||
AstNode::user2ClearTree();
|
||||
m_activep = NULL;
|
||||
m_activep = nullptr;
|
||||
m_activeReducible = true;
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
if (m_scopep) {
|
||||
UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block");
|
||||
AstVarScope* varscp = nodep->varScopep();
|
||||
|
|
@ -470,49 +464,53 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
||||
iterateNewStmt(nodep, (nodep->isJustOneBodyStmt() ? NULL : "Multiple Stmts"), NULL);
|
||||
virtual void visit(AstAlways* nodep) override {
|
||||
iterateNewStmt(nodep, (nodep->isJustOneBodyStmt() ? nullptr : "Multiple Stmts"), nullptr);
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
||||
bool lastslow = m_inSlow;
|
||||
m_inSlow = true;
|
||||
iterateNewStmt(nodep, "AlwaysPublic", NULL);
|
||||
m_inSlow = lastslow;
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
VL_RESTORER(m_inSlow);
|
||||
{
|
||||
m_inSlow = true;
|
||||
iterateNewStmt(nodep, "AlwaysPublic", nullptr);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
iterateNewStmt(nodep, "User C Function", "User C Function");
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
m_inSenItem = true;
|
||||
if (m_logicVertexp) { // Already under logic; presumably a SenGate
|
||||
iterateChildren(nodep);
|
||||
} else { // Standalone item, probably right under a SenTree
|
||||
iterateNewStmt(nodep, NULL, NULL);
|
||||
iterateNewStmt(nodep, nullptr, nullptr);
|
||||
}
|
||||
m_inSenItem = false;
|
||||
}
|
||||
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(AstInitial* nodep) override {
|
||||
VL_RESTORER(m_inSlow);
|
||||
{
|
||||
m_inSlow = true;
|
||||
iterateNewStmt(nodep, (nodep->isJustOneBodyStmt() ? nullptr : "Multiple Stmts"),
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { //
|
||||
iterateNewStmt(nodep, NULL, NULL);
|
||||
virtual void visit(AstAssignAlias* nodep) override { //
|
||||
iterateNewStmt(nodep, nullptr, nullptr);
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) VL_OVERRIDE { //
|
||||
iterateNewStmt(nodep, NULL, NULL);
|
||||
virtual void visit(AstAssignW* nodep) override { //
|
||||
iterateNewStmt(nodep, nullptr, nullptr);
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCoverToggle* nodep) override {
|
||||
iterateNewStmt(nodep, "CoverToggle", "CoverToggle");
|
||||
}
|
||||
virtual void visit(AstTraceDecl* nodep) VL_OVERRIDE {
|
||||
const bool lastslow = m_inSlow;
|
||||
m_inSlow = true;
|
||||
iterateNewStmt(nodep, "Tracing", "Tracing");
|
||||
m_inSlow = lastslow;
|
||||
virtual void visit(AstTraceDecl* nodep) override {
|
||||
VL_RESTORER(m_inSlow);
|
||||
{
|
||||
m_inSlow = true;
|
||||
iterateNewStmt(nodep, "Tracing", "Tracing");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConcat* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstConcat* nodep) 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");
|
||||
|
|
@ -520,7 +518,7 @@ private:
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isOutputter() && m_logicVertexp) m_logicVertexp->setConsumed("outputter");
|
||||
}
|
||||
|
|
@ -529,16 +527,9 @@ public:
|
|||
// CONSTRUCTORS
|
||||
explicit GateVisitor(AstNode* nodep) {
|
||||
AstNode::user1ClearTree();
|
||||
m_logicVertexp = NULL;
|
||||
m_scopep = NULL;
|
||||
m_modp = NULL;
|
||||
m_activep = NULL;
|
||||
m_activeReducible = true;
|
||||
m_inSenItem = false;
|
||||
m_inSlow = false;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~GateVisitor() {
|
||||
virtual ~GateVisitor() override {
|
||||
V3Stats::addStat("Optimizations, Gate sigs deleted", m_statSigs);
|
||||
V3Stats::addStat("Optimizations, Gate inputs replaced", m_statRefs);
|
||||
V3Stats::addStat("Optimizations, Gate sigs deduped", m_statDedupLogic);
|
||||
|
|
@ -675,7 +666,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
|
|||
// optimize it further
|
||||
logicp->unlinkFrBack();
|
||||
vvertexp->varScp()->valuep(logicp);
|
||||
logicp = NULL;
|
||||
logicp = nullptr;
|
||||
// Mark the vertex so we don't mark it as being
|
||||
// unconsumed in the next step
|
||||
vvertexp->user(true);
|
||||
|
|
@ -693,7 +684,7 @@ bool GateVisitor::elimLogicOkOutputs(GateLogicVertex* consumeVertexp,
|
|||
// Return true if can optimize
|
||||
// Return false if the consuming logic has an output signal that the
|
||||
// replacement logic has as an input
|
||||
typedef vl_unordered_set<AstVarScope*> VarScopeSet;
|
||||
typedef std::unordered_set<AstVarScope*> VarScopeSet;
|
||||
// Use map to find duplicates between two lists
|
||||
VarScopeSet varscopes;
|
||||
// Replacement logic usually has shorter input list, so faster to build list based on it
|
||||
|
|
@ -787,7 +778,7 @@ void GateVisitor::consumedMove() {
|
|||
}
|
||||
if (GateLogicVertex* lvertexp = dynamic_cast<GateLogicVertex*>(vertexp)) {
|
||||
AstNode* nodep = lvertexp->nodep();
|
||||
AstActive* oldactp = lvertexp->activep(); // NULL under cfunc
|
||||
AstActive* oldactp = lvertexp->activep(); // nullptr under cfunc
|
||||
if (!lvertexp->consumed() && oldactp) {
|
||||
// Eventually: Move the statement to a new active block
|
||||
// with "tracing-on" sensitivity
|
||||
|
|
@ -848,7 +839,7 @@ private:
|
|||
void hashReplace(AstNode* oldp, AstNode* newp);
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
if (nodep->varScopep() == m_elimVarScp) {
|
||||
// Substitute in the new tree
|
||||
// It's possible we substitute into something that will be reduced more later,
|
||||
|
|
@ -874,11 +865,11 @@ private:
|
|||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
virtual ~GateElimVisitor() {}
|
||||
virtual ~GateElimVisitor() override {}
|
||||
GateElimVisitor(AstNode* nodep, AstVarScope* varscp, AstNode* replaceTreep,
|
||||
GateDedupeVarVisitor* varVisp) {
|
||||
UINFO(9, " elimvisitor " << nodep << endl);
|
||||
|
|
@ -895,7 +886,7 @@ public:
|
|||
|
||||
void GateVisitor::optimizeElimVar(AstVarScope* varscp, AstNode* substp, AstNode* consumerp) {
|
||||
if (debug() >= 5) consumerp->dumpTree(cout, " elimUsePre: ");
|
||||
GateElimVisitor elimVisitor(consumerp, varscp, substp, NULL);
|
||||
GateElimVisitor elimVisitor(consumerp, varscp, substp, nullptr);
|
||||
if (elimVisitor.didReplace()) {
|
||||
if (debug() >= 9) consumerp->dumpTree(cout, " elimUseCns: ");
|
||||
// Caution: Can't let V3Const change our handle to consumerp, such as by
|
||||
|
|
@ -920,9 +911,9 @@ private:
|
|||
// NODE STATE
|
||||
// Ast*::user2p -> parent AstNodeAssign* for this rhsp
|
||||
// Ast*::user3p -> AstActive* of assign, for isSame() in test for duplicate
|
||||
// Set to NULL if this assign's tree was later replaced
|
||||
// Set to nullptr if this assign's tree was later replaced
|
||||
// Ast*::user5p -> AstNode* of assign if condition, for isSame() in test for duplicate
|
||||
// Set to NULL if this assign's tree was later replaced
|
||||
// Set to nullptr if this assign's tree was later replaced
|
||||
// AstUser1InUse m_inuser1; (Allocated for use in GateVisitor)
|
||||
// AstUser2InUse m_inuser2; (Allocated for use in GateVisitor)
|
||||
AstUser3InUse m_inuser3;
|
||||
|
|
@ -935,7 +926,7 @@ private:
|
|||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void hash(AstNode* nodep) {
|
||||
// !NULL && the object is hashable
|
||||
// !nullptr && the object is hashable
|
||||
if (nodep && !nodep->sameHash().isIllegal()) m_hashed.hash(nodep);
|
||||
}
|
||||
bool sameHash(AstNode* node1p, AstNode* node2p) {
|
||||
|
|
@ -985,7 +976,8 @@ public:
|
|||
}
|
||||
|
||||
AstNodeAssign* hashAndFindDupe(AstNodeAssign* assignp, AstNode* extra1p, AstNode* extra2p) {
|
||||
// Legal for extra1p/2p to be NULL, we'll compare with other assigns with extras also NULL
|
||||
// Legal for extra1p/2p to be nullptr, we'll compare with other assigns with extras also
|
||||
// nullptr
|
||||
AstNode* rhsp = assignp->rhsp();
|
||||
rhsp->user2p(assignp);
|
||||
rhsp->user3p(extra1p);
|
||||
|
|
@ -994,8 +986,8 @@ public:
|
|||
hash(extra1p);
|
||||
hash(extra2p);
|
||||
|
||||
V3Hashed::iterator inserted = m_hashed.hashAndInsert(rhsp);
|
||||
V3Hashed::iterator dupit = m_hashed.findDuplicate(rhsp, this);
|
||||
const auto inserted = m_hashed.hashAndInsert(rhsp);
|
||||
const auto dupit = m_hashed.findDuplicate(rhsp, this);
|
||||
// Even though rhsp was just inserted, V3Hashed::findDuplicate doesn't
|
||||
// return anything in the hash that has the same pointer (V3Hashed.cpp::findDuplicate)
|
||||
// So dupit is either a different, duplicate rhsp, or the end of the hash.
|
||||
|
|
@ -1004,7 +996,7 @@ public:
|
|||
return VN_CAST(m_hashed.iteratorNodep(dupit)->user2p(), NodeAssign);
|
||||
}
|
||||
// Retain new inserted information
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void check() {
|
||||
|
|
@ -1042,13 +1034,13 @@ class GateDedupeVarVisitor : public GateBaseVisitor {
|
|||
private:
|
||||
// STATE
|
||||
GateDedupeHash m_ghash; // Hash used to find dupes of rhs of assign
|
||||
AstNodeAssign* m_assignp; // Assign found for dedupe
|
||||
AstNode* m_ifCondp; // IF condition that assign is under
|
||||
bool m_always; // Assign is under an always
|
||||
bool m_dedupable; // Determined the assign to be dedupable
|
||||
AstNodeAssign* m_assignp = nullptr; // Assign found for dedupe
|
||||
AstNode* m_ifCondp = nullptr; // IF condition that assign is under
|
||||
bool m_always = false; // Assign is under an always
|
||||
bool m_dedupable = true; // Determined the assign to be dedupable
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeAssign* assignp) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* assignp) 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
|
||||
|
|
@ -1059,7 +1051,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* alwaysp) VL_OVERRIDE {
|
||||
virtual void visit(AstAlways* alwaysp) override {
|
||||
if (m_dedupable) {
|
||||
if (!m_always) {
|
||||
m_always = true;
|
||||
|
|
@ -1073,7 +1065,7 @@ private:
|
|||
// always @(...)
|
||||
// if (...)
|
||||
// foo = ...; // or foo <= ...;
|
||||
virtual void visit(AstNodeIf* ifp) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeIf* ifp) 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
|
||||
|
|
@ -1085,25 +1077,20 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstComment*) VL_OVERRIDE {} // NOP
|
||||
virtual void visit(AstComment*) override {} // NOP
|
||||
//--------------------
|
||||
virtual void visit(AstNode*) VL_OVERRIDE { //
|
||||
virtual void visit(AstNode*) override { //
|
||||
m_dedupable = false;
|
||||
}
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
GateDedupeVarVisitor() {
|
||||
m_assignp = NULL;
|
||||
m_ifCondp = NULL;
|
||||
m_always = false;
|
||||
m_dedupable = true;
|
||||
}
|
||||
GateDedupeVarVisitor() {}
|
||||
~GateDedupeVarVisitor() {}
|
||||
// PUBLIC METHODS
|
||||
AstNodeVarRef* findDupe(AstNode* nodep, AstVarScope* consumerVarScopep, AstActive* activep) {
|
||||
m_assignp = NULL;
|
||||
m_ifCondp = NULL;
|
||||
m_assignp = nullptr;
|
||||
m_ifCondp = nullptr;
|
||||
m_always = false;
|
||||
m_dedupable = true;
|
||||
iterate(nodep);
|
||||
|
|
@ -1118,7 +1105,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
void hashReplace(AstNode* oldp, AstNode* newp) { m_ghash.hashReplace(oldp, newp); }
|
||||
};
|
||||
|
|
@ -1140,9 +1127,9 @@ private:
|
|||
// AstUser2InUse m_inuser2; (Allocated for use in GateVisitor)
|
||||
VDouble0 m_numDeduped; // Statistic tracking
|
||||
GateDedupeVarVisitor m_varVisitor; // Looks for a dupe of the logic
|
||||
int m_depth; // Iteration depth
|
||||
int m_depth = 0; // Iteration depth
|
||||
|
||||
virtual VNUser visit(GateVarVertex* vvertexp, VNUser) {
|
||||
virtual VNUser visit(GateVarVertex* vvertexp, VNUser) override {
|
||||
// Check that we haven't been here before
|
||||
if (m_depth > GATE_DEDUP_MAX_DEPTH)
|
||||
return VNUser(0); // Break loops; before user2 set so hit this vertex later
|
||||
|
|
@ -1157,7 +1144,7 @@ private:
|
|||
V3GraphEdge* edgep = vvertexp->inBeginp();
|
||||
GateLogicVertex* lvertexp = static_cast<GateLogicVertex*>(edgep->fromp());
|
||||
UASSERT_OBJ(vvertexp->dedupable(), vvertexp->varScp(),
|
||||
"GateLogicVertex* visit should have returned NULL "
|
||||
"GateLogicVertex* visit should have returned nullptr "
|
||||
"if consumer var vertex is not dedupable.");
|
||||
GateOkVisitor okVisitor(lvertexp->nodep(), false, true);
|
||||
if (okVisitor.isSimple()) {
|
||||
|
|
@ -1197,7 +1184,7 @@ private:
|
|||
AstNode* lvertexNodep = lvertexp->nodep();
|
||||
lvertexNodep->unlinkFrBack();
|
||||
vvertexp->varScp()->valuep(lvertexNodep);
|
||||
lvertexNodep = NULL;
|
||||
lvertexNodep = nullptr;
|
||||
vvertexp->user(true);
|
||||
lvertexp->user(true);
|
||||
}
|
||||
|
|
@ -1208,8 +1195,8 @@ private:
|
|||
}
|
||||
|
||||
// Given iterated logic, starting at vu which was consumer's GateVarVertex
|
||||
// Returns a varref that has the same logic input; or NULL if none
|
||||
virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) {
|
||||
// Returns a varref that has the same logic input; or nullptr if none
|
||||
virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) override {
|
||||
lvertexp->iterateInEdges(*this);
|
||||
|
||||
GateVarVertex* consumerVvertexpp = static_cast<GateVarVertex*>(vu.toGraphVertex());
|
||||
|
|
@ -1228,8 +1215,7 @@ private:
|
|||
|
||||
public:
|
||||
explicit GateDedupeGraphVisitor(V3Graph* graphp)
|
||||
: GateGraphBaseVisitor(graphp)
|
||||
, m_depth(0) {}
|
||||
: GateGraphBaseVisitor{graphp} {}
|
||||
void dedupeTree(GateVarVertex* vvertexp) { vvertexp->accept(*this); }
|
||||
VDouble0 numDeduped() { return m_numDeduped; }
|
||||
};
|
||||
|
|
@ -1264,9 +1250,9 @@ void GateVisitor::dedupe() {
|
|||
class GateMergeAssignsGraphVisitor : public GateGraphBaseVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
AstNodeAssign* m_assignp;
|
||||
AstActive* m_activep;
|
||||
GateLogicVertex* m_logicvp;
|
||||
AstNodeAssign* m_assignp = nullptr;
|
||||
AstActive* m_activep = nullptr;
|
||||
GateLogicVertex* m_logicvp = nullptr;
|
||||
VDouble0 m_numMergedAssigns; // Statistic tracking
|
||||
|
||||
// assemble two Sel into one if possible
|
||||
|
|
@ -1274,22 +1260,22 @@ private:
|
|||
AstVarRef* preVarRefp = VN_CAST(pre->fromp(), VarRef);
|
||||
AstVarRef* curVarRefp = VN_CAST(cur->fromp(), VarRef);
|
||||
if (!preVarRefp || !curVarRefp || !curVarRefp->same(preVarRefp)) {
|
||||
return NULL; // not the same var
|
||||
return nullptr; // not the same var
|
||||
}
|
||||
const AstConst* pstart = VN_CAST(pre->lsbp(), Const);
|
||||
const AstConst* pwidth = VN_CAST(pre->widthp(), Const);
|
||||
const AstConst* cstart = VN_CAST(cur->lsbp(), Const);
|
||||
const AstConst* cwidth = VN_CAST(cur->widthp(), Const);
|
||||
if (!pstart || !pwidth || !cstart || !cwidth) return NULL; // too complicated
|
||||
if (!pstart || !pwidth || !cstart || !cwidth) return nullptr; // too complicated
|
||||
if (cur->lsbConst() + cur->widthConst() == pre->lsbConst()) {
|
||||
return new AstSel(curVarRefp->fileline(), curVarRefp->cloneTree(false),
|
||||
cur->lsbConst(), pre->widthConst() + cur->widthConst());
|
||||
} else {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual VNUser visit(GateVarVertex* vvertexp, VNUser) {
|
||||
virtual VNUser visit(GateVarVertex* vvertexp, VNUser) override {
|
||||
for (V3GraphEdge* edgep = vvertexp->inBeginp(); edgep;) {
|
||||
V3GraphEdge* oldedgep = edgep;
|
||||
edgep = edgep->inNextp(); // for recursive since the edge could be deleted
|
||||
|
|
@ -1362,18 +1348,14 @@ private:
|
|||
}
|
||||
return VNUser(0);
|
||||
}
|
||||
virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) { //
|
||||
virtual VNUser visit(GateLogicVertex*, VNUser vu) override { //
|
||||
return VNUser(0);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit GateMergeAssignsGraphVisitor(V3Graph* graphp)
|
||||
: GateGraphBaseVisitor(graphp) {
|
||||
m_assignp = NULL;
|
||||
m_activep = NULL;
|
||||
m_logicvp = NULL;
|
||||
m_numMergedAssigns = 0;
|
||||
m_graphp = graphp;
|
||||
: GateGraphBaseVisitor{graphp} {
|
||||
m_graphp = graphp; // In base
|
||||
}
|
||||
void mergeAssignsTree(GateVarVertex* vvertexp) { vvertexp->accept(*this); }
|
||||
VDouble0 numMergedAssigns() { return m_numMergedAssigns; }
|
||||
|
|
@ -1398,13 +1380,13 @@ void GateVisitor::mergeAssigns() {
|
|||
class GateConcatVisitor : public GateBaseVisitor {
|
||||
private:
|
||||
// STATE
|
||||
AstVarScope* m_vscp; // Varscope we're trying to find
|
||||
int m_offset; // Current offset of varscope
|
||||
int m_found_offset; // Found offset of varscope
|
||||
bool m_found; // Offset found
|
||||
AstVarScope* m_vscp = nullptr; // Varscope we're trying to find
|
||||
int m_offset = 0; // Current offset of varscope
|
||||
int m_found_offset = 0; // Found offset of varscope
|
||||
bool m_found = false; // Offset found
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeVarRef* nodep) 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
|
||||
|
|
@ -1416,23 +1398,18 @@ private:
|
|||
}
|
||||
m_offset += nodep->dtypep()->width();
|
||||
}
|
||||
virtual void visit(AstConcat* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstConcat* nodep) override {
|
||||
UINFO(9, "CLK DECOMP Concat search (off = " << m_offset << ") - " << nodep << endl);
|
||||
iterate(nodep->rhsp());
|
||||
iterate(nodep->lhsp());
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
GateConcatVisitor() {
|
||||
m_vscp = NULL;
|
||||
m_offset = 0;
|
||||
m_found_offset = 0;
|
||||
m_found = false;
|
||||
}
|
||||
virtual ~GateConcatVisitor() {}
|
||||
GateConcatVisitor() {}
|
||||
virtual ~GateConcatVisitor() override {}
|
||||
// PUBLIC METHODS
|
||||
bool concatOffset(AstConcat* concatp, AstVarScope* vscp, int& offsetr) {
|
||||
m_vscp = vscp;
|
||||
|
|
@ -1455,10 +1432,9 @@ class GateClkDecompState {
|
|||
public:
|
||||
int m_offset;
|
||||
AstVarScope* m_last_vsp;
|
||||
GateClkDecompState(int offset, AstVarScope* vsp) {
|
||||
m_offset = offset;
|
||||
m_last_vsp = vsp;
|
||||
}
|
||||
GateClkDecompState(int offset, AstVarScope* vsp)
|
||||
: m_offset{offset}
|
||||
, m_last_vsp{vsp} {}
|
||||
virtual ~GateClkDecompState() {}
|
||||
};
|
||||
|
||||
|
|
@ -1466,14 +1442,14 @@ class GateClkDecompGraphVisitor : public GateGraphBaseVisitor {
|
|||
private:
|
||||
// NODE STATE
|
||||
// AstVarScope::user2p -> bool: already visited
|
||||
int m_seen_clk_vectors;
|
||||
AstVarScope* m_clk_vsp;
|
||||
GateVarVertex* m_clk_vvertexp;
|
||||
int m_seen_clk_vectors = 0;
|
||||
AstVarScope* m_clk_vsp = nullptr;
|
||||
GateVarVertex* m_clk_vvertexp = nullptr;
|
||||
GateConcatVisitor m_concat_visitor;
|
||||
int m_total_seen_clk_vectors;
|
||||
int m_total_decomposed_clk_vectors;
|
||||
int m_total_seen_clk_vectors = 0;
|
||||
int m_total_decomposed_clk_vectors = 0;
|
||||
|
||||
virtual VNUser visit(GateVarVertex* vvertexp, VNUser vu) {
|
||||
virtual VNUser visit(GateVarVertex* vvertexp, VNUser vu) override {
|
||||
// Check that we haven't been here before
|
||||
AstVarScope* vsp = vvertexp->varScp();
|
||||
if (vsp->user2SetOnce()) return VNUser(0);
|
||||
|
|
@ -1490,7 +1466,7 @@ private:
|
|||
return VNUser(0); // Unused
|
||||
}
|
||||
|
||||
virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) {
|
||||
virtual VNUser visit(GateLogicVertex* lvertexp, VNUser vu) override {
|
||||
GateClkDecompState* currState = reinterpret_cast<GateClkDecompState*>(vu.c());
|
||||
int clk_offset = currState->m_offset;
|
||||
if (const AstAssignW* assignp = VN_CAST(lvertexp->nodep(), AssignW)) {
|
||||
|
|
@ -1556,14 +1532,8 @@ private:
|
|||
|
||||
public:
|
||||
explicit GateClkDecompGraphVisitor(V3Graph* graphp)
|
||||
: GateGraphBaseVisitor(graphp) {
|
||||
m_seen_clk_vectors = 0;
|
||||
m_clk_vsp = NULL;
|
||||
m_clk_vvertexp = NULL;
|
||||
m_total_seen_clk_vectors = 0;
|
||||
m_total_decomposed_clk_vectors = 0;
|
||||
}
|
||||
virtual ~GateClkDecompGraphVisitor() {
|
||||
: GateGraphBaseVisitor{graphp} {}
|
||||
virtual ~GateClkDecompGraphVisitor() override {
|
||||
V3Stats::addStat("Optimizations, Clocker seen vectors", m_total_seen_clk_vectors);
|
||||
V3Stats::addStat("Optimizations, Clocker decomposed vectors",
|
||||
m_total_decomposed_clk_vectors);
|
||||
|
|
@ -1603,7 +1573,7 @@ void GateVisitor::decomposeClkVectors() {
|
|||
class GateDeassignVisitor : public GateBaseVisitor {
|
||||
private:
|
||||
// VISITORS
|
||||
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarScope* nodep) override {
|
||||
if (AstNodeAssign* assp = VN_CAST(nodep->valuep(), NodeAssign)) {
|
||||
UINFO(5, " Removeassign " << assp << endl);
|
||||
AstNode* valuep = assp->rhsp();
|
||||
|
|
@ -1613,14 +1583,14 @@ private:
|
|||
}
|
||||
}
|
||||
// Speedups
|
||||
virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstActive*) VL_OVERRIDE {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstVar*) override {} // Accelerate
|
||||
virtual void visit(AstActive*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit GateDeassignVisitor(AstNode* nodep) { iterate(nodep); }
|
||||
virtual ~GateDeassignVisitor() {}
|
||||
virtual ~GateDeassignVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ private:
|
|||
AstUser3InUse m_inuser3;
|
||||
|
||||
// STATE
|
||||
AstActive* m_activep; // Inside activate statement
|
||||
AstActive* m_activep = nullptr; // Inside activate statement
|
||||
AstNodeModule* m_topModp; // Top module
|
||||
AstScope* m_scopetopp; // Scope under TOPSCOPE
|
||||
AstScope* m_scopetopp = nullptr; // Scope under TOPSCOPE
|
||||
|
||||
// METHODS
|
||||
AstVarScope* genInpClk(AstVarScope* vscp) {
|
||||
|
|
@ -78,7 +78,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTopScope* nodep) override {
|
||||
AstNode::user2ClearTree(); // user2p() used on entire tree
|
||||
|
||||
AstScope* scopep = nodep->scopep();
|
||||
|
|
@ -88,7 +88,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
//----
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
// Consumption/generation of a variable,
|
||||
AstVarScope* vscp = nodep->varScopep();
|
||||
UASSERT_OBJ(vscp, nodep, "Scope not assigned");
|
||||
|
|
@ -104,27 +104,25 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
m_activep = nodep;
|
||||
UASSERT_OBJ(nodep->sensesp(), nodep, "Unlinked");
|
||||
iterateChildren(nodep->sensesp()); // iterateAndNext?
|
||||
m_activep = NULL;
|
||||
m_activep = nullptr;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstCFunc* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
//-----
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
GenClkRenameVisitor(AstTopScope* nodep, AstNodeModule* topModp) {
|
||||
m_topModp = topModp;
|
||||
m_scopetopp = NULL;
|
||||
m_activep = NULL;
|
||||
GenClkRenameVisitor(AstTopScope* nodep, AstNodeModule* topModp)
|
||||
: m_topModp{topModp} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~GenClkRenameVisitor() {}
|
||||
virtual ~GenClkRenameVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -138,13 +136,13 @@ private:
|
|||
AstUser1InUse m_inuser1;
|
||||
|
||||
// STATE
|
||||
AstActive* m_activep; // Inside activate statement
|
||||
bool m_tracingCall; // Iterating into a call to a cfunc
|
||||
AstNodeAssign* m_assignp; // Inside assigndly statement
|
||||
AstNodeModule* m_topModp; // Top module
|
||||
bool m_tracingCall = false; // Iterating into a call to a cfunc
|
||||
AstActive* m_activep = nullptr; // Inside activate statement
|
||||
AstNodeAssign* m_assignp = nullptr; // Inside assigndly statement
|
||||
AstNodeModule* m_topModp = nullptr; // Top module
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstTopScope* nodep) override {
|
||||
AstNode::user1ClearTree(); // user1p() used on entire tree
|
||||
iterateChildren(nodep);
|
||||
{
|
||||
|
|
@ -153,14 +151,14 @@ private:
|
|||
GenClkRenameVisitor visitor(nodep, m_topModp);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
// Only track the top scopes, not lower level functions
|
||||
if (nodep->isTop()) {
|
||||
m_topModp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeCCall* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (!nodep->funcp()->entryPoint()) {
|
||||
// Enter the function and trace it
|
||||
|
|
@ -168,7 +166,7 @@ private:
|
|||
iterate(nodep->funcp());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
if (!m_tracingCall && !nodep->entryPoint()) {
|
||||
// Only consider logic within a CFunc when looking
|
||||
// at the call to it, and not when scanning whatever
|
||||
|
|
@ -180,7 +178,7 @@ private:
|
|||
}
|
||||
//----
|
||||
|
||||
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
// Consumption/generation of a variable,
|
||||
AstVarScope* vscp = nodep->varScopep();
|
||||
UASSERT_OBJ(vscp, nodep, "Scope not assigned");
|
||||
|
|
@ -195,35 +193,29 @@ private:
|
|||
vscp->circular(true);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
// UINFO(8, "ASS " << nodep << endl);
|
||||
m_assignp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_assignp = NULL;
|
||||
m_assignp = nullptr;
|
||||
}
|
||||
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
UINFO(8, "ACTIVE " << nodep << endl);
|
||||
m_activep = nodep;
|
||||
UASSERT_OBJ(nodep->sensesp(), nodep, "Unlinked");
|
||||
iterateChildren(nodep->sensesp()); // iterateAndNext?
|
||||
m_activep = NULL;
|
||||
m_activep = nullptr;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
//-----
|
||||
virtual void visit(AstVar*) VL_OVERRIDE {} // Don't want varrefs under it
|
||||
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
||||
virtual void visit(AstVar*) override {} // Don't want varrefs under it
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit GenClkReadVisitor(AstNetlist* nodep)
|
||||
: m_activep(NULL)
|
||||
, m_tracingCall(false)
|
||||
, m_assignp(NULL)
|
||||
, m_topModp(NULL) {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~GenClkReadVisitor() {}
|
||||
explicit GenClkReadVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~GenClkReadVisitor() override {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "V3Global.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3File.h"
|
||||
#include "V3HierBlock.h"
|
||||
#include "V3LinkCells.h"
|
||||
#include "V3Parse.h"
|
||||
#include "V3ParseSym.h"
|
||||
|
|
@ -34,7 +35,11 @@ AstNetlist* V3Global::makeNetlist() {
|
|||
return newp;
|
||||
}
|
||||
|
||||
void V3Global::checkTree() { rootp()->checkTree(); }
|
||||
void V3Global::shutdown() {
|
||||
VL_DO_CLEAR(delete m_hierPlanp, m_hierPlanp = nullptr); // delete nullptr is safe
|
||||
}
|
||||
|
||||
void V3Global::checkTree() const { rootp()->checkTree(); }
|
||||
|
||||
void V3Global::readFiles() {
|
||||
// NODE STATE
|
||||
|
|
@ -47,8 +52,7 @@ void V3Global::readFiles() {
|
|||
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;
|
||||
for (const string& filename : vFiles) {
|
||||
parser.parseFile(new FileLine(FileLine::commandLineFilename()), filename, false,
|
||||
"Cannot find file containing module: ");
|
||||
}
|
||||
|
|
@ -57,8 +61,7 @@ void V3Global::readFiles() {
|
|||
// 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;
|
||||
for (const string& filename : libraryFiles) {
|
||||
parser.parseFile(new FileLine(FileLine::commandLineFilename()), filename, true,
|
||||
"Cannot find file containing library module: ");
|
||||
}
|
||||
|
|
@ -78,7 +81,7 @@ void V3Global::dumpCheckGlobalTree(const string& stagename, int newNumber, bool
|
|||
}
|
||||
|
||||
const std::string& V3Global::ptrToId(const void* p) {
|
||||
PtrToIdMap::iterator it = m_ptrToId.find(p);
|
||||
auto it = m_ptrToId.find(p);
|
||||
if (it == m_ptrToId.end()) {
|
||||
std::ostringstream os;
|
||||
if (p) {
|
||||
|
|
|
|||
|
|
@ -31,26 +31,47 @@
|
|||
#include "V3Options.h"
|
||||
|
||||
#include <string>
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
|
||||
class AstNetlist;
|
||||
class V3HierBlockPlan;
|
||||
|
||||
//======================================================================
|
||||
// Statics
|
||||
// Restorer
|
||||
|
||||
/// Save a given variable's value on the stack, restoring it at
|
||||
/// end-of-stope.
|
||||
// Object must be named, or it will not persist until end-of-scope.
|
||||
// Constructor needs () or GCC 4.8 false warning.
|
||||
#define VL_RESTORER(var) const VRestorer<decltype(var)> restorer_##var(var);
|
||||
|
||||
// Object used by VL_RESTORER. This object must be an auto variable, not
|
||||
// allocated on the heap or otherwise.
|
||||
template <typename T> class VRestorer {
|
||||
T& m_ref; // Reference to object we're saving and restoring
|
||||
const T m_saved; // Value saved, for later restore
|
||||
|
||||
public:
|
||||
VRestorer(T& permr)
|
||||
: m_ref(permr)
|
||||
, m_saved(permr) {}
|
||||
~VRestorer() { m_ref = m_saved; }
|
||||
VL_UNCOPYABLE(VRestorer);
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
||||
class VWidthMinUsage {
|
||||
public:
|
||||
enum en { LINT_WIDTH, MATCHES_WIDTH, VERILOG_WIDTH };
|
||||
enum en : uint8_t { LINT_WIDTH, MATCHES_WIDTH, VERILOG_WIDTH };
|
||||
enum en m_e;
|
||||
inline VWidthMinUsage()
|
||||
: m_e(LINT_WIDTH) {}
|
||||
: m_e{LINT_WIDTH} {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline VWidthMinUsage(en _e)
|
||||
: m_e(_e) {}
|
||||
: m_e{_e} {}
|
||||
explicit inline VWidthMinUsage(int _e)
|
||||
: m_e(static_cast<en>(_e)) {}
|
||||
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
||||
operator en() const { return m_e; }
|
||||
};
|
||||
inline bool operator==(const VWidthMinUsage& lhs, const VWidthMinUsage& rhs) {
|
||||
|
|
@ -69,19 +90,19 @@ inline bool operator==(VWidthMinUsage::en lhs, const VWidthMinUsage& rhs) {
|
|||
class V3Global {
|
||||
// Globals
|
||||
AstNetlist* m_rootp; // Root of entire netlist
|
||||
V3HierBlockPlan* m_hierPlanp; // Hierarchical verilation plan, nullptr unless hier_block
|
||||
VWidthMinUsage m_widthMinUsage; // What AstNode::widthMin() is used for
|
||||
|
||||
int m_debugFileNumber; // Number to append to debug files created
|
||||
bool m_assertDTypesResolved; // Tree should have dtypep()'s
|
||||
bool m_constRemoveXs; // Const needs to strip any Xs
|
||||
bool m_needC11; // Need C++11
|
||||
bool m_needHeavy; // Need verilated_heavy.h include
|
||||
bool m_needTraceDumper; // Need __Vm_dumperp in symbols
|
||||
bool m_dpi; // Need __Dpi include files
|
||||
bool m_useParallelBuild; // Use parallel build for model
|
||||
int m_debugFileNumber = 0; // Number to append to debug files created
|
||||
bool m_assertDTypesResolved = false; // Tree should have dtypep()'s
|
||||
bool m_constRemoveXs = false; // Const needs to strip any Xs
|
||||
bool m_needHeavy = false; // Need verilated_heavy.h include
|
||||
bool m_needTraceDumper = false; // Need __Vm_dumperp in symbols
|
||||
bool m_dpi = false; // Need __Dpi include files
|
||||
bool m_useParallelBuild = false; // Use parallel build for model
|
||||
|
||||
// Memory address to short string mapping (for debug)
|
||||
typedef vl_unordered_map<const void*, std::string> PtrToIdMap; // The map type
|
||||
typedef std::unordered_map<const void*, std::string> PtrToIdMap; // The map type
|
||||
PtrToIdMap m_ptrToId; // The actual 'address' <=> 'short string' bijection
|
||||
|
||||
public:
|
||||
|
|
@ -90,21 +111,15 @@ public:
|
|||
|
||||
// CONSTRUCTORS
|
||||
V3Global()
|
||||
: m_rootp(NULL) // created by makeInitNetlist() so static constructors run first
|
||||
, m_widthMinUsage(VWidthMinUsage::LINT_WIDTH)
|
||||
, m_debugFileNumber(0)
|
||||
, m_assertDTypesResolved(false)
|
||||
, m_constRemoveXs(false)
|
||||
, m_needC11(false)
|
||||
, m_needHeavy(false)
|
||||
, m_needTraceDumper(false)
|
||||
, m_dpi(false)
|
||||
, m_useParallelBuild(false) {}
|
||||
: m_rootp{nullptr} // created by makeInitNetlist(} so static constructors run first
|
||||
, m_hierPlanp{nullptr} // Set via hierPlanp(V3HierBlockPlan*} when use hier_block
|
||||
, m_widthMinUsage{VWidthMinUsage::LINT_WIDTH} {}
|
||||
AstNetlist* makeNetlist();
|
||||
void boot() {
|
||||
UASSERT(!m_rootp, "call once");
|
||||
m_rootp = makeNetlist();
|
||||
}
|
||||
void shutdown(); // Release allocated resorces
|
||||
// ACCESSORS (general)
|
||||
AstNetlist* rootp() const { return m_rootp; }
|
||||
VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; }
|
||||
|
|
@ -112,7 +127,7 @@ public:
|
|||
|
||||
// METHODS
|
||||
void readFiles();
|
||||
void checkTree();
|
||||
void checkTree() const;
|
||||
static void dumpCheckGlobalTree(const string& stagename, int newNumber = 0,
|
||||
bool doDump = true);
|
||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||
|
|
@ -124,16 +139,19 @@ public:
|
|||
if (newNumber) m_debugFileNumber = newNumber;
|
||||
char digits[100];
|
||||
sprintf(digits, "%03d", m_debugFileNumber);
|
||||
return opt.makeDir() + "/" + opt.prefix() + "_" + digits + "_" + nameComment;
|
||||
return opt.hierTopDataDir() + "/" + opt.prefix() + "_" + digits + "_" + nameComment;
|
||||
}
|
||||
bool needC11() const { return m_needC11; }
|
||||
void needC11(bool flag) { m_needC11 = flag; }
|
||||
bool needHeavy() const { return m_needHeavy; }
|
||||
void needHeavy(bool flag) { m_needHeavy = flag; }
|
||||
bool needTraceDumper() const { return m_needTraceDumper; }
|
||||
void needTraceDumper(bool flag) { m_needTraceDumper = flag; }
|
||||
bool dpi() const { return m_dpi; }
|
||||
void dpi(bool flag) { m_dpi = flag; }
|
||||
V3HierBlockPlan* hierPlanp() const { return m_hierPlanp; }
|
||||
void hierPlanp(V3HierBlockPlan* plan) {
|
||||
UASSERT(!m_hierPlanp, "call once");
|
||||
m_hierPlanp = plan;
|
||||
}
|
||||
void useParallelBuild(bool flag) { m_useParallelBuild = flag; }
|
||||
bool useParallelBuild() const { return m_useParallelBuild; }
|
||||
const std::string& ptrToId(const void* p);
|
||||
|
|
|
|||
|
|
@ -33,18 +33,18 @@ int V3Graph::debug() { return std::max(V3Error::debugDefault(), s_debug); }
|
|||
// Vertices
|
||||
|
||||
V3GraphVertex::V3GraphVertex(V3Graph* graphp, const V3GraphVertex& old)
|
||||
: m_fanout(old.m_fanout)
|
||||
, m_color(old.m_color)
|
||||
, m_rank(old.m_rank) {
|
||||
m_userp = NULL;
|
||||
: m_fanout{old.m_fanout}
|
||||
, m_color{old.m_color}
|
||||
, m_rank{old.m_rank} {
|
||||
m_userp = nullptr;
|
||||
verticesPushBack(graphp);
|
||||
}
|
||||
|
||||
V3GraphVertex::V3GraphVertex(V3Graph* graphp)
|
||||
: m_fanout(0)
|
||||
, m_color(0)
|
||||
, m_rank(0) {
|
||||
m_userp = NULL;
|
||||
: m_fanout{0}
|
||||
, m_color{0}
|
||||
, m_rank{0} {
|
||||
m_userp = nullptr;
|
||||
verticesPushBack(graphp);
|
||||
}
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ void V3GraphVertex::verticesPushBack(V3Graph* graphp) {
|
|||
m_vertices.pushBack(graphp->m_vertices, this);
|
||||
}
|
||||
|
||||
void V3GraphVertex::unlinkEdges(V3Graph* graphp) {
|
||||
void V3GraphVertex::unlinkEdges(V3Graph*) {
|
||||
for (V3GraphEdge* edgep = outBeginp(); edgep; /*BELOW*/) {
|
||||
V3GraphEdge* nextp = edgep->outNextp();
|
||||
edgep->unlinkDelete();
|
||||
|
|
@ -71,7 +71,7 @@ void V3GraphVertex::unlinkDelete(V3Graph* graphp) {
|
|||
// Unlink from vertex list
|
||||
m_vertices.unlink(graphp->m_vertices, this);
|
||||
// Delete
|
||||
delete this; // this=NULL;
|
||||
delete this; // this=nullptr;
|
||||
}
|
||||
|
||||
void V3GraphVertex::rerouteEdges(V3Graph* graphp) {
|
||||
|
|
@ -123,7 +123,7 @@ V3GraphEdge* V3GraphVertex::findConnectingEdgep(GraphWay way, const V3GraphVerte
|
|||
aedgep = aedgep->nextp(way);
|
||||
bedgep = bedgep->nextp(inv);
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void V3GraphVertex::v3errorEnd(std::ostringstream& str) const {
|
||||
|
|
@ -165,7 +165,7 @@ void V3GraphEdge::init(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top
|
|||
m_top = top;
|
||||
m_weight = weight;
|
||||
m_cutable = cutable;
|
||||
m_userp = NULL;
|
||||
m_userp = nullptr;
|
||||
// Link vertices to this edge
|
||||
outPushBack();
|
||||
inPushBack();
|
||||
|
|
@ -185,7 +185,7 @@ void V3GraphEdge::unlinkDelete() {
|
|||
// Unlink to side
|
||||
m_ins.unlink(m_top->m_ins, this);
|
||||
// Delete
|
||||
delete this; // this=NULL;
|
||||
delete this; // this=nullptr;
|
||||
}
|
||||
|
||||
void V3GraphEdge::outPushBack() {
|
||||
|
|
@ -239,7 +239,7 @@ void V3Graph::userClearVertices() {
|
|||
// down more than help.
|
||||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) {
|
||||
vertexp->user(0);
|
||||
vertexp->userp(NULL); // Its a union, but might be different size than user()
|
||||
vertexp->userp(nullptr); // Its a union, but might be different size than user()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -248,7 +248,7 @@ void V3Graph::userClearEdges() {
|
|||
for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp = vertexp->verticesNextp()) {
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
edgep->user(0);
|
||||
edgep->userp(NULL); // Its a union, but might be different size than user()
|
||||
edgep->userp(nullptr); // Its a union, but might be different size than user()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -314,7 +314,7 @@ void V3Graph::dumpDotFilePrefixedAlways(const string& nameComment, bool colorAsS
|
|||
void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) const {
|
||||
// This generates a file used by graphviz, https://www.graphviz.org
|
||||
// "hardcoded" parameters:
|
||||
const vl_unique_ptr<std::ofstream> logp(V3File::new_ofstream(filename));
|
||||
const std::unique_ptr<std::ofstream> logp(V3File::new_ofstream(filename));
|
||||
if (logp->fail()) v3fatal("Can't write " << filename);
|
||||
|
||||
// Header
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ typedef bool (*V3EdgeFuncP)(const V3GraphEdge* edgep);
|
|||
|
||||
class GraphWay {
|
||||
public:
|
||||
enum en {
|
||||
enum en : uint8_t {
|
||||
FORWARD = 0,
|
||||
REVERSE = 1,
|
||||
NUM_WAYS = 2 // NUM_WAYS is not an actual way, it's typically
|
||||
|
|
@ -55,12 +55,12 @@ public:
|
|||
};
|
||||
enum en m_e;
|
||||
inline GraphWay()
|
||||
: m_e(FORWARD) {}
|
||||
: m_e{FORWARD} {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline GraphWay(en _e)
|
||||
: m_e(_e) {}
|
||||
: m_e{_e} {}
|
||||
explicit inline GraphWay(int _e)
|
||||
: m_e(static_cast<en>(_e)) {}
|
||||
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
||||
operator en() const { return m_e; }
|
||||
const char* ascii() const {
|
||||
static const char* const names[] = {"FORWARD", "REVERSE"};
|
||||
|
|
@ -229,7 +229,7 @@ public:
|
|||
virtual string dotStyle() const { return ""; }
|
||||
virtual string dotName() const { return ""; }
|
||||
virtual uint32_t rankAdder() const { return 1; }
|
||||
virtual FileLine* fileline() const { return NULL; } // NULL for unknown
|
||||
virtual FileLine* fileline() const { return nullptr; } // nullptr for unknown
|
||||
virtual int sortCmp(const V3GraphVertex* rhsp) const {
|
||||
// LHS goes first if of lower rank, or lower fanout
|
||||
if (m_rank < rhsp->m_rank) return -1;
|
||||
|
|
@ -250,11 +250,11 @@ public:
|
|||
// ITERATORS
|
||||
V3GraphVertex* verticesNextp() const { return m_vertices.nextp(); }
|
||||
V3GraphEdge* inBeginp() const { return m_ins.begin(); }
|
||||
bool inEmpty() const { return inBeginp() == NULL; }
|
||||
bool inEmpty() const { return inBeginp() == nullptr; }
|
||||
bool inSize1() const;
|
||||
uint32_t inHash() const;
|
||||
V3GraphEdge* outBeginp() const { return m_outs.begin(); }
|
||||
bool outEmpty() const { return outBeginp() == NULL; }
|
||||
bool outEmpty() const { return outBeginp() == nullptr; }
|
||||
bool outSize1() const;
|
||||
uint32_t outHash() const;
|
||||
V3GraphEdge* beginp(GraphWay way) const { return way.forward() ? outBeginp() : inBeginp(); }
|
||||
|
|
@ -265,7 +265,7 @@ public:
|
|||
/// Edges are routed around this vertex to point from "from" directly to "to"
|
||||
void rerouteEdges(V3Graph* graphp);
|
||||
/// Find the edge connecting ap and bp, where bp is wayward from ap.
|
||||
/// If edge is not found returns NULL. O(edges) performance.
|
||||
/// If edge is not found returns nullptr. O(edges) performance.
|
||||
V3GraphEdge* findConnectingEdgep(GraphWay way, const V3GraphVertex* waywardp);
|
||||
};
|
||||
|
||||
|
|
@ -277,7 +277,7 @@ class V3GraphEdge {
|
|||
// Wires/variables aren't edges. Edges have only a single to/from vertex
|
||||
public:
|
||||
// ENUMS
|
||||
enum Cutable { NOT_CUTABLE = false, CUTABLE = true }; // For passing to V3GraphEdge
|
||||
enum Cutable : uint8_t { NOT_CUTABLE = false, CUTABLE = true }; // For passing to V3GraphEdge
|
||||
protected:
|
||||
friend class V3Graph;
|
||||
friend class V3GraphVertex;
|
||||
|
|
|
|||
|
|
@ -35,23 +35,20 @@ class GraphAcycVertex : public V3GraphVertex {
|
|||
protected:
|
||||
friend class GraphAcyc;
|
||||
V3ListEnt<GraphAcycVertex*> m_work; // List of vertices with optimization work left
|
||||
uint32_t m_storedRank; // Rank held until commit to edge placement
|
||||
bool m_onWorkList; // True if already on list of work to do
|
||||
bool m_deleted; // True if deleted
|
||||
uint32_t m_storedRank = 0; // Rank held until commit to edge placement
|
||||
bool m_onWorkList = false; // True if already on list of work to do
|
||||
bool m_deleted = false; // True if deleted
|
||||
public:
|
||||
GraphAcycVertex(V3Graph* graphp, V3GraphVertex* origVertexp)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_origVertexp(origVertexp)
|
||||
, m_storedRank(0)
|
||||
, m_onWorkList(false)
|
||||
, m_deleted(false) {}
|
||||
virtual ~GraphAcycVertex() {}
|
||||
: V3GraphVertex{graphp}
|
||||
, m_origVertexp{origVertexp} {}
|
||||
virtual ~GraphAcycVertex() override {}
|
||||
V3GraphVertex* origVertexp() const { return m_origVertexp; }
|
||||
void setDelete() { m_deleted = true; }
|
||||
bool isDelete() const { return m_deleted; }
|
||||
virtual string name() const { return m_origVertexp->name(); }
|
||||
virtual string dotColor() const { return m_origVertexp->dotColor(); }
|
||||
virtual FileLine* fileline() const { return m_origVertexp->fileline(); }
|
||||
virtual string name() const override { return m_origVertexp->name(); }
|
||||
virtual string dotColor() const override { return m_origVertexp->dotColor(); }
|
||||
virtual FileLine* fileline() const override { return m_origVertexp->fileline(); }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -69,10 +66,12 @@ private:
|
|||
public:
|
||||
GraphAcycEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
|
||||
bool cutable = false)
|
||||
: V3GraphEdge(graphp, fromp, top, weight, cutable) {}
|
||||
virtual ~GraphAcycEdge() {}
|
||||
: V3GraphEdge{graphp, fromp, top, weight, cutable} {}
|
||||
virtual ~GraphAcycEdge() override {}
|
||||
// yellow=we might still cut it, else oldEdge: yellowGreen=made uncutable, red=uncutable
|
||||
virtual string dotColor() const { return (cutable() ? "yellow" : origEdgep()->dotColor()); }
|
||||
virtual string dotColor() const override {
|
||||
return (cutable() ? "yellow" : origEdgep()->dotColor());
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -104,7 +103,7 @@ private:
|
|||
V3List<GraphAcycVertex*> m_work; // List of vertices with optimization work left
|
||||
std::vector<OrigEdgeList*> m_origEdgeDelp; // List of deletions to do when done
|
||||
V3EdgeFuncP m_origEdgeFuncp; // Function that says we follow this edge (in original graph)
|
||||
uint32_t m_placeStep; // Number that user() must be equal to to indicate processing
|
||||
uint32_t m_placeStep = 0; // Number that user() must be equal to to indicate processing
|
||||
|
||||
static int debug() { return V3Graph::debug(); }
|
||||
|
||||
|
|
@ -136,7 +135,7 @@ private:
|
|||
void addOrigEdgep(V3GraphEdge* toEdgep, V3GraphEdge* addEdgep) {
|
||||
// Add addEdge (or it's list) to list of edges that break edge represents
|
||||
// Note addEdge may already have a bunch of similar linked edge representations. Yuk.
|
||||
UASSERT(addEdgep, "Adding NULL");
|
||||
UASSERT(addEdgep, "Adding nullptr");
|
||||
if (!toEdgep->userp()) {
|
||||
OrigEdgeList* oep = new OrigEdgeList;
|
||||
m_origEdgeDelp.push_back(oep);
|
||||
|
|
@ -186,16 +185,11 @@ private:
|
|||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
GraphAcyc(V3Graph* origGraphp, V3EdgeFuncP edgeFuncp) {
|
||||
m_origGraphp = origGraphp;
|
||||
m_origEdgeFuncp = edgeFuncp;
|
||||
m_placeStep = 0;
|
||||
}
|
||||
GraphAcyc(V3Graph* origGraphp, V3EdgeFuncP edgeFuncp)
|
||||
: m_origGraphp{origGraphp}
|
||||
, m_origEdgeFuncp{edgeFuncp} {}
|
||||
~GraphAcyc() {
|
||||
for (std::vector<OrigEdgeList*>::iterator it = m_origEdgeDelp.begin();
|
||||
it != m_origEdgeDelp.end(); ++it) {
|
||||
delete (*it);
|
||||
}
|
||||
for (OrigEdgeList* ip : m_origEdgeDelp) delete ip;
|
||||
m_origEdgeDelp.clear();
|
||||
}
|
||||
void main();
|
||||
|
|
@ -382,7 +376,7 @@ void GraphAcyc::simplifyDup(GraphAcycVertex* avertexp) {
|
|||
if (avertexp->isDelete()) return;
|
||||
// Clear marks
|
||||
for (V3GraphEdge* edgep = avertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
edgep->top()->userp(NULL);
|
||||
edgep->top()->userp(nullptr);
|
||||
}
|
||||
// Mark edges and detect duplications
|
||||
for (V3GraphEdge *nextp, *edgep = avertexp->outBeginp(); edgep; edgep = nextp) {
|
||||
|
|
@ -479,10 +473,7 @@ void GraphAcyc::place() {
|
|||
|
||||
// Process each edge in weighted order
|
||||
m_placeStep = 10;
|
||||
for (std::vector<V3GraphEdge*>::iterator it = edges.begin(); it != edges.end(); ++it) {
|
||||
V3GraphEdge* edgep = (*it);
|
||||
placeTryEdge(edgep);
|
||||
}
|
||||
for (V3GraphEdge* edgep : edges) placeTryEdge(edgep);
|
||||
}
|
||||
|
||||
void GraphAcyc::placeTryEdge(V3GraphEdge* edgep) {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ private:
|
|||
void vertexIterate(V3GraphVertex* vertexp) {
|
||||
// Clear marks
|
||||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
edgep->top()->userp(NULL);
|
||||
edgep->top()->userp(nullptr);
|
||||
}
|
||||
// Mark edges and detect duplications
|
||||
for (V3GraphEdge *nextp, *edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
|
||||
|
|
@ -119,8 +119,8 @@ private:
|
|||
|
||||
public:
|
||||
GraphRemoveRedundant(V3Graph* graphp, V3EdgeFuncP edgeFuncp, bool sumWeights)
|
||||
: GraphAlg<>(graphp, edgeFuncp)
|
||||
, m_sumWeights(sumWeights) {
|
||||
: GraphAlg<>{graphp, edgeFuncp}
|
||||
, m_sumWeights{sumWeights} {
|
||||
main();
|
||||
}
|
||||
~GraphRemoveRedundant() {}
|
||||
|
|
@ -140,13 +140,13 @@ void V3Graph::removeRedundantEdgesSum(V3EdgeFuncP edgeFuncp) {
|
|||
class GraphAlgRemoveTransitiveEdges : GraphAlg<> {
|
||||
public:
|
||||
explicit GraphAlgRemoveTransitiveEdges(V3Graph* graphp)
|
||||
: GraphAlg<>(graphp, NULL) {}
|
||||
: GraphAlg<>(graphp, nullptr) {}
|
||||
void go() {
|
||||
GraphPathChecker checker(m_graphp);
|
||||
for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
|
||||
V3GraphEdge* deletep = NULL;
|
||||
V3GraphEdge* deletep = nullptr;
|
||||
for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
if (deletep) VL_DO_CLEAR(deletep->unlinkDelete(), deletep = NULL);
|
||||
if (deletep) VL_DO_CLEAR(deletep->unlinkDelete(), deletep = nullptr);
|
||||
// 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
|
||||
|
|
@ -284,7 +284,7 @@ private:
|
|||
|
||||
public:
|
||||
GraphAlgStrongly(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<>(graphp, edgeFuncp) {
|
||||
: GraphAlg<>{graphp, edgeFuncp} {
|
||||
m_currentDfs = 0;
|
||||
main();
|
||||
}
|
||||
|
|
@ -336,7 +336,7 @@ private:
|
|||
|
||||
public:
|
||||
GraphAlgRank(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<>(graphp, edgeFuncp) {
|
||||
: GraphAlg<>{graphp, edgeFuncp} {
|
||||
main();
|
||||
}
|
||||
~GraphAlgRank() {}
|
||||
|
|
@ -389,7 +389,7 @@ private:
|
|||
|
||||
public:
|
||||
GraphAlgRLoops(V3Graph* graphp, V3EdgeFuncP edgeFuncp, V3GraphVertex* vertexp)
|
||||
: GraphAlg<>(graphp, edgeFuncp) {
|
||||
: GraphAlg<>{graphp, edgeFuncp} {
|
||||
m_done = false;
|
||||
main(vertexp);
|
||||
}
|
||||
|
|
@ -433,8 +433,8 @@ private:
|
|||
public:
|
||||
GraphAlgSubtrees(V3Graph* graphp, V3Graph* loopGraphp, V3EdgeFuncP edgeFuncp,
|
||||
V3GraphVertex* vertexp)
|
||||
: GraphAlg<>(graphp, edgeFuncp)
|
||||
, m_loopGraphp(loopGraphp) {
|
||||
: GraphAlg<>{graphp, edgeFuncp}
|
||||
, m_loopGraphp{loopGraphp} {
|
||||
// Vertex::m_userp - New vertex if we have seen this vertex already
|
||||
// Edge::m_userp - New edge if we have seen this edge already
|
||||
m_graphp->userClearVertices();
|
||||
|
|
@ -487,9 +487,7 @@ void V3Graph::sortVertices() {
|
|||
}
|
||||
std::stable_sort(vertices.begin(), vertices.end(), GraphSortVertexCmp());
|
||||
this->verticesUnlink();
|
||||
for (std::vector<V3GraphVertex*>::iterator it = vertices.begin(); it != vertices.end(); ++it) {
|
||||
(*it)->verticesPushBack(this);
|
||||
}
|
||||
for (V3GraphVertex* ip : vertices) ip->verticesPushBack(this);
|
||||
}
|
||||
|
||||
void V3Graph::sortEdges() {
|
||||
|
|
@ -507,10 +505,7 @@ void V3Graph::sortEdges() {
|
|||
// We know the vector contains all of the edges that were
|
||||
// there originally (didn't delete or add)
|
||||
vertexp->outUnlink();
|
||||
for (std::vector<V3GraphEdge*>::const_iterator it = edges.begin(); it != edges.end();
|
||||
++it) {
|
||||
(*it)->outPushBack();
|
||||
}
|
||||
for (V3GraphEdge* edgep : edges) edgep->outPushBack();
|
||||
// Prep for next
|
||||
edges.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ protected:
|
|||
V3EdgeFuncP m_edgeFuncp; // Function that says we follow this edge
|
||||
// CONSTRUCTORS
|
||||
GraphAlg(T_Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: m_graphp(graphp)
|
||||
, m_edgeFuncp(edgeFuncp) {}
|
||||
: m_graphp{graphp}
|
||||
, m_edgeFuncp{edgeFuncp} {}
|
||||
~GraphAlg() {}
|
||||
// METHODS
|
||||
inline bool followEdge(V3GraphEdge* edgep) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
// Algorithms - find starting node
|
||||
|
||||
DfaVertex* DfaGraph::findStart() {
|
||||
DfaVertex* startp = NULL;
|
||||
DfaVertex* startp = nullptr;
|
||||
for (V3GraphVertex* vertexp = this->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||
|
|
@ -83,7 +83,7 @@ private:
|
|||
return (nfaState(vertexp) && !(vertexp->user() == m_step));
|
||||
}
|
||||
|
||||
DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep = NULL) {
|
||||
DfaVertex* newDfaVertex(DfaVertex* nfaTemplatep = nullptr) {
|
||||
DfaVertex* vertexp = new DfaVertex(graphp());
|
||||
vertexp->color(1); // Mark as dfa
|
||||
if (nfaTemplatep && nfaTemplatep->start()) vertexp->start(true);
|
||||
|
|
@ -133,11 +133,7 @@ private:
|
|||
uint32_t hashDfaOrigins(const DfaStates& nfasWithInput) {
|
||||
// Find the NFA states this dfa came from,
|
||||
uint32_t hash = 0;
|
||||
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin(); nfaIt != nfasWithInput.end();
|
||||
++nfaIt) {
|
||||
DfaVertex* nfaStatep = *nfaIt;
|
||||
hash ^= hashVertex(nfaStatep);
|
||||
}
|
||||
for (DfaVertex* nfaStatep : nfasWithInput) hash ^= hashVertex(nfaStatep);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
@ -147,9 +143,7 @@ private:
|
|||
nextStep();
|
||||
// Mark all input vertexes
|
||||
int num1s = 0;
|
||||
for (DfaStates::const_iterator nfaIt = nfasWithInput.begin(); nfaIt != nfasWithInput.end();
|
||||
++nfaIt) {
|
||||
DfaVertex* nfaStatep = *nfaIt;
|
||||
for (DfaVertex* nfaStatep : nfasWithInput) {
|
||||
nfaStatep->user(m_step);
|
||||
num1s++;
|
||||
}
|
||||
|
|
@ -182,7 +176,7 @@ private:
|
|||
// not depend on order of edges
|
||||
uint32_t hash = hashDfaOrigins(nfasWithInput);
|
||||
|
||||
std::pair<HashMap::iterator, HashMap::iterator> eqrange = m_hashMap.equal_range(hash);
|
||||
const auto eqrange = m_hashMap.equal_range(hash);
|
||||
for (HashMap::iterator it = eqrange.first; it != eqrange.second; ++it) {
|
||||
DfaVertex* testp = it->second;
|
||||
if (compareDfaOrigins(nfasWithInput, testp)) {
|
||||
|
|
@ -190,7 +184,7 @@ private:
|
|||
return testp; // Identical
|
||||
}
|
||||
}
|
||||
return NULL; // No match
|
||||
return nullptr; // No match
|
||||
}
|
||||
|
||||
void findNfasWithInput(DfaVertex* dfaStatep, const DfaInput& input, DfaStates& nfasWithInput) {
|
||||
|
|
@ -371,7 +365,7 @@ private:
|
|||
|
||||
public:
|
||||
GraphNfaToDfa(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<>(graphp, edgeFuncp) {
|
||||
: GraphAlg<>{graphp, edgeFuncp} {
|
||||
m_step = 0;
|
||||
main();
|
||||
}
|
||||
|
|
@ -500,7 +494,7 @@ private:
|
|||
|
||||
public:
|
||||
DfaGraphReduce(V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<>(graphp, edgeFuncp) {
|
||||
: GraphAlg<>{graphp, edgeFuncp} {
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_in");
|
||||
optimize_accepting_out();
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("opt_acc");
|
||||
|
|
@ -545,7 +539,7 @@ private:
|
|||
|
||||
void add_complement_edges() {
|
||||
// Find accepting vertex
|
||||
DfaVertex* acceptp = NULL;
|
||||
DfaVertex* acceptp = nullptr;
|
||||
for (V3GraphVertex* vertexp = m_graphp->verticesBeginp(); vertexp;
|
||||
vertexp = vertexp->verticesNextp()) {
|
||||
if (DfaVertex* vvertexp = dynamic_cast<DfaVertex*>(vertexp)) {
|
||||
|
|
@ -592,7 +586,7 @@ private:
|
|||
|
||||
public:
|
||||
DfaGraphComplement(V3Graph* dfagraphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<>(dfagraphp, edgeFuncp) {
|
||||
: GraphAlg<>{dfagraphp, edgeFuncp} {
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_in");
|
||||
|
||||
// Vertex::m_user begin: 1 indicates new edge, no more processing
|
||||
|
|
@ -602,7 +596,7 @@ public:
|
|||
add_complement_edges();
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_preswap");
|
||||
|
||||
VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = NULL);
|
||||
VL_DO_CLEAR(m_tempNewerReject->unlinkDelete(graphp()), m_tempNewerReject = nullptr);
|
||||
if (debug() >= 6) m_graphp->dumpDotFilePrefixed("comp_out");
|
||||
}
|
||||
~DfaGraphComplement() {}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class DfaGraph : public V3Graph {
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
DfaGraph() {}
|
||||
virtual ~DfaGraph() {}
|
||||
virtual ~DfaGraph() override {}
|
||||
// METHODS
|
||||
/// Find start node
|
||||
DfaVertex* findStart();
|
||||
|
|
@ -86,17 +86,19 @@ class DfaVertex : public V3GraphVertex {
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DfaVertex(DfaGraph* graphp, bool start = false, bool accepting = false)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_start(start)
|
||||
, m_accepting(accepting) {}
|
||||
: V3GraphVertex{graphp}
|
||||
, m_start{start}
|
||||
, m_accepting{accepting} {}
|
||||
using V3GraphVertex::clone; // We are overriding, not overloading clone(V3Graph*)
|
||||
virtual DfaVertex* clone(DfaGraph* graphp) {
|
||||
return new DfaVertex(graphp, start(), accepting());
|
||||
}
|
||||
virtual ~DfaVertex() {}
|
||||
virtual ~DfaVertex() override {}
|
||||
// ACCESSORS
|
||||
virtual string dotShape() const { return (accepting() ? "doublecircle" : ""); }
|
||||
virtual string dotColor() const { return start() ? "blue" : (color() ? "red" : "black"); }
|
||||
virtual string dotShape() const override { return (accepting() ? "doublecircle" : ""); }
|
||||
virtual string dotColor() const override {
|
||||
return start() ? "blue" : (color() ? "red" : "black");
|
||||
}
|
||||
bool start() const { return m_start; }
|
||||
void start(bool flag) { m_start = flag; }
|
||||
bool accepting() const { return m_accepting; }
|
||||
|
|
@ -119,23 +121,25 @@ public:
|
|||
static DfaInput NA() { return VNUser::fromInt(1); } // as in not-applicable
|
||||
// CONSTRUCTORS
|
||||
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaInput& input)
|
||||
: V3GraphEdge(graphp, fromp, top, 1)
|
||||
: V3GraphEdge{graphp, fromp, top, 1}
|
||||
, m_input(input)
|
||||
, m_complement(false) {}
|
||||
DfaEdge(DfaGraph* graphp, DfaVertex* fromp, DfaVertex* top, const DfaEdge* copyfrom)
|
||||
: V3GraphEdge(graphp, fromp, top, copyfrom->weight())
|
||||
, m_input(copyfrom->input())
|
||||
, m_complement(copyfrom->complement()) {}
|
||||
virtual ~DfaEdge() {}
|
||||
: V3GraphEdge{graphp, fromp, top, copyfrom->weight()}
|
||||
, m_input{copyfrom->input()}
|
||||
, m_complement{copyfrom->complement()} {}
|
||||
virtual ~DfaEdge() override {}
|
||||
// METHODS
|
||||
virtual string dotColor() const { return (na() ? "yellow" : epsilon() ? "green" : "black"); }
|
||||
virtual string dotLabel() const {
|
||||
virtual string dotColor() const override {
|
||||
return (na() ? "yellow" : epsilon() ? "green" : "black");
|
||||
}
|
||||
virtual string dotLabel() const override {
|
||||
return (na() ? ""
|
||||
: epsilon() ? "e"
|
||||
: complement() ? ("not " + cvtToStr(input().toInt()))
|
||||
: cvtToStr(input().toInt()));
|
||||
}
|
||||
virtual string dotStyle() const { return (na() || cutable()) ? "dashed" : ""; }
|
||||
virtual string dotStyle() const override { return (na() || cutable()) ? "dashed" : ""; }
|
||||
bool epsilon() const { return input().toInt() == EPSILON().toInt(); }
|
||||
bool na() const { return input().toInt() == NA().toInt(); }
|
||||
bool complement() const { return m_complement; }
|
||||
|
|
|
|||
|
|
@ -38,11 +38,10 @@ struct GraphPCNode {
|
|||
// operation. We'll use this in pathExistsInternal() to avoid checking
|
||||
// the same node twice, and again in updateHalfCriticalPath() to assert
|
||||
// there are no cycles.
|
||||
vluint64_t m_seenAtGeneration;
|
||||
vluint64_t m_seenAtGeneration = 0;
|
||||
|
||||
// CONSTRUCTORS
|
||||
GraphPCNode()
|
||||
: m_seenAtGeneration(0) {
|
||||
GraphPCNode() {
|
||||
for (int w = 0; w < GraphWay::NUM_WAYS; w++) m_cp[w] = 0;
|
||||
}
|
||||
~GraphPCNode() {}
|
||||
|
|
@ -52,8 +51,8 @@ struct GraphPCNode {
|
|||
// GraphPathChecker implementation
|
||||
|
||||
GraphPathChecker::GraphPathChecker(const V3Graph* graphp, V3EdgeFuncP edgeFuncp)
|
||||
: GraphAlg<const V3Graph>(graphp, edgeFuncp)
|
||||
, m_generation(0) {
|
||||
: GraphAlg<const V3Graph>{graphp, edgeFuncp}
|
||||
, m_generation{0} {
|
||||
for (V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
|
||||
// Setup tracking structure for each node. If delete a vertex
|
||||
// there would be a leak, but ok as accept only const V3Graph*'s.
|
||||
|
|
@ -69,7 +68,7 @@ GraphPathChecker::~GraphPathChecker() {
|
|||
for (V3GraphVertex* vxp = m_graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) {
|
||||
GraphPCNode* nodep = static_cast<GraphPCNode*>(vxp->userp());
|
||||
VL_DO_DANGLING(delete nodep, nodep);
|
||||
vxp->userp(NULL);
|
||||
vxp->userp(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ public:
|
|||
|
||||
private:
|
||||
bool pathExistsInternal(const V3GraphVertex* ap, const V3GraphVertex* bp,
|
||||
unsigned* costp = NULL);
|
||||
unsigned* costp = nullptr);
|
||||
void initHalfCriticalPaths(GraphWay way, bool checkOnly);
|
||||
void incGeneration() { ++m_generation; }
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#include "V3Graph.h"
|
||||
|
||||
#include <set>
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
|
||||
//######################################################################
|
||||
// GraphStream
|
||||
|
|
@ -48,9 +48,9 @@ private:
|
|||
uint32_t m_numBlockingEdges; // Number of blocking edges
|
||||
// CONSTRUCTORS
|
||||
VxHolder(const V3GraphVertex* vxp, uint32_t pos, uint32_t numBlockingEdges)
|
||||
: m_vxp(vxp)
|
||||
, m_pos(pos)
|
||||
, m_numBlockingEdges(numBlockingEdges) {}
|
||||
: m_vxp{vxp}
|
||||
, m_pos{pos}
|
||||
, m_numBlockingEdges{numBlockingEdges} {}
|
||||
// METHODS
|
||||
const V3GraphVertex* vertexp() const { return m_vxp; }
|
||||
// Decrement blocking edges count, return true if the vertex is
|
||||
|
|
@ -68,7 +68,7 @@ private:
|
|||
T_Compare m_lessThan; // Sorting functor
|
||||
// CONSTRUCTORS
|
||||
explicit VxHolderCmp(const T_Compare& lessThan)
|
||||
: m_lessThan(lessThan) {}
|
||||
: m_lessThan{lessThan} {}
|
||||
// METHODS
|
||||
bool operator()(const VxHolder& a, const VxHolder& b) const {
|
||||
if (m_lessThan.operator()(a.vertexp(), b.vertexp())) return true;
|
||||
|
|
@ -81,7 +81,7 @@ private:
|
|||
};
|
||||
|
||||
typedef std::set<VxHolder, VxHolderCmp&> ReadyVertices;
|
||||
typedef vl_unordered_map<const V3GraphVertex*, VxHolder> WaitingVertices;
|
||||
typedef std::unordered_map<const V3GraphVertex*, VxHolder> WaitingVertices;
|
||||
|
||||
// MEMBERS
|
||||
VxHolderCmp m_vxHolderCmp; // Vertext comparison functor
|
||||
|
|
@ -97,10 +97,10 @@ public:
|
|||
// 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.
|
||||
: m_vxHolderCmp(lessThan)
|
||||
, m_readyVertices(m_vxHolderCmp)
|
||||
, m_last(m_readyVertices.end())
|
||||
, m_way(way) {
|
||||
: m_vxHolderCmp{lessThan}
|
||||
, m_readyVertices{m_vxHolderCmp}
|
||||
, m_last{m_readyVertices.end()}
|
||||
, m_way{way} {
|
||||
uint32_t pos = 0;
|
||||
for (const V3GraphVertex* vxp = graphp->verticesBeginp(); vxp;
|
||||
vxp = vxp->verticesNextp()) {
|
||||
|
|
@ -160,7 +160,7 @@ public:
|
|||
// good locality.) V3Order.cpp relies on this to order the logic
|
||||
// vertices within a given mtask without jumping over domains too much.
|
||||
const V3GraphVertex* nextp() {
|
||||
const V3GraphVertex* resultp = NULL;
|
||||
const V3GraphVertex* resultp = nullptr;
|
||||
|
||||
typename ReadyVertices::iterator curIt;
|
||||
if (m_last == m_readyVertices.end()) {
|
||||
|
|
@ -197,7 +197,7 @@ private:
|
|||
for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||
V3GraphVertex* toVertexp = edgep->top();
|
||||
|
||||
typename WaitingVertices::iterator it = m_waitingVertices.find(toVertexp);
|
||||
const auto it = m_waitingVertices.find(toVertexp);
|
||||
UASSERT_OBJ(it != m_waitingVertices.end(), toVertexp,
|
||||
"Found edge into vertex not in waiting list.");
|
||||
if (it->second.unblock()) {
|
||||
|
|
@ -209,7 +209,7 @@ private:
|
|||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
V3GraphVertex* fromVertexp = edgep->fromp();
|
||||
|
||||
typename WaitingVertices::iterator it = m_waitingVertices.find(fromVertexp);
|
||||
const auto it = m_waitingVertices.find(fromVertexp);
|
||||
UASSERT_OBJ(it != m_waitingVertices.end(), fromVertexp,
|
||||
"Found edge into vertex not in waiting list.");
|
||||
if (it->second.unblock()) {
|
||||
|
|
@ -228,6 +228,6 @@ private:
|
|||
// GraphStreamUnordered is GraphStream using a plain pointer compare to
|
||||
// break ties in the graph order. This WILL return nodes in
|
||||
// nondeterministic order.
|
||||
typedef GraphStream<std::less<const V3GraphVertex*> > GraphStreamUnordered;
|
||||
typedef GraphStream<std::less<const V3GraphVertex*>> GraphStreamUnordered;
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -55,20 +55,20 @@ class V3GraphTestVertex : public V3GraphVertex {
|
|||
|
||||
public:
|
||||
V3GraphTestVertex(V3Graph* graphp, const string& name)
|
||||
: V3GraphVertex(graphp)
|
||||
, m_name(name) {}
|
||||
virtual ~V3GraphTestVertex() {}
|
||||
: V3GraphVertex{graphp}
|
||||
, m_name{name} {}
|
||||
virtual ~V3GraphTestVertex() override {}
|
||||
// ACCESSORS
|
||||
virtual string name() const { return m_name; }
|
||||
virtual string name() const override { return m_name; }
|
||||
};
|
||||
|
||||
class V3GraphTestVarVertex : public V3GraphTestVertex {
|
||||
public:
|
||||
V3GraphTestVarVertex(V3Graph* graphp, const string& name)
|
||||
: V3GraphTestVertex(graphp, name) {}
|
||||
virtual ~V3GraphTestVarVertex() {}
|
||||
: V3GraphTestVertex{graphp, name} {}
|
||||
virtual ~V3GraphTestVarVertex() override {}
|
||||
// ACCESSORS
|
||||
virtual string dotColor() const { return "blue"; }
|
||||
virtual string dotColor() const override { return "blue"; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -77,8 +77,8 @@ public:
|
|||
|
||||
class V3GraphTestStrong : public V3GraphTest {
|
||||
public:
|
||||
virtual string name() { return "strong"; }
|
||||
virtual void runTest() {
|
||||
virtual string name() override { return "strong"; }
|
||||
virtual void runTest() override {
|
||||
V3Graph* gp = &m_graph;
|
||||
// Verify we break edges at a good point
|
||||
// A simple alg would make 3 breaks, below only requires b->i to break
|
||||
|
|
@ -115,8 +115,8 @@ public:
|
|||
|
||||
class V3GraphTestAcyc : public V3GraphTest {
|
||||
public:
|
||||
virtual string name() { return "acyc"; }
|
||||
virtual void runTest() {
|
||||
virtual string name() override { return "acyc"; }
|
||||
virtual void runTest() override {
|
||||
V3Graph* gp = &m_graph;
|
||||
// Verify we break edges at a good point
|
||||
// A simple alg would make 3 breaks, below only requires b->i to break
|
||||
|
|
@ -143,8 +143,8 @@ public:
|
|||
|
||||
class V3GraphTestVars : public V3GraphTest {
|
||||
public:
|
||||
virtual string name() { return "vars"; }
|
||||
virtual void runTest() {
|
||||
virtual string name() override { return "vars"; }
|
||||
virtual void runTest() override {
|
||||
V3Graph* gp = &m_graph;
|
||||
|
||||
V3GraphTestVertex* clk = new V3GraphTestVarVertex(gp, "$clk");
|
||||
|
|
@ -265,18 +265,18 @@ class DfaTestVertex : public DfaVertex {
|
|||
|
||||
public:
|
||||
DfaTestVertex(DfaGraph* graphp, const string& name)
|
||||
: DfaVertex(graphp)
|
||||
, m_name(name) {}
|
||||
virtual ~DfaTestVertex() {}
|
||||
: DfaVertex{graphp}
|
||||
, m_name{name} {}
|
||||
virtual ~DfaTestVertex() override {}
|
||||
// ACCESSORS
|
||||
virtual string name() const { return m_name; }
|
||||
virtual string name() const override { return m_name; }
|
||||
};
|
||||
|
||||
class V3GraphTestDfa : public V3GraphTest {
|
||||
|
||||
public:
|
||||
virtual string name() { return "dfa"; }
|
||||
virtual void runTest() {
|
||||
virtual string name() override { return "dfa"; }
|
||||
virtual void runTest() override {
|
||||
DfaGraph* gp = &m_graph;
|
||||
|
||||
// NFA Pattern for ( (LR) | (L*R)) Z
|
||||
|
|
@ -330,8 +330,8 @@ class V3GraphTestImport : public V3GraphTest {
|
|||
#endif
|
||||
|
||||
public:
|
||||
virtual string name() { return "import"; }
|
||||
virtual void runTest() {
|
||||
virtual string name() override { return "import"; }
|
||||
virtual void runTest() override {
|
||||
DfaGraph* gp = &m_graph;
|
||||
if (V3GraphTest::debug()) DfaGraph::debug(9);
|
||||
dotImport();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue