Merge from master for release.

This commit is contained in:
Wilson Snyder 2020-09-07 09:38:50 -04:00
commit 39eea781bc
301 changed files with 14715 additions and 13072 deletions

View File

@ -104,7 +104,7 @@ SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -53,6 +53,7 @@ Pieter Kapsenberg
Piotr Binkowski
Qingyao Sun
Richard Myers
Rupert Swarbrick
Sean Cross
Sebastien Van Cauwenberghe
Sergi Granell

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -99,7 +99,7 @@ int main(int argc, char** argv, char** env) {
// Destroy model
delete top;
top = NULL;
top = nullptr;
// Fin
exit(0);

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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

View File

@ -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);
}

View File

@ -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));

View File

@ -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());

View File

@ -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);

View File

@ -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(); }

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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() {}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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(); }

View File

@ -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

View File

@ -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
};

View File

@ -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;

View File

@ -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

View File

@ -203,6 +203,7 @@ RAW_OBJS = \
V3GraphPathChecker.o \
V3GraphTest.o \
V3Hashed.o \
V3HierBlock.o \
V3Inline.o \
V3Inst.o \
V3InstrCount.o \

View File

@ -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 {}
};
//######################################################################

View File

@ -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 {}
};
//######################################################################

View File

@ -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);

View File

@ -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 {}
};
//######################################################################

View File

@ -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();
}

File diff suppressed because it is too large Load Diff

View File

@ -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");

File diff suppressed because it is too large Load Diff

View File

@ -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 {}
};
//######################################################################

View File

@ -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 {}
};
//######################################################################

View File

@ -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 {}
};
//######################################################################

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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);
}

View File

@ -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 {}
};
//######################################################################

View File

@ -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);
}
};

View File

@ -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 {}
};
//######################################################################

View File

@ -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());
}

View File

@ -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 {}
};
//######################################################################

View File

@ -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 {}
};
//######################################################################

View File

@ -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);
}
};

View File

@ -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;

View File

@ -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);

View File

@ -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 {}
};
//######################################################################

View File

@ -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);
}
};

View File

@ -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 {}
};
//######################################################################

View File

@ -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);
}
};

View File

@ -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 {}
};
//######################################################################

View File

@ -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 {}
};
//######################################################################

View File

@ -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 {}
};
//######################################################################

File diff suppressed because it is too large Load Diff

View File

@ -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; }
};

View File

@ -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);
}

View File

@ -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

View File

@ -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:

View File

@ -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");

View File

@ -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);
}

View File

@ -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

View File

@ -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 {}
};
//######################################################################

View File

@ -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 {}
};
//######################################################################

View File

@ -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

View File

@ -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");

View File

@ -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 {}
};
//----------------------------------------------------------------------

View File

@ -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("&quot;");
} else if (pos[0] == '\'') {
} else if (c == '\'') {
out += string("&apos;");
} else if (pos[0] == '<') {
} else if (c == '<') {
out += string("&lt;");
} else if (pos[0] == '>') {
} else if (c == '>') {
out += string("&gt;");
} else if (pos[0] == '&') {
} else if (c == '&') {
out += string("&amp;");
} 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

View File

@ -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); }

View File

@ -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.

View File

@ -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();

View File

@ -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 {}
};
//######################################################################

View File

@ -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 {}
};
//######################################################################

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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();
}

View File

@ -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) {

View File

@ -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() {}

View File

@ -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; }

View File

@ -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);
}
}

View File

@ -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; }

View File

@ -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

View File

@ -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